Join our Newsletter — 33% off our NHI Course

Cross-Function Reentrancy

Cross-function reentrancy is a smart contract vulnerability where an attacker re-enters a contract through a different function before the first call finishes. Shared state is updated in one function and then reused unsafely in another, so access checks or balance logic can be bypassed if state is not locked or updated first.

What Cross-Function Reentrancy Means in Smart Contracts

Cross-function reentrancy is not just a single bad external call, it is a state-consistency failure across contract entry points. A function may update a shared variable too late, or not at all, and another function can read that same variable before the first execution finishes.

That makes the bug broader than the classic single-function pattern. The attacker does not need to repeat the same code path, only to find another callable function that trusts partially updated state. In practice, the problem is often tied to shared balances, accounting flags, allowances, or ownership checks that are assumed to remain stable during execution.

How the Vulnerability Bypasses Assumptions

The core issue is that smart contract execution is only safe when state changes happen before any interaction that can yield control. If one function leaves shared state in an interim condition, a second function may observe that temporary state and make an authorization or value transfer decision on it.

This is why cross-function reentrancy can evade tests that only inspect one function in isolation. The contract may appear correct at the function level while still being unsafe at the system level, because the real dependency is the relationship between entry points, not the logic inside a single routine.

It is also why simple “one-function” reasoning can miss the bug. Any callable path that reads the same state, and any callback that can re-enter before completion, expands the attack surface beyond the original call site.

Why It Is Dangerous

When cross-function reentrancy succeeds, the result is usually not a small accounting discrepancy but a trust boundary break. An attacker can exploit stale reads, reuse an old balance, or slip past an access check that was meant to be valid only after a state transition completed.

The danger increases when the affected contract manages funds, minting, withdrawal logic, or privileged actions. A single inconsistent state update can cascade into unauthorized transfers, duplicate claims, or manipulation of contract-level invariants.

Because the bug sits at the boundary between internal state and external execution, it can be hard to reason about from code review alone. The most dangerous cases are those where the contract looks protected by a check, but the check is separated from the real state update by another function boundary.

For a broader treatment of smart contract failure modes and defensive review patterns, see the Smart Contract Security Guide and the OWASP Smart Contract Top 10 Guide.

Common Defences and Review Focus

The practical defence is to design for invariant preservation across every externally reachable function, not just the most obvious one. Shared state should be updated before any external interaction, and functions that depend on the same invariant should be reviewed together rather than separately.

Reviewers should look for any call chain where one function can leave state in an intermediate condition and another function can read or act on that condition. That includes callbacks, token hooks, nested contract calls, and any pattern where one entry point can indirectly trigger another before the first has finished.

Testing should reflect that broader surface. Invariant testing, fuzzing, and targeted reentrancy checks are especially useful when the contract has multiple public or external functions that share accounting or privilege state.

Risk and Threat Considerations

Cross-function reentrancy creates a material integrity and loss risk because the attacker can exploit a temporary state transition rather than a single obvious bug. The failure mode is especially dangerous when one function writes state late and another function trusts that same state early.

Failure mechanism: An external call or callback re-enters through a different function while shared state is still inconsistent, allowing bypass of balance logic, access checks, or one-time-use assumptions.

Impact: Unauthorized value movement, duplicate execution, broken accounting, and broader compromise of contract invariants can follow, especially in systems that manage withdrawals, minting, or privileged operations.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

MITRE ATT&CK addresses the attack and risk surface, while OWASP ASVS and OWASP SAMM set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
OWASP ASVS V8 — Authorization Cross-function reentrancy bypasses authorization checks through unsafe state reuse.
V15 — Secure Coding and Architecture The flaw is an architectural state-consistency problem across functions and callbacks.
V16 — Security Logging and Error Handling Post-exploit review depends on evidence of unexpected call paths and state transitions.
Recommendation — Review authorization checks across all entry points that share mutable state. Design contracts to preserve invariants before any external interaction. Log anomalous call sequences and investigate unexpected re-entry during review.
MITRE ATT&CK T1210 — Exploitation of Remote Services The attack abuses an accessible execution path to pivot into unintended contract behavior.
Recommendation — Map the re-entry path and hunt for exploitation sequences that pivot through callable functions.
OWASP SAMM SM2 — Design Cross-function reentrancy is best prevented by secure design reviews and threat modeling.
Recommendation — Model shared-state and callback paths during design reviews before deployment.

Practitioner Guidance

What to watch for: Treat any contract with shared mutable state and multiple externally callable functions as a reentrancy candidate, even if one function appears safe on its own. The key question is whether a second entry point can observe an in-progress state change and make a decision from it.

Practitioner takeaway: Cross-function reentrancy is a design-level invariant problem, so the safest review lens is the full call graph, not a single function body.