Templates and automation for initializing and configuring Foundry projects. Use when setting up new Foundry projects or adding Foundry to existing codebases.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
scripts/init-foundry.shtemplates/foundry.tomlThis skill provides templates, scripts, and best practices for setting up Foundry-based Solidity projects.
Use this skill when:
Prerequisites: Foundry must be installed (foundryup)
Before using this skill, reference the framework-detection skill to:
# Initialize new Foundry project
forge init my-project
cd my-project
# Or initialize in existing directory
forge init --force
Foundry creates this structure:
project/
├── foundry.toml # Configuration
├── .env.example # Environment variables template
├── lib/ # Dependencies (git submodules)
├── src/ # Contract source files
│ ├── interfaces # Interfaces
│ │ └──ICounter # Example interface
│ └── Counter.sol # Example contract
├── test/ # Test files
│ └── Counter.t.sol # Example test
└── script/ # Deployment scripts
└── Counter.s.sol # Example script
See ./templates/foundry.toml for the complete configuration template.
Key Configuration Sections:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.30"
optimizer = true
optimizer_runs = 200
via_ir = false
# Testing
verbosity = 2
fuzz_runs = 256
# Gas reporting
gas_reports = ["*"]
# Formatting
line_length = 120
tab_width = 4
bracket_spacing = false
See ./templates/.env.example for complete environment variable template.
Essential Variables:
# RPC URLs
MAINNET_RPC_URL=
SEPOLIA_RPC_URL=
ARBITRUM_RPC_URL=
# Private Keys (NEVER commit actual keys)
PRIVATE_KEY=
# Etherscan API Keys
ETHERSCAN_API_KEY=
ARBISCAN_API_KEY=
# Gas Price Settings
GAS_PRICE=
[profile.production]
optimizer = true
optimizer_runs = 10000
via_ir = true
[profile.test]
verbosity = 3
fuzz_runs = 1000
invariant_runs = 256
[profile.gas-optimized]
optimizer = true
optimizer_runs = 1000000
via_ir = true
gas_reports = ["*"]
[profile.default]
fork_url = "${MAINNET_RPC_URL}"
fork_block_number = 18000000
# Add OpenZeppelin contracts
forge install OpenZeppelin/openzeppelin-contracts
# Add Solmate
forge install transmissions11/solmate
# Add Forge Standard Library (included by default)
forge install foundry-rs/forge-std
Foundry auto-generates remappings.txt, but you can customize:
@openzeppelin/=lib/openzeppelin-contracts/
@solmate/=lib/solmate/src/
forge-std/=lib/forge-std/src/
Or configure in foundry.toml:
remappings = [
"@openzeppelin/=lib/openzeppelin-contracts/",
"@solmate/=lib/solmate/src/"
]
See ./scripts/init-foundry.sh for automated setup.
Usage:
# Basic initialization
./scripts/init-foundry.sh
# With project name
./scripts/init-foundry.sh my-project
# In existing directory
./scripts/init-foundry.sh --force
What the script does:
When adding Foundry to an existing Hardhat project:
# Initialize but don't overwrite existing files
forge init --no-commit
# foundry.toml
[profile.default]
src = "contracts" # Use Hardhat's contracts dir
test = "test/foundry" # Separate Foundry tests
out = "out"
libs = ["node_modules", "lib"] # Include both package managers
# Foundry
out/
cache/
lib/
# Hardhat
artifacts/
cache/
node_modules/
# Install via Foundry
forge install OpenZeppelin/openzeppelin-contracts
# Reference in Hardhat
# Add to hardhat.config.js:
# paths: { sources: "./contracts" }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import "../src/MyContract.sol";
contract MyContractTest is Test {
MyContract public myContract;
function setUp() public {
myContract = new MyContract();
}
function testBasic() public {
// Test implementation
}
function testFuzz_Amount(uint256 amount) public {
// Fuzz test
}
}
# Run all tests
forge test
# Run specific test
forge test --match-test testBasic
# Run with verbosity
forge test -vvvv
# Run with gas reporting
forge test --gas-report
# Run with coverage
forge coverage
⚠️ CRITICAL: Never store production private keys in .env files!
# Deploy using Ledger
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--ledger \
--broadcast
# Deploy using Trezor
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--trezor \
--broadcast
Create a named keystore:
# Create a new wallet (prompts for password)
cast wallet new ~/.foundry/keystores/deployer
# Import existing private key into keystore
cast wallet import deployer --interactive
Use in deployment:
# Deploy using named account
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--account deployer \
--sender 0xYourAddress \
--broadcast
Update your script to use the account:
contract DeployScript is Script {
function run() external {
// No private key needed - uses --account flag
vm.startBroadcast();
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}
# Prompts for private key (not stored anywhere)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--private-key-interactive \
--broadcast
⚠️ Use ONLY for local development or testnet testing with non-production keys!
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}
If using .env:
# Dry run (simulation)
forge script script/Deploy.s.sol:DeployScript --rpc-url $RPC_URL
# Actual deployment with hardware wallet (RECOMMENDED for production)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--ledger \
--broadcast \
--verify
# Actual deployment with cast wallet (RECOMMENDED for all deployments)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--account deployer \
--sender 0xYourAddress \
--broadcast \
--verify
# Development only: with .env private key
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--broadcast \
--verify
cast wallet for all deployments; never store production keys in .envtest/foundry/ for Foundry tests in hybrid setupsvia_ir = true for complex contractssolc_version in foundry.toml# Install/update Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Prioritize Foundry libs over node_modules
libs = ["lib", "node_modules"]
# Regenerate remappings
forge remappings > remappings.txt
# Check test file naming (must end in .t.sol)
mv test/MyTest.sol test/MyTest.t.sol
| Task | Command | Notes |
|---|---|---|
| Init project | forge init | Creates new project |
| Add dependency | forge install <repo> | Uses git submodules |
| Build | forge build | Compiles contracts |
| Test | forge test | Runs tests |
| Coverage | forge coverage | Test coverage |
| Gas report | forge test --gas-report | Gas usage |
| Format | forge fmt | Code formatting |
| Deploy | forge script | Run deployment |
| Verify | forge verify-contract | Verify on Etherscan |
This skill provides the following templates:
./templates/foundry.toml - Complete Foundry configuration./templates/.env.example - Environment variables templateThis skill provides the following scripts:
./scripts/init-foundry.sh - Automated project initializationNext Steps After Setup:
foundry.toml for your specific needs.env.example to .env and fill in valuesforge installsrc/test/forge test to verify setup