🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 5 Min Lesezeit
0

Foundry Fuzz & Invariant Testing: A Practical Cookbook

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Most hacks happen in edge cases the dev never considered. Fuzz testing throws random inputs at your contracts until something breaks — and Foundry makes it fast enough that you run it before every commit. Here are the patterns I actually use.






Getting Started






CODE
forge install tiancaijb366-pixel/foundry-security-tests






The companion repo has all these examples runnable. Fork it, run forge test, then rip out the patterns for your own contracts.









1. Basic Fuzzing with bound / vm.assume



Don't write ten test_RevertIf_* functions. Give the fuzzer a range and let it find the off-by-one.




CODE
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {Token} from "../src/Token.sol";

contract TokenFuzzTest is Test {
Token t;

function setUp() public {
t = new Token(1_000_000e18);
}

function testFuzz_Transfer_Bounds(address sender, address to, uint256 amount) public {
// `bound` keeps inputs practical
amount = bound(amount, 1, t.balanceOf(sender));

// `vm.assume` filters — use it sparingly (slows the fuzzer)
vm.assume(sender != address(0) && to != address(0) && sender != to);

vm.prank(sender);
t.transfer(to, amount);

assertGe(t.balanceOf(sender), 0);
assertEq(t.totalSupply(), 1_000_000e18);
}
}






Key point: bound is faster than vm.assume — it narrows the range instead of discarding inputs. Use assume only for relationships the fuzzer can't infer (e.g., sender != to).









2. Invariant Testing: ERC20 totalSupply



Invariant tests check a property holds across random sequences of calls. They catch state-machine bugs that single-function fuzzing misses.




CODE
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {StdInvariant} from "forge-std/StdInvariant.sol";
import {Token} from "../src/Token.sol";

contract TokenInvariantTest is StdInvariant, Test {
Token t;

function setUp() public {
t = new Token(1_000_000e18);
targetContract(address(t));
}

// This should _always_ be true
function invariant_totalSupply() public {
assertEq(t.totalSupply(), 1_000_000e18);
}
}






Run with:




CODE
forge test --match-test invariant -vvv






Add --fuzz-runs 50000 for serious fuzzing. On a commodity laptop that runs in ~30s and catches things you'd never write a unit test for.



Ghost variable pattern: When the invariant involves contract state over time, track a ghost variable in the test contract that mirrors expected state after every handler call.









3. Reentrancy Detection via Fuzz



Foundry rolls back state after every fuzz run, so you can brute-force reentrancy paths without setting up a separate exploit contract for each scenario.




CODE
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {Vault} from "../src/Vault.sol";

contract ReentrancyFuzzTest is Test {
Vault v;

// Track the reentrancy attempt
bool public attackAttempted;
uint256 public balanceBefore;

receive() external payable {
if (attackAttempted) return; // only re-enter once
attackAttempted = true;

// Try to drain before the first call finishes
v.withdraw(balanceBefore);
}

function testFuzz_Reentrancy(uint256 depositAmount) public {
depositAmount = bound(depositAmount, 1 ether, 100 ether);

// Fund victim
v.deposit{value: depositAmount}();
balanceBefore = depositAmount;

// Attack from this contract
attackAttempted = false;
v.withdraw(depositAmount);

// If reentrancy worked, vault balance would be < 0
assertLe(address(v).balance, depositAmount);
}
}






Why this works: Foundry isolates each fuzz run. You don't need expectRevert — just check the final state. If totalSupply or balance diverged, the fuzzer found a path.









4. Access Control Fuzzing



The most common finding in real audits: an onlyOwner modifier that doesn't cover all state-changing paths. Fuzz every function from every caller.




CODE
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {Vault} from "../src/Vault.sol";

contract AccessControlFuzzTest is Test {
Vault v;

address owner = makeAddr("owner");
address attacker = makeAddr("attacker");

function setUp() public {
vm.prank(owner);
v = new Vault();

deal(attacker, 100 ether);
}

// Fuzz every state-changing function as an attacker
function testFuzz_AccessControl_Withdraw(uint256 amount) public {
vm.assume(amount > 0 && amount <= 100 ether);

vm.prank(attacker);
vm.expectRevert(); // should always revert for non-owner
v.emergencyWithdraw(amount);
}

function testFuzz_AccessControl_Pause(bool paused) public {
vm.prank(attacker);
vm.expectRevert();
v.setPaused(paused);
}

function testFuzz_AccessControl_Mint(uint256 amount) public {
amount = bound(amount, 0, 1_000_000e18);

vm.prank(attacker);
vm.expectRevert();
v.mint(attacker, amount);
}
}






Pro tip: Build a handler contract that wraps every permissioned function and call it from both privileged and unprivileged addresses in your invariant test suite. One function per access level.









5. Oracle Manipulation Fuzzing



DeFi exploits almost always involve price oracles returning manipulated values. Fuzz the oracle input and check what happens to your core accounting.




CODE
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {LendingPool} from "../src/LendingPool.sol";
import {MockOracle} from "../src/MockOracle.sol";

contract OracleManipulationFuzzTest is Test {
LendingPool pool;
MockOracle oracle;

address user = makeAddr("user");

function setUp() public {
oracle = new MockOracle(1000e8); // ETH/USD = $1000
pool = new LendingPool(address(oracle));
deal(user, 100 ether);
}

// What happens if the oracle price swings wildly?
function testFuzz_OracleManipulation(uint256 manipulatedPrice, uint256 collateral) public {
collateral = bound(collateral, 1 ether, 50 ether);
manipulatedPrice = bound(manipulatedPrice, 1e8, 100_000e8); // $1 to $100k

// User deposits collateral
vm.prank(user);
pool.deposit{value: collateral}();

// Oracle is manipulated (flash loan, sandwich, etc.)
oracle.setPrice(manipulatedPrice);

// User borrows against inflated collateral — or gets liquidated unfairly
vm.prank(user);
pool.borrow();

// Check: can the pool cover all deposits?
assertGe(address(pool).balance, pool.totalDeposits());
}
}






What this catches: If your borrow() or liquidation math assumes prices stay within 5% of the previous value, the fuzzer will find the exact value that breaks it. Then you add a circuit breaker or TWAP window.









Running the Full Suite






CODE
# Standard fuzz (default 256 runs per test)
forge test

# Heavy fuzz (closer to what auditors run)
forge test --fuzz-runs 50000 --ffi

# Invariant tests (sequences of calls)
forge test --match-test invariant --fuzz-runs 50000






On CI, run the light suite on every push and the heavy suite nightly.






Useful? Check out these resources:





  • — what to check before any deployment


  • Solidity Snippets — copy-paste patterns for common patterns

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Foundry Fuzz & Invariant Testing: A Practical Cookbook

Thematisch verwandte Begriffe: Foundry, Fuzz, Invariant, Testing · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...