Description
Component
Forge
Describe the feature you would like
Core Description
I'd like a fundamentally different execution method in foundry. One that executes individual view calls using actual independent eth_calls
against the environment and non-view calls as top-level transactions. This is unlike the current default and only execution mode which is all executed within 1 top-level transaction leading to several (often) undesirable side effects:
- arguably incorrect or at least unintuitive gas accounting between transactions due to:
- missing intrinsic gas cost (21k gas)
- missing calldata costs
- inability to pre-warm slots with access lists (and accounting their cost)
- capped gas refunds dependent on tx gas usage (Forge gas reporting is misleading due to obfuscation of transaction overhead #6578)
- addresses and slots accessed in previous slots remaining warm (storage kept hot when should be cold #4900)
- inability to simulate/test things easily related to self-destruct (bug:
selfdestruct
has no effect in test whereas a user expects it would #1543) - (newly relevant) transient storage slots not being reset (comment in Add support for solc
0.8.24
#6903)
There are likely more issues that I'm missing. The pain of the above issues is compounded when attempting to use foundry scripts for more special transaction sequences as this mismatch may lead to false positive reverts preventing the script runner from submitting transactions (#6825).
There are a bunch of separate feature requests attempting to address different aspects of this:
vm.cool
(feat:cool
cheatcode #5830)meterTxGas
(feat(cheatcodes): addvm.meterTxGas
cheatcode #6590)vm.clearTransientStorage
(feat: allowisolate
config to be defined inline #6908)
While the current execution mode (using one big tx to run tests and simulations) is desirable for many use cases & reasons (faster test & sim execution, testing intra-tx changes). It's undesirable in many others. Instead of solving the different symptoms by adding new cheat codes I suggest taking a more holistic approach: adding a new execution mode.
The new Execution Mode
I'm likely oversimplifying (due to a lack of knowledge of revm and foundry internals please correct where required) but I wanted to offer a potential design/approach for this new mode. In this mode you'd run 2, separate instances of revm within foundry. One that runs the actual test/script and the other that maintains the actual simulated/forked state. CALLs and STATICCALLs made in the simulation environment are dispatched as eth_call
s and actual top-level transactions into the second "world" environment. Results are relayed into the first.
While this does add some overhead this solves all the aforementioned issues with one 1 (all be it larger) change without requiring the addition of many separate cheat codes and requiring devs to manually adds this everywhere just so their tests can accurately account gas.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status