logoAcademy

Interacting with ERC20 Tokens

Fungible Token Standard

In this section, we will go through an example of how to interact with an ERC-20 from another contract.

Read Operations

Before calling any operations of an ERC-20 contract, we will need to have the following available:

  • The ERC-20 interface
  • The address of the ERC-20 token we want to interact with

Our starting Solidity file, therefore, will the following code:

 
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {


    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address _owner) external view returns (uint256 balance);

    function transfer(address _to, uint256 _value) external returns (bool success);

    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

    function approve(address _spender, uint256 _value) external returns (bool success);

    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

}
contract Test {
​
    address tokenAddress;
​
}

As a starter, let's write a function that gets the name of the token:

contract Test {

    address tokenAddress;
  
    function getName() public view returns(string memory) {
      return IERC20(tokenAddress).name();
    }

}

Perhaps the only unfamiliar piece of syntax is in line 6. In Solidity, note the following:

  • Contracts and interfaces are inherently types.
  • We can wrap an address type into a contract/interface type. If the contract associated with the address

With the above in mind, the logic of getName is as follows:

  • We call the function name at address token by wrapping the address type with the IERC20 interface
  • name returns us the name of the token contract
  • getName returns the name of the token contract

Just like that, we were able to call a read function of an ERC-20 contract. But what if we wanted to modify the state of an ERC-20 contract?

Write Operations

In this example, we will look at calling the transferFrom function of an ERC-20 token contract. Recall that, if authorized, transferFrom allows us to transfer tokens from one account to another. As a starter, we have the following code:

contract Test {

    address tokenAddress;
    address from;
    address to;
    uint amt;
  
    function getName() public view returns(string memory) {
      return IERC20(tokenAddress).name();
    }
  
    function doTransferFrom() public returns(bool) {
        return IERC20(tokenAddress).transferFrom(from, to, amt);
    }

}

In addition to adding additional state variables for context, we have also added the function doTransferFrom which calls the transferFrom function of the ERC-20 token contract. In particular, doTransferFrom returns the boolean returned by transferFrom, which represents whether if the function was successful or not. While the code above works, we can make it better by first checking if we are have been allocated enough tokens such that transferFrom(from, to, amt) will return true. To do this, we can make a call to the allowance function of the ERC-20 token contract. Our updated code is as follows:

contract Test {

    address token;
    address from;
    address to;
    uint amt;
  
    function getName() public view returns(string memory) {
      return IERC20(token).name();
    }
  
    function doTransferFrom() public returns(bool) {
        if (IERC20(token).allowance(from, address(this) < amt) {
            return false;
        }
        return IERC20(token).transferFrom(from, to, amt);
    }

}

In line 13, we are passing in both the address of the spender and the address of our own smart contract to the allowance function, which returns the amount of allocated tokens which we compare to our amt variable. If we are have not been allocated enough tokens, we return false and therefore, we do not spend any additional computation resources calling transferFrom, which we know would have been unsuccessful.

On this page