Skip to free scan
high

READ-ONLY REENTRANCY: MECHANISM, REVIEW, AND MITIGATION

September 14, 2026Updated September 15, 2026
Chainsethereumarbitrumbaseoptimismpolygonbnb-chainavalanche
Review toolsslithermythrilhound-ai

Severity depends on reachable impact and deployment context. Listed tools are review aids; their applicability depends on language, version and configuration.

Read-only reentrancy occurs when a callback observes state before an operation has restored its invariants. The re-entered function may be marked view and make no writes; the danger is that another contract treats its temporary output as a valid price, exchange rate, or solvency value. This is an integration failure as much as a local call-ordering failure.

HOW THE MECHANISM WORKS

Any external interaction can hand control to untrusted code. A native-asset transfer, token receiver hook, or arbitrary protocol call may invoke an attacker-controlled callback while the caller is partway through updating balances or supply. During that callback, the attacker calls a getter that derives a value from the inconsistent state. An integrating lender or vault then uses that value to mint, borrow, swap, or liquidate.

The view modifier does not promise that the returned value represents a settled invariant. It only restricts state changes in that execution context. The Solidity documentation therefore tells reviewers to consider reentrancy across contracts, not only recursive writes within one function.

Curve's published StableSwap-NG audit illustrates the pattern: a metapool could read an old ETH base pool's get_virtual_price during read-only reentrancy, temporarily inflating the LP rate. The report notes that newer pools protected the getter with a reentrancy lock.

REVIEW AND TESTING

Start from every operation that calls outside the protocol before all price-relevant state is final. For each callback point, enumerate public getters over the affected balances, supply, debt, reserves, and cached rates. Then trace every contract that consumes those getters on-chain.

Tests should install a malicious receiver that calls the getter during the callback and immediately passes the result to the integrating action. Assert protocol invariants both during and after the callback. Also test cross-function and cross-contract paths; a guard on the original entry point does not automatically protect a separate getter or consumer.

Firepan can review a submitted repository and commit for external-call ordering, state-dependent getters, and consumers in the analyzed scope. That evidence is not continuous monitoring and cannot prove safety for integrations or code that was not supplied.

MITIGATION AND LIMITS

  • Restore all price-relevant state before external interactions where the protocol design permits it.
  • Make sensitive getters reject reads while the relevant state-changing path is locked, or expose a lock that integrators can check atomically.
  • Avoid treating a spot balance-derived getter as an oracle. Use a design whose manipulation assumptions, update cadence, and failure modes match the consuming protocol.
  • Document which getters are unsafe during callbacks and which pool variants or assets create callback surfaces.

A normal state-changing nonReentrant modifier cannot simply be copied onto a view function if it writes the lock. A read guard instead observes an existing lock or uses another design that remains valid under a static call. Oracle smoothing can reduce some manipulation but does not repair an inconsistent-state dependency by itself.

SOURCES

Firepan

Scan Your Contracts Now

Run a free scan — results in minutes, no credit card required.

Run Free Scan →