Skip to main content
Sigvex

Anchor Constraint TOCTOU Remediation

How to fix TOCTOU race conditions in an account-validation framework 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.

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.

References