Control Flow
critical severity
Reentrancy Attacks
A reentrancy attack occurs when a contract makes an external call before updating its state, allowing the called contract to re-enter the calling function and drain funds.
How It Works
The attacker deploys a malicious contract that calls a vulnerable withdraw function. When the victim contract sends ETH, the attacker's fallback function triggers another withdrawal before the balance is updated, draining funds repeatedly.
Real-World Examples
The DAO Hack
2016
$60M
The most famous reentrancy attack drained 3.6M ETH from The DAO, leading to the Ethereum hard fork.
Cream Finance
2021
$130M
A reentrancy exploit in Cream Finance's lending protocol drained $130M in assets.
Code Examples
Vulnerable Code
// VULNERABLE: State updated after external call
function withdraw() external {
uint256 balance = balances[msg.sender];
(bool success, ) = msg.sender.call{value: balance}("");
require(success);
balances[msg.sender] = 0; // Too late!
}Secure Code
// FIXED: Checks-Effects-Interactions pattern
function withdraw() external nonReentrant {
uint256 balance = balances[msg.sender];
balances[msg.sender] = 0; // Update state first
(bool success, ) = msg.sender.call{value: balance}("");
require(success);
}Prevention
- Use the Checks-Effects-Interactions pattern: update state before external calls
- Use OpenZeppelin's ReentrancyGuard modifier
- Prefer pull over push payment patterns
- Minimize external calls and use transfer() or send() when possible
Related Vulnerabilities
Scan Your Contract for Reentrancy Attacks
Our AI-powered auditor automatically detects reentrancy attacks and 20+ other vulnerability types. Get a detailed report in minutes.