Reentrancy: From The DAO to Euler Finance
The single vulnerability class that has drained the most funds in smart contract history: reentrancy. From the 2016 DAO hack (~$60M) to Cream Finance in 2021 ($130M) and Euler Finance in 2023 ($197M), it has accounted for billions of dollars in losses.
What Is Reentrancy?
When contract A makes an external call to contract B, B can call back into A before A's state has been updated — re-executing logic against stale state.
Vulnerable Code
contract VulnerableBank {
mapping(address => uint256) public balances;
function withdraw() external {
uint256 amount = balances[msg.sender];
require(amount > 0);
// ⚠️ ETH sent before balance update — reentrancy possible
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
balances[msg.sender] = 0; // Too late!
}
}
The DAO (2016, ~$60M)
function splitDAO(uint _proposalID) returns (bool) {
if (!msg.sender.call.value(reward)()) throw; // Transfer first
totalSupply -= balances[msg.sender]; // State update later
balances[msg.sender] = 0;
}
→ Directly caused the ETH/ETC hard fork
Cream Finance (2021, ~$130M)
The AMP token's ERC1820 callback was used as a cross-contract reentrancy vector. Collateralized AMP was repeatedly borrowed through reentrant calls.
Euler Finance (2023, ~$197M)
donateToReserves() did not validate the health factor, allowing an artificial liquidation state to be created. Combined with a flash loan for the exploit.
Defense 1: CEI Pattern
function withdraw() external {
uint256 amount = balances[msg.sender];
require(amount > 0);
balances[msg.sender] = 0; // Effects first
(bool success, ) = msg.sender.call{value: amount}(""); // Interactions last
require(success);
}
Defense 2: ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SafeBank is ReentrancyGuard {
function withdraw() external nonReentrant {
uint256 amount = balances[msg.sender];
require(amount > 0);
balances[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
}
Defense 3: Pull Payment
Instead of pushing ETH directly, let the recipient pull it themselves.
Checklist
- [ ] Is state fully updated before any external calls? (CEI)
- [ ] Is the
nonReentrantmodifier applied? - [ ] Have ERC777/ERC1155 callback tokens been reviewed?
- [ ] Has cross-contract reentrancy been considered?
Detecting These Issues with ContractScan
Slither + Semgrep + AI triple-layer analysis automatically detects reentrancy patterns.
→ ContractScan Free Scan
Try ContractScan free — automated Solidity vulnerability scanning powered by Slither, Semgrep, Mythril, and AI.
Top comments (0)