Read-Only Reentrancy
Detects potential read-only reentrancy through CPI calls where a callee reads stale state from the caller during a callback.
Read-Only Reentrancy
Overview
The read-only reentrancy detector identifies CPI patterns where a Solana program invokes another program that may call back and read the invoking program’s account data before state updates are complete. Unlike write reentrancy (where the attacker modifies state), read-only reentrancy exploits stale read values — a callee reads a pool’s reserves or total supply mid-update and uses the stale values for pricing.
Why This Is an Issue
In Solana, CPI calls execute synchronously. If Program A updates reserves in two steps (update reserve0, invoke Program B, then update reserve1), Program B sees an inconsistent state where reserve0 is updated but reserve1 is not. If Program B calculates prices from these reserves, it gets an incorrect result. This enables the attacker to trade at a favorable price or extract value from the pool.
How to Resolve
// Before: Vulnerable — CPI between state updates
pub fn swap(ctx: Context<Swap>, amount: u64) -> Result<()> {
ctx.accounts.reserve_a.amount -= amount; // Update first reserve
// CPI — callee sees inconsistent reserves
invoke(&oracle_update_ix, &ctx.accounts.to_account_infos())?;
ctx.accounts.reserve_b.amount += output; // Update second reserve
Ok(())
}
// After: Fixed — complete all state updates before CPI
pub fn swap(ctx: Context<Swap>, amount: u64) -> Result<()> {
ctx.accounts.reserve_a.amount -= amount;
ctx.accounts.reserve_b.amount += output;
// All state is consistent before any CPI
invoke(&oracle_update_ix, &ctx.accounts.to_account_infos())?;
Ok(())
}
Detection Methodology
- CPI identification: Locates
invokeandinvoke_signedcalls within function bodies. - State update ordering: Tracks
StoreAccountDataoperations relative to CPI calls. - Stale read detection: Identifies cases where account data is modified before CPI but related data is modified after, creating an inconsistent window.
- Read-path analysis: Checks if the CPI target could read the partially-updated accounts.
Limitations
False positives: Programs that intentionally perform CPI between independent state updates may be flagged. False negatives: Indirect read-only reentrancy through multi-hop CPI chains may not be detected.
Related Detectors
- CPI Reentrancy — detects write reentrancy through CPI
- Missing Signer Check — detects missing authorization