Foundry v1.8.0
Foundry v1.8.0 ships an opt-in preview of native symbolic testing, mutation testing, and major fuzzing and invariant improvements, while making isolate mode and dynamic test linking the defaults. It also adds first-class Monad support, embeds the Solar language server in Forge, and delivers broad performance improvements across Anvil, Forge, Cast, and the debugger. This release also ships the Rust foundryup, expands forge lint with a large set of security and gas detectors, and makes JSON output and stdout/stderr behavior more predictable across Forge and Cast.
Highlights
Testing & Fuzzing
Testing is the main theme of v1.8.0. The release expands the ways Forge can find failures, make them reproducible, and turn them into smaller actionable counterexamples.
- Native symbolic testing is available as an opt-in preview through
forge test --symbolic, using a local solver (Z3 by default) (#14796). The preview supports KZG precompile witnesses,ADDMOD/MULMOD, CancunSELFDESTRUCTsemantics, selector pruning, deploy-code modeling, and byte-preserving solving (#15157, #15172, #15179, #15180, #15374). Symbolic failures can be exported as JSON and replayable counterexample artifacts, minimized for single-call and stateful tests, seeded into fuzz corpora, and emitted as Solidity regression tests with--emit-regression(#15139, #15217, #15325, #15288, #15335, #15354, #15563). A passing result is scoped to the modeled semantics and configured bounds; unsupported or timed-out paths are reported as incomplete. - Mutation testing is now available through
forge test --mutate, giving test suites a direct way to check whether assertions actually catch behavioral changes (#13091). The cycle also added mutation compiler overrides and fixed dynamic linking, Windows source-path normalization, and misleading score reporting while the feature was hardened (#15284, #15105, #15044, #15104). - Assembly robustness testing is available through
forge test --brutalize. It rewrites a temporary workspace to dirty unused high bits and scratch memory and to misalign the free-memory pointer, exposing assumptions that normal zeroed and aligned memory can hide (#13342). - Fuzzer improvements cover invariant corpus seeding from observed calls, constant folding for common Solidity expressions, comparison-log sampling, configurable ensemble defaults, safer enum input generation, AFL
showmap-style replay, collision-free EVM edge coverage, bounded replay output, campaign sharding, per-test-contract grouping, lower campaign memory retention, and cheaper metric and log decoding (#15220, #15189, #15234, #15235, #15375, #14675, #14853, #14801, #15279, #15414, #15412, #14989, #14844, #15047, #15070, #15057, #15372, #15282). Newforge fuzzcommands can run selected fuzz and invariant tests, and replay, inspect, or minimize persisted cases directly from the CLI (#14522, #15227, #15517). --isolateis now the default for Forge tests, backed by compatibility fixes for cheatcodes, state diffs,SELFDESTRUCT, reverted creates, and the newvm.isIsolateMode()runtime check (#15226, #14493, #15382, #15385, #14637, #15411).
Security Lints
forge lint gained a broad set of security, correctness, and gas detectors, with project-wide analysis support and nearly complete Slither/Aderyn parity.
Notable additions include:
arbitrary-send-eth,arbitrary-send-erc20, andarbitrary-send-erc20-permit(#14943, #14677, #15037).reentrancy-eth,reentrancy-no-eth, andreentrancy-events(#14970, #15000, #14882).controlled-delegatecall,delegatecall-loop,calls-loop, andreturn-bomb(#15046, #14752, #14778, #14793).missing-events-access-control,missing-events-arithmetic,missing-zero-check, andevent-fields(#14954, #14907, #14460, #14751).incorrect-modifier,incorrect-exp,incorrect-strict-equality,type-based-tautology, andtautological-compare(#15201, #15213, #14749, #14697, #15203).
Beyond analysis, v1.8 hardens secret and filesystem handling. Signing and key cheatcodes redact private material and unsafe nonces from traces (#15921, #15922, #15923); Anvil redacts credentials and API keys from fork endpoints (#16223); sensitive script caches and saved vanity-wallet files use owner-only permissions on Unix (#16234, #16163); and keystore names can no longer escape their account directory (#16237). Existing logs and previously written files are not retroactively sanitized or re-permissioned and should still be treated as sensitive. Foundry also emits non-blocking warnings on stderr before loading project .env files or running configured local Solc or Vyper executables (#16113, #16343).
Solar LSP
Forge now includes an embedded Solar language server through forge lsp, so Solidity projects can use Solar-powered editor features with Foundry project configuration and remappings without installing a separate language-server binary (#16254). The Solar binary is also included in Foundry releases and installed through foundryup, supporting direct Solar workflows (#15611, #15693).
Monad
Foundry now has first-class Monad execution support across Forge, Anvil, Cast, Chisel, traces, and cheatcodes. Users can select it through --network monad, network-qualified hardfork configuration, and Monad-aware local or forked execution (#15343). MonadTen support adds MIP-8 page-based storage accounting and makes MonadTen the default for local Monad execution while preserving hardfork-aware behavior for historical and live forks (#16352).
Tempo
Compared with v1.7.1, Foundry v1.8 adds Tempo hardfork compatibility through T10, wallet sessions, receive-policy tooling, richer trace and debugger decoding, and broader Forge, Cast, and Anvil integration.
- Wallet sessions and access-key flows now cover Cast transaction commands, batch sends, Forge scripts, policy commands, session create/revoke flows, non-EOA
KeyAuthorizationsigning, andcast keychain doctor(#15075, #15081, #15085, #15096, #14916, #14978, #14996, #14743, #14766). - Receive-policy and fee-token tooling landed across Cast and the shared provider stack, including receive-policy commands, T6 guards, resolved fee-token display, and on-chain fee-token symbol resolution (#15195, #15239, #15130, #15158, #15161).
- T5/T6 includes T5 payment lane classification, implicit approval behavior and cheatcodes, channel reserve precompile support, T6 admin access-key authorization tooling, receive-policy receipt decoding, and local regression coverage (#15051, #15022, #15036, #15193, #15280, #15129, #15222, #15346).
- Anvil and execution fixes cover Tempo fork coinbase selection, T5 hardfork selection, nonce lanes, valid-after checks, create expiry handling, and latest hardfork defaults in tests (#14964, #14997, #14896, #14469, #14912, #14850).
- Trace and debugger support now decodes Tempo T5 surfaces and shows chain-aware precompile clues for Tempo-specific debugging (#15032, #15383).
Distribution
The separately released Rust foundryup is now the default implementation, with the legacy Bash launcher providing the transition path for existing installations (#15498, #16359). Alongside the migration, release resolution was hardened to avoid GitHub API rate limits, skip unready nightly releases, preserve --path symlinks, create missing binary directories before activation, and mirror tag resolution consistently between install and use flows (#15337, #15148, #15356, #15370, #14908, #14968, #14611).
Debugger and TUI
The debugger gained a shared TUI foundation, non-interactive fallback handling, layout selection, opcode search, storage access views and source-level storage labels, scoped variables, stack-word previews, gas stats, goto-PC support, and better precompile hints (#14710, #14720, #14725, #14780, #15171, #15211, #15218, #15141, #15140, #15100, #15049, #15379, #15383, #16246).
Forge can also emit EVM execution profiles for Speedscope via --evm-profile (#15394).
Performance
Performance improved across the toolchain, with the largest concentrated passes in Anvil and Forge.
- Anvil now mines blocks more efficiently, keeps long-chain mining stable, avoids unnecessary block and receipt conversions, and accelerates block and transaction receipt queries and fee-history reward calculations (#15739, #15715, #16063, #16079, #16078, #16245).
- Forge and EVM execution speed up filtered tests and
test --list, linting, documentation and binding generation, selectors and inspection, path-filtered coverage, bytecode verification, forked scripts, gas reports, and clone compilation, while reducing per-opcode inspector overhead (#15703, #15595, #15697, #15621, #15627, #15624, #15622, #15936, #15791, #16007, #15948, #16158, #16129, #16367). - Cast and the debugger speed up read-only commands, transaction construction, local interface generation, trace artifact matching, block lookup, repeated storage scans, and large opcode views (#15754, #15912, #15620, #15970, #16174, #15771, #16289, #16293).
PR-local workloads illustrate the size of some concentrated wins: eth_getBlockReceipts on a synthetic 10,000-transaction block fell from 17.1 seconds to 47.7 milliseconds (about 358x faster) (#16063); a batched 2,000-transaction receipt workload fell from 3.77 seconds to 300 milliseconds (12.55x faster) (#16245); and a cached Solady gas-report run fell from 23.0 seconds to 18.6 seconds while peak memory dropped from 3.08 GB to 1.37 GB (#16158). These are workload-specific measurements rather than whole-suite averages.
More Predictable JSON and Output Channels
Foundry continued the stdout/stderr and JSON-output cleanup started in earlier releases. Many Cast --json paths now use versioned envelopes more consistently, forge test --json-file <PATH> can write machine-readable test results to a separate file, and many commands moved prose and status text off stdout (#14716, #14727, #14986, #15021, #16004).
Breaking / Behavior Changes
Isolate Mode Is the Default
Forge tests now run in isolate mode by default (#15226). Each top-level call runs in a separate transaction and EVM context, making results less dependent on accidental state shared across calls.
The default flip landed after a series of compatibility fixes and hot fixes that made isolate mode viable for real projects:
vm.fee,vm.txGasPrice, andvm.blobhashesnow work under isolate mode (#14493).CREATEaddresses andCreatedLocalstate are preserved correctly across reverted isolated flows, includingSELFDESTRUCTcases (#14637, #15385).- State-diff recording no longer warms slots or recorded cold accesses while recording, preserving cold-access semantics (#15382, #15404).
- Invariant and fuzz replay paths gained follow-up fixes around persisted corpus entries and replay failure output (#15349, #15414).
vm.isIsolateMode()lets tests and helpers detect the effective isolation mode at runtime (#15411).
Projects with tests that intentionally depend on non-isolated behavior can use forge test --no-isolate or set isolate = false in their Foundry profile. The default can change gas snapshots, exact traces and gas costs, and CREATE-derived addresses.
Dynamic Test Linking Is the Default
Dynamic test linking is now enabled by default to avoid unnecessary recompilation and speed up common Forge workflows (#14718). Projects that encounter incompatibilities can use --no-dynamic-test-linking or set dynamic_test_linking = false.
Other Behavior Changes
- Compatible boolean invariant functions in the same contract now share one contract-level campaign and corpus, while failures are still reported per predicate; optimization invariants remain separate (#12587, #14844). Use
--match-testor separate contracts when independent campaigns are required. - The deprecated
forge generatecommand was removed (#16242). It only produced a basic test scaffold; create or scaffold those test files through another workflow. - No new versions of the existing
@foundry-rs/*packages will be published to npm; previously published versions remain available (#14811). Usefoundryupor the GitHub release binaries for current releases. - With no explicit severity filter,
forge lintnow includes all severities, including Info and, where applicable, Gas and CodeSize (#15331). To restore the earlier filter, set[lint] severity = ["high", "medium", "low"]. - Cast integer JSON serialization now follows the declared ABI type rather than whether each runtime value fits in 64 bits, making arrays consistent but changing some existing JSON values (#14824).
Upgrade Notes
- Review test suites and snapshots under the new isolate and dynamic-linking defaults. Use
--no-isolateand--no-dynamic-test-linking, or their corresponding profile settings, only where the previous behavior is required. - Remove automation that invokes
forge generate; the command no longer exists. - If you parse Forge or Cast output, recheck each command contract: many commands now keep structured data on stdout and diagnostics on stderr, and Cast integer JSON now follows declared ABI types.
- New and rewritten sensitive cache files receive stricter permissions, but existing logs and files are not retroactively sanitized or re-permissioned.
- If you install through
foundryup, the separately released Rust implementation is now the default implementation for this release.
Benchmarks
Live dashboard: getfoundry.sh/benchmarks
The final v1.8.0 benchmark snapshot compares v1.7.1 with v1.8.0 in matched modes: dynamic test linking is disabled for both sides, and isolated tests are reported separately. Across the tracked repositories, aggregate wall time improved by 18.4% for tests, 19.1% for fuzzing, 18.0% for isolated tests, 43.2% for cached builds, and 12.8% for coverage. Uncached builds were effectively neutral at +0.3%. Aave improved in every displayed category, including 19.0% for tests, 19.4% for fuzzing, 18.1% for isolated tests, and 15.7% for coverage.
Other Notable Changes
Cast and Cheatcodes
cast eventscan fetch and decode events from transaction receipts or filtered log queries, using explorer ABIs and signature lookup when available and falling back to raw logs (#16238). Canonical fallback decoding now rejects ambiguous indexed layouts instead of returning misleading values (#16370).- Packaged Apple Silicon macOS releases can enroll and use Touch ID-backed encrypted keystores (#15995).
- New and stabilized cheatcodes cover secp256k1 point arithmetic,
vm.expectDelegateCall, typed FFI results throughvm.ffiUint,vm.ffiString, andvm.ffiBytes, EVM-error matching invm.expectRevert, and concrete and symbolic storage hooks (#16160, #16192, #16287, #16294, #15954, #15976, #16286).
Forge, Config, and Compilation
- All Foundry binaries accept a global
--profile <PROFILE>, overridingFOUNDRY_PROFILE(#15831). forge script --confirmations <N>waits for the requested confirmation depth before finishing or verifying (#15947).forge fmt --nearestresolves the nearestfoundry.tomlfor each file in multi-project repositories (#16064).forge build --lockedprovides an optional strict CI gate forfoundry.lockand Git-submodule consistency; ordinary builds remain unchanged (#16048).forge inspectcan print contract artifact JSON (#15242).vm.getCodecan specify the compilation profile (#13191).[profile.<name>.coverage]config sections are supported (#14599).- Contract size limits are configurable (#14761).
- Solidity
--experimentalis supported through config (#15177). - Extended Vyper settings are exposed (#14739).
forge fmtpreserves indentation for uninitialized state variables withoverrideattributes (#15153).- Forge scripts now invalidate fork-cache entries after state-mutating
vm.rpcandvm.rpcJsoncalls, fixing stale-state broadcast replays (#15507).
Verification
forge verify-contractcan submit to Etherscan and Sourcify in one go (#15124).- Verification accepts SPDX identifiers and Etherscan license types (#15162, #14975).
- Bytecode verification fixes cover canonical source paths, fork chain IDs, full-project compilation for path targets, and Sourcify fallback behavior (#15417, #15378, #15475, #14765).
Forge Doc and Chisel
forge docwas migrated from Solang to Solar and Vocs (#14447, #14568).- Chisel was migrated to Solar and now dispatches by EVM network (#14532, #14813).
- Chisel can reuse the previous result through
$_and inspect value-producing inline assembly expressions (#16244, #16310).
Network and EVM Support
- EIP-4788 beacon roots and EIP-2935 history storage are supported (#15371, #15406).
- Amsterdam hardfork mapping was added and Osaka remains the default (#14683).
- Optimism dependencies are now feature-gated across the workspace, while official release and nightly assets retain OP Stack support alongside Monad (#14572, #14577, #14581, #14593, #14596, #14600, #16186).
Anvil
Anvil gained a large RPC-compatibility pass:
- New RPC support for
eth_baseFee,eth_getHeaderByNumber,eth_getHeaderByHash,eth_pendingTransactions,eth_resend,txpool_contentFrom, receipt subscriptions, syncing subscriptions, create-access-list overrides, and access-list results for reverting calls (#15419, #15420, #15422, #15423, #15136, #15421, #15428, #15427, #15425, #14569). - Debug RPC additions for raw receipts, clearing the txpool, modified accounts by number, and freeing OS memory (#15433, #15429, #15468, #15458).
- New call-bundle and tracing APIs include
eth_callMany,eth_callBundle,trace_call,trace_callMany,trace_rawTransaction,trace_replayTransaction,trace_get,debug_traceBlock, anddebug_executionWitness(#15437, #15691, #15443, #15446, #15445, #15436, #15444, #15435, #16185). - Safer state loading, block hash cache restoration, genesis number handling, transaction pooling, and numeric RPC parsing (#14624, #15167, #14488, #14891, #14650, #14658).
anvil --network tempoincludes a built-in fee payer, configurable through--tempo.fee-payer, for local sponsored-transaction flows (#16278).--fund-accounts, default JS tracer support, and better tracer config compatibility (#14392, #14745, #15199).
Full Changelog
Contributors (82)
- Improve CI action (#14484) by @grandizzy
- fix(config): warn instead of erroring on unknown FOUNDRY_PROFILE (#14486) by @zerosnacks
- fix(anvil): pre-check Tempo valid_after before execution (#14469) by @Perico-perica46
- feat(lint): add missing-zero-check (#14460) by @stevencartavia
- chore: bump Tempo deps + test
tempo_forkSchedule(#14485) by @0xrusowsky - fix(anvil): miner forced-tx deadlock (#14453) by @isagi-y22
- feat(doc): migrate from solang to solar (#14447) by @mablr
- fix(cheatcodes): fix solc 0.8.35 error keyword warning (#14509) by @figtracer
- chore: update codeowners (#14529) by @onbjerg
- test(fmt): cover erc7201 layout formatting (#14519) by @decofe
- perf(forge): avoid unnecessary gas_snapshots clones (#13969) by @ArshLabs
- fix(cli): fix jsonwebtoken panic (#14562) by @pepyakin
- perf: short-circuit find_by_name_or_identifier instead of full collect (#14514) by @cuiweixie
- fix(evm): query
state_snapshot.storageinForkDbStateSnapshot::storage_ref(#14007) by @gutonosa - fix(cheatcodes): transfer value for payable mock calls (#14547) by @srdtrk
- fix(anvil): classify EVM halts as transaction rejections (#14592) by @mmv08
- fix(forge):
--fuzz-seedparameter is not effective inforge coverage(#14610) by @wtdcode - fix(ci): keep no-default builds free of op deps (#14612) by @emmajam
- feat(lint): add tx-origin detector (#14589) by @vikions
- fix(anvil): respect non-zero genesis block in Otterscan APIs (#14490) by @AissataF
- fix(anvil): abort node tasks on handle drop (#14636) by @mattsse
- feat(anvil): add --fund-accounts CLI flag (#14392) by @exp0nge
- fix(anvil): saturate
mintwhen parsing OP deposit txs (#14652) by @DanielBoye - docs(lint): fix duplicated "use" in lintrules guide (#14701) by @abhicris
- fix(fmt): correct indentation of named args nested inside chained calls (#13367) by @Himess
- fix(anvil): use configured epoch slots for block tags (#14714) by @haythemsellami
- fix(traces): prefer contract ABI for decoding (#14788) by @DaniPopes
- feat(lint): add delegatecall-loop lint (#14752) by @0xKarl98
- fix(anvil): ignore nonzero Tempo nonce lanes (#14502) by @solanaXpeter
- fix(anvil): keep chain-id inferred network in node config (#14833) by @esorense
- anvil: stop masking gas estimation errors in send paths (#14679) by @ralme1da
- fix(forge): resolve Tempo expiry for creates (#14912) by @nivanovvv
- feat: add configurable collision-free EVM edge coverage (#14853) by @0xalpharush
- fix(foundryup): create bin dir before activating version (#14968) by @BROCCOLO1D
- fix(tui): always restore terminal state during panic unwinding (#14965) by @bravesasha
- fix(traces): retry Cloudflare blocks instead of aborting identification (#14981) by @0xMars42
- feat(forge): mutation testing (#13091) by @gakonst
- feat(forge): add
[profile.<name>.coverage]config section (#14599) by @ccashwell - fix(forge): preserve debug traces when setUp reverts (#14390) by @IrshadKohl51
- Use TUI fallback for debugger in non-interactive mode (#14780) by @cmende
- fix(anvil): handle zero prune history safely (#14307) by @mk0walsk
- fix(anvil): consistent revert data format between eth_call and eth_estimateGas (#13547) by @FredPhilipy
- ci: add
derek benchtrigger (#15138) by @kuyziss - fix(script): honour --code-size-limit CLI flag (#15170) by @shapeshed
- fix(chisel): remove unused
latestvariable in next_cached_session (#13923) by @strmfos - fix(verify): print Sourcify job UI URL instead of status API URL on submission (#15210) by @manuelwedler
- fix: correct typos and grammar in doc comments (#13845) by @alexchenai
- anvil: add help description for --mixed-mining flag (#13871) by @ParthSinghPS
- fix: add support for
--jwt-secretin cast--curl(#15160) by @LeTamanoir - feat(lint): add non-reentrant-not-first detector (#15248) by @Osraka
- feat(lint): add require-revert-in-loop detector (#15236) by @Berektassuly
- feat(verify): accept SPDX identifiers for --license-type (#15162) by @maksim-romanov
- fix(cast): consistent serialization of Uint/Ints depending on actual type (#14824) by @0xferrous
- feat(script): auto-detect sender address from keystore without --sender flag (#13869) by @intelliDean
- fix(cli): avoid panic on invalid remappings env and validate config path (#13660) by @edgarr1986
- Implement EIP 4788 (#15371) by @tskoyo
- fix(corpus): skip unreadable corpus files instead of failing the campaign (#15276) by @mark0-cn
- feat(cli): allow soldeer to update the logging level (#13485) by @beeb
- feat(config): support solc --via-ssa-cfg (#15501) by @Amxx
- chore(forge/assets): update workflows (#15560) by @StackOverflowExcept1on
- fix(primitives): use proper JSON serialization for deposit tx fields (#13476) by @dizer-ti
- fix(forge): allow verify-bytecode to run without a block explorer (#15142) by @PrazwalR
- fix(fmt): dropped statements for single-line nested if statements (#13560) by @quangloc99
- feat(forge): add coverage attribution report (#14511) by @smartcontracts
- feat(anvil): add anvil_setNextBlockPrevRandao (#15644) by @ritzdorf
- feat: print optional opcodes in forge test (#14843) by @jaimebarrancos
- fix(doc): match inherited params with underscore-wrapped names (#15238) by @flag4table
- fix(mutation): prune equivalent bounds (#15942) by @gretzke
- fix(cast): reject malformed vanity wallet files (#15978) by @grandpig
- chore(cast): upgrade evmole to 0.9.3 (#15985) by @cdump
- fix(cast): accept 0x-prefixed vanity patterns (#15994) by @racequite
- fix(anvil): return complete eth_feeHistory when the cache lags the chain head (#15128) by @satyakwok
- feature(forge): support transient storage inspection (#16062) by @kuzminxyz
- fix(cast): detect uppercase numeric prefixes (#16070) by @rappie
- feat(cast): add Touch ID enrollment (#15995) by @dadadave80
- fix(cast): secure vanity wallet permissions (#16163) by @questfever
- fix(coverage): report file-level (free) functions (#16098) by @zexoverz
- fix(traces): decode P256VERIFY precompile calls (#15972) by @HwanHeo
- fix(wallet): reject BIP32 paths that overflow the harden bit (#16096) by @SashaMIT
- fix(cast): reject impossible to match vanity addresses (#16230) by @siosw
- refactor(verify): drop the unreachable unknown optimizer runs branch (#16066) by @mkzung
- fix(common): classify OpenChain 5xx responses as connectivity failures (#16258) by @zloglevel