EVM
Evm
is the primary structure that implements the Ethereum Virtual Machine (EVM), a stack-based virtual machine that executes Ethereum smart contracts.
What is inside
It is consisting of two main parts the Context
and the Handler
. Context
represent the state that is needed for execution and Handler
contains list of functions that act as a logic.
Context
is additionally split between EvmContext
and External
context. EvmContext
is internal and contains Database
, Environment
, JournaledState
and Precompiles
. And External
context is fully generic without any trait restrains and its purpose is to allow custom handlers to save state in runtime or allows hooks to be added (For example external contexts can be a Inspector), more on its usage can be seen in EvmBuilder
.
Evm
implements the Host
trait, which defines an interface for the interaction of the EVM Interpreter with its environment (or "host"), encompassing essential operations such as account and storage access, creating logs, and invoking sub calls and selfdestruct.
Data structures of block and transaction can be found inside Environment
. And more information on journaled state can be found in JournaledState
documentation.
Runtime
Runtime consists of list of functions from Handler
that are called in predefined order.
They are grouped by functionality on Verification
, PreExecution
, Execution
, PostExecution
and Instruction
functions.
Verification function are related to the pre-verification of set Environment
data.
Pre-/Post-execution functions deduct and reward caller beneficiary.
And Execution
functions handle initial call and creates and sub calls.
Instruction
functions are part of the instruction table that is used inside Interpreter
to execute opcodes.
The Evm
execution runs two loops:
Call loop
The first loop is call loop that everything starts with, it creates call frames, handles subcalls, it returns outputs and calls Interpreter
loop to execute bytecode instructions.
It is handled by ExecutionHandler
.
The first loop implements a stack of Frames
.
It is responsible for handling sub calls and its return outputs.
At the start, Evm
creates Frame
containing Interpreter
and starts the loop.
The Interpreter
returns the InterpreterAction
which can be:
Return
: This interpreter finished its run.Frame
is popped from the stack and its return value is pushed to the parentFrame
stack.SubCall
/SubCreate
: A newFrame
needs to be created and pushed to the stack. A newFrame
is created and pushed to the stack and the loop continues. When the stack is empty, the loop finishes.
Interpreter loop
The second loop is the Interpreter
loop which is called by the call loop and loops over bytecode opcodes and executes instructions based on the InstructionTable
.
It is implemented in the Interpreter
crate.
To dive deeper into the Evm
logic check Handler
documentation.
Functionalities
The function of Evm
is to start execution, but setting up what it is going to execute is done by EvmBuilder
.
The main functions of the builder are:
preverify
- that only pre-verifies transaction information.transact preverified
- is next step after pre-verification that executes transactions.transact
- it calls both preverifies and executes transactions.builder
andmodify
functions - allow building or modifying theEvm
, more on this can be found inEvmBuilder
documentation.builder
is the main way of creatingEvm
andmodify
allows you to modify parts of it without dissolvingEvm
.into_context
- is used when we want to get theContext
fromEvm
.