﻿---
title: "ERC-20 授权竞态"
description: "ERC-20 支出方可能在替换授权确认前先使用旧额度，然后再使用新额度。本文说明这种竞态的原理，以及如何更安全地更改或撤销授权。"
image: "https://wiki.fcontext.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.fcontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ERC-20 授权竞态

> 仅供教育参考，不构成投资建议；投资可能产生损失。

<a id="answer"></a>

## 直接答案

当所有者调用 `approve(spender, newAmount)`，把一个非零授权额度替换为另一个非零额度时，可能出现 ERC-20 授权竞态。支出方可以看到待处理的更改，先通过 `transferFrom` 用掉旧额度，再在替换授权确认后使用新额度。

因此，ERC-20 规范建议客户端界面先将同一支出方的授权额度设为 `0`，再设置新值。每笔交易都必须依次等待确认。如果代币支持原子化的 `increaseAllowance` 或 `decreaseAllowance` 调用，就可以避免直接替换非零授权额度。

<a id="mechanism"></a>

## 工作原理

ERC-20 将 `approve` 定义为覆盖操作：成功调用 `approve(spender, amount)` 会把支出方的授权额度设为 `amount`。另一方面，`transferFrom(owner, recipient, amount)` 允许该支出方转移所有者的代币，并且通常会减少剩余授权额度。待处理交易不会预留执行顺序，因此支出方可以提交一笔在所有者更改授权前执行的转账。

有风险的转换是 `N -> M`，其中 `N > 0` 且 `M > 0`。如果支出方在替换授权执行前用掉 `N`，之后的授权会重新设立额度 `M`。因此，在所有者的代币余额和代币实现允许的范围内，这一过程中最多可能支出 `N + M`。

<a id="example"></a>

## 示例

Alice 已授权某个协议支出 `100` 枚代币。她提交 `approve(protocol, 50)`，打算把剩余授权额度降至 `50`。在这笔交易确认前，协议的支出方提交 `transferFrom(Alice, recipient, 100)`，并让它先执行。随后，Alice 的授权把额度设为 `50`，支出方可以在另一笔转账中继续使用。两笔转账合计 `150` 枚代币。

更安全的替换流程是先提交 `approve(protocol, 0)`，等待确认并检查更新后的授权额度和余额，然后仅在新授权仍然合适时提交 `approve(protocol, 50)`。如果支出方在归零交易确认前使用旧额度，Alice 就能看到余额变化，并在授予新的 `50` 额度前停止操作。

<a id="risks"></a>

## 风险

- 将授权额度设为 `0` 无法撤销已经执行的支出，也无法阻止支出方在归零交易确认前使用旧额度。
- 如果不等待第一笔交易确认，就同时发送归零授权和替换授权，执行顺序风险会再次出现。
- `increaseAllowance` 和 `decreaseAllowance` 不属于基础 ERC-20 标准；只有在经验证的代币合约支持它们时才应使用。
- 只要无限授权仍然有效，所有者的全部代币余额都可能面临风险。签名前请核对链、代币合约、支出方和金额。
- 有些代币采用非标准的授权行为。请查看钱包模拟结果和交易 calldata，并在每一步之后确认链上授权额度。

<a id="misconceptions"></a>

## 常见误区

- “最新的授权交易会立即替换旧授权。”只有当交易在链上执行时，状态才会改变。
- “降低授权额度会把未来的总支出限制在新额度内。”支出方可能在更改执行前使用旧额度。
- “先归零可以保证不再有代币转出。”在归零交易确认前，旧额度仍然可以使用。
- “每种 ERC-20 都有 `increaseAllowance` 和 `decreaseAllowance`。”它们是可选扩展，并非 ERC-20 的要求。
- “断开网站连接就会撤销代币授权。”钱包连接状态与代币合约的链上授权额度是两回事。

<a id="related"></a>

## 相关主题

- [如何区分规范代币和封装代币](/zh-cn/crypto/canonical-vs-wrapped-token/)
- [内存池](/zh-cn/crypto/mempool/)
- [Permit2 签名风险](/zh-cn/crypto/permit2-signature-risk/)
- [只减仓订单](/zh-cn/crypto/reduce-only-order/)
- [钱包授权](/zh-cn/crypto/wallet-approval/)

<a id="sources"></a>

## 来源

- [ERC-20: Token Standard](https://eips.ethereum.org/EIPS/eip-20) - Ethereum Improvement Proposals (查阅日期: 2026-08-20)
- [ERC20 | OpenZeppelin Docs](https://docs.openzeppelin.com/contracts/4.x/api/token/erc20) - OpenZeppelin (查阅日期: 2026-08-20)

Source: https://wiki.fcontext.com/zh-cn/crypto/erc20-approval-race-condition/index.mdx
