How to transfer an external ERC20 token with IERC20?

Currently, I try to send Wrapped ETH from my account to a contract address by using IERC20. But it returned an error on Remix. By the way, I could call token.balanceOf(msg.sender) but can’t execute token.transferFrom(msg.sender, address(this), amount) somehow.

:computer: Environment
Remix IDE
compiler version : 0.6.12

:memo:Details
My code is below

pragma solidity ^0.6.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol";


contract Test2 {
       
        IERC20 public token;
       
        constructor(address _token) public {
        token = IERC20(_token);
        }
        
        function getBalance() public view returns(uint) {
            uint balance_ = token.balanceOf(msg.sender);
            return balance_;
        }
        
        function deposit(uint amount) public {
            require(amount <= token.balanceOf(msg.sender), "you don't have enough balance.");
            token.transferFrom(msg.sender, address(this), amount);
        }
    
}

And ERC20 token I want to send is Wrapped ETH. So I copied the WETH contract and deployed on Remix before I deployed this contract. And when I deploy the above contract I add deployed WETH contract address as an argument of the constructor.

The error message is always like below on Javascript VM on Remix IDE. But this error message doesn’t tell what the real problem is. making my contract payable doesn’t make sense and I checked that the balance I own is always more than I want to send.

VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance.

WETH contract is here but actually which erc20 I use doesn’t matter because I tried the same thing with other deployed ERC20 tokens and even external LINK contract on the Ropsten net. ( btw, I already tried it not only on JVM but also ganache and ropsten testnet.)

contract WETH9 {
    string public name     = "Wrapped Ether";
    string public symbol   = "WETH";
    uint8  public decimals = 18;

    event  Approval(address indexed src, address indexed guy, uint wad);
    event  Transfer(address indexed src, address indexed dst, uint wad);
    event  Deposit(address indexed dst, uint wad);
    event  Withdrawal(address indexed src, uint wad);

    mapping (address => uint)                       public  balanceOf;
    mapping (address => mapping (address => uint))  public  allowance;

    function() public payable {
        deposit();
    }
    function deposit() public payable {
        balanceOf[msg.sender] += msg.value;
        Deposit(msg.sender, msg.value);
    }
    function withdraw(uint wad) public {
        require(balanceOf[msg.sender] >= wad);
        balanceOf[msg.sender] -= wad;
        msg.sender.transfer(wad);
        Withdrawal(msg.sender, wad);
    }

    function totalSupply() public view returns (uint) {
        return this.balance;
    }

    function approve(address guy, uint wad) public returns (bool) {
        allowance[msg.sender][guy] = wad;
        Approval(msg.sender, guy, wad);
        return true;
    }

    function transfer(address dst, uint wad) public returns (bool) {
        return transferFrom(msg.sender, dst, wad);
    }

    function transferFrom(address src, address dst, uint wad)
        public
        returns (bool)
    {
        require(balanceOf[src] >= wad);

        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }

        balanceOf[src] -= wad;
        balanceOf[dst] += wad;

        Transfer(src, dst, wad);

        return true;
    }
}

this idea using IERC20 comes from a couple of DeFi projects’ contracts, for example, Yearn’s yWETH.sol and Opyn’s Optioncontrac.sol. Each of them uses transferFrom function with variables of ERC20 contracts created with IERC20. So I want to do the same thing!

Please help me if you know what the problem is! thanks!

1 Like

Hi @wat,

Welcome to the community :wave:

Have you approved an allowance for the Test2 contract for the amount that of WETH that you want to send?

See the following example: Example on how to use ERC20 token in another contract

Hi abcoathup, I could successfully execute this contract approving an allowance for the Test2 contract as you said. Thanks for answering my question!

1 Like

Hi @wat,

Great to hear. If you have a moment it would be nice if you could introduce yourself to the community.