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

ERC20调用transferFrom转账至合约报allowance不足问题排查

问题根因

你的代码完全搞混了ERC20 approve 接口的调用方逻辑,才会触发额度不足的报错。

1. transferToC 函数逻辑错误

你在函数内执行的 WETH.approve(msg.sender,amount),本质是合约以自己的身份,把自己持有的WETH额度批准给调用用户。但你接下来要执行的 transferFrom(msg.sender,address(this),amount) 是要把用户持有的WETH转到合约地址,这个操作需要的是用户主动以自己的身份,提前给你的合约地址批准对应额度的WETH使用权,你在合约内部调用approve完全达不到这个效果,自然会报额度不足。

2. transferFromC 函数逻辑冗余

你写的 WETH.approve(address(this),amount) 是合约自己批准自己花费自己的WETH,没有任何实际意义。合约要转出自己持有的WETH,直接调用transfer接口即可,不需要走approve+transferFrom的流程。

修正后的代码

// SPDX-License-Identifier: MIT
pragma solidity =0.7.6;
pragma abicoder v2;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

}

contract transferToContract {
    address public constant _WETH = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984;
    IERC20 public constant WETH = IERC20(_WETH);

    // 用户需要先自己调用WETH的approve方法,给本合约地址批准对应额度的WETH,再调用这个函数
    function transferToC (uint amount) public
    {
        // 这里不需要在合约内调用approve,额度是用户提前给的
        bool success = WETH.transferFrom(msg.sender, address(this), amount);
        require(success, "transfer failed");
    }
    
    function transferFromC(uint amount) public{
        // 直接转合约自己的WETH给调用用户即可
        bool success = WETH.transfer(msg.sender, amount);
        require(success, "transfer failed");
    }
    
    function getbal() public view returns(uint){
        return WETH.balanceOf(msg.sender);
    }
    
    // 新增查询合约WETH余额的方法,方便调试
    function getContractBal() public view returns(uint) {
        return WETH.balanceOf(address(this));
    }
}

正确操作步骤

  1. 部署修正后的合约到Rinkeby测试网
  2. 你自己的测试钱包地址,直接调用Rinkeby WETH合约的approve方法,spender参数填你刚部署的合约地址,amount填你要转账的额度
  3. 再调用合约的transferToC方法,传入对应额度即可完成用户到合约的转账
  4. 需要把合约里的WETH转回给自己,直接调用transferFromC方法传入对应额度即可,不需要额外approve操作

内容的提问来源于stack exchange,提问作者Im retarded but

相关产品推荐
方舟 Agent Plan

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

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