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): ability to capture and store state diffs #2846

Closed
sakulstra opened this issue Aug 19, 2022 · 12 comments · Fixed by #9435
Closed

feat(cheatcodes): ability to capture and store state diffs #2846

sakulstra opened this issue Aug 19, 2022 · 12 comments · Fixed by #9435
Assignees
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge Cmd-forge-test Command: forge test D-hard Difficulty: hard P-normal Priority: normal T-feature Type: feature
Milestone

Comments

@sakulstra
Copy link
Contributor

sakulstra commented Aug 19, 2022

Component

Forge

Describe the feature you would like

For certain transactions (especially related to DAO governance processes) it makes sense to diff the chain state from before and after a certain tx execution to have a reasonable preview of what the outcome/side effects of a certain action are.

I'm aware this feature can grow to infinite complexity when trying to decode the stateDiffs accross proxy implementations or similar, so for a first iteration i'd suggest to keep it as simple as possible and just track address.key.before/after values and see where we can go from there.

Not quite sure if diffs over multiple txn or overlapping diffs are needed.
A simple api could be sth like vm.diff(identifier) which would track state changes of the next txn executed. The identifier could be the file to log to.

As for a more complex api I would imagine sth similar to startPrank api but allowing overlaps.

vm.startStorageDiff('execution');
contract.doSthAwesome();
vm.startStorageDiff('partial');
contract.doSthElse();
vm.stopStorageDiff('partial');
vm.stopStorageDiff('execution');

Additional context

tenderly has a great feature called "State changes" used in aave/unswap seatbelt, which does exactly that (diff the state between before and after a simulation). Would be cool if sth similar or a slimmed down version of this could exist within foundry as foundry & tenderly don't work very well together. For complex scenarios tenderly would probably still be the go-to as they solved state decoding in a relatively reliable way, but for more simple cases it would be cool if one could resort to foundry.

@sakulstra sakulstra added the T-feature Type: feature label Aug 19, 2022
@gakonst gakonst added this to Foundry Aug 19, 2022
@gakonst gakonst moved this to Todo in Foundry Aug 19, 2022
@rkrasiuk rkrasiuk added the C-forge Command: forge label Aug 19, 2022
@onbjerg onbjerg added Cmd-forge-test Command: forge test A-cheatcodes Area: cheatcodes P-low Priority: low D-hard Difficulty: hard labels Aug 19, 2022
@mattsse
Copy link
Member

mattsse commented Aug 22, 2022

we support id = vm.snapshot which basically record the entire state and can revert via vm.revertTo(id)

rn revertTo(id) also reverts all snapshots taken after the id

is that a start, or what should we add to the snapshot feature?

I guess diffing between snapshots, right?

ref https://book.getfoundry.sh/cheatcodes/snapshots

@wp-lai
Copy link
Contributor

wp-lai commented Sep 27, 2022

upvote for this snapshot diff feature. It would be better if the state diff could be displayed in the traces of forge test.

@mattsse
Copy link
Member

mattsse commented Sep 27, 2022

unsure how this would look like when integrating diffs in traces.

but perhaps we could do something like

Diff diff = vm.diffSnapshot(id)
console.log(diff)

@mds1
Copy link
Collaborator

mds1 commented Sep 27, 2022

I think there's two things here that would be useful:

  1. Below a trace, showing the decoded state diffs for the full transaction. For forge test it'd be the state changes of that test, and for cast run <tx> you get the state changes of that tx.
  2. Within a test, using vm.diffSnapshot(id) (though I'd probably name it vm.stateDiff(uint snapshotId)). We can update console2.sol to support this type and add a forge-std method like [log|print]StateDiff(uint snapshotId, string memory name) (second arg is optional) to simplify the process of snapshotting/logging. I think having it displayed in-line in the trace would be very hard to read and clutter the trace

@sakulstra
Copy link
Contributor Author

Just noticed that #6310 was merged which is quite close to what I originally requested here.


As far as i can tell it currently does not support decoding which would be insanely cool, anyhow feel free to close this one as the original issue is solved.

@mds1
Copy link
Collaborator

mds1 commented Dec 1, 2023

Perhaps we close this one and create a new issue to track a decoded state diff similar to what tenderly does? Not sure if this is tracked anywhere else offhand since I know it's been mentioned, deferring to @Evalir for how to handle

@sakulstra
Copy link
Contributor Author

Yah the issue with tenderly and phalcon is that they only support a small subset of chains. Also it's a bit cumbersome to mix the tools.

@zerosnacks zerosnacks added this to the v1.0.0 milestone Jul 26, 2024
@zerosnacks
Copy link
Member

zerosnacks commented Aug 2, 2024

Marking as duplicate of #6704

I think this will be resolved by #8571 as a diff can be derived by the recorded state changes, let me know if this PR would sufficiently cover your suggested feature.

@zerosnacks zerosnacks closed this as not planned Won't fix, can't repro, duplicate, stale Aug 2, 2024
@sakulstra
Copy link
Contributor Author

@zerosnacks , i think it's not a duplicate.
At least by reading the pr i don't see how one could extract the storage labels from the recording.

The goal would be to identify changes like:

- _balances[0x1] = 0;
+ _balances[0x1] = 1000;
- _balances[0x2] = 1000;
+ _balances[0x2] = 0;

@zerosnacks zerosnacks reopened this Aug 5, 2024
@zerosnacks zerosnacks changed the title Store state diffs feat(cheatcodes): ability to capture and store state diffs Aug 5, 2024
@grandizzy grandizzy removed this from the v1.0.0 milestone Oct 15, 2024
@grandizzy grandizzy added this to the v1.0.0 milestone Nov 20, 2024
@grandizzy
Copy link
Collaborator

adding it in 1.0 to be discussed ref https://twitter.com/msolomon44/status/1859021021984289220

@grandizzy
Copy link
Collaborator

I think there's two things here that would be useful:

1. Below a trace, showing the decoded state diffs for the full transaction. For forge test it'd be the state changes of that test, and for `cast run <tx>` you get the state changes of that tx.

for cast run, proposed solution in PR #9013 is to add a --with-state-changes arg that would print diffs as shown bellow (we could also use verbosity instead new arg), @mds1 @sakulstra wdyt?

image

@grandizzy grandizzy removed the P-low Priority: low label Nov 21, 2024
@grandizzy
Copy link
Collaborator

@sakulstra @mds1 please share your thoughts re proposed cheatcode and output here #9435 thank you!

@grandizzy grandizzy self-assigned this Dec 2, 2024
@grandizzy grandizzy moved this from Todo to In Progress in Foundry Dec 2, 2024
@github-project-automation github-project-automation bot moved this from In Progress to Done in Foundry Dec 6, 2024
@grandizzy grandizzy moved this from Done to Completed in Foundry Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge Cmd-forge-test Command: forge test D-hard Difficulty: hard P-normal Priority: normal T-feature Type: feature
Projects
Status: Completed
Development

Successfully merging a pull request may close this issue.

8 participants