Blockchain technology and smart contracts have, without a doubt, many excellent use cases. However, while there are a lot of pros, smart contracts can still have vulnerabilities. For instance, while going through its development phase, attacks can unfortunately occur. In this article, we’ll take a closer look at one particular danger – reentrancy smart contract attacks. First, we’ll explore the basics by answering the question of “what is reentrancy?”. With the basics under your belt, we will be analyzing some reentrancy smart contract example attacks. Now, you might be wondering if you can protect yourself against reentrancy attacks. Don’t let the alarming thought of doubt against this hinder you from wanting to become a blockchain developer. By understanding the potential weaknesses of your Web3 apps, you can position your dApps on the safe side, away from reentrancy possibilities.
Moreover, to provide you with a clearer understanding of reentrancy, we will take on a reentrancy smart contract example project ourselves. As such, you will get to see where the vulnerability lies firsthand. Furthermore, for the sake of your accurate understanding, we will also exploit our example smart contract’s vulnerability. In addition, we will create a testing dashboard, which will assist us in fixing our reentrancy smart contract example. This is where you’ll get a chance to utilize the ultimate shortcut offered by Moralis (a.k.a. Firebase for crypto). Moreover, we will go through three different ways of fixing our reentrancy smart contract example. On top of Moralis, we’ll use some other valuable tools, namely MetaMask and Remix. So, what is reentrancy? Without further ado, let’s dive right in!
What is Reentrancy?
By its definition, the word “reentrancy” means “the act of entering again (reentering)”. However, the word is almost exclusively used in computing. In that sense, software or subroutine is called reentrant when it supports multiple invocations/requests to safely run concurrently (either on multiple processors or on a single processor system). In such systems, a reentrant procedure can be interrupted in the middle of its execution. Following the interruption, the procedure can be called again (“reentered”) before its previous invocations complete execution.
The above definition shows you that there are applications where reentrancy may be a good thing. However, with smart contracts, it can be a huge vulnerability. Thus, let’s now answer the “what is reentrancy?” question in the case of smart contracts. Whenever a smart contract makes an external call to another smart contract, a reentrancy exploit could take place. In addition, when a smart contract makes an external call, the execution of EVM is passed from a smart contract making a call to the one that is called (the green line in the image below). Hence, unless the smart contract making the call has full knowledge of the called smart contract’s code, a potential danger exists. The called smart contract could potentially do with the external code whatever it pleases.
Among other actions, the called smart contract could make a call back to the initial smart contract (a reenter call [the red line in the image above]). Moreover, in case the initial smart contract has some vulnerabilities, the reenter call could exploit that. These vulnerabilities present themselves when the initial smart contract is not properly updated at the time of making its call. With that said, it makes sense that these types of exploits are called reentrancy smart contract attacks.
Reentrancy Smart Contract Attacks
There have been several reentrance smart contract attacks in the last couple of years. While this kind of attack ruffled the most feathers in 2016, there were several instances last year (2021) as well. Some of the most well-known reentrancy smart contract example hacks include:
- The DAO Hack – This is the most famous Ethereum hack that took place back in 2016. Unfortunately, the transfer mechanism of the DAO’s smart contract was set to transfer ETH to an external address before updating its internal state. As such, it did note that the balance was already transferred promptly. The latter gave the attackers a way to exploit reentrancy and to withdraw more ETH than they were eligible for from the contract.
- Uniswap/Lendf.Me – Back in April 2020, this reentrancy hack resulted in $25 million being snatched.
- Cream Finance – In September 2021, this DeFi protocol suffered a hard blow. The hackers behind the reentrancy attack took over $34 million worth of AMP and ETH.
- BurgerSwap – This token swap protocol, based on Binance Smart Chain (BSC), was attacked in May 2021. Using a fake token address and a reentrancy exploit, the attackers stole about $7.2 million worth of tokens.
- SurgeBNB – This is another noticeable reentrancy attack worth $4 million. It took place in August 2021.
- Siren Protocol – Back in September 2021, attackers managed to take $3.5 million worth of tokens from AMM pools by exploiting the reentrancy weakness.
These are just some of the most known reentrancy smart contract attacks. Moreover, the dates of most attacks indicated that many teams do not devote enough time to the “reentrancy” topic. As such, the five-year-old lesson offered by the DAO hack has a tendency to replay itself. However, by taking this article seriously, you ought to be on the safe side.
Reentrancy Smart Contract Example
Now that you can answer “what is reentrancy?” with confidence and knowing that reentrancy attacks aren’t just a thing of the past, it’s time to take on an example project. Hence, you’ll get a chance to see the vulnerability up close. For the purpose of this example project, we will be working on Avalanche’s testnet. As such, we’ll also be using SnowTrace, which is the equivalent of Ethereum’s Etherscan or BscScan for BSC. Furthermore, for your convenience, we also made the entire code available on GitHub. Thus, you can access our unsafe smart contract as well as its fixed counterparts.
So, here is our unsafe contract after being deployed on the Avalanche testnet:
By clicking on the “Contract” tab, we can view the contract’s code. As mentioned above, you can also access it on GitHub. Please, keep in mind that this smart contract is intentionally not safe for the sake of this reentrancy smart contract example. Moreover, if you are more of a video person, use the video at the end of this article. There, an experienced developer will guide you through the details of our example smart contract starting at 2:43.
The Main Vulnerability
The main vulnerability of this reentrancy smart contract example is the fact that it is receiving addresses as function parameters:
function deposit(address _beneficiary, address _approver) external payable
The latter is extremely dangerous as it enables a potentially harmful external contract to do what we don’t want it to do. Moreover, with the call (as seen below) from the “withdrawFunds” function, we pass the execution of EVM to the external smart contract, which opens the gates to a reentrancy attack.
(bool result,) = caller.call{value: escrowRegistry[_escrowID].amount}("");
In other words, the external smart contract has a possibility to call the “withdrawFunds” function once again. If this is done prior to our smart contract’s state being updated, the reentrancy attack will be successful.
Exploiting Our Smart Contract
This is where you can gain an even deeper understanding of the vulnerabilities of our reentrancy smart contract example. With a smart contract deploying tool, such as Remix, you can take action immediately. Using the above smart contract example, it may serve as a boilerplate. Hence, we can easily create a new contract that will exploit the weakness of our “unsafe” one. Again, for your convenience, the “attacker.sol” smart contract is at your disposal on GitHub. If you are interested in detailed guidance, refer to the video starting at 14:19. That way, you will also see how to create the “EscrowInterface.sol” contract. The latter will be used inside the “attacker” smart contract.
With the “attacker” contract ready for deployment, we will follow these steps to exploit our initial smart contract:
- Send a small amount of tokens to the victim’s contract. We’ll use SnowTrace to access our interface. This is where we enter the beneficiary’s address and define ourselves as the approver:
- We execute the “attack” function inside the “attacker” contract using the amount deposited in the previous step. This will execute the “withdrawFunds” function. As you know, that function has an external execution, which means we can hijack it. This is where we use reentrancy. Based on our “attacker” contract, the withdrawal will be repeated until the funds are depleted.
- The last step is to transfer the hijacked balance to another address.
Note: To see the above three steps in action, watch the video below (21:30). As such, it will help you to deepen your understanding of “what is reentrancy?”.
Fixing The Issues
The previous section demonstrated that reentrancy vulnerability is extremely easy to exploit. The attacker doesn’t need to be extra skillful. Publicly available tools, such as blockchain scanners, Web3 wallets, and smart contract deploying platforms, is all one needs. Hence, it is crucial to be able to fix these kinds of vulnerabilities. This is exactly what you will learn to do herein.
However, in order to make the process neater, we decided to create a testing dashboard using Moralis. If that interests you, check out the video at 24:45. Also, help yourself with the “frontend” folder on GitHub. With a testing dashboard ready, we will create an innocent user smart contract (“user.sol”) (video at 29:12). Once we have our testing environment and example user smart contract ready, we can start applying fixes.
There are three fixes (seen in the video below) that you need to pay attention to:
- The special “transfer()” fix, starting at 30:17 (fixed smart contract: “EscrowFixed00.sol”)
- The check and effects pattern fix, starting at 37:53 (fixed smart contract: “EscrowFixed01.sol”)
- The non-reentrant modifier fix, starting at 44:34 (fixed smart contract: “EscrowFixed02.sol”)
Each of the three possible solutions to reentrancy attacks has its advantages and disadvantages. However, fixing the vulnerability with the check and effects pattern is considered best practice. Hence, you may want to devote extra attention to it (the video at 37:53). In addition, we encourage you to also take a closer look at the other two fixing methods to broaden your “what is reentrancy?” horizons.
Here’s the video we’ve been referencing throughout the article:
What is Reentrancy? – Reentrancy Smart Contract Example – Summary
So, what is reentrancy? At this point, you should be able to answer that question without any problems. Furthermore, you know that reentrancy can be an intentional or accidental feature. Moreover, while certain applications can benefit from it, It is something that can be harmful in the case of smart contracts. By considering some major reentrancy smart contract attacks, you know that it is a costly vulnerability. For an in-depth encounter with the issue of reentrancy, you’ve also had a chance to take on an example project.
In addition, you also had an opportunity to create a simple testing dashboard by following along in our video. As such, you might have seen the power of the ultimate Web3 development platform – Moralis. This irreplaceable tool enables you to cut down an average of 87% of the time it takes to bring dApps and Web3 projects to market. The Moralis SDK includes several impressive features. From the ultimate Ethereum API, including NFT API, to an advanced database and the “sync” feature, which together enable you to index the blockchain. Plus, Moralis supports most of the main programmable blockchains and is fully cross-chain interoperable. In turn, you get to future-proof your work and tackle multiple chains without extra resources.
Nonetheless, the Moralis YouTube channel and the Moralis blog both offer a ton of valuable content. Thus, many programmers use them as the foundation of their free crypto education. Some of the latest topics explore the metaverse, Web3 authentication via email, Web3 backend platforms, React Native Web3, Web3 gamification, and NFT game characters. However, in case you are interested in taking a more professional approach and propelling your blockchain career forward, you need to consider enrolling in Moralis Academy. There you’ll find countless pro-level courses, a kind and supportive community, and expert mentors.