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)); } }
正确操作步骤
- 部署修正后的合约到Rinkeby测试网
- 你自己的测试钱包地址,直接调用Rinkeby WETH合约的
approve方法,spender参数填你刚部署的合约地址,amount填你要转账的额度 - 再调用合约的
transferToC方法,传入对应额度即可完成用户到合约的转账 - 需要把合约里的WETH转回给自己,直接调用
transferFromC方法传入对应额度即可,不需要额外approve操作
内容的提问来源于stack exchange,提问作者Im retarded but
相关产品推荐
相关产品推荐

