Definition
A reentrancy attack is a smart contract vulnerability where a malicious contract can repeatedly call back into a vulnerable contract before the original function execution completes — exploiting the fact that the victim contract’s state (like a balance ledger) is updated after making external calls rather than before. The most famous reentrancy attack was “The DAO” hack in June 2016, where an attacker exploited a reentrancy vulnerability to drain $60 million in ETH, leading to Ethereum’s controversial hard fork to recover funds and create the Ethereum/Ethereum Classic split. Reentrancy remains a common vulnerability: the Curve Finance pools (July 2023, $73M) were exploited via read-only reentrancy. Modern Solidity best practices include the “Checks-Effects-Interactions” (CEI) pattern and reentrancy guard modifiers to prevent these attacks.
Reentrancy Attack Mechanics
Vulnerable Contract (pseudocode): function withdraw(uint amount) { require(balances[msg.sender] >= amount); msg.sender.call{value: amount}(“”); // External call BEFORE state update balances[msg.sender] -= amount; // State updated AFTER call }
Attack Contract: receive() external payable { // Called when victim sends ETH if (address(victim).balance >= 1 ETH) { victim.withdraw(1 ETH); // Re-enter before balance updated! } }
Attack Sequence: Attacker deposits 1 ETH in victim contract Attacker calls victim.withdraw(1 ETH) Victim sends 1 ETH to attacker (triggers receive()) Attacker’s receive() calls victim.withdraw(1 ETH) AGAIN → Balance still shows 1 ETH (not yet updated!) Loop repeats until victim is drained Finally: victim.balances[attacker] = 0 – too late
The Fix (Checks-Effects-Interactions pattern): function withdraw(uint amount) { require(balances[msg.sender] >= amount); // Check balances[msg.sender] -= amount; // Effect (update first!) msg.sender.call{value: amount}(“”); // Interaction (call last) } → State updated BEFORE external call → Reentry changes nothing
Major Reentrancy Exploits
|
Incident |
Date |
Amount |
Vulnerability |
|
The DAO |
June 2016 |
$60M (3.6M ETH) |
Classic reentrancy; triggered ETH fork |
|
SpankChain |
Oct 2018 |
$38K |
Payment channel reentrancy |
|
Uniswap/Lendf.me |
Apr 2020 |
$25M |
Cross-function reentrancy |
|
Curve Finance |
July 2023 |
$73M |
Vyper compiler reentrancy guard bug |
|
BurgerSwap |
May 2021 |
$7.2M |
Cross-contract reentrancy |
FAQ
Q: What is “read-only reentrancy”?
Read-only reentrancy (exploited in Curve’s 2023 hack) occurs when an attacker reenters a view/read function during a state transition. While traditional reentrancy exploits state changes via write functions, read-only reentrancy exploits the window when a contract’s state is being modified but the view function returns an intermediate (incorrect) state. If a lending protocol reads a Curve pool’s price during an attacker-triggered state change, it may read a manipulated price — enabling economic exploitation without the direct fund drain of classic reentrancy.
Q: Does OpenZeppelin’s ReentrancyGuard eliminate reentrancy risk?
OpenZeppelin’s ReentrancyGuard modifier adds a mutex (mutual exclusion lock) that prevents reentrant calls within a single transaction. For most functions, this effectively prevents classic reentrancy. However, it doesn’t protect against cross-function reentrancy (calling a different function in the same contract), cross-contract reentrancy (different contract in the same protocol system), or read-only reentrancy (view functions). Multiple defensive layers — CEI pattern + ReentrancyGuard + audits + formal verification — provide stronger protection than any single measure.
Q: Why did The DAO hack lead to Ethereum Classic?
After The DAO hack (June 2016), the Ethereum community debated whether to hard fork to recover the stolen funds — a controversial “bail out” that violated the principle that blockchain transactions are immutable. The majority of the community voted to hard fork (creating today’s Ethereum with recovered funds). A minority that believed in absolute immutability refused to upgrade — their chain became Ethereum Classic (ETC). The controversy demonstrated the real-world governance tensions in “code is law” blockchain systems.
UPay Tip: When interacting with newer DeFi protocols, a quick security check is reviewing the contracts on Etherscan for OpenZeppelin’s ReentrancyGuard modifier (look for “nonReentrant” in function signatures) and whether the code follows the Checks-Effects-Interactions pattern (state updates happen before external calls). You don’t need to be a security expert — simply recognizing these patterns and their absence is a meaningful risk signal. Protocols that implement multiple defensive patterns for reentrancy are demonstrating security awareness; those with none may not have considered this class of vulnerability.
Disclaimer: This content is for educational purposes only and does not constitute financial advice.
UPay — Making Crypto Encyclopedic










