-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: do not flood dictionary with data dependent on fuzz inputs #7552
Conversation
this rang a bell re #7462 which I cannot reproduce with this PR anymore (reproducible with master and UniStaker repo by reverting commit uniswapfoundation/UniStaker@1573451 that workarounds this issue) |
I used PoC #3607 (comment) to collect and visualize some stats on |
hey @grandizzy thanks! an aside: how are you getting these metrics? I think you dropped the info in another issue or PR, but we should document further |
hey @Evalir , tagged you in the metrics issue #3607 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all of this makes sense to me, but would appreciate another look @DaniPopes
@@ -19,16 +19,116 @@ use std::{fmt, sync::Arc}; | |||
/// A set of arbitrary 32 byte data from the VM used to generate values for the strategy. | |||
/// | |||
/// Wrapped in a shareable container. | |||
pub type EvmFuzzState = Arc<RwLock<FuzzDictionary>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great, one less type alias 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gg
* fix dictionary * clippy + fmt * fix
* chore: make cast use an alloy provider * move initial methods to alloy * feat(`foundry-common`): NameOrAddress ENS util (#7122) * feat(foundry-common): NameOrAddress ENS util * chore: rename err * chore: remove from impl for str * chore: unrelated fix from alloy upgrade * nit * feat(`cast`): Move non `tx` methods to alloy (#7129) * chore: add alloy contract * feat(cast): migrate most methods to alloy * chore: leave todo for converting a tx envelope into an rpc tx * fix: use proper type for storage * readd decodetx for now * chore: extend txbuilder to build an alloy tx request * feat: migrate most methods bar send/decode raw tx * fix: include tx data * simplify txbuilder * chore: simplify back access_list * chore: remove unnecesary conversion * fmt * doctests * fmt * do not use trait * Update crates/cast/bin/main.rs Co-authored-by: Matthias Seitz <[email protected]> * cleanup builder * clippy * fix doc comments --------- Co-authored-by: Matthias Seitz <[email protected]> * DocumentMut * wip * wip * wip: bump alloy * wip * wip * wip * [wip] migrate to alloy providers and signers (#7425) wip * fix wallets after alloy bump * clean up deps * use serde on consensus types * update TypedTransaction for anvil * make anvil compile * wip: make script compile * fix script * make forge compile * fix: anvil tests * bump alloy * fix tests * fix tx builder * fix cargo.toml * fix cargo.toml * fix script gas price logic * remove ethers from anvil * clippy * rm all_derives * deps * fmt * fix tests * configure clippy * clippy * add feature * fix cargo deny * fix persist * fix doctests * fmt * fix clap * review fixes * fmt * bump alloy * Update cargo.toml * fmt * fixes * ethers clean-up * fix(fmt): fix indent closing parenthesis enclosed in { } (#7557) * fix(fmt): fix indent closing parenthesis enclosed in { } * Fix testdata bad formatting * feat(test): only compile files needed for tests (#7334) * feat(forge test): only compile files needed for tests * remove comment * clippy * update fixtures * getCode + getDeployedCode updates * fixes * fix path matching * clippy * add config flag * fix * docs * fmt * patch compilers * fix Cargo.toml * update patch * update patch * doc * rm space * cargo cheats * new output selection fn * log compiler errors on failure * fixes * fix: do not flood dictionary with data dependent on fuzz inputs (#7552) * fix dictionary * clippy + fmt * fix * Feat: Index cheatcode for Strings (#7539) * feat: index cheatcode * some nits to make it work * nit: use as_str() * final changes * chore: reviewed changes * chore: reduce logs in tests (#7566) * fix(script): decode custom error in script fail message (#7563) * clippy * bump alloy * AnyNetwork * bump alloy * add comment * clippy * bump alloy * fixes * refactor cast logs to use alloy (#7594) * refactor cast logs to use alloy * fmt * make clippy happy * cleanup * doc nits --------- Co-authored-by: evalir <[email protected]> --------- Co-authored-by: Matthias Seitz <[email protected]> Co-authored-by: Arsenii Kulikov <[email protected]> Co-authored-by: grandizzy <[email protected]> Co-authored-by: Krishang <[email protected]> Co-authored-by: DaniPopes <[email protected]> Co-authored-by: bernard-wagner <[email protected]>
Motivation
Currently data collected during individual fuzz/invariant run (e.g. logs, storage writes) persists in fuzz dictionary resulting in large dictionary sizes due to it being flooded by data dependent on fuzz inputs. In #7551 case it resulted in dictionary accumulating log topics which directly contained fuzz inputs thus decreasing a chance of picking actually useful value from push byte as a fuzz input.
Solution
For fuzz tests we now don't call
collect_state_from_call
at all making calldata choice completely stateless.For invariant tests I've refactored
EvmFuzzState
to keep track of all newly added keys and an option to remove them viarevert
fn. Thus, on invariant runs we accumulate and persist dictionary between separate calls, but it is getting cleared after each invariant sequence run.Setters now also don't let dictionary size to grow beyond configured limit which didn't really work before
Results
This does not directly resolv #7551 because in this exact case fuzz-test has a structure with many branches and a chance to reach a branch which should've caused failure is relatively low because most of the runs are getting caught earlier.
For the sake of experiment let's remove some of the branches to increase chance of hitting this exact failure:
On latest nightly, forge is not able to catch a revert after 100.000 runs.
On this PR's version, revert is catched on 9261 run.
This benchmark is dependent on exact test and seed and this is kind of an edge case as this test suite results in 7000 push bytes being pre-collected after setUp, but I believe that cleaning up fuzz dictionary is reasonable anyway.