Open GalloDaSballo opened 4 days ago
Right, so overrideCaller
is set from Nothing
to the address when startPrank
is called. This also sets resetCaller
to False
. Then, when stopPrank
is called, overrideCaller
is set to Nothing
, and resetCaler
is set to True
.
So what you are saying would I think mean that when we do another call
, overrideCaller
should be reset to Nothing
, along with resetCaller
being reset to True
. Let me make a PR like that, and maybe you can then check if that fixes it. Would that be OK?
So I have a new branch, fix_prank
that may fix this. I'm trying to check if it does now :)
@msooseth I don't think that would be enough, as when you return from the call, overrideCaller
should be set back to the address and resetCaller
should be back to True
. I'm thinking those two options should be moved to the frame rather than being a global VM setting.
EDIT: I think you did just that on the branch, it'll probably work fine now 💯 thanks!
From what I understand it should be like this:
A.foo()
\__startPrank(X)
|__B.bar() /* msg.sender is X */
| \__C.baz() /* msg.sender is B, as the override only applies on A.foo's frame */
|__B.baz() /* msg.sender is X */
|__stopPrank()
|__B.bar() /* msg.sender is A */
\__C.baz() /* msg.sender is B */
@GalloDaSballo I opened a draft PR on Echidna that uses @msooseth's hevm branch, if you can try it out and see if it behaves as expected now, that'd be great: https://github.com/crytic/echidna/pull/1331
Thank you all, will test it soon
OK, seems to be fixed with c6c4b44af0137ccfdab8197a7dd1e4ae69114edb. The corresponding echidna is:
https://github.com/msooseth/echidna/pull/1
You can cone that, go into fix_prank
branch, then nix shell
, then git clone https://github.com/Recon-Fuzz/prank-echidna-vs-foundry
then cd prank-echidna-vs-foundry
and then echidna . --contract CryticTester --config echidna.yaml
and it should all pass.
Have tested this release candidate by @elopez : https://github.com/crytic/echidna/actions/runs/12081766889
I ran it for 1 Million tests with no reverts
In contrast see the previous version failing in less than 50k tests
Impact
I have written this repo which shows a full repro
https://github.com/Recon-Fuzz/prank-echidna-vs-foundry
Fundamentally, when using
startPrank
and calling a contract that performs atransferFrom
, echidna (using hevm under the hood), will perform thetransferFrom
with the pranked address instead of the router, causing the transfer to failMitigation
I believe that the prank should only be enforced at the current call level, a nested call should not longer have it's msg.sender altered