Examples

End-to-end patterns: a cheatcode-driven unit test, a forked-mainnet Cast call, and a scripted deployment.

Path: examples

Third-party documentation. This is independently authored analysis of the public Foundry codebase — not the official docs, and not reviewed or endorsed by the Foundry team.

Examples

Three patterns cover the majority of day-to-day Foundry usage: cheatcode-driven unit tests, forked-network queries, and scripted deployments. Each is deliberately minimal — production code adds access control, events, and error paths on top of the same shapes.

Testing against a live protocol

Configure a fork in foundry.toml or pass --fork-url, then write tests that assume real mainnet state exists. A test can deposit into the real Uniswap router, for example, because Anvil materializes remote storage lazily and impersonation lets you act as any holder.

Scripted deployment

forge script executes a Solidity script's run() function first in simulation (printing full traces and state diffs), then — with --broadcast — replays it as real signed transactions. Because simulation and broadcast share one code path, what you see in the dry run is what gets submitted.

Shell-native interaction

Cast commands compose with standard shell tools: pipe cast call output into jq, resolve selectors with cast 4byte, watch new blocks with cast block --latest. No REPL required.

Examples

Unit test with cheatcodes

Unit test with cheatcodes
typescript
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
import {Test} from "forge-std/Test.sol";
 
contract VaultTest is Test {
Vault vault;
 
function setUp() public {
vault = new Vault();
deal(address(this), 100 ether);
}
 
function testDepositIncreasesShares() public {
vm.prank(alice);
uint256 shares = vault.deposit{value: 1 ether}();
assertEq(vault.balanceOf(alice), shares);
}
}
STATUSexample

setUp runs fresh before every test. vm.prank impersonates alice for the next call and deal sets an address balance — both are cheatcodes interpreted by the embedded EVM rather than real chain state.

Querying a forked mainnet contract

Querying a forked mainnet contract
typescript
cast call 0xdAC17F958D2ee523a2206206994597C13D831ec7 \
"balanceOf(address)(uint256)" 0x000...dEaD \
--rpc-url mainnet
STATUSexample

Cast decodes return values using inline ABI signatures — the (uint256) suffix tells it the expected output type so no separate ABI file is needed.

Edge Cases

  • Tests run against Anvil's default chain id and genesis unless a fork URL is configured — code asserting on chainid or block.number behaves differently between plain and forked test runs.
  • vm.prank applies to exactly one external call; a second call in the same test reverts to the default sender unless vm.startPrank was used.
  • Fuzz runs shrink failing inputs, but the reported counterexample depends on the configured [fuzz] seed — reproducing a CI failure locally requires matching the seed and runs values.