Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Glossary

Reentrancy Guard

A reentrancy guard is a smart contract security pattern that prevents a function from being called again before its initial execution completes, blocking reentrancy attacks.
Chainscore © 2026
definition
SECURITY PATTERN

What is a Reentrancy Guard?

A reentrancy guard is a smart contract security mechanism designed to prevent reentrancy attacks, a critical vulnerability where an external contract maliciously calls back into a function before its initial execution is complete.

A reentrancy guard is a software pattern implemented in a smart contract that uses a state variable—often a boolean flag like locked—to block recursive calls to a vulnerable function. Before executing sensitive operations like fund transfers, the contract checks this flag. If the function is not locked, it sets the flag to true, performs its logic (e.g., sending Ether via .call), and then resets the flag to false. This "checks-effects-interactions" pattern in its enforced form ensures state changes are finalized before any external calls are made, removing the window for recursive exploitation.

The classic vulnerability this guard prevents is exemplified by the 2016 DAO hack. An attacker's contract had a fallback function that, upon receiving Ether from a vulnerable victim contract, would recursively call back into the victim's withdrawal function before the victim's internal balance was updated. This allowed the attacker to drain funds in a loop. A reentrancy guard makes such recursion impossible by throwing a revert if a function is entered while the guard is active, effectively serializing access to the protected logic.

In practice, developers do not typically implement this guard manually for each function. Instead, they use battle-tested library implementations. The most common is OpenZeppelin's ReentrancyGuard contract, which provides a nonReentrant modifier. Applying this modifier to a function, like function withdraw() public nonReentrant { ... }, automatically injects the guard logic. This modular approach reduces human error and is considered a security best practice for any function that makes external calls to untrusted addresses or performs transfers.

It is crucial to understand the guard's scope. A nonReentrant modifier protects against reentrancy within a single contract. However, cross-function reentrancy—where an attacker re-enters a different, unprotected function in the same contract—or cross-contract reentrancy is not prevented by a simple guard on one function. Mitigating these requires careful architectural design, strict adherence to checks-effects-interactions across the entire system, and potentially using more sophisticated locking mechanisms that track callers or transaction origins.

While essential, a reentrancy guard is one layer in a defense-in-depth strategy. It should be combined with other practices: using transfer or send (which limit gas) for simple Ether transfers, employing the pull-over-push pattern for payments, and conducting thorough audits. The guard primarily protects against the most straightforward form of the attack, allowing developers to focus on securing the broader state transition logic of their application without the constant threat of recursive entry points.

how-it-works
SECURITY PRIMITIVE

How a Reentrancy Guard Works

A reentrancy guard is a smart contract security pattern that prevents a critical vulnerability where an external contract can recursively call back into a function before its initial execution completes.

A reentrancy guard is a state variable and modifier that enforces a mutual exclusion lock (mutex) on a function. The most common implementation uses a boolean flag, often named locked or _reentrancyGuard, which is set to true upon function entry and false upon exit. The function's logic is wrapped in a require(!locked, "Reentrant call detected") check and a locked = true assignment. This simple mechanism ensures that while a protected function is executing, any subsequent call to a function sharing the same guard will revert, blocking recursive reentrancy attacks at the contract level.

The classic vulnerability this guard mitigates is the withdrawal pattern flaw. Without a guard, a malicious contract's fallback or receive function could call back into the vulnerable contract's withdraw function before its balance was updated. This allows the attacker to drain funds in a single transaction. The guard breaks this cycle by making the state change—reducing the user's internal balance—atomic with the external call. Modern development frameworks like OpenZeppelin provide a standardized, audited ReentrancyGuard contract with nonReentrant modifiers, which is considered a best practice for any function performing external calls after state changes.

It is crucial to apply the guard correctly and comprehensively. Developers must ensure that all functions sharing sensitive state use the same guard variable; using separate guards for different functions can leave cross-function reentrancy vulnerabilities. Furthermore, the guard only protects against single-contract reentrancy. Sophisticated attacks like cross-contract reentrancy, which exploits multiple contracts in a system, require broader architectural safeguards such as checks-effects-interactions pattern adherence and careful system design. The reentrancy guard is a fundamental, but not exhaustive, component of secure smart contract development.

code-example
REENTRANCY GUARD

Code Example (Solidity)

A practical illustration of implementing a reentrancy guard in a Solidity smart contract to prevent a critical security vulnerability.

A reentrancy guard is a code-level security pattern that prevents a function from being called recursively before its initial execution completes, thereby mitigating reentrancy attacks. In Solidity, this is most commonly implemented using a boolean state variable—often named locked or reentrancyGuard—that is set to true at the start of a sensitive function and reset to false at the end. This boolean acts as a simple mutex lock, ensuring the function's critical logic, such as transferring funds or updating state, cannot be re-entered via an external call. The OpenZeppelin library provides a standardized, audited ReentrancyGuard contract that is widely imported and used.

The core mechanism involves a modifier that checks the guard status. A typical implementation begins with a modifier like nonReentrant, which contains a require(!locked, "ReentrancyGuard: reentrant call"); statement. When the function executes, it sets locked = true, performs its operations (e.g., a .call.value() to send Ether), and then sets locked = false. If an attacker's fallback function attempts to call back into the original contract, the modifier will revert the transaction because the locked flag is still true. This pattern is essential for any function that performs an external call before resolving its internal state changes, a sequence famously exploited in the DAO hack.

Beyond the basic boolean guard, developers should consider the checks-effects-interactions pattern as a complementary best practice. This pattern dictates that code should: first, perform all checks (e.g., validating inputs and balances); second, apply all effects (updating the contract's state variables); and only then, make external interactions (calls to other contracts or transferring Ether). By combining a reentrancy guard with this pattern, you create a robust defense-in-depth strategy. It's also crucial to apply the guard to all public/external functions that could lead into the protected logic, not just the primary entry point, to prevent cross-function reentrancy.

When implementing a guard, be mindful of gas costs and contract inheritance. The OpenZeppelin ReentrancyGuard uses a uint256 private constant (not a boolean) for more gas-efficient packing. Furthermore, if your contract inherits from multiple contracts, ensure the guard modifier is correctly applied in the inheritance hierarchy to avoid shadowing or conflicts. For functions that use delegatecall, remember that the guard variable exists in the context of the calling contract, not the delegate's code. Testing the guard with dedicated unit tests that simulate reentrant callback attacks is a non-negotiable part of secure development.

key-features
SECURITY PATTERN

Key Features of a Reentrancy Guard

A reentrancy guard is a smart contract design pattern that prevents a function from being called recursively before its initial execution completes, a critical defense against one of the most common and costly vulnerabilities in DeFi.

01

State Locking (Mutex)

The core mechanism uses a boolean state variable (e.g., _locked, _notEntered) that acts as a mutex (mutual exclusion lock). The function checks this flag at entry, sets it to a "locked" state, executes the critical logic, and only resets the flag at the very end. This prevents any nested call from re-entering the same function path.

  • Standard Implementation: Uses a modifier like nonReentrant.
  • Key Property: Ensures all state changes (e.g., balance updates) are finalized before the lock is released.
02

Checks-Effects-Interactions Pattern

While not the guard itself, this is the complementary practice a guard protects. It mandates a specific, safe order of operations within a function:

  1. Checks: Validate all conditions (e.g., sufficient balance).
  2. Effects: Perform all state updates first (e.g., deducting the user's internal balance).
  3. Interactions: Make external calls to other contracts or addresses last.

The reentrancy guard ensures this order is enforced even if an external call attempts a recursive attack.

03

Single-Function vs. Cross-Function

Guards protect against two attack vectors:

  • Single-Function Reentrancy: An attacker re-enters the same function they just called (e.g., withdraw calling withdraw again). This is the primary target of a standard guard.
  • Cross-Function Reentrancy: An attacker uses an external call from Function A to re-enter a different but state-sharing Function B (e.g., withdraw -> transfer). A standard guard on each function may not prevent this, requiring more sophisticated design using a single lock for multiple functions.
05

Limitations & Advanced Attacks

A basic guard is not a silver bullet. Key limitations include:

  • Read-Only Reentrancy: An attack that doesn't re-enter the vault contract but exploits other protocols that read the vault's intermediate, inconsistent state via on-chain price oracles.
  • Cross-Contract State Assumptions: If Contract A's guard is lifted before it updates a shared state in Contract B, an attack may still be possible.
  • Delegatecall & CREATE2: Advanced attacks can bypass guards using low-level calls and contract creation tricks, requiring deeper security audits.
06

Historical Context: The DAO Hack

The necessity of reentrancy guards was catastrophically demonstrated by The DAO hack in 2016, which led to the loss of 3.6 million ETH and the Ethereum network's hard fork.

  • Vulnerability: The DAO's splitDAO function performed an external call to send ETH before updating the user's internal token balance.
  • Attack: The attacker's fallback function recursively called splitDAO, draining funds in a loop before the balance was ever deducted.
  • Legacy: This event is the canonical case study that made the Checks-Effects-Interactions pattern and reentrancy guards fundamental to smart contract security.
etymology
TERM HISTORY

Etymology and Origin

The term 'Reentrancy Guard' originates from computer science and was adapted by the blockchain community following a critical vulnerability.

The core concept of reentrancy is a classic problem in concurrent programming and operating systems, where a function can be interrupted and called again before its first execution finishes, potentially corrupting its state. In the context of Ethereum smart contracts, this vulnerability was catastrophically demonstrated by The DAO attack in 2016, where an attacker recursively drained funds by exploiting a flaw in a contract's withdrawal function. The term guard was adopted from software design patterns, specifically the mutex or lock, which protects a critical section of code from concurrent access.

The pattern's formalization within Solidity emerged as a direct response to The DAO hack. Early implementations were custom, but the need for a standardized, audited solution led to its inclusion in widely-used libraries. The OpenZeppelin Contracts library, a cornerstone of secure smart contract development, introduced a canonical ReentrancyGuard abstract contract. This provided a simple modifier—nonReentrant—that developers could apply to functions, making the security pattern a reusable and verifiable building block. This library-driven adoption cemented 'Reentrancy Guard' as the standard terminology.

The evolution of the guard reflects broader security practices. Initially focused on preventing direct reentrancy in a single function, best practices now also guard against cross-function reentrancy and cross-contract reentrancy. The underlying mechanism typically uses a boolean state variable (e.g., _locked) that is checked at the function's entry (require(!_locked, 'ReentrancyGuard: reentrant call')) and set for the duration of execution. This simple check-and-set pattern is the etymological and functional heart of the guard, transforming a complex vulnerability into a manageable, standardized defense.

security-considerations
REENTRANCY GUARD

Security Considerations and Best Practices

A reentrancy guard is a smart contract security pattern that prevents a function from being called recursively before its initial execution completes, which is a critical defense against one of the most common and costly attack vectors in decentralized finance.

01

The Core Vulnerability

A reentrancy attack occurs when a malicious contract exploits the Ethereum Virtual Machine (EVM)'s ability to make external calls before state changes are finalized. The attacker's fallback function recursively calls back into the vulnerable function, draining funds. The classic example is The DAO hack, where this vulnerability led to the loss of 3.6 million ETH.

02

The Checks-Effects-Interactions Pattern

This is the fundamental coding practice to prevent reentrancy without a dedicated guard.

  • Checks: Validate all conditions (e.g., sufficient balance).
  • Effects: Update all internal state variables (e.g., deduct the user's balance).
  • Interactions: Perform external calls (e.g., send ETH) last. By finalizing state before interacting with external contracts, recursive calls see the updated state and cannot re-enter.
03

ReentrancyGuard Modifier

A standardized, reusable contract modifier that uses a boolean lock flag (e.g., nonReentrant). When a function is entered, the flag is set to true, and it is only set back to false upon exiting. Any reentrant call will fail the initial check, reverting the transaction. This is the implementation used by libraries like OpenZeppelin and is considered a best practice for any function with external calls.

04

Cross-Function Reentrancy

Guards must protect against not just direct recursion, but also cross-function reentrancy. An attacker may call a different function that shares state with the vulnerable one. A single nonReentrant modifier may not be sufficient; contracts often use a single guard for all functions that modify sensitive shared state to prevent this lateral attack.

05

Gas and Implementation Limits

While effective, reentrancy guards have considerations:

  • Gas Overhead: Adds a small SSTORE operation for the lock.
  • Not a Silver Bullet: Does not protect against other logic errors or attacks like front-running.
  • Deadlock Risk: Improper implementation (e.g., forgetting to unlock) can permanently brick a function. Always use audited, standard libraries.
ecosystem-usage
SECURITY PATTERN

Ecosystem Usage and Standards

The Reentrancy Guard is a critical smart contract security pattern designed to prevent a specific class of vulnerability where a malicious contract can recursively call back into a function before its initial execution is complete, potentially draining funds.

01

The Core Vulnerability

A reentrancy attack occurs when a function makes an external call to an untrusted contract before updating its own internal state. The attacker's contract uses the fallback or receive function to call back into the original function, exploiting the unchanged state to withdraw assets multiple times. The infamous DAO hack in 2016, which resulted in the loss of 3.6 million ETH, was a classic example of this exploit.

02

The Checks-Effects-Interactions Pattern

This is the foundational coding practice that prevents reentrancy without a dedicated guard. Developers must strictly order operations:

  • Checks: Validate all conditions (e.g., balances, permissions).
  • Effects: Update all internal state variables (e.g., deducting a balance).
  • Interactions: Perform external calls (e.g., transferring ETH or tokens). By updating state before the external call, subsequent reentrant calls will fail the initial checks.
04

Gas Implications and Best Practices

While effective, guards add a small gas overhead for storing and checking the lock state. Best practices include:

  • Applying the nonReentrant modifier only to functions that perform external calls.
  • Using the Checks-Effects-Interactions pattern as a primary defense, with the guard as a secondary safety net.
  • Being aware that reentrancy guards do not protect against cross-function reentrancy, where an attacker re-enters a different function; this requires careful architectural design.
05

Audit and Tooling Focus

Reentrancy detection is a top priority for smart contract security tools and auditors. Static analyzers like Slither and MythX flag potential vulnerable patterns. Formal verification tools can prove the absence of reentrancy. Manual audit reports consistently list reentrancy as a critical finding, and its prevention is considered a baseline requirement for any contract handling value.

examples
REENTRANCY GUARD

Historical and Protocol Examples

Reentrancy attacks are a foundational security vulnerability in smart contracts. These examples illustrate its historical impact and how modern protocols implement defenses.

01

The DAO Hack (2016)

The most famous reentrancy attack, which led to the theft of 3.6 million ETH and the Ethereum hard fork. The attacker exploited a vulnerable withdraw function in The DAO's smart contract. The flaw allowed the malicious contract's fallback function to recursively call withdraw before the contract's internal balance was updated, draining funds in a loop. This event is the primary historical catalyst for the widespread adoption of reentrancy guards.

03

Checks-Effects-Interactions Pattern

A code ordering principle that is a logical, non-library defense against reentrancy. Developers structure functions in this strict sequence:

  1. Checks: Validate all conditions and inputs (e.g., balances, permissions).
  2. Effects: Update all internal state variables before any external calls.
  3. Interactions: Perform external calls to other contracts or addresses. By updating state before interacting with external contracts, any reentrant call will see the updated state (e.g., a zero balance), making the attack ineffective.
04

Pull vs. Push Payments

A design pattern that mitigates reentrancy risk by shifting the responsibility for fund transfers.

  • Push Payments: The contract actively sends funds (e.g., transfer). This is risky if done before state updates.
  • Pull Payments: The contract tracks owed amounts in a mapping and allows users to withdraw their allocated funds via a separate function. This separates the logic that determines the owed amount from the actual transfer, making reentrancy attacks far more difficult as the attacker cannot re-enter the core logic.
06

Limitations & Advanced Attacks

Standard reentrancy guards are not a silver bullet. Advanced attack vectors include:

  • Cross-function Reentrancy: Re-entering a different function that shares state with the vulnerable one.
  • Read-Only Reentrancy: Exploiting a protocol that reads another protocol's state mid-transaction, where that state is temporarily inconsistent due to a reentrant call elsewhere. Defenses require careful state isolation and using reentrancy locks that span an entire transaction or protocol module.
MECHANISM OVERVIEW

Comparison: Reentrancy Guard vs. Other Mitigations

A comparison of different smart contract patterns and tools used to prevent reentrancy attacks, detailing their implementation, security guarantees, and trade-offs.

Feature / MechanismReentrancy Guard (Checks-Effects-Interactions)Pull Payment PatternFormal Verification

Core Principle

Enforces state updates before external calls

Shifts trust to recipients for fund withdrawal

Mathematically proves code correctness

Implementation Complexity

Low

Medium

Very High

Gas Overhead

Low (5k-10k gas for modifier)

Medium (extra transaction for user)

None (compile-time)

Attack Surface

Eliminates single-function reentrancy

Eliminates reentrancy for designated functions

Eliminates specified vulnerability classes

Protection Scope

Function-level

Payment-specific

Contract-wide (for proven properties)

Developer Adoption

Standard (OpenZeppelin library)

Common for payments

Niche (academic/enterprise)

Key Limitation

Vulnerable to cross-function reentrancy

User experience friction

Limited to properties defined in spec

DEBUNKED

Common Misconceptions About Reentrancy Guards

Reentrancy guards are a fundamental security primitive, but their implementation and limitations are often misunderstood. This section clarifies the most frequent points of confusion for developers.

A reentrancy guard is a smart contract pattern that uses a mutex lock (a boolean state variable) to prevent a function from being called recursively before its initial execution completes. When a function marked with the guard is called, it checks a locked flag; if it's false, it sets it to true, executes the function's logic, and then resets the flag to false. This prevents any external call within that function from re-entering the same function or another guarded function, blocking the classic reentrancy attack vector. The most common implementation is OpenZeppelin's ReentrancyGuard contract, which uses a modifier like nonReentrant.

solidity
// Simplified example
bool private locked;
modifier nonReentrant() {
    require(!locked, "Reentrant call");
    locked = true;
    _;
    locked = false;
}

Frequently Asked Questions (FAQ)

Common questions about reentrancy attacks, a critical smart contract vulnerability, and the mechanisms used to prevent them.

A reentrancy attack is a smart contract vulnerability where an external malicious contract exploits the state-changing logic of a victim contract by recursively calling back into it before its initial execution is complete. This typically occurs during an external call (e.g., transferring funds) that cedes control flow to the attacker's contract, allowing it to re-enter the victim function and manipulate an inconsistent state (like a balance that hasn't been updated). The infamous DAO hack of 2016, which resulted in the loss of 3.6 million ETH, was a classic reentrancy attack.

Key Mechanism:

  1. Victim contract function A checks user balance.
  2. Function A sends ETH to the attacker's contract via call.value().
  3. The attacker's fallback function is triggered, which calls back into function A again.
  4. Since the victim's internal balance hasn't been updated yet, the check passes a second time, allowing the attacker to drain funds.
ENQUIRY

Get In Touch
today.

Our experts will offer a free quote and a 30min call to discuss your project.

NDA Protected
24h Response
Directly to Engineering Team
10+
Protocols Shipped
$20M+
TVL Overall
NDA Protected Directly to Engineering Team