ERC20 token transferFrom failed even successfully doing approve().reason: 'invalid address (argument="address", value=1000, code=INVALID_ARGUMENT, version=address/5.0.5)'

:computer: Environment
Truffle v5.2.6 (core: 5.2.6)
Solidity - ^0.6.6 (solc-js)
Node v12.21.0
Web3.js v1.2.9
@openzeppelin/contracts”: “^3.3.0”,
@truffle/hdwallet-provider”: “^1.0.36”
“web3-provider-engine”: “^16.0.1”,

:memo:Details
I am simply trying to use approve() and transferFrom to transfer my kovan testnet DAI token to my flashloan contract. My code is listed below:

Flashloan.sol

pragma solidity ^0.6.6;

import "./aave/FlashLoanReceiverBase.sol";
import "./aave/ILendingPoolAddressesProvider.sol";
import "./aave/ILendingPool.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";


contract Flashloan is FlashLoanReceiverBase{
    // IERC20 token = IERC20(0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD);
    IERC20 public token;
    address beneficiary;
    constructor(address _addressProvider) FlashLoanReceiverBase(_addressProvider) public {}

    function setToken(address _asset) public {
        token = IERC20(_asset);
    }

    function withdraw(uint _amount) public {
        token.transferFrom(msg.sender, address(this), _amount);
    }

    function executeOperation(
        address _reserve,
        uint256 _amount,
        uint256 _fee,
        bytes calldata _params
    )
        external
        override
    {
        // Flashloan logic
    }

    function flashloan(address _asset, uint _amount, address _beneficiary) public onlyOwner {
        // Flashloan logic
    }
}

Everything goes well (truffle migration, approve, allowance) until I do transferFrom(). See my procedure below:

$ truffle console
truffle(development)> migrate -->
truffle(development)> let f = Flashloan.deployed()
truffle(development)> let abi = <IERC20abi>
truffle(development)> let dai = <kovan testnet DAI contract ID>
truffle(development)> let tok = await new web3.eth.Contract(abi, dai)
truffle(development)> await tok.methods.approve(f.address, 10000).send({from:accounts[0]})
truffle(development)> await tok.methods.allowance(accounts[0], f.address).call()
'10000'
truffle(development)> await tok.methods.transferFrom(accounts[0], f.address, 1000).send({from: accounts[0]})

Then it turns error:
Uncaught Error: The execution failed due to an exception.
Reverted

And I try calling withdraw method of Flashloan contract and it fails with following error msg:

truffle(development)> await f.withdraw(1000)
Uncaught:
Error: invalid address (argument="address", value=1000, code=INVALID_ARGUMENT, 
version=address/5.0.5) (argument="_assetAddress", value=1000, code=INVALID_ARGUMENT, 
version=abi/5.0.0-beta.153)

My development network setting in truffle-config.js is:

development: {
	provider: ()=> new HDWalletProvider(process.env.DEPLOYMENT_ACCOUNT_KEY, "https://kovan.infura.io/v3/" + process.env.INFURA_API_KEY),
    network_id: 42,
    gas: 5000000,
	gasPrice: 5000000000, // 5 Gwei
	skipDryRun: true,
},

To make a comparison, I actually tried creating my own ERC20 token by following abcoathup’s tutorial and tested approve, allowance and transferFrom. All process went through without issue. See below:

Environemnt
Truffle v5.2.6 (core: 5.2.6)
Solidity - 0.8.0 (solc-js)
Node v12.21.0
Web3.js v1.2.9
@openzeppelin/contracts”: “^4.0.0”,

myToken.sol

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract myToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("ColorfuleLife Token", "CFL") {
        _mint(msg.sender, initialSupply);
    }
}

TokenReceiver.sol

pragma solidity ^0.8.0;

import "./MyToken.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenReceiver {
    ERC20 token;
    constructor(address _tokenAddress) {
        token = ERC20(_tokenAddress);
    }
    function withdraw(uint _amount) public {
        token.transferFrom(msg.sender, address(this), _amount);
    }
}

In this case, following steps have successfully gone through:

$ truffle console
truffle(development)> migrate
truffle(development)> tok = await myToken.deployed()
truffle(development)> rec = await TokenReceiver.deployed()
truffle(development)> tok.approve(rec.address, 5000)
truffle(development)> tok.allowance(accounts[0], rec.address)
'5000'
truffle(development)> rec.withdraw(1000)

I would say the only environmental difference in my comparison are solidity, openzepplin and testNetwork version:

  • self-created token: solidity 0.8.0 + openzepplin 4.0.0 + ganache localhost test network
  • flashloan: solidity 0.6.6 + openzepplin 3.3.0 + infura kovan test network

Very appreciated if anyone could share any idea letting me know if I misunderstand any concept.Or
there is anywhere goes wrong on the flashloan project.

1 Like

Hi @happyeric77,

Welcome to the community :wave:

You can have a look at the following example: Example on how to use ERC20 token in another contract