![[Ethereum] Tether USDT doesn’t follow the ERC20 standard [Ethereum] Tether USDT doesn’t follow the ERC20 standard](https://mr-v.fi/wp-content/uploads/2019/05/3bt7zeQH-1024x576.jpg)
[Ethereum] Tether USDT doesn’t follow the ERC20 standard
When I tried to use smart contract to collect ERC20 Token from the contract, but I found the “Transfer” function of USDT doesn’t work on my smart contract. It means I can send the ERC20 USDT to the smart contract, but I can’t send out from the contract, let’s find out what’s going on.
1. Rough analysis
I use the standard ERC20 format to generate a Test token on the Test net, then just use my smart contract to send in and send out, it succeeded.
My smart contract code:
contract Receiver is Ownable { function sendFundsTo( address tracker, uint256 amount, address receiver) public onlyOwner { // Transfer tokens from this address to the receiver IERC20(tracker).transfer(receiver, amount); } function balanceOf(address tracker, address owner) public view returns(uint amounts) { return IERC20(tracker).balanceOf(owner); } }
ERC20 USDT contract code: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code
Then, I copied a copy of the code, then deploy into Test net, and generate the fake USDT Token on the Test net.
I sent the fake USDT Token into my smart contract, then trying to send it out, I can’t send out the fake USDT Token on the Test net, so there is must be something wrong.
2. In-depth analysis
We can see the part of the code of USDT contract as below. The “Transfer” function doesn’t return anything
// Forward ERC20 methods to upgraded contract if this one is deprecated function transfer(address _to, uint _value) public whenNotPaused { require(!isBlackListed[msg.sender]); if (deprecated) { return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value); } else return super.transfer(_to, _value) } }
and we can see the Transfer function of ERC20 require a return value
interface IERC20 { function totalSupply() external view returns (uint); function balanceOf(address tokenOwner) external view returns (uint); function allowance(address tokenOwner, address spender) external view returns (uint); function transfer(address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); event Transfer(address indexed from, address indexed to, uint tokens); event Approval(address indexed tokenOwner, address indexed spender, uint tokens); }
that’s why we can’t use the smart contract to call the USDT transfer function to transfer out the Token.
3. Solution
Revise the IERC20 interface as below. Delete the return value of the Transfer function.
interface IERC20 { function totalSupply() external view returns (uint); function balanceOf(address tokenOwner) external view returns (uint); function allowance(address tokenOwner, address spender) external view returns (uint); function transfer(address to, uint value) external view; function approve(address spender, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); event Transfer(address indexed from, address indexed to, uint tokens); event Approval(address indexed tokenOwner, address indexed spender, uint tokens); }
But, if you want to support another ERC20 token, you should write another ERC20 interface to adopt it.
