一键导入
foundry-testing
// Write Foundry-based tests and scripts. Trigger phrases - foundry testing, write test, fuzz test, fork test, invariant test, deploy script, gas benchmark, coverage, or when working in tests/ or scripts/ directories.
// Write Foundry-based tests and scripts. Trigger phrases - foundry testing, write test, fuzz test, fork test, invariant test, deploy script, gas benchmark, coverage, or when working in tests/ or scripts/ directories.
| name | foundry-testing |
| user-invocable | true |
| description | Write Foundry-based tests and scripts. Trigger phrases - foundry testing, write test, fuzz test, fork test, invariant test, deploy script, gas benchmark, coverage, or when working in tests/ or scripts/ directories. |
Rules and patterns for Foundry tests. Find examples in the actual codebase.
| Reference | Content | When to Read |
|---|---|---|
.claude/skills/foundry-testing/references/test-infrastructure.md | Constants, defaults, mocks | When setting up tests |
.claude/skills/foundry-testing/references/cheat-codes.md | Common cheatcode patterns | When using vm cheatcodes |
.claude/skills/foundry-testing/references/invariant-patterns.md | Handlers, stores, invariants | When writing invariant tests |
.claude/skills/foundry-testing/references/formal-verification.md | Halmos, Certora, symbolic exec | When proving correctness |
.claude/skills/foundry-testing/references/deployment-scripts.md | Script patterns, verification | When writing deploy scripts |
.claude/skills/foundry-testing/references/deployment-checklist.md | Pre-mainnet deployment steps | Before deploying to production |
.claude/skills/foundry-testing/references/gas-benchmarking.md | Snapshot, profiling, CI | When measuring gas performance |
.claude/skills/foundry-testing/references/sablier-conventions.md | Sablier-specific patterns | When working in Sablier repos |
| Type | Directory | Naming | Purpose |
|---|---|---|---|
| Integration | tests/integration/concrete/ | *.t.sol | BTT-based concrete tests |
| Fuzz | tests/integration/fuzz/ | *.t.sol | Property-based testing |
| Fork | tests/fork/ | *.t.sol | Mainnet state testing |
| Invariant | tests/invariant/ | Invariant*.t.sol | Stateful protocol properties |
| Scripts | scripts/solidity/ | *.s.sol | Deployment/initialization |
| Pattern | Usage |
|---|---|
test_RevertWhen_{Condition} | Revert on input |
test_RevertGiven_{State} | Revert on state |
test_When_{Condition} | Success path |
vm.expectEmit() then call functionexpectRevert_DelegateCall, expectRevert_Null)assertEq(actual, expected, "description")tests/mocks/*Good, *Reverting, *InvalidSelector, *ReentranttestFuzz_{FunctionName}_{Scenario}
_bound() is more efficient than vm.assume()// 1. Bound independent params first
cliffDuration = boundUint40(cliffDuration, 0, MAX - 1);
// 2. Bound dependent params based on constraints
totalDuration = boundUint40(totalDuration, cliffDuration + 1, MAX);
vm.createSelectFork("ethereum")deal() to give tokens to test usersassumeNoBlacklisted() for USDC/USDTforceApprove() for non-standard tokens (USDT)| Token | Issue | Solution |
|---|---|---|
| USDC/USDT | Blacklist | assumeNoBlacklisted() |
| USDT | Non-standard | forceApprove() |
| Fee-on-transfer | Balance diff | Check actual received amount |
tests/invariant/
├── handlers/ # State manipulation (call functions with bounded params)
├── stores/ # State tracking (record totals, IDs)
└── Invariant.t.sol
targetContract(address(handler))excludeSender(address(vault))BaseScript with broadcast modifierETH_FROM, MNEMONIC# Simulation
forge script scripts/Deploy.s.sol --sig "run(...)" ARGS --rpc-url $RPC
# Broadcast
forge script scripts/Deploy.s.sol --sig "run(...)" ARGS --rpc-url $RPC --broadcast --verify
# By type
forge test --match-path "tests/integration/concrete/**"
forge test --match-path "tests/fork/**"
forge test --match-contract Invariant_Test
# Specific test
forge test --match-test test_WhenCallerRecipient -vvvv
# Fuzz with more runs
forge test --match-test testFuzz_ --fuzz-runs 1000
# Coverage
forge coverage --report lcov
| Flag | Shows |
|---|---|
-v | Logs for failing tests |
-vv | Logs for all tests |
-vvv | Stack traces for failures |
-vvvv | Stack traces + setup traces |
-vvvvv | Full execution traces |
import { console2 } from "forge-std/console2.sol";
console2.log("value:", someValue);
console2.log("address:", someAddress);
console2.logBytes32(someBytes32);
# Trace specific failing test
forge test --match-test test_MyTest -vvvv
# Gas report for a test
forge test --match-test test_MyTest --gas-report
# Debug in interactive debugger
forge debug --debug tests/MyTest.t.sol --sig "test_MyTest()"
# Inspect storage layout
forge inspect MyContract storage-layout
vm.label(addr, "Recipient") for readable tracesconsole2.log before reverts--match-test--gas-report to spot unexpected costsvm.snapshot() / vm.revertTo() to isolate state changesDefaults/Constants - never hardcodetests/mocks/Modifiers.sol - centralize BTT path modifiersvm.label() for tracesvm.expectEmit() then callTest this skill with these prompts:
withdraw that expects Errors.Flow_Overdraw when amount exceeds
balance"deposit that bounds amount between 1 and type(uint128).max"deposit and withdraw functions"Security audit and code review for Solidity smart contracts. Trigger phrases - audit, check PR, security review, pre-audit preparation, vulnerability check, or when preparing code for external audit.
Write bulloak tree specifications (.tree files) for smart contract integration tests. Trigger phrases - write a tree, create test tree, BTT spec, bulloak tree, Branching Tree Technique, or when writing integration tests for contract functions.
Verify smart contracts on Etherscan, Routescan, and Blockscout block explorers. This skill should be used when the user asks to "verify contract", "verify on etherscan", "verify on blockscout", "verify on routescan", "verify on chain scan". Handles standard verification, Etherscan V2 API, Routescan, Blockscout verification, proxy patterns, and factory-created contracts.
Protocol domain knowledge - Lockup (vesting), Flow (streaming), Airdrops (merkle distribution). This skill provides context when implementing business logic, understanding protocol formulas, state transitions, or answering questions about how Sablier protocols work.
Write production-quality Solidity contracts. Trigger phrases - write contract, implement function, add feature, add error, gas optimization, event design, contract architecture, or when working in src/ directories.