Last Updated: November 21, 2025
Installation
curl -L https://foundry.paradigm.xyz | bash
Install Foundryup (installer)
foundryup
Install/update Foundry tools
forge --version
Check Forge version
cast --version
Check Cast version
anvil --version
Check Anvil version
Forge - Project Management
forge init myproject
Create new Foundry project
forge install
Install dependencies from foundry.toml
forge install openzeppelin/openzeppelin-contracts
Install dependency from GitHub
forge install @openzeppelin/contracts@v4.9.0
Install specific version
forge remove openzeppelin/openzeppelin-contracts
Remove dependency
forge update
Update all dependencies
forge update lib/openzeppelin-contracts
Update specific dependency
Forge - Build & Compile
forge build
Compile all contracts
forge build --force
Force recompilation
forge build --sizes
Show contract sizes
forge build --optimize
Build with optimizer enabled
forge build --optimize --optimizer-runs 1000000
Custom optimizer runs
forge clean
Remove build artifacts
forge inspect Contract abi
Get contract ABI
forge inspect Contract bytecode
Get contract bytecode
forge inspect Contract storage
Get storage layout
Forge - Testing
forge test
Run all tests
forge test -vv
Verbose output (show test names)
forge test -vvv
Show stack traces for failures
forge test -vvvv
Show stack traces for all tests
forge test -vvvvv
Maximum verbosity (show storage)
forge test --match-test testTransfer
Run tests matching pattern
forge test --match-contract TokenTest
Run tests in specific contract
forge test --match-path test/Token.t.sol
Run tests in specific file
forge test --gas-report
Show gas usage report
forge test --fork-url $RPC_URL
Fork mainnet for testing
forge test --fork-url $RPC_URL --fork-block-number 17000000
Fork at specific block
forge snapshot
Create gas snapshot
forge snapshot --diff
Compare with existing snapshot
forge coverage
Generate coverage report
Forge - Test Cheatcodes
vm.prank(address)
Set msg.sender for next call
vm.startPrank(address)
Set msg.sender for all subsequent calls
vm.stopPrank()
Reset msg.sender
vm.deal(address, 100 ether)
Set ETH balance of address
vm.roll(blockNumber)
Set block.number
vm.warp(timestamp)
Set block.timestamp
vm.expectRevert("Error message")
Expect next call to revert
vm.expectEmit(true, true, true, true)
Expect event emission
vm.mockCall(address, abi, returnData)
Mock external call
vm.store(address, slot, value)
Write to storage slot
vm.load(address, slot)
Read storage slot
vm.etch(address, bytecode)
Set code at address
vm.label(address, "MyContract")
Label address for traces
vm.assume(condition)
Filter fuzz test inputs
Forge - Deployment
forge create Contract --private-key $PRIVATE_KEY --rpc-url $RPC_URL
Deploy contract
forge create Contract --constructor-args "arg1" "arg2"
Deploy with constructor args
forge create Contract --verify --etherscan-api-key $KEY
Deploy and verify on Etherscan
forge script script/Deploy.s.sol --rpc-url $RPC_URL --broadcast
Run deployment script
forge script script/Deploy.s.sol --private-key $KEY --broadcast --verify
Deploy script with verification
forge verify-contract ADDRESS Contract --etherscan-api-key $KEY
Verify existing contract
forge flatten src/Contract.sol
Flatten contract for verification
Cast - Blockchain Interaction
cast call ADDRESS "balanceOf(address)" USER_ADDRESS
Call view function
cast send ADDRESS "transfer(address,uint256)" RECIPIENT AMOUNT --private-key $KEY
Send transaction
cast balance ADDRESS
Get ETH balance
cast block latest
Get latest block info
cast block-number
Get current block number
cast tx TXHASH
Get transaction details
cast receipt TXHASH
Get transaction receipt
cast storage ADDRESS SLOT
Read storage slot
cast code ADDRESS
Get contract bytecode
cast nonce ADDRESS
Get account nonce
cast chain-id
Get chain ID
cast gas-price
Get current gas price
cast estimate ADDRESS "function(args)" ARGS
Estimate gas
Cast - Utility Commands
cast abi-encode "transfer(address,uint256)" ADDRESS AMOUNT
Encode function call
cast abi-decode "function()(uint256)" DATA
Decode function return
cast 4byte 0x70a08231
Decode function selector
cast 4byte-decode 0x70a08231...
Decode calldata
cast sig "transfer(address,uint256)"
Get function selector
cast keccak "Hello"
Keccak-256 hash
cast to-hex 42
Convert to hexadecimal
cast to-dec 0x2a
Convert to decimal
cast to-wei 1 ether
Convert ether to wei
cast from-wei 1000000000000000000
Convert wei to ether
cast address-zero
Get zero address
cast max-int
Get max uint256 value
cast min-int
Get min int256 value
Cast - Wallet Commands
cast wallet new
Generate new wallet
cast wallet address --private-key $KEY
Get address from private key
cast wallet sign MESSAGE --private-key $KEY
Sign message
cast wallet verify MESSAGE SIGNATURE ADDRESS
Verify signature
cast wallet vanity --starts-with cafe
Generate vanity address
Anvil - Local Node
anvil
Start local Ethereum node
anvil --port 8546
Start on custom port
anvil --fork-url $RPC_URL
Fork mainnet
anvil --fork-url $RPC_URL --fork-block-number 17000000
Fork at specific block
anvil --accounts 20
Create 20 test accounts
anvil --balance 10000
Set initial balance (ETH)
anvil --mnemonic "test test test..."
Use custom mnemonic
anvil --block-time 12
Set block time (seconds)
anvil --no-mining
Disable auto-mining
anvil --gas-limit 30000000
Set block gas limit
Default: http://127.0.0.1:8545
Default Anvil endpoint
10 funded test accounts
Each with 10000 ETH
Foundry Configuration (foundry.toml)
[profile.default]
Default configuration profile
src = "src"
Source directory
out = "out"
Output directory
test = "test"
Test directory
libs = ["lib"]
Library directories
solc_version = "0.8.19"
Solidity compiler version
optimizer = true
Enable optimizer
optimizer_runs = 200
Optimizer runs
via_ir = false
Use IR-based compilation
gas_reports = ["*"]
Contracts to include in gas report
[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
Define RPC endpoints
[etherscan]
mainnet = { key = "${ETHERSCAN_API_KEY}" }
Etherscan API keys
Fuzz Testing
function testFuzz_Transfer(uint256 amount) public
Fuzz test with random inputs
vm.assume(amount > 0 && amount < 1000)
Constrain fuzzing inputs
runs = 1000 (in foundry.toml)
Set number of fuzz runs
function invariant_balanceNeverNegative() public
Invariant test
forge test --fuzz-runs 10000
Override fuzz runs
Pro Tip:
Foundry is blazingly fast compared to Hardhat! Use 'forge test -vvvv' for detailed stack traces. Leverage cheatcodes like vm.prank() and vm.deal() for powerful test scenarios. Always run 'forge snapshot' to track gas usage changes. Use Anvil's forking feature to test against mainnet state!