# reentrancy is possible whenever external calls precede state updates
Four distinct types exist: single-function reentrancy (re-entering the same function), cross-function reentrancy (calling another function that shares state), cross-contract reentrancy (exploiting shared state across contract boundaries), and [[read-only reentrancy exploits view functions to cause other protocols to read inconsistent state|read-only reentrancy]] (targeting view functions that other protocols depend on). The root mechanism is identical in all cases — an external call transfers execution control before the calling contract has updated its state, allowing the callee to re-enter and operate on stale values.
Since [[checks-effects-interactions pattern prevents reentrancy by updating state before external calls]], the defense is well-understood, driving reentrancy from #1 to #5 in the OWASP 2025 ranking. Critically, simple `nonReentrant` mutex guards do NOT prevent read-only reentrancy — the reentrant call targets a view function that does not modify state and thus does not trigger the mutex.
---
Relevant Notes:
- [[read-only reentrancy exploits view functions to cause other protocols to read inconsistent state]] — a variant targeting view functions
- [[checks-effects-interactions pattern prevents reentrancy by updating state before external calls]] — the primary defense pattern
- [[Uniswap V4 hooks introduce arbitrary external code execution into pool swap paths creating new reentrancy attack surfaces]] — hooks architecture creates new reentrancy vectors in AMM swap paths
- [[vyper compiler reentrancy lock storage slot bug broke cross-function reentrancy protection in versions 0.2.15 through 0.3.0]] — compiler bug that silently broke cross-function reentrancy protection, weaponizing this fundamental vulnerability
- [[vyper nonreentrant decorator uses a single global storage lock eliminating cross-function reentrancy by design in versions 0.4.0 and later]] — language-level defense that addresses cross-function reentrancy structurally
- [[the Fei Protocol Rari Capital exploit demonstrated that incomplete reentrancy guard coverage enables cross-function reentrancy through unprotected state-sharing functions]] — $80M cross-function reentrancy where incomplete mutex coverage left exitMarket() unguarded
- [[the Curve Finance Vyper compiler exploit proved that source-level reentrancy guards can be silently broken by compiler bugs invisible to auditors]] — $50-70M compiler-level reentrancy where correct source-level guards produced broken bytecode
- [[ERC-721 safeTransferFrom and ERC-777 tokensReceived callbacks create reentrancy entry points in any protocol handling these token standards]] — token standard callbacks as hidden external calls that create reentrancy entry points
- [[the dForce exploit demonstrated cross-contract read-only reentrancy where stale Curve get_virtual_price values enabled artificial liquidation of lending positions]] — $3.7M cross-contract read-only reentrancy via stale Curve oracle values
- [[reentrancy attacks have caused over 500 million dollars in cumulative losses across 70 plus incidents from 2016 through 2025 despite being the most well-known smart contract vulnerability]] — cumulative evidence that this root cause persists across 7 variant types despite universal awareness
Topics:
- [[vulnerability-patterns]]