Skip to content

Commit dac6e5b

Browse files
committed
Add study notes for 2025-08-18
1 parent da34fd3 commit dac6e5b

1 file changed

Lines changed: 16 additions & 0 deletions

File tree

qiaopengjun5162.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ web3 开发者,Python、Go、Rust、Solidity 等语言经验丰富,项目开
1515
## Notes
1616

1717
<!-- Content_START -->
18+
# 2025-08-18
19+
20+
## Solidity `approve` 函数授权的抢跑问题及其解决方案
21+
22+
在 Solidity 智能合约中,特别是遵循 ERC20 标准的代币合约,`approve` 函数存在一个常见的安全隐患,即“授权抢跑”(Front-running)问题。该问题源于以太坊交易的异步特性。当一个用户决定修改之前给予另一个地址(例如一个去中心化交易所)的代币花费授权额度时,会发起一笔新的 `approve` 交易。在旧的授权额度(例如 1000)尚未被新额度(例如 500)覆盖的这笔交易等待被矿工打包的间隙,被授权方可以监听到这笔待处理的交易。恶意攻击者可以立即以更高的 Gas 费发起一笔 `transferFrom` 交易,抢先将原有的 1000 额度全部或部分转走,待用户的修改授权交易被确认后,攻击者可能还可以继续使用新的 500 额度,从而导致用户的资产损失超出预期。
23+
24+
为解决此问题,业界提出了几种有效的解决方案:
25+
26+
1. **先归零再授权**:这是一种简单有效的策略。用户在修改授权额度之前,先发送一笔交易将授权额度设置为 0,等待该交易确认后,再发送一笔新的交易,将额度设置为期望的目标值。这样就彻底杜绝了旧额度被利用的风险窗口,但缺点是需要用户执行两次交易,增加了操作复杂性和 Gas 成本。
27+
28+
2. **使用 `increaseAllowance``decreaseAllowance`**:许多现代的 ERC20 实现(如 OpenZeppelin 的早期版本)提供了 `increaseAllowance` (增加授权) 和 `decreaseAllowance` (减少授权) 这两个函数来替代标准的 `approve`。这些函数通过在当前授权值的基础上进行原子化的加减操作来更新额度,而不是直接覆盖。例如,若想将授权从 1000 降至 500,应调用 `decreaseAllowance(500)`。即使攻击者在此期间抢跑交易,也只会影响减少前的额度,而不会出现“旧额度+新额度”的重复花费问题。
29+
30+
3. **使用 `safeApprove`**:尽管在最新版本的 OpenZeppelin 合约库中已被弃用,但 `safeApprove` 曾是推荐的解决方案之一。它强制要求在设置非零的新额度之前,当前额度必须为零,从而在合约层面强制执行了“先归零再授权”的最佳实践。
31+
32+
在当前的开发实践中,最推荐的做法是谨慎处理授权变更,优先考虑使用原子化的额度增减函数。如果合约未提供此类函数,则应在用户界面引导用户采用“先归零再授权”的两步操作流程,以确保资金安全。
33+
1834
# 2025-08-17
1935

2036
# Monad 验证合约

0 commit comments

Comments
 (0)