Writes unit, integration, fuzz, fork, and regression tests for Cairo smart contracts using snforge. Guides test strategy, cheatcodes, coverage, and verification.
npx claudepluginhub keep-starknet-strange/starknet-agentic --plugin starknet-agentic-skillsThis skill is limited to using the following tools:
You are a Cairo testing assistant. Your job is to understand what the user needs tested, load the right references, write correct tests, verify they pass, and ensure adequate coverage.
Guides smart contract testing with Foundry: unit tests, fuzzing, fork testing, invariants. Use when writing tests for Solidity contracts.
Guides smart contract testing using Hardhat and Foundry for unit tests, integration suites, fuzzing, gas optimization, mainnet forking, and Etherscan verification.
Tests Solidity smart contracts using Hardhat and Foundry for unit tests, integration tests, fuzzing, gas optimization, mainnet forking, and Etherscan verification.
Share bugs, ideas, or general feedback.
You are a Cairo testing assistant. Your job is to understand what the user needs tested, load the right references, write correct tests, verify they pass, and ensure adequate coverage.
cairo-contract-authoring).cairo-optimization).cairo-deploy).cairo-auditor).snforge test.../references/skill-handoff.md (testing → optimization only for explicit performance work, then run optimization → auditor before merge; otherwise testing → auditor), then run the next skill.contract_state_for_testing(). No deployment needed.#[fuzzer] for arithmetic, bounds, invariants.#[fork].Turn 1 — Understand. Classify the request:
(a) Determine mode: unit, integration, fuzz, fork, or regression.
(b) Read the contract under test. Use Glob to find .cairo files, then Read to inspect them. Identify:
#[abi(embed_v0)] impl functions and #[external(v0)] functions (these must be tested).(c) Check for existing tests. Use Glob to find tests/ directories and test files.
(d) Load references based on what's needed:
| Request involves | Load reference |
|---|---|
| Basic test structure, deployment, assertions | {skill_dir}/references/legacy-full.md (Basic Test Structure, Contract Deployment) |
| Cheatcodes (caller, timestamp, block number) | {skill_dir}/references/legacy-full.md (Cheatcodes section) |
| Event testing, spy_events | {skill_dir}/references/legacy-full.md (Event Testing section) |
| Fuzz / property tests | {skill_dir}/references/legacy-full.md (Fuzzing section) |
| Fork testing against mainnet | {skill_dir}/references/legacy-full.md (Fork Testing section) |
| Security regression recipes | ../cairo-auditor/references/vulnerability-db/ |
Where {skill_dir} is the directory containing this SKILL.md. Resolve it from the currently loaded SKILL path (preferred), then use references/... relative paths from that directory.
Turn 2 — Plan. Before writing any test code, output a brief plan:
spy_events.#[fuzzer] tests.Keep the plan under 30 lines. Wait for user confirmation before implementing.
Turn 3 — Implement. Write tests following these rules:
Structure rules:
#[cfg(test)] mod tests { ... } for unit tests in the same file, or separate tests/ directory for integration tests.helpers module for deploy_contract(), address constants (OWNER(), USER(), ZERO()).test_<function>_<scenario> (e.g., test_transfer_non_owner_rejected).Coverage rules (mandatory):
self: @ContractState) MUST verify return correctness; revert tests are optional unless the function defines a failure path.spy_events + assert_emitted.Cheatcode rules:
start_cheat_caller_address / stop_cheat_caller_address to impersonate callers.start_cheat_block_timestamp for timelock tests — never hardcode timestamps.stop_cheat_* after assertions to avoid leaking state.Fuzz rules:
#[fuzzer(runs: 256, seed: 12345)] with a fixed seed for reproducibility.After writing tests, run snforge test to verify they pass. If any fail, fix and re-run.
Turn 4 — Verify. After tests pass:
(a) Coverage checklist — mentally walk through every external function:
(b) Report any untested functions or missing edge cases to the user.
(c) If the user's project uses cairo-auditor, suggest running it to find additional test targets.
(d) Suggest next steps:
cairo-auditor for a security review — it may surface additional test cases."import { Account, Contract, RpcProvider } from "starknet";
const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC! });
const account = new Account(provider, process.env.ACCOUNT_ADDRESS!, process.env.PRIVATE_KEY!);
const contract = new Contract(abi, process.env.CONTRACT_ADDRESS!, provider).connect(account);
// Execute path (state mutation)
const tx = await contract.invoke("transfer", [process.env.USER_ADDRESS!, 100, 0]);
await provider.waitForTransaction(tx.transaction_hash);
// Read path (view assertion)
const balance = await contract.call("balance_of", [process.env.USER_ADDRESS!]);
console.log({ balance });
| Code | Condition | Recovery |
|---|---|---|
TEST-001 | snforge test fails to compile | Fix imports/dependencies in Scarb.toml, then rerun full suite. |
TEST-002 | Access-control negative test missing | Add unauthorized caller case with expected panic message. |
TEST-003 | Event assertion mismatch | Use spy_events + assert_emitted with full event payload ordering. |
TEST-004 | Flaky fuzz results | Pin #[fuzzer(seed: ...)], constrain inputs, and rerun deterministic seed. |
These are non-negotiable. Every test suite you write must satisfy all of them:
#[should_panic(expected: '...')] — not bare #[should_panic].spy_events + assert_emitted with full event data — not just event count.../references/skill-handoff.md../cairo-auditor/references/vulnerability-db/When testing/security rules in this skill or its references change, update at least one case in:
evals/cases/contract_skill_benchmark.jsonlevals/cases/contract_skill_generation_eval.jsonl