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

Hardhat测试时ERC20合约deposit方法transferFrom调用失败如何解决

ERC20 transferFrom执行失败问题分析

核心错误成因

  • 授权逻辑完全错误:ERC20(token).approve(address(this), amount)这行代码是合约自身给自身授予了token的操作权限,而transferFrom要求的是token的实际持有者(也就是调用deposit的外部地址msg.sender)给当前合约授权转账额度,这步授权完全没有生效,所以transferFrom触发ERC20的额度校验失败报错。
  • 测试逻辑缺失授权步骤:Hardhat测试代码里只给arb合约转了WETH,没有让owner账号给arb合约授权对应数量的WETH转账额度,也没有调整合约里的错误授权逻辑,直接调用deposit必然失败。
  • 额外的逻辑瑕疵:require判断里用的是balance > amount,如果用户余额刚好等于要存的数量也会报错,建议改成balance >= amount更符合常规业务逻辑。

补充说明:ERC20的transferFrom机制设计就是为了让第三方代付转账,必须由资金持有方主动给第三方授予额度,任何第三方都无法主动给自己授予操作他人资产的权限,这是ERC20的安全基础设计。

修复方案

第一步:修改Solidity合约代码

去掉合约里无效的self-approve逻辑,调整后的deposit代码如下:

function deposit(address token, uint256 amount) external onlyOwner {
    uint256 balance = ERC20(token).balanceOf(msg.sender);
    console.log(token, balance);
    // 调整判断条件为大于等于,避免刚好相等时报错
    require(balance >= amount, "not enough money to deposit");
    ERC20(token).transferFrom(msg.sender, address(this), amount);
}

第二步:调整Hardhat测试代码,提前执行授权操作

在调用arb.deposit之前,先让owner账号给arb合约授权对应额度的WETH,调整后的测试代码如下:

await WETH.transfer(arb.address, ethers.utils.parseUnits("2", "ether"));

await IWETH.deposit({
  value: ethers.utils.parseUnits("100.0", "ether"),
});

// 新增授权步骤:owner给arb合约授权2个WETH的转账额度
await WETH.connect(owner).approve(arb.address, ethers.utils.parseUnits("2", "ether"));

await arb
  .connect(owner)
  .deposit(
    "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    ethers.utils.parseUnits("2", "ether")
  );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:30:03