Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Reasoning about depth
call
is called before the depth is increased. This effectively means thatdepth
incall
is the depth of the current call, anddepth + 1
is the depth of the call we are about to execute.call_end
is called after the depth is decreased. This effectively means thatdepth + 1
is the depth of the call that just finished executingImplications:
depth == 0
, then the root call (depth 1 during execution, but depth 0 incall
/call_end
) is terminatingdepth + 1
represents the depth of the call that is about to execute incall
, and the depth of the call that just finished executing incall_end
depth - 1
represents the depth at which the current call will terminate incall
andcall_end
depth
depth
in calls to cheatcodes represent the depth of the current call, not the depth of the call to the cheatcode.Illustrated, if you have:
Then:
call
methods are invoked withdepth == 0
when we first calltestSomething
call
methods are invoked withdepth == 1
when we call the cheatcodecall_end
methods are invoked withdepth == 1
when the call to the cheatcode has finishedcall
methods are invoked withdepth == 1
when we callsomewhere.something()
call_end
methods are invoked withdepth == 1
when thesomewhere.something()
call has finishedcall_end
methods are invoked withdepth == 0
when thetestSomething
call has finishedexpectEmit
bug (#1214)This means that if we do:
Then:
call
methods are invoked withdepth == 0
when we first calltestSomeEmit
call
methods are invoked withdepth == 1
when we call the cheatcodedepth == 1
call_end
methods are invoked withdepth == 1
when the call to the cheatcode has finishedcall_end
handler since we just exited a cheatcode callcall
methods are invoked withdepth == 1
when we callsomewhere.someValue()
call_end
methods are invoked withdepth == 1
when thesomewhere.someValue()
call has finishedIn fact we should test for the expected emit at
depth - 1
. In other words, when the call from which the cheatcode was invoked ends.tx.origin
bug (#1210)Whenever
call
is invoked, we check if the depth is greater than or equal to the depth at which the cheatcode was invoked. If it is, then we check:depth
is exactly the depth at which the cheatcode was invoked, then we setmsg.sender
. This is sound because we only want to prank the firstmsg.sender
, not the nested ones in case of nesting. If the depth is greater than or equal to the depth at which the cheatcode was invoked, we settx.origin
, which is sound, because we want this to persist even in the case of nesting.Whenever
call_end
is invoked, we check if we have an ongoing prank. If we do, then we check if the prank is for one call only. If it is, then we erase the prank from memory, so we don't setmsg.sender
in subsequent calls. This is sound. However, we always resettx.origin
to the original value, regardless of the depth of the call that is terminating. This is sound when we usestartPrank
, since it will just continually reapplytx.origin
, but forprank
this is unsound. We should only do that when we are back at the depth at which the prank was started.Closes #1214
Closes #1210