跳到正文

ERC-20 授权竞态

ERC-20 支出方可能在替换授权确认前先使用旧额度,然后再使用新额度。本文说明这种竞态的原理,以及如何更安全地更改或撤销授权。

更新于

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

直接答案

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

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

ERC-20 授权竞态
0 / 5
0 项已核查; 5 项仍未解决

完成核查不代表资产、交易或系统已经安全。

工作原理

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

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

示例

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

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

风险

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

常见误区

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

相关主题

来源

导航

搜索知识库...