Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
An invariant is a property that must hold after any sequence of calls — sum(balances) == totalSupply, treasuryBalance >= sumOfClaims, priceImpact <= 5%. Fuzzers (Echidna, Foundry's invariant tests) generate millions of random call sequences and assert your invariants. Done right, they catch real bugs without anyone having to hypothesise the exploit.
Foundry pattern: function invariant_userBalanceSumEqualsTotalSupply() public { ... uint sum = 0; for (uint i; i<users.length; ++i) sum += token.balanceOf(users[i]); assertEq(sum, token.totalSupply()); }. Foundry runs --fuzz-runs 100000 rounds of random calls; on violation, it shrinks to a minimal failing sequence.
forge test --match-test invariant; watch the fuzzer find a minimal failing trace.Use these three in order. Each builds on the one before.
In one paragraph, explain invariant-based fuzz testing.
Walk me through Foundry's invariant-test runner.
Pick a protocol; design its top 5 invariants. Justify each.