{"owner":"foundry-rs","repo":"foundry","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Project Overview\n\nFoundry is a fast, portable, modular toolkit for Ethereum application development,\nwritten in Rust.\n\n- `forge`: build, test, fuzz, debug, lint, and deploy Solidity contracts\n- `cast`: command-line utilities for EVM contracts, transactions, and chain data\n- `anvil`: local Ethereum development node\n- `chisel`: Solidity REPL\n\nThe repository is a Cargo workspace. Core crates live under `crates/`, docs for\ncontributors live under `docs/dev/`, and Solidity fixtures and integration test\nprojects live under `testdata/`.\n\n## Commands\n\n```bash\ncargo build --workspace                               # Build the workspace\ncargo nextest run --workspace                         # Run tests\ncargo +nightly fmt --all                              # Format Rust code\ncargo +nightly fmt --all -- --check                   # Check Rust formatting\ncargo +nightly clippy --workspace --all-targets --all-features # Lint Rust code\ncargo deny check                                      # Check dependencies\ncargo shear                                           # Check unused dependencies\n```\n\nRust formatting uses nightly.\n\n## Architecture\n\n- `crates/forge`: Forge CLI and test/build workflows\n- `crates/cast`: Cast CLI commands\n- `crates/anvil`: local Ethereum node\n- `crates/chisel`: Solidity REPL\n- `crates/cheatcodes`: Forge cheatcode definitions and implementations\n- `crates/common`: shared CLI, shell, compile, and terminal utilities\n- `crates/config`: Foundry configuration\n- `crates/debugger`: debugger support\n- `crates/lint`: Solidity linter\n- `crates/script`: script execution support\n- `crates/verify`: contract verification support\n\nFoundry's EVM execution tooling is built around `revm`. Cheatcodes are calls to\nthe fixed cheatcode address and are dispatched through the cheatcode inspector.\nCustom network behavior for `anvil`, `forge`, and `cast` is implemented through\nthe EVM networks crate.\n\nFor symbolic execution work under `crates/evm/symbolic`, read\n`crates/evm/symbolic/AGENTS.md` before editing.\n\n## Testing\n\n- Add tests for code changes that fix behavior or add functionality.\n- Use focused unit tests for small pure logic.\n- Use integration tests for CLI behavior and larger workflows.\n- Tests that use forking must contain `fork` in their name.\n- Forge integration fixtures live under `testdata/`.\n- Lint rule tests live under `crates/lint/testdata/` with blessed `.stderr`\n  output.\n\nFor CLI and integration tests:\n\n- Put Forge CLI coverage under `crates/forge/tests/cli/` and Cast CLI coverage\n  under `crates/cast/tests/cli/`.\n- Use the existing `forgetest!`, `forgetest_init!`, and `casttest!` macros to\n  create isolated test projects and command handles.\n- Assert command output with snapbox helpers such as `assert_success()`,\n  `assert_failure()`, `stdout_eq(str![...])`, `stderr_eq(str![...])`, and\n  `assert_empty_stdout()`.\n- For JSON output, use `assert_json_stdout(...)` or `assert_json_stderr(...)`\n  so comparisons are parsed as JSON and unordered where appropriate.\n- Prefer full output snapshots with redactions over ad hoc `String::contains`\n  checks or manual `serde_json::Value` inspection.\n\nFor lint rules:\n\n- Add a Solidity test file under `crates/lint/testdata/`.\n- Use `//~WARN:` and `//~NOTE:` annotations for expected diagnostics.\n- Regenerate blessed output with `cargo bless-lints`.\n- Run lint UI tests with `cargo nextest run -p forge --test ui`.\n\nFor script work, keep the two execution phases separate: `ScriptArgs::execute`\nruns the script, while on-chain simulation only executes the collected\nbroadcastable transactions. `--resume` resumes publishing transactions; it does\nnot recreate the original `--broadcast` state.\n\nFor fuzz or invariant corpus coverage work, `forge test --showmap-out <DIR>`\nreplays persisted corpus entries and writes AFL `showmap`-style coverage files.\n\n## CLI Output\n\nFoundry CLIs follow a stdout/stderr contract:\n\n- stdout is the command's machine-readable primary result\n- stderr is for warnings, errors, progress, status text, prompts, and banners\n- `--json` changes stdout format, not channel cleanliness\n- `--quiet` suppresses diagnostics and progress, not the command result\n- verbosity flags such as `-vvv` must not change stdout content\n\nUse the `sh_*` macros from `foundry_common::io`:\n\n- `sh_println!` / `sh_print!`: primary stdout result only\n- `sh_status!`: status prose on stderr\n- `sh_progress!`: progress on stderr\n- `sh_warn!`: recoverable warnings on stderr\n- `sh_err!`: errors on stderr\n- `prompt!`: prompt on stderr and read from stdin\n\nDo not use `println!`, `print!`, `eprintln!`, or `eprint!`; workspace clippy\nconfiguration forbids them.\n\n## Configuration\n\nWhen adding or changing a `foundry.toml` setting:\n\n1. Define the field and its documentation in `crates/config`, including an\n   explicit default and any required serde behavior. Keep related settings in a\n   dedicated nested config type when they form a coherent section.\n2. Wire the setting through every command that consumes it. If a CLI flag can\n   override the setting, resolve precedence in one shared place and test config,\n   CLI, and combined behavior.\n3. Add focused config parsing and serialization tests. Update the `forge config`\n   and default-config snapshots when the serialized surface changes.\n4. For renamed or moved settings, preserve compatibility when practical and add\n   a targeted deprecation warning that points to the canonical key. Test aliases,\n   profiles, inheritance, environment variables, collisions, and malformed values\n   where those providers are affected.\n5. Document the setting in `foundry-rs/book` under\n   `src/pages/config/reference/`, including its section, type, default, environment\n   variable when supported, behavior, and a valid TOML example. Update the config\n   reference navigation and `default-config.mdx` in the same documentation PR.\n6. Keep CLI option text in the Rust clap definition; the book's CLI reference is\n   generated from command help and should not be edited by hand.\n\nUse the implementation, defaults, and tests as the source of truth. Do not merge\nnew user-facing configuration without the corresponding book update.\n\n## Cheatcodes\n\nWhen adding a cheatcode:\n\n1. Add the Solidity definition in `crates/cheatcodes/spec/src/vm.rs`.\n2. Implement the generated call type in `crates/cheatcodes/`.\n3. Update `spec::Cheatcodes::new` if `Vm` gained a struct, enum, error, or event.\n4. Run `cargo cheats` twice to update generated JSON assets.\n5. Add an integration test under `testdata/default/cheats/`.\n\nCheatcode functions and structs must be documented and function parameters must\nbe named.\n\n## Commit and PR Style\n\nDefault format is conventional commits:\n\n```text\ntype: description\ntype(scope): description\ntype(scope)!: breaking description\n```\n\nUse `feat`, `fix`, `perf`, `chore`, `docs`, `test`, or `refactor`. Check recent\n`git log` output before committing to match the repository's current style.\n\n- Use imperative mood.\n- Keep the description under 50 characters when practical.\n- Do not end the description with a period.\n- Include a body for performance changes, bug fixes, and complex changes.\n- For performance changes, include measurements.\n- PR titles should follow the same format as commit messages.\n\nPR descriptions should explain what changed and why in flowing prose. Link\nrelated issues and PRs when they exist. Include only real measurements, and do\nnot include validation/testing boilerplate such as \"Validated with\", \"Tested\nwith\", or command lists unless explicitly requested. Do not use templates,\nbullet lists, or long essays. When writing PR bodies from scripts, use a file or\nheredoc with real newlines; never pass escaped `\\n` sequences.\n\n### Changelog Entries\n\nEvery pull request must add or update at least one `.changelog/*.md` entry unless\na maintainer applies the `L-ignore` label. Add an entry by default; when a change\nshould not appear in release notes, such as a CI-only or repository-maintenance\nchange, call out that a maintainer must apply `L-ignore`.\n\nUse a descriptive, unique filename and the format documented in\n`.changelog/README.md`:\n\n```md\n---\nforge: minor\ncast: patch\n---\n\nAdded a Forge feature and fixed the related Cast behavior.\n```\n\nList every affected publishable workspace package by its actual Cargo package\nname and assign each a `major`, `minor`, or `patch` bump. Include a concise,\nnon-empty user-facing release note. Do not use unknown or aggregate package\nnames, leave the package mapping or note empty, or satisfy the requirement only\nby deleting an existing entry.\n\n### Performance PRs\n\nWhen drafting or updating a PR body for a performance-related change, benchmark\nthe feature branch against `master` or the user-specified base before writing the\nperformance claims.\n\n- Use the local benchmark runners under `benches/` unless the user explicitly\n  asks for GitHub Actions or the Derek/decofe automation.\n- Use `foundry-bench` when the claim is about elapsed time for a Foundry command\n  on an existing Solidity project: `forge build`, cached rebuilds, `forge test`,\n  fuzz-test replay, isolated tests, coverage, or focused symbolic tests.\n- For invariant or campaign-style benchmarking, use `foundry-scfuzzbench`; this\n  is the local equivalent of the `derek bench invariant`/`decofe bench\n  invariant` PR flow, which publishes a `scfuzzbench` event.\n- The local runners do not compare two local refs in one invocation. Run the\n  baseline and candidate separately, with identical benchmark inputs, timeout,\n  worker count, environment, target repository, and output schema.\n- For branch-vs-base PR comparisons, use the profiling profile\n  (`FOUNDRY_BENCH_LOCAL_BUILD_PROFILE=profiling`) rather than an ad hoc debug or\n  release build. Keep ordinary `foundry-bench --versions local` comparisons on\n  the default release distribution profile.\n- Include only benchmarks that exercise the changed path. Do not pad the PR body\n  with unrelated benchmark suites.\n- Report both wall-time results and domain counters when available, for example\n  solver queries, reported solver time, throughput, coverage relscore/relcov,\n  or invariant findings.\n- If results are neutral, noisy, or regress a secondary metric, state that\n  directly. Do not convert noise into a performance claim.\n- Keep the PR body short: one paragraph explaining the optimization and why it\n  is correct, followed by a `### Results` table.\n- Exact benchmark commands and result-table mechanics in `benches/README.md`.\n\n## Notes\n\n- Use `RUST_LOG=<filter>` for debugging CLI internals, for example\n  `RUST_LOG=forge` or `RUST_LOG=cast`.\n- Disclose AI assistance in PRs when used, per `CONTRIBUTING.md`.\n- Do not send spelling-only or grammar-only documentation PRs.\n- Keep release feature lists aligned between the root `Makefile` and release\n  workflows when changing published CLI feature surfaces.\n\n## Code Style\n\n- Comments end with periods (except URLs)\n- Files end with LF and trailing newline\n- Follow existing patterns\n- Never expose secrets\n\n### Rust\n\n- Put doc comments before attributes, always: `/// ...` comes before `#[derive]`, `#[inline]`, `#[cfg]`, and every other attribute.\n- Put module documentation at the top of the module file with inner doc comments (`//! ...`), not on the `mod` item in the parent module.\n- NEVER put imports inside functions unless required for `#[cfg(...)]` gating. All imports go at the top of the file.\n- Group all `use` imports together. Keep `pub use` imports in a separate group. For local module re-exports, write `mod x;` before `pub use x;`; for re-exporting another module or external crate, use `use x;`, then a blank line, then `pub use y;`, then a blank line before local `mod my_mod; pub use my_mod::*;`.\n- In `Cargo.toml`, generally group optional dependencies for a feature together. Put a comment immediately above the group containing only the feature name, for example `# jit`.\n- Prefer `let Some(x) = x else { return };` / `let Ok(x) = x else { return };` over `match x { Some(x) => x, _ => return }`.\n- Use `let ... else` only for a single early-exit guard. When multiple conditions or patterns gate the same block, prefer a combined `if let` / `let` chain instead of several sequential `let ... else` statements.\n- Use combined `if let` chains (`if let Some(x) = x && let Some(y) = y { ... }`) instead of nesting (`if let Some(x) = x { if let Some(y) = y { ... } }`).\n- In loops, prefer an `if let` chain around the loop body over multiple `let ... else { continue };` statements when the body only runs if all patterns match.\n- NEVER use `ref` / `ref mut` in patterns as the first resort. Always prefer borrowing the expression with `&` / `&mut` instead.\n- Avoid specifying type hints in variables unless absolutely necessary (e.g. `HashMap<_, Vec<_>>` for `x.entry(y).or_default().push(z)` where type inference won't work). Rely on the compiler.\n- When type hints are needed, prefer turbofish (`let x = Type::<X, Y>::new()`) over annotation (`let x: Type<X, Y> = Type::new()`).\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Project Overview\n\nFoundry is a fast, portable, modular toolkit for Ethereum application development,\nwritten in Rust.\n\n- `forge`: build, test, fuzz, debug, lint, and deploy Solidity contracts\n- `cast`: command-line utilities for EVM contracts, transactions, and chain data\n- `anvil`: local Ethereum development node\n- `chisel`: Solidity REPL\n\nThe repository is a Cargo workspace. Core crates live under `crates/`, docs for\ncontributors live under `docs/dev/`, and Solidity fixtures and integration test\nprojects live under `testdata/`.\n\n## Commands\n\n```bash\ncargo build --workspace                               # Build the workspace\ncargo nextest run --workspace                         # Run tests\ncargo +nightly fmt --all                              # Format Rust code\ncargo +nightly fmt --all -- --check                   # Check Rust formatting\ncargo +nightly clippy --workspace --all-targets --all-features # Lint Rust code\ncargo deny check                                      # Check dependencies\ncargo shear                                           # Check unused dependencies\n```\n\nRust formatting uses nightly.\n\n## Architecture\n\n- `crates/forge`: Forge CLI and test/build workflows\n- `crates/cast`: Cast CLI commands\n- `crates/anvil`: local Ethereum node\n- `crates/chisel`: Solidity REPL\n- `crates/cheatcodes`: Forge cheatcode definitions and implementations\n- `crates/common`: shared CLI, shell, compile, and terminal utilities\n- `crates/config`: Foundry configuration\n- `crates/debugger`: debugger support\n- `crates/lint`: Solidity linter\n- `crates/script`: script execution support\n- `crates/verify`: contract verification support\n\nFoundry's EVM execution tooling is built around `revm`. Cheatcodes are calls to\nthe fixed cheatcode address and are dispatched through the cheatcode inspector.\nCustom network behavior for `anvil`, `forge`, and `cast` is implemented through\nthe EVM networks crate.\n\nFor symbolic execution work under `crates/evm/symbolic`, read\n`crates/evm/symbolic/AGENTS.md` before editing.\n\n## Testing\n\n- Add tests for code changes that fix behavior or add functionality.\n- Use focused unit tests for small pure logic.\n- Use integration tests for CLI behavior and larger workflows.\n- Tests that use forking must contain `fork` in their name.\n- Forge integration fixtures live under `testdata/`.\n- Lint rule tests live under `crates/lint/testdata/` with blessed `.stderr`\n  output.\n\nFor CLI and integration tests:\n\n- Put Forge CLI coverage under `crates/forge/tests/cli/` and Cast CLI coverage\n  under `crates/cast/tests/cli/`.\n- Use the existing `forgetest!`, `forgetest_init!`, and `casttest!` macros to\n  create isolated test projects and command handles.\n- Assert command output with snapbox helpers such as `assert_success()`,\n  `assert_failure()`, `stdout_eq(str![...])`, `stderr_eq(str![...])`, and\n  `assert_empty_stdout()`.\n- For JSON output, use `assert_json_stdout(...)` or `assert_json_stderr(...)`\n  so comparisons are parsed as JSON and unordered where appropriate.\n- Prefer full output snapshots with redactions over ad hoc `String::contains`\n  checks or manual `serde_json::Value` inspection.\n\nFor lint rules:\n\n- Add a Solidity test file under `crates/lint/testdata/`.\n- Use `//~WARN:` and `//~NOTE:` annotations for expected diagnostics.\n- Regenerate blessed output with `cargo bless-lints`.\n- Run lint UI tests with `cargo nextest run -p forge --test ui`.\n\nFor script work, keep the two execution phases separate: `ScriptArgs::execute`\nruns the script, while on-chain simulation only executes the collected\nbroadcastable transactions. `--resume` resumes publishing transactions; it does\nnot recreate the original `--broadcast` state.\n\nFor fuzz or invariant corpus coverage work, `forge test --showmap-out <DIR>`\nreplays persisted corpus entries and writes AFL `showmap`-style coverage files.\n\n## CLI Output\n\nFoundry CLIs follow a stdout/stderr contract:\n\n- stdout is the command's machine-readable primary result\n- stderr is for warnings, errors, progress, status text, prompts, and banners\n- `--json` changes stdout format, not channel cleanliness\n- `--quiet` suppresses diagnostics and progress, not the command result\n- verbosity flags such as `-vvv` must not change stdout content\n\nUse the `sh_*` macros from `foundry_common::io`:\n\n- `sh_println!` / `sh_print!`: primary stdout result only\n- `sh_status!`: status prose on stderr\n- `sh_progress!`: progress on stderr\n- `sh_warn!`: recoverable warnings on stderr\n- `sh_err!`: errors on stderr\n- `prompt!`: prompt on stderr and read from stdin\n\nDo not use `println!`, `print!`, `eprintln!`, or `eprint!`; workspace clippy\nconfiguration forbids them.\n\n## Configuration\n\nWhen adding or changing a `foundry.toml` setting:\n\n1. Define the field and its documentation in `crates/config`, including an\n   explicit default and any required serde behavior. Keep related settings in a\n   dedicated nested config type when they form a coherent section.\n2. Wire the setting through every command that consumes it. If a CLI flag can\n   override the setting, resolve precedence in one shared place and test config,\n   CLI, and combined behavior.\n3. Add focused config parsing and serialization tests. Update the `forge config`\n   and default-config snapshots when the serialized surface changes.\n4. For renamed or moved settings, preserve compatibility when practical and add\n   a targeted deprecation warning that points to the canonical key. Test aliases,\n   profiles, inheritance, environment variables, collisions, and malformed values\n   where those providers are affected.\n5. Document the setting in `foundry-rs/book` under\n   `src/pages/config/reference/`, including its section, type, default, environment\n   variable when supported, behavior, and a valid TOML example. Update the config\n   reference navigation and `default-config.mdx` in the same documentation PR.\n6. Keep CLI option text in the Rust clap definition; the book's CLI reference is\n   generated from command help and should not be edited by hand.\n\nUse the implementation, defaults, and tests as the source of truth. Do not merge\nnew user-facing configuration without the corresponding book update.\n\n## Cheatcodes\n\nWhen adding a cheatcode:\n\n1. Add the Solidity definition in `crates/cheatcodes/spec/src/vm.rs`.\n2. Implement the generated call type in `crates/cheatcodes/`.\n3. Update `spec::Cheatcodes::new` if `Vm` gained a struct, enum, error, or event.\n4. Run `cargo cheats` twice to update generated JSON assets.\n5. Add an integration test under `testdata/default/cheats/`.\n\nCheatcode functions and structs must be documented and function parameters must\nbe named.\n\n## Commit and PR Style\n\nDefault format is conventional commits:\n\n```text\ntype: description\ntype(scope): description\ntype(scope)!: breaking description\n```\n\nUse `feat`, `fix`, `perf`, `chore`, `docs`, `test`, or `refactor`. Check recent\n`git log` output before committing to match the repository's current style.\n\n- Use imperative mood.\n- Keep the description under 50 characters when practical.\n- Do not end the description with a period.\n- Include a body for performance changes, bug fixes, and complex changes.\n- For performance changes, include measurements.\n- PR titles should follow the same format as commit messages.\n\nPR descriptions should explain what changed and why in flowing prose. Link\nrelated issues and PRs when they exist. Include only real measurements, and do\nnot include validation/testing boilerplate such as \"Validated with\", \"Tested\nwith\", or command lists unless explicitly requested. Do not use templates,\nbullet lists, or long essays. When writing PR bodies from scripts, use a file or\nheredoc with real newlines; never pass escaped `\\n` sequences.\n\n### Changelog Entries\n\nEvery pull request must add or update at least one `.changelog/*.md` entry unless\na maintainer applies the `L-ignore` label. Add an entry by default; when a change\nshould not appear in release notes, such as a CI-only or repository-maintenance\nchange, call out that a maintainer must apply `L-ignore`.\n\nUse a descriptive, unique filename and the format documented in\n`.changelog/README.md`:\n\n```md\n---\nforge: minor\ncast: patch\n---\n\nAdded a Forge feature and fixed the related Cast behavior.\n```\n\nList every affected publishable workspace package by its actual Cargo package\nname and assign each a `major`, `minor`, or `patch` bump. Include a concise,\nnon-empty user-facing release note. Do not use unknown or aggregate package\nnames, leave the package mapping or note empty, or satisfy the requirement only\nby deleting an existing entry.\n\n### Performance PRs\n\nWhen drafting or updating a PR body for a performance-related change, benchmark\nthe feature branch against `master` or the user-specified base before writing the\nperformance claims.\n\n- Use the local benchmark runners under `benches/` unless the user explicitly\n  asks for GitHub Actions or the Derek/decofe automation.\n- Use `foundry-bench` when the claim is about elapsed time for a Foundry command\n  on an existing Solidity project: `forge build`, cached rebuilds, `forge test`,\n  fuzz-test replay, isolated tests, coverage, or focused symbolic tests.\n- For invariant or campaign-style benchmarking, use `foundry-scfuzzbench`; this\n  is the local equivalent of the `derek bench invariant`/`decofe bench\n  invariant` PR flow, which publishes a `scfuzzbench` event.\n- The local runners do not compare two local refs in one invocation. Run the\n  baseline and candidate separately, with identical benchmark inputs, timeout,\n  worker count, environment, target repository, and output schema.\n- For branch-vs-base PR comparisons, use the profiling profile\n  (`FOUNDRY_BENCH_LOCAL_BUILD_PROFILE=profiling`) rather than an ad hoc debug or\n  release build. Keep ordinary `foundry-bench --versions local` comparisons on\n  the default release distribution profile.\n- Include only benchmarks that exercise the changed path. Do not pad the PR body\n  with unrelated benchmark suites.\n- Report both wall-time results and domain counters when available, for example\n  solver queries, reported solver time, throughput, coverage relscore/relcov,\n  or invariant findings.\n- If results are neutral, noisy, or regress a secondary metric, state that\n  directly. Do not convert noise into a performance claim.\n- Keep the PR body short: one paragraph explaining the optimization and why it\n  is correct, followed by a `### Results` table.\n- Exact benchmark commands and result-table mechanics in `benches/README.md`.\n\n## Notes\n\n- Use `RUST_LOG=<filter>` for debugging CLI internals, for example\n  `RUST_LOG=forge` or `RUST_LOG=cast`.\n- Disclose AI assistance in PRs when used, per `CONTRIBUTING.md`.\n- Do not send spelling-only or grammar-only documentation PRs.\n- Keep release feature lists aligned between the root `Makefile` and release\n  workflows when changing published CLI feature surfaces.\n\n## Code Style\n\n- Comments end with periods (except URLs)\n- Files end with LF and trailing newline\n- Follow existing patterns\n- Never expose secrets\n\n### Rust\n\n- Put doc comments before attributes, always: `/// ...` comes before `#[derive]`, `#[inline]`, `#[cfg]`, and every other attribute.\n- Put module documentation at the top of the module file with inner doc comments (`//! ...`), not on the `mod` item in the parent module.\n- NEVER put imports inside functions unless required for `#[cfg(...)]` gating. All imports go at the top of the file.\n- Group all `use` imports together. Keep `pub use` imports in a separate group. For local module re-exports, write `mod x;` before `pub use x;`; for re-exporting another module or external crate, use `use x;`, then a blank line, then `pub use y;`, then a blank line before local `mod my_mod; pub use my_mod::*;`.\n- In `Cargo.toml`, generally group optional dependencies for a feature together. Put a comment immediately above the group containing only the feature name, for example `# jit`.\n- Prefer `let Some(x) = x else { return };` / `let Ok(x) = x else { return };` over `match x { Some(x) => x, _ => return }`.\n- Use `let ... else` only for a single early-exit guard. When multiple conditions or patterns gate the same block, prefer a combined `if let` / `let` chain instead of several sequential `let ... else` statements.\n- Use combined `if let` chains (`if let Some(x) = x && let Some(y) = y { ... }`) instead of nesting (`if let Some(x) = x { if let Some(y) = y { ... } }`).\n- In loops, prefer an `if let` chain around the loop body over multiple `let ... else { continue };` statements when the body only runs if all patterns match.\n- NEVER use `ref` / `ref mut` in patterns as the first resort. Always prefer borrowing the expression with `&` / `&mut` instead.\n- Avoid specifying type hints in variables unless absolutely necessary (e.g. `HashMap<_, Vec<_>>` for `x.entry(y).or_default().push(z)` where type inference won't work). Rely on the compiler.\n- When type hints are needed, prefer turbofish (`let x = Type::<X, Y>::new()`) over annotation (`let x: Type<X, Y> = Type::new()`).\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Project Overview\n\nFoundry is a fast, portable, modular toolkit for Ethereum application development,\nwritten in Rust.\n\n- `forge`: build, test, fuzz, debug, lint, and deploy Solidity contracts\n- `cast`: command-line utilities for EVM contracts, transactions, and chain data\n- `anvil`: local Ethereum development node\n- `chisel`: Solidity REPL\n\nThe repository is a Cargo workspace. Core crates live under `crates/`, docs for\ncontributors live under `docs/dev/`, and Solidity fixtures and integration test\nprojects live under `testdata/`.\n\n## Commands\n\n```bash\ncargo build --workspace                               # Build the workspace\ncargo nextest run --workspace                         # Run tests\ncargo +nightly fmt --all                              # Format Rust code\ncargo +nightly fmt --all -- --check                   # Check Rust formatting\ncargo +nightly clippy --workspace --all-targets --all-features # Lint Rust code\ncargo deny check                                      # Check dependencies\ncargo shear                                           # Check unused dependencies\n```\n\nRust formatting uses nightly.\n\n## Architecture\n\n- `crates/forge`: Forge CLI and test/build workflows\n- `crates/cast`: Cast CLI commands\n- `crates/anvil`: local Ethereum node\n- `crates/chisel`: Solidity REPL\n- `crates/cheatcodes`: Forge cheatcode definitions and implementations\n- `crates/common`: shared CLI, shell, compile, and terminal utilities\n- `crates/config`: Foundry configuration\n- `crates/debugger`: debugger support\n- `crates/lint`: Solidity linter\n- `crates/script`: script execution support\n- `crates/verify`: contract verification support\n\nFoundry's EVM execution tooling is built around `revm`. Cheatcodes are calls to\nthe fixed cheatcode address and are dispatched through the cheatcode inspector.\nCustom network behavior for `anvil`, `forge`, and `cast` is implemented through\nthe EVM networks crate.\n\nFor symbolic execution work under `crates/evm/symbolic`, read\n`crates/evm/symbolic/AGENTS.md` before editing.\n\n## Testing\n\n- Add tests for code changes that fix behavior or add functionality.\n- Use focused unit tests for small pure logic.\n- Use integration tests for CLI behavior and larger workflows.\n- Tests that use forking must contain `fork` in their name.\n- Forge integration fixtures live under `testdata/`.\n- Lint rule tests live under `crates/lint/testdata/` with blessed `.stderr`\n  output.\n\nFor CLI and integration tests:\n\n- Put Forge CLI coverage under `crates/forge/tests/cli/` and Cast CLI coverage\n  under `crates/cast/tests/cli/`.\n- Use the existing `forgetest!`, `forgetest_init!`, and `casttest!` macros to\n  create isolated test projects and command handles.\n- Assert command output with snapbox helpers such as `assert_success()`,\n  `assert_failure()`, `stdout_eq(str![...])`, `stderr_eq(str![...])`, and\n  `assert_empty_stdout()`.\n- For JSON output, use `assert_json_stdout(...)` or `assert_json_stderr(...)`\n  so comparisons are parsed as JSON and unordered where appropriate.\n- Prefer full output snapshots with redactions over ad hoc `String::contains`\n  checks or manual `serde_json::Value` inspection.\n\nFor lint rules:\n\n- Add a Solidity test file under `crates/lint/testdata/`.\n- Use `//~WARN:` and `//~NOTE:` annotations for expected diagnostics.\n- Regenerate blessed output with `cargo bless-lints`.\n- Run lint UI tests with `cargo nextest run -p forge --test ui`.\n\nFor script work, keep the two execution phases separate: `ScriptArgs::execute`\nruns the script, while on-chain simulation only executes the collected\nbroadcastable transactions. `--resume` resumes publishing transactions; it does\nnot recreate the original `--broadcast` state.\n\nFor fuzz or invariant corpus coverage work, `forge test --showmap-out <DIR>`\nreplays persisted corpus entries and writes AFL `showmap`-style coverage files.\n\n## CLI Output\n\nFoundry CLIs follow a stdout/stderr contract:\n\n- stdout is the command's machine-readable primary result\n- stderr is for warnings, errors, progress, status text, prompts, and banners\n- `--json` changes stdout format, not channel cleanliness\n- `--quiet` suppresses diagnostics and progress, not the command result\n- verbosity flags such as `-vvv` must not change stdout content\n\nUse the `sh_*` macros from `foundry_common::io`:\n\n- `sh_println!` / `sh_print!`: primary stdout result only\n- `sh_status!`: status prose on stderr\n- `sh_progress!`: progress on stderr\n- `sh_warn!`: recoverable warnings on stderr\n- `sh_err!`: errors on stderr\n- `prompt!`: prompt on stderr and read from stdin\n\nDo not use `println!`, `print!`, `eprintln!`, or `eprint!`; workspace clippy\nconfiguration forbids them.\n\n## Configuration\n\nWhen adding or changing a `foundry.toml` setting:\n\n1. Define the field and its documentation in `crates/config`, including an\n   explicit default and any required serde behavior. Keep related settings in a\n   dedicated nested config type when they form a coherent section.\n2. Wire the setting through every command that consumes it. If a CLI flag can\n   override the setting, resolve precedence in one shared place and test config,\n   CLI, and combined behavior.\n3. Add focused config parsing and serialization tests. Update the `forge config`\n   and default-config snapshots when the serialized surface changes.\n4. For renamed or moved settings, preserve compatibility when practical and add\n   a targeted deprecation warning that points to the canonical key. Test aliases,\n   profiles, inheritance, environment variables, collisions, and malformed values\n   where those providers are affected.\n5. Document the setting in `foundry-rs/book` under\n   `src/pages/config/reference/`, including its section, type, default, environment\n   variable when supported, behavior, and a valid TOML example. Update the config\n   reference navigation and `default-config.mdx` in the same documentation PR.\n6. Keep CLI option text in the Rust clap definition; the book's CLI reference is\n   generated from command help and should not be edited by hand.\n\nUse the implementation, defaults, and tests as the source of truth. Do not merge\nnew user-facing configuration without the corresponding book update.\n\n## Cheatcodes\n\nWhen adding a cheatcode:\n\n1. Add the Solidity definition in `crates/cheatcodes/spec/src/vm.rs`.\n2. Implement the generated call type in `crates/cheatcodes/`.\n3. Update `spec::Cheatcodes::new` if `Vm` gained a struct, enum, error, or event.\n4. Run `cargo cheats` twice to update generated JSON assets.\n5. Add an integration test under `testdata/default/cheats/`.\n\nCheatcode functions and structs must be documented and function parameters must\nbe named.\n\n## Commit and PR Style\n\nDefault format is conventional commits:\n\n```text\ntype: description\ntype(scope): description\ntype(scope)!: breaking description\n```\n\nUse `feat`, `fix`, `perf`, `chore`, `docs`, `test`, or `refactor`. Check recent\n`git log` output before committing to match the repository's current style.\n\n- Use imperative mood.\n- Keep the description under 50 characters when practical.\n- Do not end the description with a period.\n- Include a body for performance changes, bug fixes, and complex changes.\n- For performance changes, include measurements.\n- PR titles should follow the same format as commit messages.\n\nPR descriptions should explain what changed and why in flowing prose. Link\nrelated issues and PRs when they exist. Include only real measurements, and do\nnot include validation/testing boilerplate such as \"Validated with\", \"Tested\nwith\", or command lists unless explicitly requested. Do not use templates,\nbullet lists, or long essays. When writing PR bodies from scripts, use a file or\nheredoc with real newlines; never pass escaped `\\n` sequences.\n\n### Changelog Entries\n\nEvery pull request must add or update at least one `.changelog/*.md` entry unless\na maintainer applies the `L-ignore` label. Add an entry by default; when a change\nshould not appear in release notes, such as a CI-only or repository-maintenance\nchange, call out that a maintainer must apply `L-ignore`.\n\nUse a descriptive, unique filename and the format documented in\n`.changelog/README.md`:\n\n```md\n---\nforge: minor\ncast: patch\n---\n\nAdded a Forge feature and fixed the related Cast behavior.\n```\n\nList every affected publishable workspace package by its actual Cargo package\nname and assign each a `major`, `minor`, or `patch` bump. Include a concise,\nnon-empty user-facing release note. Do not use unknown or aggregate package\nnames, leave the package mapping or note empty, or satisfy the requirement only\nby deleting an existing entry.\n\n### Performance PRs\n\nWhen drafting or updating a PR body for a performance-related change, benchmark\nthe feature branch against `master` or the user-specified base before writing the\nperformance claims.\n\n- Use the local benchmark runners under `benches/` unless the user explicitly\n  asks for GitHub Actions or the Derek/decofe automation.\n- Use `foundry-bench` when the claim is about elapsed time for a Foundry command\n  on an existing Solidity project: `forge build`, cached rebuilds, `forge test`,\n  fuzz-test replay, isolated tests, coverage, or focused symbolic tests.\n- For invariant or campaign-style benchmarking, use `foundry-scfuzzbench`; this\n  is the local equivalent of the `derek bench invariant`/`decofe bench\n  invariant` PR flow, which publishes a `scfuzzbench` event.\n- The local runners do not compare two local refs in one invocation. Run the\n  baseline and candidate separately, with identical benchmark inputs, timeout,\n  worker count, environment, target repository, and output schema.\n- For branch-vs-base PR comparisons, use the profiling profile\n  (`FOUNDRY_BENCH_LOCAL_BUILD_PROFILE=profiling`) rather than an ad hoc debug or\n  release build. Keep ordinary `foundry-bench --versions local` comparisons on\n  the default release distribution profile.\n- Include only benchmarks that exercise the changed path. Do not pad the PR body\n  with unrelated benchmark suites.\n- Report both wall-time results and domain counters when available, for example\n  solver queries, reported solver time, throughput, coverage relscore/relcov,\n  or invariant findings.\n- If results are neutral, noisy, or regress a secondary metric, state that\n  directly. Do not convert noise into a performance claim.\n- Keep the PR body short: one paragraph explaining the optimization and why it\n  is correct, followed by a `### Results` table.\n- Exact benchmark commands and result-table mechanics in `benches/README.md`.\n\n## Notes\n\n- Use `RUST_LOG=<filter>` for debugging CLI internals, for example\n  `RUST_LOG=forge` or `RUST_LOG=cast`.\n- Disclose AI assistance in PRs when used, per `CONTRIBUTING.md`.\n- Do not send spelling-only or grammar-only documentation PRs.\n- Keep release feature lists aligned between the root `Makefile` and release\n  workflows when changing published CLI feature surfaces.\n\n## Code Style\n\n- Comments end with periods (except URLs)\n- Files end with LF and trailing newline\n- Follow existing patterns\n- Never expose secrets\n\n### Rust\n\n- Put doc comments before attributes, always: `/// ...` comes before `#[derive]`, `#[inline]`, `#[cfg]`, and every other attribute.\n- Put module documentation at the top of the module file with inner doc comments (`//! ...`), not on the `mod` item in the parent module.\n- NEVER put imports inside functions unless required for `#[cfg(...)]` gating. All imports go at the top of the file.\n- Group all `use` imports together. Keep `pub use` imports in a separate group. For local module re-exports, write `mod x;` before `pub use x;`; for re-exporting another module or external crate, use `use x;`, then a blank line, then `pub use y;`, then a blank line before local `mod my_mod; pub use my_mod::*;`.\n- In `Cargo.toml`, generally group optional dependencies for a feature together. Put a comment immediately above the group containing only the feature name, for example `# jit`.\n- Prefer `let Some(x) = x else { return };` / `let Ok(x) = x else { return };` over `match x { Some(x) => x, _ => return }`.\n- Use `let ... else` only for a single early-exit guard. When multiple conditions or patterns gate the same block, prefer a combined `if let` / `let` chain instead of several sequential `let ... else` statements.\n- Use combined `if let` chains (`if let Some(x) = x && let Some(y) = y { ... }`) instead of nesting (`if let Some(x) = x { if let Some(y) = y { ... } }`).\n- In loops, prefer an `if let` chain around the loop body over multiple `let ... else { continue };` statements when the body only runs if all patterns match.\n- NEVER use `ref` / `ref mut` in patterns as the first resort. Always prefer borrowing the expression with `&` / `&mut` instead.\n- Avoid specifying type hints in variables unless absolutely necessary (e.g. `HashMap<_, Vec<_>>` for `x.entry(y).or_default().push(z)` where type inference won't work). Rely on the compiler.\n- When type hints are needed, prefer turbofish (`let x = Type::<X, Y>::new()`) over annotation (`let x: Type<X, Y> = Type::new()`).\n","category":"root","tokens":3271}]}