Skip to content
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): expectRevert with specific reverter address #8770

Merged
merged 5 commits into from
Sep 17, 2024

Conversation

grandizzy
Copy link
Collaborator

@grandizzy grandizzy commented Aug 29, 2024

Motivation

Closes #5299
Closes foundry-rs/book#945
#5299 (comment)

Solution

  • added expectRevert cheatcodes with reverter (expects an error on next call from the given address)
function expectRevert(bytes calldata revertData, address reverter) external;
function expectRevert(bytes4 revertData, address reverter) external;
function expectRevert(address reverter) external;
function expectPartialRevert(address reverter) external;
  • when reverter arg passed then process expected revert for next call, at any depth. If address of contract that reverted the call (call's target address) is different than the expected reverter, then fail test with Reason: Reverter != expected reverter reason.
  • code refactoring: pass ExpectedRevert directly to handle_expect_revert
  • added tests

@grandizzy grandizzy force-pushed the issue-5299-re branch 2 times, most recently from 8479102 to 068b91b Compare August 29, 2024 11:25
@grandizzy grandizzy changed the title [WIP] feat(cheatcodes): specify reverter address in expectReverts [WIP] feat(cheatcodes): expectReverts with specific reverter address Aug 29, 2024
@grandizzy grandizzy force-pushed the issue-5299-re branch 2 times, most recently from 232aa0f to 619bdd3 Compare August 30, 2024 05:10
@grandizzy grandizzy marked this pull request as ready for review August 30, 2024 05:38
@grandizzy grandizzy changed the title [WIP] feat(cheatcodes): expectReverts with specific reverter address feat(cheatcodes): expectRevert with specific reverter address Aug 30, 2024
@grandizzy grandizzy requested a review from mds1 August 30, 2024 14:48
@mds1
Copy link
Collaborator

mds1 commented Aug 30, 2024

Continuing from #4762:

I thought, like other expect* cheats, that expectRevert wants the revert to happen on the next call?

That still holds true but it should be read as expectRevert(reverterAddress) wants the revert to happen on the next call to reverterAddress

Personally I am not a fan of this behavior, and I think expectRevert(reverterAddress) should expect the revert on the next call. The main reason here is this is consistent with how expectEmit(emitter) behaves—it always applies to the next call, and consistent is important for UX.

Additionally, I think "the next call to reverterAddress" is not always obvious, because calls to a different top level address may end up making subcalls to reverterAddress

@grandizzy
Copy link
Collaborator Author

Personally I am not a fan of this behavior, and I think expectRevert(reverterAddress) should expect the revert on the next call. The main reason here is this is consistent with how expectEmit(emitter) behaves—it always applies to the next call, and consistent is important for UX.

Agree, consistency makes sense. However not clear how the bubbling revert described in #5299 (comment) could be achieved if we expect the revert on the next call, I could be missing something

@mds1
Copy link
Collaborator

mds1 commented Aug 30, 2024

So it might be better to just consider all 3 of those bullets a success, i.e. we're expecting that A throws that error anywhere in the call stack, and does not have to be the originator

I think this is probably the simplest solution, just ignore whether or not it bubbled up at all, and as long as reverterAddress reverts with the expected error it's a success

@grandizzy
Copy link
Collaborator Author

So it might be better to just consider all 3 of those bullets a success, i.e. we're expecting that A throws that error anywhere in the call stack, and does not have to be the originator

I think this is probably the simplest solution, just ignore whether or not it bubbled up at all, and as long as reverterAddress reverts with the expected error it's a success

👍 will do so then

@grandizzy grandizzy marked this pull request as draft August 30, 2024 15:13
@grandizzy grandizzy changed the title feat(cheatcodes): expectRevert with specific reverter address [WIP] feat(cheatcodes): expectRevert with specific reverter address Aug 30, 2024
@grandizzy grandizzy marked this pull request as ready for review September 2, 2024 06:17
@grandizzy grandizzy changed the title [WIP] feat(cheatcodes): expectRevert with specific reverter address feat(cheatcodes): expectRevert with specific reverter address Sep 2, 2024
mattsse
mattsse previously approved these changes Sep 3, 2024
Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

lgtm, pending @klkvr

@klkvr
Copy link
Member

klkvr commented Sep 3, 2024

is this basically expectRevert + assert the target of the next call is reverterAddress?

@grandizzy
Copy link
Collaborator Author

grandizzy commented Sep 3, 2024

is this basically expectRevert + assert the target of the next call is reverterAddress?

yeah, pls check #5299 for identical selectors but in different contracts

@grandizzy
Copy link
Collaborator Author

@klkvr ptal and lmk if any things you'd like to be changed before merging. Thank you!

@klkvr
Copy link
Member

klkvr commented Sep 9, 2024

the approach LGTM, though I don't think we're actually resolving #5299 usecase here? eg there's no way to assert B reverting without calling it directly.

IMO having a way to assert revert of the given contract at any subcall of the next call might be useful. such reverts might not even end up bubbled up, and this should still be fine — try-catch blocks are not used that much, and it's arguably useful to have a way to test them being entered as well.

I also think that this would be consistent, because expectEmit(address emitter) catches emits of any depth as well

@grandizzy
Copy link
Collaborator Author

the approach LGTM, though I don't think we're actually resolving #5299 usecase here? eg there's no way to assert B reverting without calling it directly.

IMO having a way to assert revert of the given contract at any subcall of the next call might be useful. such reverts might not even end up bubbled up, and this should still be fine — try-catch blocks are not used that much, and it's arguably useful to have a way to test them being entered as well.

I also think that this would be consistent, because expectEmit(address emitter) catches emits of any depth as well

@mds1 would you concur with @klkvr comment? Imo makes sense but needs to be able to check subcalls of next call. So kind of a mix of how was implemented initially but only for the next call

@mds1
Copy link
Collaborator

mds1 commented Sep 11, 2024

is this basically expectRevert + assert the target of the next call is reverterAddress?

yeah, pls check #5299 for identical selectors but in different contracts

Oh, I thought this was: expectRevert + assert the revert came from reverterAddress, regardless of the target of the next call? I agree with @klkvr and think that is actually what we want to resolve #5299

@grandizzy grandizzy marked this pull request as draft September 11, 2024 15:58
@grandizzy grandizzy changed the title feat(cheatcodes): expectRevert with specific reverter address [WIP] feat(cheatcodes): expectRevert with specific reverter address Sep 11, 2024
@grandizzy grandizzy force-pushed the issue-5299-re branch 3 times, most recently from 37c3bf8 to 6e3b7ff Compare September 16, 2024 07:59
@grandizzy
Copy link
Collaborator Author

IMO having a way to assert revert of the given contract at any subcall of the next call might be useful. such reverts might not even end up bubbled up, and this should still be fine — try-catch blocks are not used that much, and it's arguably useful to have a way to test them being entered as well.

I also think that this would be consistent, because expectEmit(address emitter) catches emits of any depth as well

@klkvr please recheck. thank you!

@grandizzy grandizzy marked this pull request as ready for review September 16, 2024 08:33
@grandizzy grandizzy dismissed mattsse’s stale review September 16, 2024 08:35

dismissing as several other changes were done since this review

@grandizzy grandizzy changed the title [WIP] feat(cheatcodes): expectRevert with specific reverter address feat(cheatcodes): expectRevert with specific reverter address Sep 16, 2024
Copy link
Member

@klkvr klkvr left a comment

Choose a reason for hiding this comment

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

LGTM

@grandizzy grandizzy merged commit 2b39094 into foundry-rs:master Sep 17, 2024
20 checks passed
@grandizzy grandizzy deleted the issue-5299-re branch September 17, 2024 13:33
rplusq pushed a commit to rplusq/foundry that referenced this pull request Sep 25, 2024
…y-rs#8770)

* feat(cheatcodes): expectRevert with specific reverter address

* Support assert revert of the given contract at any subcall of the next call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants