Skip to content

feat(invariant): add fail_on_assert for Solidity assert failures#13519

Open
aviggiano wants to merge 5 commits intofoundry-rs:masterfrom
aviggiano:feat/invariant-fail-on-assert
Open

feat(invariant): add fail_on_assert for Solidity assert failures#13519
aviggiano wants to merge 5 commits intofoundry-rs:masterfrom
aviggiano:feat/invariant-fail-on-assert

Conversation

@aviggiano
Copy link

@aviggiano aviggiano commented Feb 23, 2026

Summary

  • add [invariant].fail_on_assert to InvariantConfig (default false)
  • fail invariant campaigns on Solidity assert failures even when fail_on_revert = false
    • Panic(0x01)
    • legacy invalid-opcode assertion behavior (InstructionResult::InvalidFEOpcode)
  • keep behavior unchanged for:
    • require/generic reverts
    • non-assert panics (e.g. Panic(0x11))
    • vm.assert* / GLOBAL_FAIL_SLOT semantics
  • classify fail_on_assert failures as BrokenInvariant (not generic Revert)
  • apply the same condition in replay/shrink paths so persisted failures stay reproducible

Implementation Notes

  • config model
    • crates/config/src/invariant.rs
  • runtime decision paths
    • crates/evm/evm/src/executors/invariant/result.rs
    • crates/evm/evm/src/executors/invariant/mod.rs
  • replay/shrink parity
    • crates/evm/evm/src/executors/invariant/shrink.rs
    • crates/forge/src/runner.rs
  • propagated case data
    • crates/evm/evm/src/executors/invariant/error.rs
  • config snapshots
    • crates/forge/tests/cli/config.rs
  • regression tests
    • crates/forge/tests/cli/test_cmd/invariant/common.rs

Tests

  • cargo +1.91.0 test -p foundry-evm invariant::result::tests --lib --locked
  • cargo +1.91.0 test -p forge --test cli fail_on_assert --locked
  • cargo +1.91.0 test -p forge --test cli invariant_ignore_assert_panic_when_flag_off --locked
  • cargo +1.91.0 test -p forge --test cli test_default_config --locked

Closes #13322

@aviggiano
Copy link
Author

Wait a sec, this is not exactly what we need

I'm testing this branch on Recon-Fuzz/scfuzzbench-canary#2 but it is reporting invariant_noop as a root cause for assertion failure, when in reality it should report counter_increment

I'll try to fix this

@aviggiano
Copy link
Author

Still not feature parity with medusa, since we will only see assertion failures on logs. I'd also see them as "first class citizen" in metrics JSON

@0xalpharush
Copy link
Contributor

I rebased #12587 and got assertion failures working on this canary (with shrinking/replay working w/o changing from an assertion to invariant). I also updated the logs and trace format

https://github.com/0xalpharush/foundry/tree/fail_on_assert

@aviggiano
Copy link
Author

hey, thanks for the contribution

This looks really good overall, with one caveat: it is picking up assert(...) but not Forge cheatcode assertions vm.assert*

So we need to think whether we'd want to support both out of the box (I think so)

@0xalpharush
Copy link
Contributor

It is checking this slot but maybe there's some weird interaction with assertions_revert. or it's not the right way..
2cf1340#diff-6547e74fc7387bb7d95a9612a3a04ba728664f9b0a359c598fd6bdb64b2ce118R702-R720

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Report assertion failures as broken invariants

2 participants