Difference between importing ERC20 token/importing IERC20

Hello everyone,

I'm kinda new in this space and I think I'm missing something to understand a concept.

My problem in short:

I have created my own ERC20 token (myToken).
Next to this i want to create a contract with a simple transfer function, assuming the contract balance of myToken > 0.

Now is the thing, I found two different ways of doing it:

  1. By importing myToken.sol and making my contract is myToken (see contract first example)
  2. By importing IERC20.sol (see contract second example)

FIRST EXAMPLE

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.15;

import "./myToken.sol";

contract firstExample is myToken {
    constructor() {}

    function transfer(address _to, uint256 _amount) public payable {
        myToken.transfer(_to, _amount);
    }
}

SECOND EXAMPLE

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.15;

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

contract secondExample {
    IERC20 private addressMyToken;

    constructor(IERC20 _tokenAddress) {
        addressMyToken = _tokenAddress;
    }

    function transfer(address _to, uint256 _amount) public payable {
        IERC20(addressMyToken).transfer(_to, _amount);
    }
}

Can you ELI5 what is the difference in those two methods?
And also in example 2 what does IERC20 private addressMyToken actually do or mean?

Thanks a lot in advance for your help.

By using the interface your contract will be a lot smaller to deploy. You don't need a full contract but just a way to know the functions that you can call. (the interface)

If you use the full ERC20 you will deploy a full token contract that is probably not needed.

import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; //you import the interface

contract secondExample {
    IERC20 private addressMyToken; // you declare an interface named addressMyToken

    constructor(IERC20 _tokenAddress) { // you pass an address that is declared as an IERC20
        addressMyToken = _tokenAddress; // you set addressMyToken as the provided _tokenAddress
    }

    function transfer(address _to, uint256 _amount) public payable {
        IERC20(addressMyToken).transfer(_to, _amount); // you don't need to redeclare it as an IERC20
        
        addressMyToken.transfer(_to, _amount); // is the same

    }
}

you first contract firstExample would be a token contract

The second one would not be a token contract but a contract that can call your token contract because you provided the interface.

Thanks a lot for the detailed response and the comments on the contract! I think I get the idea now :slight_smile:

1 Like