-
Notifications
You must be signed in to change notification settings - Fork 817
Description
Hey,
following #1865 I did a spike to implement a Foundry-style cheatcode inspector using the new interfaces. I really like the new design, but I ran into difficulties when trying to implement the transact
and rollFork(uint256 forkId, bytes32 transaction)
cheatcodes. Both of these cheatcodes initiate transactions from a call step in the cheatcode inspector.
I'll detail the issues below. I created a minimal repro with comments explaining the setup, but it's still ~500 LOC, so I will link to the relevant sections.
JournaledState<DB>
Moving the database inside the journal state in the EVM context prevents mutably borrowing both at the same from a &mut Context
. This causes problems detailed here. There is also a failing test case related to this here.
I think this could be solved by lifting the DB to the Context
and introducing a temporary struct that has mutable journaled state and database fields and implementing the JournaledState
trait for this temporary struct.
Precompiles
When using an inspector, the PrecompileProvider
needs an InspectorContext
as its context. The InspectorContext
needs to know the inspector type and the database type. This prevents declaring a method that takes the precompile provider as a generic parameter and constructs an inspector in the body to execute a transaction. There is an example here.
I think this could be solved by just passing the block, transaction and config environments to the PrecompileProvider
instead of the entire context.
I also noticed that precompiles are no longer accessible in Inspector::call
. Previously this was available via EvmContext::precompiles
, but as far as I can tell, removing this doesn't block any cheatcode functionality.
Missing implementations
The following seems to be only implemented for mainnet types:
Evm::transact()
implementation hard-codes mainnetHaltReason
in theEVMResult
return type.InspectorCtx for InspectorContext
implementation hard-codes mainnetEthInterpreter
. It should be possible to pass a generic interpreter type here.
I also noticed that NoOpInspector::default()
doesn't work with mainnet types due to unsatisfied trait bounds.
It's possible that I overlooked something and there is a solution for the mentioned issues. I'm also happy to submit PRs to resolve them. Let me know please!