Reentrancy attacks in smart contracts, explained
Potential vulnerabilities in smart contracts
Despite being groundbreaking, smart contracts are not impervious to flaws that malevolent parties could exploit.
Inadequate input validation is a prevalent weakness that enables attackers to affect contract execution by providing unexpected inputs. Furthermore, improper application of business logic might result in vulnerabilities by creating unexpected behaviors or logical gaps in the contract. Furthermore, if handled improperly, insecure external calls — such as those involving interfaces with external data sources or other contracts — can pose vulnerabilities.
Reentrancy attacks are weaknesses that occur when a contract calls another contract externally before completing its own state changes. This allows the called contract to reenter the calling contract and maybe carry out some of its operations again. This may result in unanticipated actions and allow attackers to alter the contract’s state, thereby depleting funds or having other negative effects.
Given the possibility of such attacks, developers should also exercise caution when working with external contracts or data sources, ensuring that external calls are handled correctly to avoid unexpected behaviors and vulnerabilities. They can assist in protecting smart contracts from evolving threats by paying close attention to security procedures like smart contract testing.
What are reentrancy attacks in smart contracts?
In smart contracts, reentrancy attacks happen when a contract calls another contract or function externally before finishing its own state changes.
This allows the called contract to reenter the calling contract and possibly perform parts of its operations again, which can result in unforeseen and frequently malevolent behaviors. For instance, a situation in which contract A calls contract B to send funds and then modifies its own state.
Contract B’s code may contain a callback function that allows it to reenter contract A and possibly re-execute the transfer function before contract A finishes its state changes. This would enable the attacker to take money from contract A several times before completing the initial transaction.
The infamous decentralized autonomous organization (DAO) hack on the Ethereum blockchain in 2016 is another well-known example. An attacker recursively removed funds from the DAO by taking advantage of a reentrancy flaw in the smart contract code, which ultimately resulted in the theft of millions of dollars worth of Ether (ETH).
Moreover, several decentralized finance (DeFi) protocols, including Uniswap, Lendf.Me, BurgerSwap, SURGEBNB, Cream Finance and Siren Protocol suffered significant financial losses due to reentrancy exploits. These breaches resulted in losses ranging from $3.5 million to $25 million, highlighting the persistent threat posed by reentrancy vulnerabilities in the DeFi space.
How reentrancy attacks work
Reentrancy attacks use the sequential execution of smart contract functions along with external calls to form a loop in which attackers can execute specific functions multiple times before they finish, which can result in malicious behaviors and unapproved fund withdrawals.
Before the victim has completed its state modifications, the attacker’s contract effectively “tricks” the victim’s contract into calling back into the attacker’s contract. Recurring withdrawals or other negligent behaviors may result from this action.
The above image demonstrates a reentrancy attack on a smart contract. The attacker’s contract calls the victim’s “withdraw()” function, which sends Ether before updating the balance. The attacker’s fallback function is then triggered, recursively calling withdraw() again to drain funds from the victim contract. This attack exploits the victim’s failure to update the balance before sending funds.
Let’s break down how reentrancy attacks work using a simplified example:
Smart contract with a “withdraw” function
Assume that there is a digital wallet smart contract that permits users to withdraw funds. In addition to keeping track of user balances, this contract has a withdraw function that facilitates funds withdrawal. The withdraw function typically allows users to withdraw their tokens or Ether from the smart contract to their personal wallet.
User interaction and function execution
A user requests a withdrawal from their wallet on their own. They use the withdraw feature to enter the desired withdrawal amount.
The withdraw function verifies if the user has enough money to make a withdrawal when it is called. It transfers the required funds to the user’s selected address if the requirements are satisfied.
External call
This is where the weakness surfaces. Before the withdrawal is reflected in the user’s balance, the contract makes an external call to another contract or account.
Recursive call
If the code of the external contract includes a function that can call the original contract again (like another withdraw function), then a recursive loop is created. This makes it possible to call the withdraw method again before it finishes.
Reentrancy exploitation
An attacker then uses a malicious contract to take advantage of this loop. The attacker’s contract quickly calls the wallet’s withdraw function once more before the balance update during the wallet contract’s invocation of the external contract.
Fallback function
In certain situations, a smart contract’s fallback function — a unique feature that kicks in when the contract receives a call without any data or Ether — may be used by the attacker. Reentrancy attacks can be carried out by repeatedly invoking the fallback function while the funds are still being processed.
State manipulation and repeated withdrawals
The attacker’s contract can repeatedly use the withdraw function within the same transaction since the wallet contract delays updating balances until after receiving external calls. As a result, this makes it easier for funds to be taken out without authorization, allowing the attacker to steal more than they are legally entitled to. Subsequently, it inflicts substantial financial losses upon users of the wallet contract.
Related: Key Ethereum EIPs to watch in 2024
Consequences of reentrancy attacks
Reentrancy attacks have serious ramifications for smart contract users, owing to their potential to cause substantial financial losses.
One of the most immediate consequences of a reentrancy attack is unauthorized withdrawal or manipulation of cash kept in a susceptible smart contract. Attackers utilize the vulnerability to repeatedly withdraw funds from the contract, depleting its balance and potentially causing significant financial loss to users who have invested or stored assets in the affected contract.
Furthermore, users’ faith in the security and integrity of smart contracts and blockchain technology in general may be weakened by reentrancy attacks. Reentrancy vulnerabilities can have disastrous effects, as demonstrated by high-profile occurrences like the 2016 DAO hack on the Ethereum blockchain, which caused enormous financial losses and harm to the community’s reputation.
Beyond the short-term financial consequences, reentrancy attacks may have longer-term effects, such as regulatory and legal attention, diminished investor trust and harm to the standing of blockchain platforms and projects. The perception of vulnerability to attacks may cause users to be cautious when interacting with smart contracts or investing in decentralized applications (DApps), thereby impeding the adoption and expansion of blockchain technology.
How to mitigate reentrancy attacks
Implementing best practices in smart contract creation and auditing is necessary to mitigate reentrancy threats.
This includes using well-known code libraries with a track record of security, which is one way to go about it. These libraries have undergone extensive testing and peer review, which lowers the chance of introducing vulnerabilities.
Developers should also use security checks like the “checks-effects-interaction” design, which minimizes the chances of opportunity for reentrancy attacks by ensuring that state modifications happen atomically. An additional line of defense against such vulnerabilities can be added by using reentrancy-safe smart contract development frameworks if they are available.
Developers are less likely to have to manually add security protections because these frameworks frequently include built-in methods and safeguards expressly designed to avoid reentrancy attacks. However, as blockchain security is still developing, developers must continue to be on the lookout for new threats and weaknesses.