Aayushman Thapa Magar is a cybersecurity practitioner with experience in helping organizations secure their digital infrastructure and …
Re-entrancy Vulnerabilities in Smart Contracts
Table Of Contents
This is second in a series of articles on vulnerabilities that smart contracts are susceptible to. You can find my articles in this topic by following the links.
The primary purpose for these articles is not to educate others, but to test the depth of my own understanding. However, I do hope that my efforts provide even a little value to you dear readers. Please let me know if any questions arise or any mistakes are made so we can learn and grow together.
- Re-entrancy Overview
- Security Risk
- Identification techniques
- Mitigation measures
In computer science, re-entrancy refers to multiple invocation of a procedure, where it can be interrupted and called again without completing its previous execution. This issue is especially prevalent in single threaded systems, such as the EVM. Re-entrancy vulnerabilities occur when a function makes an external call to untrusted contracts which can recursively call the original function and hijack the control flow.
This often happens when funds are transferred and the fallback/receive functions on the receiving contract call the original transfer function.
If the accounting mechanism executes after the transfer mechanism, re-entrancy can be used to siphon funds out of the vulnerable contract. This iterative calling of functions can last as long as there is remaining gas.
Such was the case with the infamous DAO hack which led to $60M worth of ether to be stolen. As a response, the Ethereum blockchain, was forked into Ethereum and Ethereum Classic. Below are some notable re-entrancy hacks.
- Uniswap/Lendf.Me lost $25M (April 2020)
- The BurgerSwap lost $7.2M (May 2021)
- The SURGEBNB lost $4M (August 2021)
- CREAM FINANCE lost $18.8M (August 2021)
- Siren protocol lost $3.5M (September 2021)
- Fei Protocol lost $80M (April 2022)
Re-entrancy is perhaps the most popular web3 vulnerability due to its impact and prevalence. It can also be easy to miss during development as it is a type of logic flaw.
Lets take a look at the code snip below to better understand the vulnerability.
The above contract is a simple one. Users can send some ether to the contract and withdraw it later. However, this contract is vulnerable to re-entrancy attack.
An attacker could write a malicious contract such as the following to exploit this weakness.
Here, the attacker is depositing some amount of ether pass the check at line 12 in the vulnerable contract. The deposited amount is then immediately withdrawn. The withdraw function in the victim contract will send the amount to the attacker contract, where the receive function will be executed, which in turn withdraws more amount.
The accounting mechanism at line 15 in the victim contract will never get a chance to execute and reset the balance of the attacker as the two functions are called recursively until all the funds are exhausted.
There is always risk associated with performing external calls. To identify whether a contract is vulnerable to re-entrancy attacks, the following must be considered.
- Call to external untrusted contracts is made.
- A state change is made afterwards.
Although these are not always indicative of whether re-entrancy is present, it can be a good indicator. In our case, the answer was yes to both, hence we had the vulnerability.
The simplest way to prevent re-entrancy vulnerabilities would be to complete all the internal accounting mechanisms before interacting with external functions. This is also known as the check-effects-interactions pattern, where each statement is categorized as either a check, an effect (state change) or an interaction and arranged strictly accordingly.
In our example, it would look something like this;
Re-entrancy guards can also be used to prevent such vulnerabilities. Re-entrancy guards are function modifiers that prevents re-entrancy attacks. Open Zeppelin has a library that enables this feature, which can be found here.