protocols/foundry-guide

Foundry Development Framework Guide

ethereumguide🏛️ Officialconfidence highhealth 100%
v1.0.0·Updated 3/20/2026

Installation

curl -L https://foundry.paradigm.xyz | bash
foundryup

Project Structure

my-project/
├── src/          # Contracts
├── test/         # Tests (*.t.sol)
├── script/       # Deployment scripts (*.s.sol)
├── lib/          # Dependencies (git submodule)
└── foundry.toml

Writing Tests (Solidity-native)

// test/MyToken.t.sol
import "forge-std/Test.sol";
import "../src/MyToken.sol";

contract MyTokenTest is Test {
  MyToken token;
  address alice = makeAddr("alice");
  address bob = makeAddr("bob");

  function setUp() public {
    token = new MyToken(1000e18);
    deal(address(token), alice, 100e18);  // Give alice 100 tokens
  }

  function test_transfer() public {
    vm.prank(alice);  // Impersonate alice
    token.transfer(bob, 10e18);
    assertEq(token.balanceOf(bob), 10e18);
  }

  // Fuzz testing
  function testFuzz_transfer(uint256 amount) public {
    amount = bound(amount, 1, 100e18);
    vm.prank(alice);
    token.transfer(bob, amount);
    assertEq(token.balanceOf(bob), amount);
  }
}

Cheatcodes Quick Reference

vm.prank(address)         // Impersonate address for next call
vm.startPrank(address)    // Continuously impersonate until stopPrank()
vm.deal(address, amount)  // Set ETH balance
deal(token, address, amount)  // Set ERC20 balance
vm.warp(timestamp)        // Set block timestamp
vm.roll(blockNumber)      // Set block number
vm.expectRevert("msg")    // Expect revert
vm.expectEmit(true, true, false, true)  // Expect event
vm.createFork(rpcUrl)     // Create fork
vm.selectFork(forkId)     // Switch fork

Deployment Script

// script/Deploy.s.sol
import "forge-std/Script.sol";

contract Deploy is Script {
  function run() external {
    uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
    vm.startBroadcast(deployerPrivateKey);
    
    MyToken token = new MyToken(1000000e18);
    console.log("Token:", address(token));
    
    vm.stopBroadcast();
  }
}
forge script script/Deploy.s.sol --rpc-url $SEPOLIA_RPC --broadcast --verify

cast Common Commands

cast call $CONTRACT "balanceOf(address)(uint256)" $ADDRESS    # Call read-only function
cast send $CONTRACT "transfer(address,uint256)" $TO $AMOUNT --private-key $KEY
cast abi-encode "f(address,uint256)" 0x... 100
cast storage $CONTRACT 0   # Read slot 0
cast code $CONTRACT        # Read bytecode
cast 4byte 0xa9059cbb      # Decode function selector

Common Commands

forge build
forge test -vvv              # Verbose output
forge test --match-test test_transfer
forge coverage
forge snapshot               # Gas snapshot
forge fmt                    # Format

Hardhat vs Foundry Selection

ScenarioRecommended
Rapid prototypingFoundry
Complex JS/TS logicHardhat
Fuzz/Invariant testingFoundry
Deep frontend integrationHardhat
Gas optimization analysisFoundry