0

Hi I've written a simple smart contract to transfer erc20 token from user to smart contract and from smart contract to user. I'm approving it before calling the transferFrom function but the transactions fails. I've tried only calling approve and not calling transferFrom it works. I'm testing on rinkeby testnet.

// 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 _WETH = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984;
    IERC20 public WETH = IERC20(_WETH);

    function transferToC (uint amount) public
    {
        WETH.approve(msg.sender,amount);
        WETH.transferFrom(msg.sender,address(this),amount);
    }
    
    function transferFromC(uint amount) public{
        WETH.approve(address(this),amount);
        WETH.transferFrom(address(this),msg.sender,amount);
    }
    
    function getbal() public view returns(uint){
        return WETH.balanceOf(msg.sender);
    }
    
    
}

I'm testing on remix with web3 injected. The error I'm getting is

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted: Uni::transferFrom: transfer amount exceeds spender allowance { "originalError": { "code": 3, "data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003c556e693a3a7472616e7366657246726f6d3a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636500000000", "message": "execution reverted: Uni::transferFrom: transfer amount exceeds spender allowance" } }

Also I have the token in my test wallet on rinkeby testnet and I'm deploying using remix web3 injected.

2 Answers2

2
WETH.approve(msg.sender,amount);

This line approves the user to spend your contract's tokens. Not the other way around.

If you want to approve the contract to manipulate the user's tokens, the user needs to execute approve(yourContractAddress, amount) directly on the WETH contract (not through your contract).


I've covered a similar topic in another answer. The TLDR part is also relevant to your question - https://stackoverflow.com/a/67642090/1693192

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • That makes sense. How can I call WETH.approve directly from my user wallet instead of a smart contract. – Im retarded but Jul 07 '21 at 11:15
  • One way I can think of is using etherjs, calling the WETH smart contract for approval first then calling this smart contract to transfer – Im retarded but Jul 07 '21 at 11:18
  • Yes, that's a valid way. – Petr Hejda Jul 07 '21 at 11:22
  • One last doubt if I call WETH.approve from my user wallet and allowing my contract to spend my balance for how long is that valid. I mean the time duration. Is it valid forever? – Im retarded but Jul 07 '21 at 11:22
  • 1
    It depends on the contract implementation. In case of WETH specifically, it's valid "forever", until you reset the value to another (you can also set the value to 0)... And of course, the approved amount decreases with the spent amount. So if the user approves your contract to spend 100 tokens, then the contract spends 20 (of the user's) tokens, there's still 80 approved. – Petr Hejda Jul 07 '21 at 11:25
0

I want my contract to accept tokens from external accounts, which has few tokens (can be any, but based on ERC20). So to call the approve function directly I need to create an instance of the token's contract, so how do I create the instance using web3?

Any code piece would help or if you could share link to any document for the same would help too.