﻿---
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-tw/crypto/canonical-vs-wrapped-token/)
- [記憶池](/zh-tw/crypto/mempool/)
- [Permit2 簽章風險](/zh-tw/crypto/permit2-signature-risk/)
- [只減倉訂單](/zh-tw/crypto/reduce-only-order/)
- [錢包授權](/zh-tw/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-tw/crypto/erc20-approval-race-condition/index.mdx
