Back to Blog8 min read
Smart Contract Security

Reentrancy Attack in Solidity: What It Is, Real Examples & How to Prevent It (2026)

Learn what reentrancy attacks are, how the $60M DAO hack happened, and how to prevent reentrancy in Solidity with CEI pattern, ReentrancyGuard, and pull payment examples. Free vulnerability checker included.

Published: August 4, 2026
8 min read
52 views
✓ Written by blockchain developers·✓ Reviewed for technical accuracy
Reentrancy Attack in Solidity:  What It Is, Real Examples & How to Prevent It (2026)

Reentrancy Attack in Solidity: What It Is, Real Examples, and How to Prevent It (2026)

A reentrancy attack occurs when a malicious smart contract repeatedly calls a vulnerable contract's withdraw function before the balance updates — draining all funds in a loop. It is the most common smart contract vulnerability and caused the $60 million DAO hack in 2016. Reentrancy attacks cost $35.7 million in 2025 alone — including the $62 million Curve Finance exploit, one of the most battle-tested protocols in DeFi. Use the free Blockhertz AI Smart Contract Auditor to check your contracts for reentrancy vulnerabilities in under 60 seconds.


What is a Reentrancy Attack?

A reentrancy attack exploits the order of operations in a smart contract. When a contract sends ETH to an external address before updating its own state, an attacker can use a malicious contract to call back into the vulnerable contract before the state update happens. The result: the balance check passes every time, and the attacker withdraws funds repeatedly until the contract is empty.

Reentrancy is not a new vulnerability — it has been known since 2016. Yet it continues to drain millions every year because developers still make the same fundamental mistake: interacting with external contracts before updating internal state.


How Did the $60 Million DAO Hack Happen?

In June 2016, an attacker exploited a reentrancy vulnerability in The DAO — a decentralized autonomous organization holding $150 million in ETH. The attacker drained $60 million before the team could react. The attack was so significant it led to the Ethereum hard fork that created ETH and ETC — the most controversial event in Ethereum's history and a decision that permanently split the community.

The DAO hack remains the most studied smart contract exploit ever. It directly caused Ethereum to hard fork to recover stolen funds. No other smart contract vulnerability has had deeper consequences for blockchain infrastructure.

The attack sequence:

  1. Attacker calls withdraw()
  2. Contract checks balance — passes
  3. Contract sends ETH to attacker
  4. Attacker's fallback function calls withdraw() again
  5. Contract checks balance again — still not updated
  6. Contract sends ETH again
  7. Loop repeats until contract is empty

Real World Reentrancy Incidents

Incident Year Loss Protocol Type
The DAO 2016 $60M Investment DAO
Cream Finance 2021 $18.8M Lending protocol
Curve Finance 2023 $62M Stablecoin DEX
Orion Protocol 2023 $3M DEX aggregator
Total losses 2025 2025 $35.7M Multiple protocols

The Curve Finance exploit in 2023 is particularly important to understand. Curve is one of the most audited and battle-tested protocols in DeFi — yet a reentrancy vulnerability in a specific version of Vyper (not even in Solidity) allowed attackers to drain $62 million. No contract is immune without proper protection at every layer.


What Does Vulnerable Reentrancy Code Look Like?

// VULNERABLE — do not use
contract VulnerableBank {
    mapping(address => uint256) public balances;

    function withdraw() external {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance");

        // ❌ Sends ETH BEFORE updating balance
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");

        // ❌ Balance updated AFTER sending — too late
        balances[msg.sender] = 0;
    }
}
// ATTACKER CONTRACT
contract Attacker {
    VulnerableBank public target;

    constructor(address _target) {
        target = VulnerableBank(_target);
    }

    function attack() external payable {
        target.deposit{value: msg.value}();
        target.withdraw();
    }

    receive() external payable {
        if (address(target).balance >= msg.value) {
            target.withdraw();
        }
    }
}

How Do You Prevent Reentrancy Attacks in Solidity?

Prevent reentrancy using three proven approaches: the Checks-Effects-Interactions pattern, OpenZeppelin ReentrancyGuard, and the Pull Payment pattern. Always update state before making external calls and add the nonReentrant modifier to all functions that send ETH.

According to smart contract security research, reentrancy accounts for approximately 1% of total blockchain losses — but its historical significance is disproportionate. The $60M DAO hack in 2016 triggered the most controversial event in Ethereum history and shaped every security standard that followed. In 2025, $35.7 million was still lost to reentrancy attacks despite the fix being well-known and straightforward to implement.

What is the Checks-Effects-Interactions Pattern?

The Checks-Effects-Interactions (CEI) pattern is the most important rule in Solidity: always update state BEFORE making external calls. First check conditions, then update state variables, then make external calls.

// SECURE — CEI pattern applied
contract SecureBank {
    mapping(address => uint256) public balances;

    function withdraw() external {
        uint256 amount = balances[msg.sender];

        // CHECK — verify condition
        require(amount > 0, "No balance");

        // EFFECT — update state first
        balances[msg.sender] = 0;

        // INTERACTION — external call last
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }
}

How Does OpenZeppelin ReentrancyGuard Work?

OpenZeppelin's ReentrancyGuard adds a mutex lock that prevents reentrant calls. Add the nonReentrant modifier to any function that sends ETH or calls external contracts — it automatically reverts if the function is called again before completing.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SecureBank is ReentrancyGuard {
    mapping(address => uint256) public balances;

    function withdraw() external nonReentrant {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance");
        balances[msg.sender] = 0;
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
        emit Withdrawal(msg.sender, amount);
    }

    event Withdrawal(address indexed user, uint256 amount);
}

What is the Pull Payment Pattern in Solidity?

The Pull Payment pattern eliminates push-based ETH transfers entirely. Instead of sending ETH to users, record what they are owed and let them withdraw it themselves. This removes the external call from critical state-changing logic.

contract PullPayment {
    mapping(address => uint256) private pendingWithdrawals;

    function allowWithdrawal(address recipient, uint256 amount) internal {
        pendingWithdrawals[recipient] += amount;
    }

    function withdraw() external {
        uint256 amount = pendingWithdrawals[msg.sender];
        require(amount > 0, "Nothing to withdraw");
        pendingWithdrawals[msg.sender] = 0;
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }
}

Reentrancy Attack Checklist

Check Status
State updated before external calls ✅ Required
ReentrancyGuard on withdraw functions ✅ Recommended
No external calls in loops ✅ Required
Return values from call() checked ✅ Required
Pull payment pattern for ETH distribution ✅ Recommended

What is Cross-Function Reentrancy?

Cross-function reentrancy occurs when two functions in the same contract share state and one makes an external call before updating that shared state. An attacker can exploit both functions in a single transaction.

// VULNERABLE — cross-function reentrancy
contract CrossFunctionVuln {
    mapping(address => uint256) public balances;

    function withdraw() external {
        uint256 amount = balances[msg.sender];
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success);
        balances[msg.sender] = 0;
    }

    function transfer(address to, uint256 amount) external {
        require(balances[msg.sender] >= amount);
        balances[msg.sender] -= amount;
        balances[to] += amount;
    }
}

Fix: Apply ReentrancyGuard to all functions that share state, not just withdraw.


What is Read-Only Reentrancy?

Read-only reentrancy is a newer attack vector (2022+) where view functions are exploited during a reentrant call when state is temporarily inconsistent. Price oracle reads stale state, flash loan attacks combine with read-only reentrancy, and multiple DeFi protocols were exploited this way in 2022-2023.

The Curve Finance $62 million exploit in 2023 involved a read-only reentrancy variant. Several protocols that integrated with Curve read its stale pool state during the exploit window and made incorrect decisions as a result — amplifying the total damage beyond the initial attack.

Fix: Add ReentrancyGuard to view functions that read critical state when used as price oracles by other protocols.


How Do You Check Smart Contracts for Reentrancy Vulnerabilities?

The Blockhertz AI Smart Contract Auditor automatically detects reentrancy vulnerabilities in your Solidity, Rust, Move, or Vyper contracts in under 60 seconds.

  1. Go to blockhertz.com/tools/ai-auditor
  2. Paste your smart contract
  3. Click Audit Contract
  4. Get a full security report with risk score and fix recommendations

Free to start — no signup required: blockhertz.com/tools/ai-auditor


Summary

  • Reentrancy = attacker calls back into your contract before state updates
  • DAO hack = $60M stolen via reentrancy in 2016 → caused Ethereum hard fork
  • Curve Finance = $62M lost in 2023 despite being a battle-tested protocol
  • 2025 losses = $35.7M still lost to reentrancy that year
  • CEI pattern = always update state before external calls
  • ReentrancyGuard = add nonReentrant modifier to all sensitive functions
  • Cross-function and read-only reentrancy = newer variants to watch for

References


Automatically detect reentrancy and 10+ other vulnerabilities in your smart contracts at blockhertz.com/tools/ai-auditor — free, no signup required.

Related Articles

Resource Hub

Smart Contract Security Hub

Free AI auditor, vulnerability guides and security research

🔐

Views

52

Read Time

8 min read

Likes

2

Published

Aug 4, 2026

smart contract securitysolidityblockchainweb3AI Toolsreentrancysecurity
smart contract securitysolidityblockchainweb3AI Toolsreentrancysecurity

SIGNAL THREAD

00 SIGNALS

NO SIGNALS YET — BE FIRST TO TRANSMIT

Muhammad Asif

Senior Blockchain Developer & Founder, Blockhertz

Blockchain developer and security engineer with 8+ years of experience. Founded Blockhertz in 2018 to build AI-powered tools for Web3 teams — smart contract auditing, architecture generation, gas optimization, and RWA tokenization platforms. Serving clients worldwide.