Foundry Development Environment Setup
Foundry is a Rust-based toolchain for smart contract development: Forge (tests and compilation), Cast (chain interaction), Anvil (local node), Chisel (Solidity REPL). It outperforms Hardhat in compilation speed and test execution by 10-50x on typical projects.
Installation and Basic Configuration
curl -L https://foundry.paradigm.xyz | bash
foundryup # install/update to latest version
Structure of a new project (forge init my-project):
my-project/
├── foundry.toml # main config
├── src/ # contracts
├── test/ # tests (.t.sol)
├── script/ # deployment scripts (.s.sol)
└── lib/ # dependencies (git submodules)
foundry.toml — compiler and test configuration:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.24"
optimizer = true
optimizer_runs = 200
via_ir = false # enable for complex contracts with Stack too deep
fuzz = { runs = 1000 }
invariant = { runs = 256, depth = 500 }
[profile.ci]
fuzz = { runs = 10000 }
invariant = { runs = 1000, depth = 1000 }
Separate [profile.ci] allows running heavier fuzzing in CI without slowing local development.
Dependencies via forge install
forge install OpenZeppelin/openzeppelin-contracts
forge install foundry-rs/forge-std
Dependencies are git submodules in lib/. Remappings in foundry.toml:
remappings = [
"@openzeppelin/=lib/openzeppelin-contracts/",
"forge-std/=lib/forge-std/src/",
]
Anvil — Local Node
# Run with mainnet fork
anvil --fork-url $MAINNET_RPC --fork-block-number 19000000 --chain-id 1
# With pre-configured accounts and balances
anvil --accounts 10 --balance 1000
Fork mainnet — key feature for testing integrations. Contract interacts with real Uniswap, Aave, Chainlink — no mocks, on real chain state at a specific block.
Fuzz and Invariant Tests
Foundry fuzzing works out of the box — just declare a function parameter:
function testFuzz_Deposit(uint256 amount) public {
amount = bound(amount, 1, 1e27); // limit range
token.mint(alice, amount);
vm.prank(alice);
vault.deposit(amount);
assertEq(vault.balanceOf(alice), amount);
}
Invariant tests verify system invariants after arbitrary sequences of calls:
function invariant_TotalSupplyEqualsDeposits() public {
assertEq(vault.totalSupply(), vault.totalDeposits());
}
It's exactly an invariant test that finds in 20 minutes an edge case that manual tests missed: at a specific sequence of deposit → withdraw → deposit with specific amounts, totalSupply diverged by 1 wei due to rounding.
CI Integration (GitHub Actions)
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Run tests
run: forge test --profile ci -v
env:
FOUNDRY_ETH_RPC_URL: ${{ secrets.MAINNET_RPC }}
Timeline
Setting up Foundry with dependencies, profile configuration and CI integration: 2-3 hours for a standard project. If fork testing setup with specific protocols and writing basic invariant tests is needed — up to one day.
Cost is calculated individually.







