Solidity ERC20转账报错transfer amount exceeds spender allowance排查
报错根本原因及可能性排查
核心错误
你合约中fundToken函数的授权逻辑完全不符合ERC20的设计规则,是触发报错的主要原因:
// 这行代码逻辑完全错误 IERC20(tokenAddress).approve(address(this), amount);
在合约内部调用外部ERC20的approve方法时,调用方msg.sender是你的FundTokenContract合约地址,这行代码的实际效果是:合约给自己授权了支配自身持有的该ERC20代币的额度,对你后续要执行的「从用户账户转账代币到合约」的逻辑没有任何作用。
transferFrom要从用户(调用fundToken的msg.sender)账户转走代币,需要的是用户本人提前给你的合约地址授权对应额度,而非合约自己给自己授权。
其他可能触发该报错的原因
- 你手动给合约授权的额度小于调用
fundToken时传入的amount参数,比如你只授权了10枚代币,转账时传入了20枚的数值 - 授权额度的单位和转账单位不匹配:大多数ERC20代币默认是18位小数,如果你授权时传的数值没有乘10^18,实际授权额度会远小于你预期的转账金额
- 对应ERC20代币实现了「授权前必须先将原有额度清零」的安全逻辑(防范前置攻击),如果之前给合约授权过非0额度,没有先调用
approve(合约地址, 0)就直接更新为新的额度,会导致授权失败,实际可用额度没有更新
修复方案
- 删除
fundToken函数中的approve调用代码,该行没有任何作用 - 每次调用
fundToken之前,先由代币持有人直接调用对应ERC20合约的approve方法,spender参数填你的FundTokenContract合约地址,amount参数填你要存入的代币数量(注意和代币小数位匹配) - 授权交易链上确认后,再调用
fundToken即可正常完成转账
内容的提问来源于stack exchange,提问作者Giorgiu
相关产品推荐
相关产品推荐

