Token Security in Ethereum
Foreword
For this week, I want to keep my usual series on smart contract vulnerabilities on hold and talk about something more general — Token security, ERC-20 tokens to be more specific.
You may find my other articles in this link.
Like always, I am simply sharing what I understand to test my knowledge, these articles are not intended to educate others, however, I do hope that my work provides even a little value to others.
Contents
- ERC-20 Overview
- ERC-20 Implementation
- Secure Token Development and Integration
- Conclusion
- References
1. ERC-20 Overview
ERC-20 is an Ethereum standard for implementing fungible tokens… so what are fungible tokens? Well, the “official” definition says that fungible tokens are assets that are non-unique and can be sub-divided, but that is not very clear either.
We use a form of fungible token already in our daily lives - Money. Fiat currencies are a form of fungible tokens as each $10 bill has the same value as the next. Sure, they are all physically different, some might be more worn out than the others and have different serial numbers, but their intrinsic value is the same. If Bob and Alice swap their $10 bills, they both still have $10. Furthermore, the $10 bills can be exchanged for two $5 bills or five $2 bills without losing the total overall value. These are the non-unique and sub-divisible aspect of fungible tokens.
However, fungible tokens can represent more than money. According to the Ethereum foundation;
Tokens in the ethereum ecosystem can represent any fungible tradable good:
coins, loyalty points, gold certificates, IOUs, in game items, etc.
1.1 Fungible tokens in Ethereum
Fungible tokens have long been a part of blockchain technology. Even during the early days of Bitcoin, there were already plans to create ‘colored coins’ — and eventually gave rise to projects such as Omni (previously known as MasterCoin).
With Ethereum, programmers could write their own smart contracts to implement fungible tokens. This eventually led to hundreds of tokens being developed independently. This posed a problem for exchanges and wallets as supporting all the different implementations would be very impractical.
Feeling a need for standardization, Fabian Vogelsteller in November 2015, proposed a universal implementation of APIs for tokens within smart contracts. All ERC-20 compliant tokens are required to support the following functionalities.
- Transfer of tokens from one account to another.
- Get current token balance of an account.
- Get the total supply of token in the network.
- Approve whether an amount of token from an account can be spent by a third-party account.
What these methods are and what they are supposed to do is defined in EIP-20, however, how they are coded/implemented is up to the developer. So, if we were to create our own ERC-20 token, it would have to adhere to all the above requirements. So lets do just that.
2. ERC-20 Implementation
Since the ERC-20 standard is so popular, various libraries that have been time tested and audited many times exists. For our purpose, I will be using an ERC-20 library by Openzeppelin and the online remix IDE. From a security perspective, it is always better to avoid reinventing the wheel.
Paste the following codesnip into the remix ide to create your very own BibekToken (named after my colleague). Now selling 10,000 BKT for 1 NPR.
Yes, its really that simple. In 10 lines of code we can create our very own ERC-20 compliant token and make millions of moneys.
3. Secure Token Development and Integration
There are a few key security concepts we need to be aware of when developing and integrating ERC-20 tokens in our projects. Some flaws I found interesting are detailed in the following sections.
3.1 Broken Access Control
Broken Access Control are some of the most common vulnerabilities in the web2 world. In-fact, OWASP ranks broken access control as the most common vulnerability in their top 10 list.
Lack of access control can enable users to act outside their intended permissions, which has severe impact in all aspects of the CIA triad. In the case of ERC-20 token contracts, such vulnerabilities can be caused by unprotected functions in the form of missing modifiers (such as an “ownerOnly” modifier). Sensitive functions (such as minting and burning) should always be used with access control mechanisms in place.
Such vulnerability was present in the AURA Token contract. While all of the sensitive functions are protected by an “ownerOnly” modifer, the function to set an owner is missing.
Fortunately, at this point the owner has the same privileges as a normal user so there is no security implications.
3.2 Arithmetic flaws
I have already done a detailed article on this security flaw, which you can read here. TL;DR: Overflows and underflow vulnerabilities present in Solidity prior to 0.8.0 can lead to users gaining an absurd amount of ERC-20 tokens, which can significantly undermine their value.
Although Solidity now has checks to avoid such vulnerabilities, a vast majority of tokens are written in older version which can be easily abused by hackers. Such was the case with SmartMesh Token (SMT) contract.
This logic was originally intended to check whether the caller had enough balance. However, since the _value parameter is user controlled, passing a value larger than its type (unit256) will cause integer overflow, causing the check in line 210 to wrap back around to 0 and continue from there. The absurdly large _value will be transferred to the target address at line 222.
In-fact, this exact hack was performed in this transaction.
3.3 Transfers
When integrating ERC-20 tokens onto our DAPPs, we must be weary of how the transfer and transferFrom functions are implemented. Lets take a quick look at how these methods are defined in EIP-20.
Here, we can see that upon success, both methods return a bool ‘true’ and are expected to revert upon failure. However, a token contract may also return ‘false’ upon failure — this is in-spec with the standard.
The problem arises when DAPPs fail to account for this behavior. When a transaction fails, the token contract might return a false instead of reverting. If the DAPP is expecting the transaction to revert, it may fail to verify this and continue executing. So, it is important that developers to check for both conditions.
Popular protocols such as Uniswap implement this.
Here we can see that Uniswap is explicitly checking for false condition in lines 777 and 782.
3.4 Incorrect Decimals
Solidity does not support floating point numbers (decimals). All numbers in solidity are integers. This means that floating point numbers are also represented as Integers. While using 18 decimals is the norm, not all tokens follow this. In-fact, USDC has 6, and cETH and WEBTC have 8. We can represent 9.84 as 984 by using two decimal places. We can get the decimal place used by a token by calling the decimals() getter function.
Problems may arise when the DAPP do not account for the variation in decimal places. This can lead to internal mathematical errors when dealing with multiple tokens. Wallet applications can also be affected by this issue. Since the primary reason for using decimals in solidity is for the visual aid for users, using the wrong decimal places to represent tokens can lead to confusion.
3.5 Front Running in allowance and transferFrom
Front running (Transaction order dependence) vulnerabilities have been well-known vulnerability in ERC-20 token. You can read more about this vulnerability in my article.
The attack scenario of this flaw could be the following:
- Bob is approved by Alice to spend 2 BKT. This is the current state.
- Alice decides to reduce this amount to 1 BKT.
- Alice initiates a transaction to update the state.
- Bob notices this transaction before it has been mined.
- Bob front runs Alice’s transaction and quickly spends 2 BKT.
- Alice’s transaction is mined and the state is updated.
- Bob can spend 1 more of Alice’s BKT, which she never intended.
4. Conclusion
I hope this article was able to provide a peek into the vast world of developing and integrating tokens securely. In this article, I covered five security issues that I found interesting. However, this by nomeans is an exhaustive list of security issues that might be present (such as re-entrancy). I hope you readers use this story as a diving board to dive deeper in your self-study. During my research, I found blogs by ConsenSys and OpenZeppelin incredibly helpful among many other resources — all of which are included in the references.
Happy learning!
5. References
- https://consensys.net/diligence/blog/2020/11/token-interaction-checklist/
- https://blog.openzeppelin.com/workshop-recap-secure-development-workshop-1/
- https://www.apriorit.com/dev-blog/555-erc20-token-vulnerability
- https://www.investopedia.com/news/what-erc20-and-what-does-it-mean-ethereum/#:~:text=ERC%2D20%20is%20the%20technical,a%20way%20to%20be%20exchanged.
- https://www.wealdtech.com/articles/understanding-erc20-token-contracts/