Fuzzing and Invariant Testing
Learn how property-based fuzzing and invariant testing catch edge-case bugs in smart contracts that fixed unit tests miss, using Foundry as the example framework.
Fuzzing and Invariant Testing is a free Blockchain Smart Contracts with Solidity lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Blockchain Smart Contracts with Solidity learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Limits of Example Tests
You have written unit tests with specific inputs. But attackers find the one input you did not try. Fixed examples cannot cover the huge space of possible values. This is where fuzzing helps.
What Is Fuzzing?
Fuzz testing runs a test many times with randomly generated inputs. Instead of asserting on one value, you assert a property that should hold for all inputs.
A Fuzz Test in Foundry
In Foundry, any test function parameter is automatically fuzzed. The framework feeds in many random values.
function testFuzz_DepositIncreasesBalance(uint256 amount) public {
vm.assume(amount > 0 && amount < 1e30);
vault.deposit(amount);
assertEq(vault.balanceOf(address(this)), amount);
}Bounding Inputs
Random values can be absurd (like the max uint256). Use vm.assume to discard bad inputs or bound to map a value into a valid range so tests stay meaningful.
function testFuzz_Transfer(uint256 amount) public {
amount = bound(amount, 1, token.balanceOf(address(this)));
token.transfer(bob, amount);
assertEq(token.balanceOf(bob), amount);
}Thinking in Properties
The shift is from 'with input X expect Y' to 'no matter the input, this rule holds'. Common properties:
- Total supply never changes on a transfer
- A user can never withdraw more than they deposited
- Balances never underflow
What Are Invariants?
An invariant is a property that must hold after any sequence of operations, not just one call. Invariant testing fires many random function calls in random order, then checks the invariant after each step.
Declaring an Invariant
In Foundry, functions prefixed with invariant_ are checked after each randomized call sequence.
function invariant_TotalSupplyEqualsSumOfBalances() public {
assertEq(token.totalSupply(), handler.sumOfBalances());
}The Handler Pattern
Raw random calls often revert or wander into useless states. A handler contract wraps the target with guided, valid actions and tracks expected totals (ghost variables) for the invariant to check.
contract Handler {
Token token;
uint256 public sumOfBalances;
function transfer(uint256 toSeed, uint256 amount) external {
// bounded, valid transfer logic that updates ghost totals
}
}Shrinking Failures
When a fuzzer finds a failing input, it shrinks it to the simplest counterexample. This makes the bug far easier to understand and reproduce than a random gigantic number.
Tuning Test Runs
More runs find deeper bugs but take longer. Configure run counts in foundry.toml for CI versus quick local checks.
[fuzz]
runs = 1000
[invariant]
runs = 256
depth = 50When to Use Each
Use fuzzing to harden individual functions against unexpected single inputs. Use invariant testing to verify system-wide rules survive any sequence of actions. Together they catch classes of bugs fixed tests never reach.
Quick Check
Test your understanding of property-based testing.
Recap
You learned fuzzing and invariant testing:
- Fuzzing runs functions with many random inputs against properties
vm.assumeandboundkeep inputs valid- Invariants check system rules across random call sequences
- Handlers guide actions; shrinking simplifies failures
These techniques uncover edge cases that example-based tests miss.
Frequently asked questions
Is the “Fuzzing and Invariant Testing” lesson free?
Yes — the full text of “Fuzzing and Invariant Testing” is free to read here on the web, and the Blockchain Smart Contracts with Solidity course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Blockchain Smart Contracts with Solidity course, upgrade to CoddyKit PRO.
What will I learn in “Fuzzing and Invariant Testing”?
Learn how property-based fuzzing and invariant testing catch edge-case bugs in smart contracts that fixed unit tests miss, using Foundry as the example framework. You practise Blockchain Smart Contracts with Solidity with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Blockchain Smart Contracts with Solidity?
No prior experience is required. Blockchain Smart Contracts with Solidity on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Fuzzing and Invariant Testing” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Blockchain Smart Contracts with Solidity lesson?
Yes. Every Blockchain Smart Contracts with Solidity lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Advanced Testing with Foundry/Hardhat
- Formal Verification Basics
- Mainnet Deployment & Monitoring
- Fuzzing and Invariant Testing