-
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
feat(cheatcodes): add ability to ignore (multiple) specific and partial reverts in fuzz and invariant tests #9179
base: master
Are you sure you want to change the base?
Conversation
23bb2c6
to
3d057c1
Compare
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.
looks good! left couple of comments, going to move back in draft until fix added
@mds1 would be great to have your thoughts re new proposed cheatcodes. Thanks! |
59efe2d
to
3800b7a
Compare
@grandizzy should be in a good state now – apologies, had a hectic week. let me know if anything else looks off. |
moving PR to ready for review |
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.
thank you, left couple of comments.
db65b86
to
ed112a7
Compare
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.
Thank you, looks good! I pushed a change to simplify test and have one more nit re assume_no_revert
fn. @zerosnacks @yash-atreya @klkvr pls chime in when time permits. thank you!
ac4a7d5
to
c215515
Compare
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, thank you! Pending additional review before merging
In general UX LGTM! One thing is let's make sure the behavior between this and the various |
@mds1 apologies, i can update the description (pending final decision) – @grandizzy suggested having the default behavior to accept partial matches. having the granularity of i do appreciate the explicitness, though i do think happy to add back in if there's consensus |
Thanks for those details, so my thoughts are:
|
thanks both for comments! the
For |
Thanks @emo-eth for your PR!
I would prefer we use an array parameter to express the intent of checking against multiple cases in line I agree that
|
@zerosnacks @grandizzy apologies for delay here. Here's a rethought interface that takes an array of structs, let me know your thoughts: /// Represents a "potential" revert reason from a single subsequent call when using vm.assumeNoPotentialReverts.
/// Reverts that match will result in a FOUNDRY::ASSUME rejection, whereas unmatched reverts will be surfaced
/// as normal.
struct PotentialRevert {
/// The allowed origin of the revert opcode; address(0) allows reverts from any address
address reverter;
/// When true, only matches on the beginning of the revert data, otherwise, matches on entire revert data
bool partialMatch;
/// The data to use to match encountered reverts
bytes revertData;
}
/// Discard this run's fuzz inputs and generate new ones if next call reverts with the potential revert parameters
#[cheatcode(group = Evm, safety = Safe)]
function assumeNoPotentialRevert(PotentialRevert calldata potentialRevert) external pure;
/// Discard this run's fuzz inputs and generate new ones if next call reverts with the any of the potential revert parameters
#[cheatcode(group = Evm, safety = Safe)]
function assumeNoPotentialReverts(PotentialRevert[] calldata potentialReverts) external pure; I really don't like the I am probably overthinking this, but here's my logic for the "NoPotential" name (could also be "anticipated?" "Specific?")
|
Hi @emo-eth, no worries! I honestly don't mind the previous Regarding the proposed interface, it looks good. I general prefer a single /// Represents a "potential" revert reason from a single subsequent call when using `vm.assumeNoReverts`.
/// Reverts that match will result in a FOUNDRY::ASSUME rejection, whereas unmatched reverts will be surfaced
/// as normal.
struct PotentialRevert {
/// The allowed origin of the revert opcode; address(0) allows reverts from any address
address reverter;
/// When true, only matches on the beginning of the revert data, otherwise, matches on entire revert data
bool partialMatch;
/// The data to use to match encountered reverts
bytes revertData;
}
/// Discard this run's fuzz inputs and generate new ones if next call reverts with the potential revert parameters.
#[cheatcode(group = Evm, safety = Safe)]
function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure;
/// Discard this run's fuzz inputs and generate new ones if next call reverts with the any of the potential revert parameters.
#[cheatcode(group = Evm, safety = Safe)]
function assumeNoRevert(PotentialRevert[] calldata potentialReverts) external pure; |
can this get merged or what is the hold up? |
Motivation
As raised in #4271, sometimes the fuzzer dictionary will uncover real but irrelevant errors in contract code, especially when testing against stateful forks. Runs that encounter anticipated errors should be thrown out and count towards the global
assume
counter.Closes #4271.
Solution
This PR adds several overloaded and related function definitions to
vm.assumeNoRevert
, introduced in #8780, as follows:The
reverter
param ensures a revert comes from a specific called contract, per #8770, and thePartialRevert
methods allow matching on selectors with arbitrary extra data, per #8763.Behavior
vm.assumeNoRevert(bytes4)
)vm.assumeNoRevert(bytes)
)vm.assumeNoPartialRevert(bytes4)
)vm.assumeNoRevert
definitions that accept params)address reverter
param)vm.assumeNoRevert()
with avm.assumeNoRevert(args)
call should result in an error (currently, the inverse correctly errors, but the ordering provided here will result in a\
vm.assume` rejected too many inputserror due to how cheatcode errors are encoded, see note about
vm.expectRevert` below)Questions
pure
andSafe
? I see thatexpectRevert
is notpure
, and is marked asUnsafe
, butassumeNoRevert()
is markedpure
andSafe
.vm.assumeNoRevert
multiple times to build up anticipated reverts per-call acceptable, or should it be forced to take an array of structs with revert parameters, since I think aggregating parameters from separate calls is new behavior (correct me if I'm wrong).TODO
s in the code with questions, which I will try to surface via comments here.expectRevert()
without args seems to not play strangely with cheatcode errors – eg,vm.expectRevert()
will swallow a cheatcode revert, including those thrown byvm.assumeNoRevert
and subsequent calls tovm.expectRevert()
. This seems like a separate bug that I can log if we agree there.