SafeERC20 only reverts with message if token returns False

Consider the reason that this library has been created to begin with, being a few token contracts which had been deployed to the network at a very early phase (2017ish), without properly conforming to the ERC20 standard.

More specifically, these token creators simply did not bother to return a boolean value in some of the ERC20 functions (transfer, approve, etc), which would typically be as simple as returning true upon completion, since nothing needs to be returned otherwise (upon reverting).

This, in turn, leads any attempt to call any of these functions using a standard ERC20 interface, to revert on "evm crash" (kinda similar to undefined behavior in "bare metal languages" like C and C++).

The SafeERC20 library simply wraps any given ERC20 contract in a manner which works around this potential problem.

FYI, you can avoid using it for any token which conforms to the ERC20 standard (for example, if your system isn't design to handle any arbitrary token, but only specific token or tokens which implement the standard correctly).

See this post for more details.


Here is a quick coding example which might help illustrating the problem:

Consider the following terminology:

  • GoodToken - a token contract which conforms to the ERC20 standard
  • BadToken - a token contract which doesn't conform to the ERC20 standard

Then given the following contracts:

contract GoodToken {
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    function transfer(address _to, uint256 _value) public returns (bool) {
        emit Transfer(msg.sender, _to, _value);
        return true;
    }
}

contract BadToken {
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    function transfer(address _to, uint256 _value) public {
        emit Transfer(msg.sender, _to, _value);
    }
}

contract Caller {
    function transferGoodToken(address _token, address _to, uint256 _value) public {
        GoodToken(_token).transfer(_to, _value);
    }
    function transferBadToken(address _token, address _to, uint256 _value) public {
        BadToken(_token).transfer(_to, _value);
    }
}

We can observe the following results:

  • Calling transferGoodToken with a the address of a GoodToken as input: completes successfully
  • Calling transferGoodToken with a the address of a BadToken as input: reverts the transaction
  • Calling transferBadToken with a the address of a GoodToken as input: completes successfully
  • Calling transferBadToken with a the address of a BadToken as input: completes successfully

The SafeERC20 works around this potential problem.

1 Like