A reentrancy attack occurs when a smart contract makes an external call and gives the called contract a chance to call back into the first contract before the original operation has finished. If the first contract has not yet updated or protected relevant state, the callback may repeat an action against the stale state—for example, withdrawing more than the caller’s recorded balance. The bug is in the order and invariants of the contract’s logic; an ordinary callback is not automatically an attack.
How reentrancy happens
Imagine a withdrawal function that checks a user’s credit, sends assets to the user, and only afterward reduces the recorded credit. If the recipient is a contract, receiving the assets can run its code. That code can call the withdrawal function again while the earlier call is still waiting for the external call to finish. If the balance has not changed, the check may pass again. Each nested call then acts on an outdated view of the same state.
Ether transfers are one possible trigger, but Solidity’s security guidance cautions that calls to other contracts can also hand over control. Token hooks, callbacks, and interactions among several contracts can create other paths back into state-changing logic. The relevant question is whether the callback can violate an invariant, not simply whether a function is called recursively.
The DAO incident
In 2016, a reentrancy flaw in The DAO’s split function was used to move more than 3.6 million ETH from the contract. The response became a major governance dispute: the Ethereum community adopted a protocol fork that moved the affected funds, while participants who rejected that intervention continued the original chain as Ethereum Classic. The incident concerned a vulnerable application contract; it was not a failure of Ethereum’s consensus protocol itself.
The case is a reminder that deployed code can behave exactly as written while still violating the system designers’ expectations. A successful audit or a large user base does not remove the need to check what external calls can do to a contract’s state.
Prevention and limits
A common design guideline is Checks-Effects-Interactions: validate inputs and permissions first, update the contract’s own state next, and make external calls only after those updates. A reentrancy guard can block nested entry into protected functions. These techniques are not substitutes for reviewing all related functions, callbacks, token assumptions, and cross-contract state; a guard can also affect how functions compose.
Tests should cover malicious recipients and callback-capable tokens, and should verify accounting invariants across every external interaction. For complex systems, independent review and tools such as fuzzing or formal verification may help, but none proves that an application’s intended rules are correct.
Social Media Sentiment
An August 2023 r/ethdev thread asked whether reentrant behavior should be blocked by the language or virtual machine. Replies framed the issue as a tension between a useful general call model and the responsibility to order state changes safely. This is one developer discussion, not a survey of Solidity developers or evidence that a specific contract is vulnerable. Read the referenced Reddit discussion.
Last updated: 2026-10
Related Terms
See Also
- Why Smart Contract Audits Fail
- How Do Crypto Bridges Work — And Why Are They Such a Hack Target?
- Why DAO Governance Votes Often Fall Short
- Explore crypto with ChangeNOW
Sources
- Solidity Docs — Security Considerations — Explains how an external call can enable re-entry and recommends the Checks-Effects-Interactions pattern.
- Ethereum.org — Smart Contract Security — Describes callbacks, reentrancy risks, and the relationship between contract-level vulnerabilities and the DAO incident.
- OpenZeppelin Docs — ReentrancyGuard — Documents the current guard’s behavior, including its nested-call limitation.
- Ethereum.org — Ethereum Forks — Records the 2016 DAO fork and its response to the contract exploit.