Skip to content

evanstinger/foundry-skill

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Foundry Solidity Skill

Advanced Foundry toolkit for production-grade smart contract development.

Overview

This skill provides comprehensive guidance for developing, testing, and deploying smart contracts using Foundry - the blazing fast, portable, and modular toolkit for Ethereum application development.

Why This Skill Is Different

Built for AI Agents, by an AI-aware Developer.

Unlike traditional documentation that organizes by feature definitions ("here's what Forge does"), this skill is organized by intentions ("I want to..."). This approach recognizes that AI agents think in terms of goals and desired outcomes, not feature lists.

From Intention to Action

This skill acts as a translation layer between what you want to achieve and the specific technical steps required:

Your Intention Skill Translation Result
"I want to deploy this contract safely" Security checklist β†’ Dry-run β†’ Testnet β†’ Mainnet Safe deployment without accidents
"I need to test this function thoroughly" Unit β†’ Fuzz β†’ Invariant β†’ Fork test pyramid Exhaustive test coverage
"Let me check on-chain data" Read-only cast commands with safety guards Information retrieval without risk
"I should prepare for audit" Taint analysis β†’ Slither β†’ Security checklist Production-ready code

The key insight: Instead of asking "What does Foundry have?" and figuring out how to use it, you simply state your goal and the skill provides the exact workflow.

Creator

Evan Stinger
Website: evanstinger.com

Features

This skill covers all aspects of Foundry development through an intention-based lens:

  • Project Setup - Initialize projects, manage dependencies, configure remappings
  • Contract Patterns - Upgradeable contracts, factory patterns, access control systems
  • Testing - Unit tests, fuzz tests, invariant tests, fork tests, gas snapshots
  • Security - Taint analysis, linting, Slither integration, audit preparation
  • Deployment - JSON-configured scripts, dry-run testing, mainnet deployment
  • Local Development - Anvil local node, mainnet forking, impersonation
  • Chain Interaction - Cast commands for reading/writing on-chain data
  • Prototyping - Chisel REPL for quick experimentation
  • CI/CD - GitHub Actions, coverage reports, automated testing

Intention-to-Action Mapping

Use this table to translate your goal into the right reference guide:

Your Goal (Intention) Load This Key Tools
Set up a new project references/project-setup.md forge init, forge install, remappings
Build an upgradeable contract references/patterns.md OpenZeppelin Upgrades, forge script
Create a factory contract references/patterns.md type(Contract).creationCode, clone
Implement access control references/patterns.md AccessControlEnumerable, custom ACM
Write deployment scripts references/scripting.md JSON input, vm.parseJson, dry-run
Make sure I tested everything references/testing.md Fuzz, invariant, fork, table tests
Deploy without breaking things references/deployment.md foundry.toml profiles, verification
Prepare for security audit references/security.md Taint analysis, linting, Slither
Read what's on-chain references/cast.md cast call, cast balance, cast block
Send transactions safely references/cast.md cast send (with human approval)
Encode/decode data references/cast.md cast calldata, cast abi-encode
Manage wallets/keys references/cast.md cast wallet, keystore, signatures
Run a local test node references/anvil.md anvil, state management
Fork mainnet for testing references/anvil.md anvil --fork-url, impersonation
Quick prototype/testing references/chisel.md chisel, live evaluation
Set up CI/CD pipeline references/ci.md GitHub Actions, coverage, gas snapshots

How to Use This Skill

1. Start With Your Intention

Don't browse features. State what you want to accomplish:

  • ❌ "What does forge test do?"
  • βœ… "I want to ensure my contract handles edge cases"

2. Find the Matching Intention

Look at the Intention-to-Action Mapping table above and find the row that matches your goal.

3. Load the Reference

Each reference guide is organized as a workflow:

  • Phase-based progression: Setup β†’ Development β†’ Testing β†’ Security β†’ Deployment
  • Decision trees: "If X, then Y" instead of flat feature lists
  • Red flags: STOP conditions that catch common mistakes
  • Iron laws: Non-negotiable rules (like never broadcasting automatically)

4. Execute the Workflow

Follow the reference guide step-by-step. Each guide assumes you're an AI agent and provides:

  • Exact commands to run
  • Expected outputs to validate
  • Error handling patterns
  • When to ask for human confirmation

Quick Start Examples

Example 1: "I want to deploy a contract"

Agent Intention: Deploy safely without breaking anything
Skill Path: references/deployment.md
Workflow:

# Phase 1: Pre-deployment security
forge taint
forge lint
slither . --exclude-dependencies

# Phase 2: Dry-run locally
anvil --fork-url mainnet
forge script script/Deploy.s.sol --rpc-url localhost

# Phase 3: Dry-run on testnet
forge script script/Deploy.s.sol --rpc-url sepolia

# Phase 4: Provide for human execution (NEVER auto-broadcast)
echo "Ready for mainnet deployment. Run:"
echo "forge script script/Deploy.s.sol --broadcast --rpc-url mainnet"

Example 2: "I need to test this thoroughly"

Agent Intention: Ensure comprehensive coverage
Skill Path: references/testing.md
Workflow:

# Phase 1: Unit tests for every function
forge test --match-contract MyContractTest

# Phase 2: Fuzz tests for parameterized functions
forge test --match-test testFuzz -vvvv

# Phase 3: Invariant tests for system properties
forge test --match-contract InvariantTest

# Phase 4: Fork tests against real state
forge test --fork-url mainnet --match-test testAgainstMainnet

# Phase 5: Coverage report
forge coverage --report lcov

Example 3: "Let me check on-chain data"

Agent Intention: Read safely without spending gas
Skill Path: references/cast.md
Workflow:

# These are always safe (read-only)
cast balance $ADDRESS --rpc-url mainnet
cast call $CONTRACT "balanceOf(address)" $ADDRESS --rpc-url mainnet
cast block-number --rpc-url mainnet

# These require human approval (state-changing)
# NEVER run automatically:
# cast send $CONTRACT "transfer(address,uint256)" $TO $AMOUNT ...

Iron Laws (Non-Negotiable)

🚨 NEVER BROADCAST WITHOUT EXPLICIT PERMISSION

ABSOLUTE RULE: NEVER run forge, cast, or any command with --broadcast or any flag that sends transactions on-chain without explicit human confirmation.

Correct behavior:

# Show the command, let human execute:
echo "Run this command to broadcast:"
echo "forge script script/Deploy.s.sol --broadcast --rpc-url mainnet"
echo "cast send $CONTRACT 'transfer(address,uint256)' $TO $AMOUNT --rpc-url mainnet --private-key \$KEY"

Why: Broadcasting spends real funds and is irreversible. Always provide the command for human review and manual execution.

πŸ”’ Security-First Testing

Tests should be the largest section of your codebase. Every line of contract code should have multiple test scenarios:

  • Happy path (expected success)
  • All revert conditions
  • Edge cases (zero values, max values, boundary conditions)
  • Access control bypass attempts
  • Reentrancy attempts
  • Integer overflow/underflow (if using <0.8.0)

πŸ§ͺ Exhaustive Test Pyramid

  1. Unit tests (base layer): Every function, every branch
  2. Integration tests: Contract interactions, state changes
  3. Fuzz tests: Property-based testing with random inputs
  4. Table tests: Data-driven tests with specific input combinations
  5. Invariant tests: System-wide properties that must always hold
  6. Fork tests: Against live mainnet/testnet state
  7. Stress tests: High volume, edge cases, attack simulation

Configuration

foundry.toml Best Practices

Define RPC endpoints and Etherscan keys in config, avoid magic variables:

[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
sepolia = "${SEPOLIA_RPC_URL}"
bsc = "${BSC_RPC_URL}"
bsc-testnet = "${BSC_TESTNET_RPC_URL}"
polygon = "${POLYGON_RPC_URL}"
arbitrum = "${ARBITRUM_RPC_URL}"
base = "${BASE_RPC_URL}"
localhost = "http://localhost:8545"

[etherscan]
mainnet = { key = "${ETHERSCAN_API_KEY}" }
bsc = { key = "${BSCSCAN_API_KEY}" }
bsc-testnet = { key = "${BSCSCAN_API_KEY}", url = "https://api-testnet.bscscan.com/api" }
polygon = { key = "${POLYGONSCAN_API_KEY}" }
arbitrum = { key = "${ARBISCAN_API_KEY}" }
base = { key = "${BASESCAN_API_KEY}" }

[lint]
severity = "warning"
exclude = ["script/**", "test/**"]

[fmt]
line_length = 100
tab_width = 4
bracket_spacing = false

Usage:

# Use defined RPC names, not URLs:
forge script script/Deploy.s.sol --rpc-url mainnet
# Instead of: --rpc-url https://eth.merkle.io

Environment Variables

Required in .env (NEVER commit to git):

PRIVATE_KEY=0x...
MAINNET_RPC_URL=https://...
ETHERSCAN_API_KEY=...

In scripts, access via:

uint256 deployerKey = vm.envUint("PRIVATE_KEY");
string memory rpcUrl = vm.envString("MAINNET_RPC_URL");

Red Flags - STOP and Review

If you catch yourself:

  • About to broadcast without human confirmation β†’ STOP, provide command for manual execution
  • Writing tests smaller than contract code β†’ STOP, expand test coverage
  • Using hardcoded addresses without JSON config β†’ STOP, use JSON input pattern
  • Deploying without running forge taint β†’ STOP, run taint analysis
  • Deploying without Slither check β†’ STOP, run security analysis
  • Skipping dry-run on testnet β†’ STOP, test against real state
  • Not using foundry.toml RPC aliases β†’ STOP, configure properly
  • Using vm.assume() for ranges β†’ STOP, use bound() instead
  • Using Anvil default keys on mainnet β†’ STOP, they're publicly known!

Quick Reference Commands

Project Setup

# Initialize project
forge init my_project
forge init --template https://github.com/... my_project

# Install dependencies
forge install OpenZeppelin/openzeppelin-contracts

# Build contracts
forge build
forge build --sizes

Testing

# Run tests
forge test
forge test -vvvv              # With full traces
forge test --gas-report       # Gas usage analysis

# Run specific test
forge test --match-test test_Increment
forge test --match-contract CounterTest

# Fuzz with more runs
forge test --fuzz-runs 10000

# Fork testing
forge test --fork-url mainnet

# Coverage
forge coverage
forge coverage --report lcov

Security & Quality

# Taint analysis (data flow)
forge taint
forge taint src/Vault.sol

# Linting
forge lint
forge lint --json

# Formatting
forge fmt
forge fmt --check

# Static analysis
slither . --exclude-dependencies

Local Development (Anvil)

# Start local node
anvil                          # Default 10 accounts, 10000 ETH each

# Fork mainnet
anvil --fork-url mainnet
anvil --fork-url mainnet --fork-block-number 18000000

# Auto-impersonate for testing
anvil --fork-url mainnet --auto-impersonate

Chain Interaction (Cast) - Read-Only (Safe)

# Read on-chain data
cast block-number --rpc-url mainnet
cast balance $ADDRESS --rpc-url mainnet
cast call $CONTRACT "balanceOf(address)" $ADDRESS --rpc-url mainnet

# ABI encoding
cast calldata "transfer(address,uint256)" $TO $AMOUNT
cast abi-encode "constructor(string,string)" "Name" "SYMBOL"

# Wallet operations
cast wallet new
cast wallet address --private-key $KEY
cast wallet sign "message" --private-key $KEY

Cast Send (Requires Human Approval!)

# NEVER run automatically - provide for human execution
echo "Run to send transaction:"
echo "cast send $CONTRACT 'transfer(address,uint256)' $TO $AMOUNT --rpc-url mainnet --private-key \$PRIVATE_KEY"

Deployment

# Dry-run deployment (SAFE)
forge script script/Deploy.s.sol --rpc-url sepolia
forge script script/Deploy.s.sol --rpc-url mainnet -vvvv

# NEVER run this automatically:
# forge script script/Deploy.s.sol --broadcast --rpc-url mainnet

# Verify contract
forge verify-contract $ADDRESS src/Contract.sol:Contract --chain mainnet

REPL (Chisel)

# Start REPL
chisel

# Fork mainnet in REPL
chisel --fork-url mainnet

# Evaluate expression
chisel eval "uint256 x = 1 + 2; x"

Directory Structure

foundry/
β”œβ”€β”€ SKILL.md              # Main skill definition for OpenCode
β”œβ”€β”€ README.md             # This file
β”œβ”€β”€ references/           # Intention-based reference guides
β”‚   β”œβ”€β”€ project-setup.md  # "I want to set up a project"
β”‚   β”œβ”€β”€ patterns.md       # "I need to implement patterns"
β”‚   β”œβ”€β”€ testing.md        # "I need to test thoroughly"
β”‚   β”œβ”€β”€ deployment.md     # "I want to deploy safely"
β”‚   β”œβ”€β”€ scripting.md      # "I need deployment scripts"
β”‚   β”œβ”€β”€ security.md       # "I need to prepare for audit"
β”‚   β”œβ”€β”€ cast.md           # "I want to interact with chain"
β”‚   β”œβ”€β”€ anvil.md          # "I need a local node"
β”‚   β”œβ”€β”€ chisel.md         # "I want to prototype"
β”‚   └── ci.md             # "I need CI/CD"
└── scripts/              # Utility scripts (optional)

License

MIT

Contributing

This skill is designed for OpenCode agents. The intention-based organization means:

  • Add guides based on common agent goals, not feature lists
  • Include decision trees and workflows
  • Mark STOP conditions and red flags clearly
  • Always emphasize safety and human approval where needed

References


Remember: This skill is a translation layer. Your job isn't to memorize Foundry's featuresβ€”it's to articulate your intention clearly and let the skill map that to the right actions.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors