Skip to main content

Overview

A reentrancy attack is a serious vulnerability where a function calls an external contract, allowing that contract to make repeated calls back before execution completes.
The DAO hack in 2016 exploited a reentrancy vulnerability, resulting in approximately $60 million USD in losses.

How It Works

The basic mechanism: Contract A calls Contract B. The exploit allows B to call back into A before A finishes execution.

Attack Sequence

Step-by-Step Example

  1. User initiates withdrawal from bank contract holding 10 ETH
  2. Bank verifies balance equals 10 ETH
  3. Bank begins transferring 10 ETH to user
  4. Attacker’s contract receives funds and immediately triggers another withdrawal
  5. Balance hasn’t been updated yet, so contract allows another 10 ETH withdrawal
  6. Cycle repeats until bank is drained

Vulnerable Code

Attacker Contract

Safe Patterns

Checks-Effects-Interactions

Reentrancy Guard

Reentrancy Variants

API Detection

Prevention Checklist

  • Follow Checks-Effects-Interactions pattern
  • Update all state before making external calls
  • Use reentrancy guards (e.g., OpenZeppelin ReentrancyGuard) on sensitive functions
  • Use .call{value: ...}("") for ETH transfers (not transfer()/send())
  • Always check the boolean return value from .call and handle failures explicitly
transfer() and send() are deprecated due to their hardcoded 2300 gas limit, which can fail after gas cost changes (EIP-1884). Use .call{value: ...}("") instead.