ERC-20 token standard contains a major logical flaw — a lack of communication model (lack of transaction handling model).
This problem is well-known. I wrote tens of articles on Ethereum Reddit, Gitter, and GitHub during the past 6 years. Starting from this post. Also, here is Vitalik Buterin’s comment on this.
The solution exists. In 2017 I proposed the ERC-223 token standard. ERC-223 implements a transaction handling model for tokens. (Note that ERC23 and ERC-223 is the same thing, ERC23 is just the old deprecated name)
Lost ERC-20 tokens
Let’s take a look at the DAI contract address. This address has $647,211 worth of ERC-20 tokens on its balance.
But it’s a token contract — the token contract is not intended to receive and hold any tokens. The token contract is intended to only be the token.
There are not only DAI tokens in the contract; there are some USDC and USDT as well.
How does this happen?
Here is the description of ERC-20 problems that was posted on Ethereum Reddit.
Users accidentally sent tokens to a DAI contract address by mistake, and the contract successfully received tokens when it mustn’t receive them.
It is known for sure that the DAI contract (and any other token contract) is not intended to receive any assets.
- This contract WILL NOT receive Ether if it is sent to the contract address — in this case, an error will occur, and the transaction will fail. ETH will be returned to the address of the sender.
- The contract WILL NOT receive ERC-223 tokens — an error will occur similar to that of an Ether transaction.
- The contract WILL NOT receive ERC-721 NFTs if it is not intended to, and the transaction will fail; no NFTs will be lost.
- The contract WILL receive ERC-20 tokens without any errors (despite it being known that the transaction can only be a mistake), and the tokens will become stuck in the contract address without any possibility of recovering them. The user will just lose his funds.
This constantly happens because it is not possible to handle ERC-20 transactions at all. Ether transfer notifies the recipient of an incoming transaction, ERC-223 notifies the recipient, ERC-721 notifies the recipient, and ERC-20 does not.
Technical description of the ERC-20 problem
Read more about ERC-20 problem classification here.
In programming, event handling is standard practice. When one program (such as a token contract) is performing some action that involves another program, it must notify that program. A transaction is an event, and the recipient of the transaction must be able to get a notification on the incoming transaction and handle it.
The “final” ERC-20 documentation can be found here: https://eips.ethereum.org/EIPS/eip-20
According to ERC-20 EIP, it defines two methods of transferring tokens:
- transfer() function, assumed to be used to transfer tokens between addresses owned by humans.
- transferFrom() function that requires that an approval between sender and spender is issued first. Assumed to be used when a user needs to deposit tokens to contract.
None of these functions notifies the recipient about the incoming ERC-20 transfer. ERC-20 standard does not declare the logic of sending tokens directly to contracts at all.
In order to avoid the situation where a user sends tokens and these get lost in a contract that can’t operate with them, the following conditions must be met:
- If the token is sent to a contract directly and ERC-20 does not support this type of depositing tokens — then an error must occur.
- If the ERC-20 token is sent to a contract that is not intended to receive tokens — then an error must occur.
In order to reject an incoming ERC-20 or throw an error, the recipient must recognize the incoming transaction. And this is exactly the problem of the ERC-20 standard — it does not let the receiver recognize an incoming transaction.
How many tokens are lost due to this flaw?
Tens of millions of dollars worth of ERC-20 tokens.
On 27 Dec 2017, there were about $3,000,000 worth of ERC-20 tokens stuck in the contracts (you can find the number on this thread).
There is a public record — a Twitter thread where one person described how $1,000,000 worth of USDT was lost in the contract exactly because of this ERC-20 flaw.
As of today (3/9/2023), only in the next contracts there are more than $11 million tokens that were lost by users due to ERC-20's lack of transaction handling:
- $6,800,000 are lost in BNB contract https://etherscan.io/address/0xB8c77482e45F1F44dE1745F52C74426C631bDD52
- $2,600,000 are lost in SHIB contract https://etherscan.io/address/0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce
- $1,700,000 are lost in HEX contract https://etherscan.io/address/0x2b591e99afe9f32eaa6214f7b7629768c40eeb39
- $80,000 are lost in USDT contract https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7
- $549,000 are lost in MATIC contract https://etherscan.io/address/0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0
- $526,000 are lost in UNI token contract https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984
- $238,000 are lost in BUSD contract https://etherscan.io/address/0x4Fabb145d64652a948d72533023f6E7A623C7C53
You can open any contract on Etherscan and watch the amount of tokens that it holds. If the contract is not intended to receive tokens (it is not a DEX contract and not a multi-sig) — then the tokens are lost due to an ERC-20 transaction that must be rejected, but it wasn’t.
How this issue can be solved?
This is the issue of the adoption of the ERC-20 standard as it is. Unfortunately, recovering already lost tokens is not possible, but we can prevent this issue in the future.
ERC-223 is now on the list of EIPs.
It is important to spread the word about the issue to convince the token developers of new tokens to pay attention.
Here is a good example of what can be the root of the problem:
1. I warned STORJ developers that using the ERC-20 standard can be dangerous and will surely lead to the losses of funds for their users.
2. STORJ developers replied, “we know, but everyone is using ERC-20, so we will use it too despite knowing of its problems and losses of funds”.
3. Users' funds got lost on the STORJ contract, as it was expected.
So far, ERC-223 is still the most suitable solution, in my opinion, but any other token that supports the communication model could work. NFTs are safe, and ERC-721 implements a communication model derived from ERC-223.
Right now, I am building the ecosystem for ERC-223 tokens:
- Token Wrapper ERC20=>ERC223 — a contract that will allow to create “wrapped tokens” for each ERC-20 contract. Wrapped ERC-223 tokens will be backed 1:1 by the original ERC-20 tokens and can be switched back to ERC-20 at any moment. This would open up the opportunity to utilize the advantages of ERC-223 without having to delete and reconstruct the whole token ecosystem. https://github.com/Dexaran/ERC223_to_ERC20_wrapper
- DEX that supports ERC-223 standard (already deployed on Ethereum main net): https://github.com/SoyFinance/smart-contracts
- ERC-223 extensions, examples, and documentation updates on Ethereum
This is not a problem of the token standard; stupid users just send their tokens to the wrong address. User mistake, not a flaw of ERC-20.
1. When a user sends tokens to the wrong address — it is the user’s fault. When a contract accepts tokens that it shouldn’t accept— that’s the contract’s fault.
2. This is a serious problem anyways; tens of millions of dollars are lost already, and the amount is growing with each year and each day. It is solvable. So why just leave it as it is while it can be solved?
3. ETH can’t be transferred to a contract that is not intended to receive it. ERC-223 can’t be transferred to a contract that is not intended to receive it. NFT can’t be transferred to a contract that is not intended to receive it. Only ERC-20 can be transferred to a contract and get stuck there.
It can be solved on the side of a UI.
--> The issue exists for 6 years already; the amount of lost tokens only grows with time, so it doesn’t work this way.
This problem can be solved with ERC-20, just need to prevent deposits of tokens to the same contract address.
--> No. Every contract that is not intended to work with ERC-20 tokens can receive them, and there is no way to recognize and subsequently reject the improper transaction for the recipient. That’s a bigger problem. Not just stuck tokens in token contracts.
ERC-677 TransferAndCall solves this issue.
--> No, it doesn’t. If a token standard does not declare the logic of transferring tokens and only declares the API, then it does not solve the issue.
Have you lost your tokens, need any other assistance, or have a question? Feel free to contact me:
- Emails: [email protected] (preferred) / [email protected] / [email protected] (only highest priority)
- Github: https://github.com/Dexaran
- Twitter: https://twitter.com/Dexaran
- Telegram t.me/Dexaran