Security problems of ERC-20 standard

Dexaran
6 min readNov 8, 2024

--

ERC-20 is the most used token standard on Ethereum. It’s pure implementation contains a flaw that would be classified as a critical security issue according to OpenZeppelin bug bounty criteria. That flaw could lead to a permanent loss of funds for token holders. At the moment of writing $83,000,000 worth of ERC-20 tokens are lost because of this issue. This article serves the purpose of keeping historical tracks related to this issue in one place.

Lack of transaction handling on ERC-20 transfer() function

This problem was described in this article that I published in 2023. This is a copy of a reddit post that was removed from Ethereum subreddit in 2017.

Software development is not a new area so there are well-known security practices in place. Most basic ones are described here.

We are interested in this two paragraphs:

2. Secure Defaults

Adopting Secure Defaults is a fundamental principle that mandates systems configurations to be inherently safe. This approach stems from the understanding that many end-users stick to default settings. By setting these defaults to be highly secure, you can safeguard most users.

7. Failing Securely

The principle of failing securely dictates that a system should respond to errors or failures in a way that preserves the overall security of the application.

ERC-20 is a software standard. It is written in a way that violates two of the basic secure software development principles — failsafe defaults and error handling (described under “failing securely” paragraph in the above article).

There are two methods of transferring tokens in ERC-20: transfer function and approve & transferFrom pattern. The transfer function is designed to transfer tokens between externally owned addresses. It does not invoke a callback in the recipient in case it’s a contract which makes error handling impossible (and this violates a principle of failing securely) and at the same time it does not restrict transfers to smart-contracts via the transfer function which is the default one used by wallets (this violates a principle of fail-safe defaults as the default method of transferring tokens is unsafe and may result in a loss of funds).

As the result, users are losing their funds with tokens that implement ERC-20 standard if they send them to a smart-contract which is not designed to receive tokens for example. We wrote a scrip that calculates the amount of funds lost on Ethereum mainnet and you can access it at dexaran.github.io/erc20-losses

It should be noted that Ethereum developers are aware of how things need to be done securely. The native currency of Ethereum chain (ether) does not implement two different methods of transferring and it’s default transferring method does invoke a callback (the receive() function or fallback function) upon transferring ether to contracts. ERC-721 NFTs also invoke a callback and therefore are safe to use.

Why ERC-20 is built the way it is

  • ERC-20 was created in 2015. There was a 1024-call-stack depth bug in the EVM at that time which made it impossible to securely invoke a callback function upon token transfer.
  • The impossibility of implementing callback function invocation led to the development of approve & transferFrom pattern as an alternative method of depositing tokens to smart-contracts. The security problem here is that if transfer function must not be used to deposit tokens to contracts it should have been restricted so that it would only be possible to deposit tokens via approve & transferFrom. This wasn’t done.
  • In 2016 1024-call-stack-depth bug was fixed.
  • In 2017 the issue with ERC-20 tokens was discovered.

The history of the problem

Results

  • Once 1024-call-stack depth bug was fixed a new token standard that would implement a proper transferring methods should have been created. This was done. ERC-223 and ERC-777 standards do implement transactions that invoke callbacks on the recipients side allowing for error handling. ERC-777 doesn’t suffice failsafe defaults criteria however as it supports transfer function that works identical to ERC-20.
  • Once new standards emerged it was necessary to coordinate the upgrading process to convince the implementers to start using a new one and to convince exchanges / wallets / explorers and other ecosystem participants to start supporting new token standards. This wasn’t handled properly neither by Ethereum Foundation (which kept promoting ERC-20) nor by token standards creators (including myself).
  • The issue was reported (for example here and here). It was known that the problem was causing financial damage to Ethereum users. At this point, it was necessary to make a security finding disclosure to notify the implementers and ecosystem participants. It was possible to develop a solution or suggest using existing solutions (like ERC-223) instead of promoting ERC-20. This wasn’t done. Ethereum Foundation kept promoting ERC-20 standard on their resources, it was described as one of the main features on ethereum.org web page and they ignored a request for the code examples removal even after the security issues were discovered and reported to them.
  • If the EIP process is known to lead to a situation where a known security issue that was reported 8 years ago kept causing financial damage to the ecosystem — the process needed to be changed. This wasn’t done and the proposal to change the EIP process was rejected in 2024.

--

--