Anchor Constraint TOCTOU Remediation
How to fix TOCTOU race conditions in Anchor constraints.
Anchor Constraint TOCTOU Remediation
Overview
Related Detector: Anchor Constraint TOCTOU
TOCTOU races occur when account state is checked before a CPI that modifies it. The fix is to reload account data after CPI calls and re-validate, or restructure the instruction to perform CPI before state-dependent checks.
Recommended Fix
Before (Vulnerable)
let balance = ctx.accounts.token.amount;
require!(balance >= MIN, Insufficient);
token::transfer(ctx, balance)?; // Modifies token.amount
After (Fixed)
let amount = ctx.accounts.token.amount;
token::transfer(ctx, amount)?;
ctx.accounts.token.reload()?; // Refresh from on-chain state
require!(ctx.accounts.token.amount == 0, Incomplete);
Alternative Mitigations
Use Anchor reload()
Always call reload() on accounts after any CPI that could modify them:
invoke(&external_ix, accounts)?;
ctx.accounts.my_account.reload()?;
// Now safe to read my_account data
Common Mistakes
Mistake: Using Cached Variable After CPI
let data = ctx.accounts.state.value;
invoke(&modify_ix, accounts)?;
// WRONG: data is stale, state.value may have changed
if data > threshold { /* ... */ }
Always re-read from the account after CPI, never trust cached variables.