You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用transferFrom时我的ERC20合约会回滚?

问题分析与解决方案

你的问题核心在于对OpenZeppelin ERC20合约的transferFrom函数行为理解有误,同时代码存在竞态条件问题:

关键问题点

  1. OpenZeppelin ERC20的transferFrom不返回布尔值
    从OpenZeppelin v4.x版本开始,适配Solidity 0.8+的ERC20实现中,transferFrom、transfer等函数不再返回bool类型结果。当转账失败时(比如授权额度不足、余额不足),函数会直接触发revert抛出错误,而非返回false。你代码中试图用bool success接收返回值的写法是错误的,这会导致编译警告或运行时异常,最终触发你自定义的"Transfer failed"错误。

  2. 竞态条件风险
    你先调用token.allowance(from, msg.sender)检查额度,再执行transferFrom的操作存在竞态窗口:两次调用之间,from地址可能已经修改了给msg.sender的授权额度(比如调用approve减少额度),导致transferFrom执行时实际额度不足,即使之前的检查结果是充足的。

修改后的代码

直接移除多余的额度检查和返回值判断,让transferFrom自身处理所有校验逻辑:

function spend(address from, address to, uint256 amount) public {
    token.transferFrom(from, to, amount);
}

补充说明

如果需要自定义错误提示,可以利用Solidity 0.8+的try/catch捕获transferFrom抛出的异常,但通常不需要——OpenZeppelin的ERC20已经内置了清晰的错误类型(比如ERC20InsufficientAllowance、ERC20InsufficientBalance),这些错误会直接暴露给调用者,便于排查问题。

内容的提问来源于stack exchange,提问作者Fauzan Hidayatulloh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:42:11