1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! # Ethereum Virtual Machine in Rust
//!
//! Rust EVM is a flexible Ethereum Virtual Machine interpreter that can be
//! easily customized.
//!
//! ## Basic usage
//!
//! If you want to simply run EVM against Ethereum mainnet, use the
//! [evm-mainnet](https://docs.rs/evm-mainnet) crate.
//!
//! The entrypoint of a normal EVM execution is through the [transact] function.
//! The [transact] function implements a hybrid (stack-based, and then
//! heap-based) call stack.
//!
//! To use the [transact] function, you will need to first implement a
//! backend. This is anything that implements
//! [interpreter::runtime::RuntimeEnvironment], and
//! [interpreter::runtime::RuntimeBackend] traits. You will also need to select
//! a few other components to construct the `invoker` parameter needed for the
//! function.
//!
//! * Select an [Invoker]. The invoker defines all details of the execution
//! environment except the external backend. [standard::Invoker] is
//! probably want you want if you are not extending EVM.
//! * For the standard invoker, select a [standard::Config], which represents
//! different Ethereum hard forks.
//! * Select the precompile set. You may want the `StandardPrecompileSet` in
//! `evm-precompile` crate.
//! * Select a resolver. This defines how the interpreter machines are resolved
//! given a code address for call or an init code for create. You may want
//! [standard::EtableResolver], which accepts a precompile set.
//!
//! ## Debugging
//!
//! Rust EVM supports two different methods for debugging. You can either single
//! step the execution, or you can trace the opcodes.
//!
//! ### Single stepping
//!
//! Single stepping allows you to examine the full machine internal state every
//! time the interpreter finishes executing a single opcode. To do this, use the
//! heap-only call stack [HeapTransact]. Parameters passed to [HeapTransact] are
//! the same as [transact].
//!
//! ### Tracing
//!
//! The interpreter machine uses information from an
//! [interpreter::etable::Etable] to decide how each opcode behaves. The default
//! implementation is
//! [interpreter::etable::DispatchEtable]. [interpreter::etable::DispatchEtable]
//! is fully customizable and a helper function is also provided
//! [interpreter::etable::DispatchEtable::wrap].
//!
//! If you also want to trace inside gasometers, simply create a wrapper struct
//! of the gasometer you use, and pass that into the invoker.
//!
//! ## Customization
//!
//! All aspects of the interpreter can be customized individually.
//!
//! * New opcodes can be added or customized through [interpreter::etable::DispatchEtable].
//! * Gas metering behavior can be customized by wrapping [standard::eval_gasometer] or
//! creating new ones.
//! * Code resolution and precompiles can be customized by [standard::Resolver]. Async
//! precompile is also possible through the [evm-future](https://docs.rs/evm-future) crate.
//! * Call invocation and transaction behavior can be customized via [standard::Invoker].
extern crate alloc;
pub use evm_interpreter as interpreter;
pub use crate::;
/// Merge strategy of a backend substate layer or a call stack gasometer layer.