Skip to content

feat(invariant): assert all invariants on continuous_run (merge upstream #12587)#1

Merged
aviggiano merged 90 commits intomasterfrom
aviggiano-pr-12587
Feb 18, 2026
Merged

feat(invariant): assert all invariants on continuous_run (merge upstream #12587)#1
aviggiano merged 90 commits intomasterfrom
aviggiano-pr-12587

Conversation

@aviggiano
Copy link
Copy Markdown
Owner

This ports upstream PR foundry-rs#12587 onto aviggiano/master.

grandizzy and others added 30 commits November 17, 2025 18:33
…th comments (foundry-rs#13319)

Co-authored-by: onbjerg <onbjerg@users.noreply.github.com>
…xs tracing (foundry-rs#13098)

Co-authored-by: onbjerg <onbjerg@users.noreply.github.com>
…s#13293)

Co-authored-by: onbjerg <onbjerg@users.noreply.github.com>
…undry-rs#13318)

* fix(config): handle vyper section with skip_serializing_if fields

The vyper config section uses skip_serializing_if = Option::is_none on all
fields, causing the default serialization to produce an empty dict. This led to
all vyper keys being flagged as unknown.

Add explicit VYPER_KEYS constant and special-case the vyper section in
collect_standalone_section_warnings to use these known keys instead of
deriving them from the (empty) default serialization.

Fixes foundry-rs#13316

* test(config): add regression tests for vyper config warnings

Tests for foundry-rs#13316:
- no_false_warnings_for_vyper_config_keys: valid vyper keys in standalone section
- no_false_warnings_for_nested_vyper_config_keys: valid vyper keys in profile
- warns_on_unknown_vyper_keys: unknown vyper keys should still warn

Amp-Thread-ID: https://ampcode.com/threads/T-019c28b9-9c8c-76bf-96a5-ff5a504c0507
Co-authored-by: Amp <amp@ampcode.com>

* fix build issues

* fix(config): handle nested vyper section with skip_serializing_if fields

The VyperConfig struct uses skip_serializing_if on all Option fields,
causing the default serialization to produce an empty dict. This caused
false warnings for valid vyper keys like optimize, path, and
experimental_codegen when used in profile nested sections like
[profile.default.vyper].

Uses the existing VYPER_KEYS constant for nested vyper sections,
matching how standalone [vyper] sections are already handled.

Fixes foundry-rs#13316

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c297e-a282-7188-8f79-5080d3e451a9

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: zerosnacks <zerosnacks@protonmail.com>
Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com>
…s#13331)

* kip checksum hash in create2 mining

* fix the clippy
… does not exist (foundry-rs#13339)

avoid encoding FOUNDRY_PROFILE: ci, profile does not exist
…undry-rs#13327)

* perf(evm): wrap Executor.backend in Arc for copy-on-write cloning

During parallel fuzzing, each worker clones the Executor. Previously this
deep-cloned the entire Backend (CacheDB, JournaledState, state snapshots),
which could be 10-50MB per clone with 16 workers = 160-800MB wasted memory.

This change wraps Backend in Arc<Backend> and uses Arc::make_mut() for
copy-on-write semantics. When workers only read state, they share the same
backend. When a worker mutates, it gets its own copy.

Expected impact:
- ~80% memory reduction for parallel fuzz runs
- Faster executor clone (pointer copy instead of deep clone)
- No behavioral change: mutations still get isolated copies

Amp-Thread-ID: https://ampcode.com/threads/T-019c2af1-f00b-723a-a3c3-25cbd6f3e92b
Co-authored-by: Amp <amp@ampcode.com>

* test: update config test expectations for new mixed_case_exceptions

Fix test expectations after 1bd687f added new values (ID, URL, API,
JSON, XML, HTML, HTTP, HTTPS) to lint.mixed_case_exceptions defaults.

Amp-Thread-ID: https://ampcode.com/threads/T-019c2af1-f00b-723a-a3c3-25cbd6f3e92b
Co-authored-by: Amp <amp@ampcode.com>

* Update config.rs

* Update config.rs

* fix: restore "URI" in config test JSON expectations

Amp-Thread-ID: https://ampcode.com/threads/T-019c2f68-f9df-76bc-ba4c-94fbe1789c9c
Co-authored-by: Amp <amp@ampcode.com>

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com>
Co-authored-by: zerosnacks <zerosnacks@protonmail.com>
…etSigner` (foundry-rs#13343)

- superseeded by `EthereumWallet`'s one, which is integrated in `TransactionBuilder` flow
…tabase_at (foundry-rs#13267)

* return error when querying future block number

* fix test

---------

Co-authored-by: onbjerg <onbjerg@users.noreply.github.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
* chore: remove stale tiny-keccak profile override

* chore: remove stale tiny-keccak deny exception
foundry-rs#13363)

perf(anvil): reuse storage root from prove_storage instead of recomputing
Updating git repository `https://github.com/rust-cli/rexpect`
    Updating git repository `https://github.com/paradigmxyz/solar`
    Skipping git submodule `https://github.com/argotorg/solidity.git` due to update strategy in .gitmodules
    Updating git repository `https://github.com/tempoxyz/tempo`
    Updating git repository `https://github.com/paradigmxyz/reth`
     Locking 94 packages to latest compatible versions
    Updating alloy-consensus v1.5.2 -> v1.6.1
    Updating alloy-consensus-any v1.5.2 -> v1.6.1
    Updating alloy-contract v1.5.2 -> v1.6.1
    Updating alloy-eip5792 v1.5.2 -> v1.6.1
    Updating alloy-eips v1.5.2 -> v1.6.1
    Updating alloy-ens v1.5.2 -> v1.6.1
    Updating alloy-evm v0.26.3 -> v0.26.4 (available: v0.27.2)
    Updating alloy-genesis v1.5.2 -> v1.6.1
    Updating alloy-json-rpc v1.5.2 -> v1.6.1
    Updating alloy-network v1.5.2 -> v1.6.1
    Updating alloy-network-primitives v1.5.2 -> v1.6.1
    Updating alloy-op-evm v0.26.3 -> v0.26.4 (available: v0.27.2)
    Updating alloy-provider v1.5.2 -> v1.6.1
    Updating alloy-pubsub v1.5.2 -> v1.6.1
    Updating alloy-rlp v0.3.12 -> v0.3.13
    Updating alloy-rlp-derive v0.3.12 -> v0.3.13
    Updating alloy-rpc-client v1.5.2 -> v1.6.1
    Updating alloy-rpc-types v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-anvil v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-any v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-beacon v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-debug v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-engine v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-eth v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-trace v1.5.2 -> v1.6.1
    Updating alloy-rpc-types-txpool v1.5.2 -> v1.6.1
    Updating alloy-serde v1.5.2 -> v1.6.1
    Updating alloy-signer v1.5.2 -> v1.6.1
    Updating alloy-signer-aws v1.5.2 -> v1.6.1
    Updating alloy-signer-gcp v1.5.2 -> v1.6.1
    Updating alloy-signer-ledger v1.5.2 -> v1.6.1
    Updating alloy-signer-local v1.5.2 -> v1.6.1
    Updating alloy-signer-trezor v1.5.2 -> v1.6.1
    Updating alloy-signer-turnkey v1.5.2 -> v1.6.1
    Updating alloy-transport v1.5.2 -> v1.6.1
    Updating alloy-transport-http v1.5.2 -> v1.6.1
    Updating alloy-transport-ipc v1.5.2 -> v1.6.1
    Updating alloy-transport-ws v1.5.2 -> v1.6.1
    Updating alloy-trie v0.9.3 -> v0.9.4
    Updating alloy-tx-macros v1.5.2 -> v1.6.1
    Updating anyhow v1.0.100 -> v1.0.101
    Updating async-compression v0.4.37 -> v0.4.39
    Updating aws-config v1.8.12 -> v1.8.13
    Updating aws-runtime v1.5.18 -> v1.6.0
    Updating aws-sdk-kms v1.98.0 -> v1.99.0
    Updating aws-sdk-sso v1.92.0 -> v1.93.0
    Updating aws-sdk-ssooidc v1.94.0 -> v1.95.0
    Updating aws-sdk-sts v1.96.0 -> v1.97.0
    Updating aws-sigv4 v1.3.7 -> v1.3.8
    Updating aws-smithy-async v1.2.10 -> v1.2.11
    Updating aws-smithy-http v0.62.6 -> v0.63.3
    Updating aws-smithy-http-client v1.1.8 -> v1.1.9
    Updating aws-smithy-json v0.61.9 -> v0.62.3
    Updating aws-smithy-observability v0.2.3 -> v0.2.4
    Updating aws-smithy-query v0.60.12 -> v0.60.13
    Updating aws-smithy-runtime v1.9.8 -> v1.10.0
    Updating aws-smithy-runtime-api v1.11.2 -> v1.11.3
    Updating aws-smithy-types v1.4.2 -> v1.4.3
    Updating clap v4.5.56 -> v4.5.57
    Updating clap_builder v4.5.56 -> v4.5.57
    Updating flate2 v1.1.8 -> v1.1.9
   Unchanged generic-array v0.14.7 (available: v0.14.9)
    Updating hyper-util v0.1.19 -> v0.1.20
   Unchanged icu_collections v2.0.0 (available: v2.1.1)
   Unchanged icu_normalizer v2.0.1 (available: v2.1.1)
   Unchanged icu_normalizer_data v2.0.0 (available: v2.1.1)
   Unchanged icu_properties v2.0.2 (available: v2.1.2)
   Unchanged icu_properties_data v2.0.1 (available: v2.1.2)
   Unchanged idna_adapter v1.1.0 (available: v1.2.1)
    Updating interprocess v2.2.3 -> v2.3.1
    Updating jiff v0.2.18 -> v0.2.19
    Updating jiff-static v0.2.18 -> v0.2.19
   Unchanged matchit v0.8.4 (available: v0.8.6)
    Updating memchr v2.7.6 -> v2.8.0
    Updating nybbles v0.4.7 -> v0.4.8
    Updating pest v2.8.5 -> v2.8.6
    Updating pest_derive v2.8.5 -> v2.8.6
    Updating pest_generator v2.8.5 -> v2.8.6
    Updating pest_meta v2.8.5 -> v2.8.6
    Updating proptest v1.9.0 -> v1.10.0
   Unchanged rand v0.8.5 (available: v0.9.2)
    Updating rapidhash v4.2.1 -> v4.2.2
    Updating regex v1.12.2 -> v1.12.3
    Updating regex-automata v0.4.13 -> v0.4.14
    Updating regex-lite v0.1.8 -> v0.1.9
    Updating regex-syntax v0.8.8 -> v0.8.9
   Unchanged reqwest v0.12.28 (available: v0.13.2)
    Updating schemars v1.2.0 -> v1.2.1
    Updating schemars_derive v1.2.0 -> v1.2.1
    Updating sval v2.16.0 -> v2.17.0
    Updating sval_buffer v2.16.0 -> v2.17.0
    Updating sval_dynamic v2.16.0 -> v2.17.0
    Updating sval_fmt v2.16.0 -> v2.17.0
    Updating sval_json v2.16.0 -> v2.17.0
    Updating sval_nested v2.16.0 -> v2.17.0
    Updating sval_ref v2.16.0 -> v2.17.0
    Updating sval_serde v2.16.0 -> v2.17.0
    Updating system-configuration v0.6.1 -> v0.7.0
    Updating webbrowser v1.0.6 -> v1.1.0
    Updating webpki-roots v1.0.5 -> v1.0.6
    Updating zerocopy v0.8.37 -> v0.8.39
    Updating zerocopy-derive v0.8.37 -> v0.8.39
    Updating zlib-rs v0.5.5 -> v0.6.0
    Updating zmij v1.0.18 -> v1.0.19
note: to see how you depend on a package, run `cargo tree --invert <dep>@<ver>`

Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com>
flake.lock: Update

Flake lock file updates:

• Updated input 'fenix':
    'github:nix-community/fenix/b2344f3' (2026-01-31)
  → 'github:nix-community/fenix/e1b28f6' (2026-02-07)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/eb05888' (2026-01-30)
  → 'github:rust-lang/rust-analyzer/d2a00da' (2026-02-05)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/6308c3b' (2026-01-30)
  → 'github:NixOS/nixpkgs/ae67888' (2026-02-06)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
…hing twice (foundry-rs#13391)

* perf(verify): reuse transaction from earlier RPC call instead of fetching twice

* fix ci
DanielGuupta and others added 25 commits February 13, 2026 19:37
…-rs#13459)

* feat(evm): `ForkDatabase`/`MultiFork` generic over `Network`

bump `foundry-fork-db`

* fix: typo
…ndry-rs#13460)

Precompile calls don't create an interpreter frame, so
`initialize_interp` never fires and `max_depth` never gets bumped
beyond the cheatcode call depth. This causes the depth check in
`handle_expect_revert` to fail with "call didn't revert at a lower
depth than cheatcode call depth".

Track `max_depth` in the `call` hook as well, accounting for the
callee depth (`curr_depth + 1`).


Amp-Thread-ID: https://ampcode.com/threads/T-019c63a2-2c36-7334-ab55-2931a174b59c

Co-authored-by: Amp <amp@ampcode.com>
* chore(flake): use nightly rustfmt

* chore(flake): update flake
feat: add executeTransaction cheatcode

Port the executeTransaction cheatcode from
tempoxyz/tempo-foundry. Executes RLP-encoded
signed transactions in an isolated EVM context
with full semantics (like --isolate mode).

OP deposit and Tempo AA transactions return
errors for now (marked with TODOs).
foundry-rs#13446)

* Update external.rs

* chore: fmt

* test: rm useless tests

---------

Co-authored-by: Oliver Nordbjerg <hi@notbjerg.me>
* feat(cheatcodes): add Ed25519 crypto cheatcodes

Add four new cheatcodes for Ed25519 cryptography:
- createEd25519Key(bytes32 salt) - deterministic key generation
- publicKeyEd25519(bytes32 privateKey) - derive public key
- signEd25519(namespace, message, privateKey) - sign with domain separation
- verifyEd25519(signature, namespace, message, publicKey) - verify signatures

Uses ed25519-consensus crate. Includes comprehensive unit tests for
determinism, namespace separation, edge cases, and invalid inputs.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c5f04-a6ed-7015-9b4d-4464a35bc26c

* chore: solidity test

* test: fix assertions

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Oliver Nordbjerg <hi@notbjerg.me>
)

* notify subscribers for txs promoted after block mining

* refactor: extract notify_ready helper to deduplicate notification logic

Amp-Thread-ID: https://ampcode.com/threads/T-019c6840-d225-723a-bf92-46e4e29c7ad1
Co-authored-by: Amp <amp@ampcode.com>

---------

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Co-authored-by: Amp <amp@ampcode.com>
…dry-rs#13465)

Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.67.27 to 2.68.0.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](taiki-e/install-action@1e67ded...f8d25fb)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-version: 2.68.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…0.2 (foundry-rs#13466)

Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/taiki-e/cache-cargo-install-action/releases)
- [Changelog](https://github.com/taiki-e/cache-cargo-install-action/blob/main/CHANGELOG.md)
- [Commits](taiki-e/cache-cargo-install-action@34ce512...2bfc3ce)

---
updated-dependencies:
- dependency-name: taiki-e/cache-cargo-install-action
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
)

Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.43.4 to 1.43.5.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](crate-ci/typos@78bc6fb...57b11c6)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.43.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…6f64df54f62adb34aa5fbfdb0109d34 to a135ea602656a8348c5c34887131dd9f7a28bd8c (foundry-rs#13468)

chore(deps): bump DeterminateSystems/update-flake-lock

Bumps [DeterminateSystems/update-flake-lock](https://github.com/determinatesystems/update-flake-lock) from 5adeaaaf36f64df54f62adb34aa5fbfdb0109d34 to a135ea602656a8348c5c34887131dd9f7a28bd8c.
- [Release notes](https://github.com/determinatesystems/update-flake-lock/releases)
- [Commits](DeterminateSystems/update-flake-lock@5adeaaa...a135ea6)

---
updated-dependencies:
- dependency-name: DeterminateSystems/update-flake-lock
  dependency-version: a135ea602656a8348c5c34887131dd9f7a28bd8c
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…undry-rs#13469)

Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.4.2 to 2.5.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](softprops/action-gh-release@5be0e66...a06a81a)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
These tests hit real Etherscan/Sourcify APIs and fail intermittently due to rate limiting and network issues. They will now run in the nightly flaky test workflow with retries instead of blocking every PR.

Amp-Thread-ID: https://ampcode.com/threads/T-019c6840-d225-723a-bf92-46e4e29c7ad1

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d20285a0a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +165 to +169
assert_invariants(
invariant_contract,
invariant_config,
&invariant_test.targeted_contracts,
&invariant_run.executor,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore optimization-mode handling in can_continue

This success-path now unconditionally calls assert_invariants(...) and no longer branches on optimization invariants (int256 return), so update_optimization_value is never reached during invariant fuzzing. As a result, optimization_best_value stays None and optimization campaigns lose their objective tracking/output, effectively degrading optimization invariants into plain check-mode runs.

Useful? React with 👍 / 👎.

Comment on lines +188 to +190
failures
.errors
.insert(invariant.name.clone(), InvariantFuzzError::Revert(case_data));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overwriting first invariant failure on revert

This unconditional insert in the revert path can clobber a previously recorded BrokenInvariant for the same invariant name when later calls revert during a continuous run. In that case the final reported reason/counterexample is replaced with a later revert, which misattributes the failure and can persist the wrong failure artifact; this should skip invariants that already have a stored failure (as assert_invariants already does).

Useful? React with 👍 / 👎.

Comment on lines 57 to +60
let (call_result, success) = call_invariant_function(
executor,
invariant_contract.address,
invariant_contract.invariant_function.abi_encode_input(&[])?.into(),
invariant_contract.invariant_fn.abi_encode_input(&[])?.into(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preflight-check all invariants in continuous mode

invariant_preflight_check only invokes the currently selected invariant function, even though continuous mode evaluates invariant_fns. If generated calls are all reverted/discarded (so the runtime assert_invariants branch is never reached), secondary invariants that are already broken at initial state are never recorded, which can let a continuous run miss real failures.

Useful? React with 👍 / 👎.

@aviggiano aviggiano merged commit 5300f97 into master Feb 18, 2026
4 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.