critical

Reentrancy Attack: How It Works, Real Exploits & Automated Detection

April 1, 2026
Chainsethereumarbitrumbaseoptimismpolygonbnb-chainavalanche
Detected byslithermythrilechidnahound-ai

Reentrancy is a critical smart contract vulnerability where a contract calls an external contract before updating its own state, allowing the external contract to recursively call back and drain funds. This flaw has resulted in over $100M in cumulative losses across DeFi, including The DAO ($60M, 2016), Lendf.me ($25M, 2020), and Cream Finance ($37.5M, 2021). Firepan's HOUND AI detects reentrancy vulnerabilities automatically during development and post-deployment monitoring, covering continuous analysis across the full contract lifecycle.

What Is Reentrancy Attack?

Reentrancy occurs when a contract makes an external call (typically sending ETH or tokens) before updating its own state variables. If the external contract is malicious, it can call back into the original contract's functions, exploiting the stale state to extract funds repeatedly in a single transaction. This violates the atomicity assumption most developers rely on.

The vulnerability breaks down into three categories:

  • Single-function reentrancy: Attacker recursively calls the same withdrawal function
  • Cross-function reentrancy: Attacker calls different functions that share vulnerable state
  • Read-only reentrancy: Attacker exploits view functions during state inconsistency

The core issue stems from violating the Checks-Effects-Interactions (CEI) pattern: state updates must happen before external calls, not after.

How Reentrancy Attack Works

The attack sequence follows a predictable pattern:

  1. Attacker calls a withdrawal or transfer function in the target contract
  2. Target contract sends ETH/tokens to attacker's malicious contract
  3. The fallback function in the malicious contract calls back into the target contract's withdrawal function
  4. Target contract checks balance (which hasn't been updated yet) and allows another withdrawal
  5. This recursion continues until the target contract's funds are exhausted
// VULNERABLE — example only
// Demonstrates: Reentrancy Attack
// Do NOT use in production

pragma solidity ^0.8.0;

contract VulnerableBank {
    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    // VULNERABLE: State update happens AFTER external call
    function withdraw(uint256 amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");

        // External call before state update — reentrancy window opens
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");

        // State update happens too late
        balances[msg.sender] -= amount;
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

contract Attacker {
    VulnerableBank public target;
    uint256 public attackCount = 0;

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

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

    // Fallback function — called when receiving ETH
    receive() external payable {
        attackCount++;
        if (attackCount < 10) {
            // Recursively drain the contract
            target.withdraw(msg.value);
        }
    }
}

Real-World Reentrancy Attack Exploits

| Protocol | Date | Loss | Root Cause | |----------|------|------|-----------| | The DAO | 2016-06 | $60M | Recursive call in splitDAO() before state update | | Lendf.me | 2020-02 | $25M | ERC777 token hook reentrancy in lending contract | | Cream Finance | 2021-02 | $37.5M | Reentrancy in crToken transfer logic | | Curve (Vyper) | 2023-07 | $70M+ | Vyper compiler reentrancy lock bug in stable pools | | bZx Flash Loan | 2020-02 | $954K | Reentrancy combined with flash loan manipulation |

How to Detect Reentrancy Attack

Manual detection requires analyzing call sequences:

  • Flow analysis: Identify all external calls (.call{}, .send(), .transfer(), interface calls)
  • State checks: Verify state updates occur before external calls, not after
  • Balance patterns: Flag contracts that read balance, then send, then decrement
  • Fallback functions: Review fallback/receive functions for calls back into the contract
  • Loop invariants: Check whether loop variables can be modified during iteration via reentrancy

Look for these red flags:

  • State variables updated after external calls
  • User-controlled amounts combined with external calls
  • Contracts accepting ETH with fallback/receive functions
  • Nested or chained external calls within a single transaction

How Firepan Detects Reentrancy Attack Automatically

Firepan's HOUND AI combines static and dynamic analysis:

  1. Control flow mapping: Builds a directed graph of all external calls and state updates
  2. CEI pattern analysis: Flags violations of Checks-Effects-Interactions ordering
  3. Symbolic execution: Traces whether state variables remain consistent during call sequences
  4. Echidna fuzzing: Generates reentrancy-specific invariant checks to detect exploitable patterns
  5. Cross-chain monitoring: Post-deployment monitoring tracks suspicious recursive call patterns in transaction mempool

Firepan's HOUND AI engine catches single-function, cross-function, and read-only reentrancy across all monitored contracts.

Prevention Best Practices

1. Follow Checks-Effects-Interactions (CEI) Pattern

Update all state variables before making external calls:

// SECURE
function withdraw(uint256 amount) public {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;  // Update state first
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
}

2. Use Reentrancy Guards

Implement a mutex pattern with OpenZeppelin's ReentrancyGuard:

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

contract SecureBank is ReentrancyGuard {
    function withdraw(uint256 amount) public nonReentrant {
        // Function can only be called once per transaction
    }
}

3. Pull Over Push Pattern

Let users withdraw funds themselves rather than pushing to them:

// SECURE: Users pull funds
function withdraw() public {
    uint256 amount = balances[msg.sender];
    balances[msg.sender] = 0;
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
}

4. Use Safe Transfer Functions

For ERC20/ERC721, use OpenZeppelin's safe wrappers that handle reentrancy:

IERC20(token).safeTransfer(recipient, amount);

5. Beware of ERC777 and Custom Callbacks

ERC777 tokens invoke a hook during transfer—treat like external calls. Never hold tokens across external calls without guards.

Frequently Asked Questions

Q: What is reentrancy attack in smart contracts?

A: Reentrancy occurs when a contract calls an external contract before updating its own state, allowing the external contract to recursively call back and exploit the stale state. The classic example is a withdrawal function that sends ETH before decrementing the user's balance.


Q: Which protocols have been exploited via reentrancy attack?

A: The DAO (2016, $60M), Lendf.me (2020, $25M), and Cream Finance (2021, $37.5M) suffered major reentrancy exploits. The DAO attack was the most infamous, leading to the Ethereum hard fork. Reentrancy remains a critical vulnerability vector across DeFi.


Q: How does Firepan detect reentrancy attack?

A: Firepan uses HOUND AI to map control flow, detect Checks-Effects-Interactions violations, perform symbolic execution, and run Echidna fuzz tests. Slither and Mythril provide static analysis, while deployment monitoring detects suspicious recursive call patterns in real-time.


Q: Can reentrancy attack be exploited after deployment?

A: Yes. Reentrancy is exploitable post-deployment if the code violates CEI ordering. Attackers watch the mempool for vulnerable function calls and deploy malicious contracts to intercept and exploit them in the same transaction.


Q: How do I prevent reentrancy attack?

A: Follow Checks-Effects-Interactions ordering: update state before external calls. Use OpenZeppelin's ReentrancyGuard, implement pull-over-push patterns, and avoid state-dependent fallback functions. Scoped analysis with Firepan prevents these issues during development.

Conclusion

Reentrancy remains blockchain's most devastating vulnerability class, responsible for over $100M in losses. The fix is straightforward: always update state before external calls. Firepan's HOUND AI detects CEI violations across all monitored contracts, blocking reentrancy exploits before they reach mainnet.

Start securing your smart contracts at https://app.firepan.com/

Firepan

Scan Your Contracts Now

12,453 contracts secured. 2,851 vulnerabilities blocked. 236 exploits prevented. Run a free surface scan — results in minutes, no credit card required.

Run Free Scan →