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 aGoodToken
as input: completes successfully - Calling
transferGoodToken
with a the address of aBadToken
as input: reverts the transaction - Calling
transferBadToken
with a the address of aGoodToken
as input: completes successfully - Calling
transferBadToken
with a the address of aBadToken
as input: completes successfully
The SafeERC20 works around this potential problem.