Revm
Revm is a highly efficient and stable implementation of the Ethereum Virtual Machine (EVM) written in Rust.
Known for its robustness, it stands as one of the most popular libraries and critical component of the Ethereum ecosystem. Revm plays a crucial role across various projects, being widely utilized by almost all tooling and block builders. It is integrated into Reth, multiple Layer 2 variants and other clients and serving as a standard for zkVMs.
Revm offers two primary applications: firstly, it functions as an executor where users can set up block info and process mainnet transactions; secondly, it acts as a framework that facilitates the extension and support of different EVM variants such as revm-optimism.
How to use:
Here is a straightforward example of using the Execution API: It allows us to create an Ethereum Virtual Machine (EVM) and execute transactions. Additionally, it can be utilized to generate traces with the inspector or more complex example of foundry cheatcodes.
let mut evm = Context::mainnet().with_block(block).build_mainnet();
let out = evm.transact(tx);
// or you can use powerful inspection tool to trace it
let mut evm = evm.with_inspector(tracer);
let out = evm.inspect_with_tx(tx);
The Evm Framework API is somewhat complex to use, but this document provides a detailed explanation. It enables users to extend logic, incorporate various context types, and offers built-in support for inspection. For a practical example, you can refer to the revm-optimism crate.
Users:
As previously noted, there are several groups of projects that utilize this technology:
- Major block builders.
- Clients: Reth, Helios, Trin,..
- Tooling: Foundry, Hardhat,..
- L2s: Optimism, Coinbase, Scroll,..
- zkVM: Risc0, Succinct,..
The full list of projects that use Revm is available in the awesome-revm section of the book.
How to, dev section
Note that book and code docs are still in WIP stage and they are being updated!
Part of the links point to the code documentation or the book. code docs are there to explain usage of particular part of the code where book is to get more of the overview on architecture or how components/projects fit toggether.
- How to build and use revm can be found here. (code)
- Architecture overview can be seen here. (book)
- Structure of the project (list of crates) can be seen here. (book)
- How to use Revm Framework can be found here. (book)
- Release procedure and changelogs explanation. (book)
- How to use revme (Revm binary with few commands) can be found here. (code)
- How to run Ethereum test can be found here: (book)
- How to run examples and benchmark with
samply
to check performance. (book) - If there is more explanations please open PR request for it.
Community:
For questions please open an github issue or join public telegram group: https://t.me/+Ig4WDWOzikA3MzA0
Licence
Revm is licensed under MIT Licence.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions.
Security
For any security questions or findings, please reach out to me directly via email at dragan0rakita@gmail.com or contact me on Keybase under the username draganrakita.
Awesome Revm
A curated list of excellent Revm-related resources. Feel free to contribute to this list!
Repositories
- Main Repo: Revm Repository - The central code repository for Revm.
- Book: - Comprehensive user documentation for Revm.
Audits
Clients
- Reth: A modular, contributor-friendly, and ultra-fast implementation of the Ethereum protocol.
- Helios is a trustless, efficient, and portable multichain light client written in Rust.
- Trin is a Rust implementation of a Portal Network client.
EVM Variants
- Optimism is a ethereum L2 network.
- Base is an Ethereum Layer 2 (L2) chain that offers a safe, low-cost, developer-friendly way to build on-chain
- Scroll is its own Layer 2 network built on Ethereum (more specifically, a “zero-knowledge rollup”).
Tools
- Foundry: A portable and modular toolkit for rapid Ethereum application development in Rust.
- Hardhat: A comprehensive development environment for compiling, deploying, testing, and debugging Ethereum software.
- Arbiter: smart-contract simulation.
Frameworks and Libraries
- revm-inspectors: Hooks for EVM execution.
- eip3074-instructions: Implements custom instructions for AUTH and AUTHCALL operations.
- Revmc: JIT and AOT compiler for the Ethereum Virtual Machine, leveraging Revm.
- Risc0-ethereum is a zero-knowledge verifiable general computing platform, with Ethereum integration
- Kona is a suite of portable implementations of the OP Stack rollup state transition, namely the derivation pipeline and the block execution logic.
Tutorials
- Revm is All You Need: Guide on building simulated blockchain environments.
- Uniswap Swap Example: Demonstrates a USDC swap on Uniswap V2.evm is available in the awesome-revm section o
- revm-by-example: Practical examples using the Rust Ethereum Virtual Machine.
Architecture
List of crates can be found in Crates section of the book.
REVM as any EVM implement a list of EIP's (Ethereum Improvement Protocol) changes over time. Those changes are shipped in the form of hardforks. List of hardforks can be found here Ethereum Hardforks and repository that contains all EIPs can be found here EIPs.
Main components/traits:
Revm consist of few traits that implement functionality of the EVM. The main traits are:
- EvmTr: This trait allows as to access main EVM fields and to run interpreter. It defines Context, Precompiles, Instructions. Docs
- ContextTr: is gained from EvmTr and consist of types needed for execution. It defines environment such as block and transaction, database for runtime fetching of accounts and storage, journal for status changes and revert handling and few more fields. Docs
- Handler: is a trait that by default implements Ethereum logic, it takes EvmTr as a input. Entry point is a
run
function. Docs - Frame: is a associate type ofHandler and contains runtime data of the call and logic of executing the call, default impl is a type is EthFrame. Docs
Inspection for tracing is extensing above traits with:
- InspectorEvmTr is derived from EvmTr and allows running Evm in Inspection mode. It contains Inspector associate type. Docs
- InspectorHandler is derived fromHandler and allows running Evm in Inspection mode. Entry point is
inspect_run
function and it calls a alternative functions for execution loop that includes inspector calls. Docs - Inspector is a a user oriented trait that is used for inspection of the EVM. It is used for tracing. It is part of Evm struct and it is called from InspectorHandler and InspectorEvmTr. Docs
Simplified code
pub trait EvmTr {
type Context: ContextTr;
...
fn execute_interpreter(..);
}
pub trait Handler {
type Evm: EvmTr;
type Frame: Frame;
...
fn run(evm);
}
flow of execution
Execution flow can be found here (TODO Move to codebase toHandler trait):
- It starts with creation of new EVM instance
- Building of the Context
- Building of the EVM. Inspector/Precompiles are created.
- Adding of the Inspector if needed.
- transact/inspect. Both inspection and transaction have same flow where the only difference is that inspection includes calls to the inspector.
- validation of transaction and doing balance gas limit check.
- pre execution loads all warm accounts and deducts the caller.
- Execution :
- Creates first frame with Interpreter or executes precompile.
- run the frame loop:
- Calls Evm to exec interpreter with the frame. Interpreter loops is called here
- Output of Interpreter loop is NextAction that can be a Return of Call.
- If Return, then the frame is popped and the return value is pushed to the parent frame. If it is new call, then a new frame is created and pushed to the call stack.
- If call stack is empty the execution loop is done.
- handles the result of execution.s
- Post execution deals with halt and revert handling redistribution of rewards and reimbursement of unspend gas.
External core dependencies
Revm project is no_std compliant, and it uses alloc
crate for heap allocation.
Native types are imported from alloy-primitives
crate, this is where we get Address, Bytes, B256 types where big number U256 is exported from ruint
. Additionally hashbrown
crate or HashMap/HashSet
with different hashing algorithm are imported from it.
alloy-eip7702
and alloy-eip2930
are used in TxEnv as parts of transaction.
Precompiles require a lot of cryprography and math libs:
c-kzg
is a minimal implementation of the Polynomial Commitments API for EIP-4844, written in C. (With rust bindings)modexp
is a big integer modular exponentiation precompile.secp256k1
is an ECDSA public key recovery precompile, based onsecp256k1
curves.k256
is used as a fallback for no_std environments.- ...
serde
and serde-json
are behind a feature flag to serialize and deserialize data structures.
Some utility crates are used throughout the codebase: auto_impl
, derive_more
etc. Where in some places few libs are imported for specific use cases like nnum
or dawdaw
.
Revm project is split in multiple crates, each crate is responsible for different part of the project. The main crates are:
There is one binary crate revme
. It is used for running Ethereum state tests json.
Library crates
- revm:
- primitives:
- interpreter:
- precompile:
- database:
- database/interface:
- bytecode:
- state:
- specification:
- context:
- context/interface:
- handler:
variants
- optimism
- inspector
utility
- statetest-types:
examples
- block_traces:
- cheatcode_inspector:
- contract_deployment:
- database_components:
- uniswap_get_reserves:
- uniswap_v2_usdc_swap:
- erc20_gas:
Dependency of library crates can be seen here
TODO Add dependency graph here
Revm Framework
Creating new variant of Revm is done by using a framework that is provided by the project. The framework is a set of traits that can be overridden to create a new logic that is needed. Overriding those traits can add new precompile or omit/change some logic of the EVM.
The main traits that are used for creating a new variant are:
Steps to implement a new variant:
- Include Revm
- Add main Evm type
MyEvm
and give it a Context, Precompile, Instructions and optionally Inspector. - Implement EvmTr for
MyEvm
. - Create a empty
MyEvmHandler
type and implementHandler for it. Override any logic that you want. - Now you can use
MyEvmHandler
to run your ownMyEvm
instance. Other steps are more for agronomics and easier usage. - Create a
MyContextBuilder
trait that will build your context with default types you want to use. - Create a
MyEvmBuilder
trait that will build your Evm with default instructions and precompiles. - Implement
ExecuteEvm
,ExecuteCommitEvm
to have same interface as any other variant of EVM.
Dev Section
Contains information for developers who want to build and develop revm.
Building from source
git clone https://github.com/bluealloy/revm.git
cd revm
cargo build --release
Note: This project tends to use the newest rust version, so if you're encountering a build error try running rustup update first.
Note: clang
is required for building revm with c-kzg
or secp256k1
feature flags as they depend on C
libraries. If you don't have it installed, you can install it with apt install clang
.
Importing crates
Main crate is revm, inspection is in saparate crate revm-inspection and revm-database has a few database implementations.
Current versions of those crates are:
revm = "20.0.0-alpha.1"
revm-inspection = "0.1.0"
revm-database = "0.1.0"
Additional tools that can be useful can be found in Awesome Revm section of the book. For example paradigm/revm-inspector crate contains a lot of Inspector used for tracing inside Reth and Foundry.
no_std support
If you are in need of no_std support you would need to use no-default-features flag and disable default features. All crates (expect revme binary) support no_std in some capacity.
Downside of no_std support is that of right now we don't have a bls12-381 implementation that is no_std compatible. PR that would solve this:
Use case
Below is a simple usage example of Execution API: where we create an EVM and transact a transaction or when we want to generate traces with the inspector.
let mut evm = Context::mainnet().with_block(block).build_mainnet();
let out = evm.transact(tx);
// or you can use powerful inspection tool to trace it
let mut evm = evm.with_inspector(tracer);
let out = evm.inspect_with_tx(tx);
The usage of the Evm Framework API is a bit more complex, but it is extensively explained here. It allows extending logic, adding different context types, and supporting inspection out of the box. For an example, you can check the revm-optimism crate.
Examples section of the book lists all examples that are available in the repository. And it is good starting point for understanding how to use revm.
Running eth tests
Eth tests are suite of tests from Ethereum Fondation that are used to test EVM implementations.
Part of these tests are included in revm repository in tests
folder.
Download eth tests from (this will take some time): git clone https://github.com/ethereum/tests
all statetest that can be run by revme can be found in GeneralStateTests
folder.
When you have downlodaed the test they can be run via revme
with command:
cargo run --release -p revme -- statetest tests/GeneralStateTests/ tests/LegacyTests/Constantinople/GeneralStateTests
After running cargo build --release -p revme
the revme
binary can be found in target/release
folder.
CI/CD
CI/CD runs on GitHub actions and will test no_std/clippy/fmt correctness of the code. It will also run el statetests and benchmarks with codspeed. You can find the configuration in .github/workflows
folder.
List of examples
- "examples/block_traces",
- "examples/contract_deployment",
- "examples/database_components",
- "examples/uniswap_get_reserves",
- "examples/uniswap_v2_usdc_swap",
- "examples/erc20_gas",
- "examples/cheatcode_inspector" PENDING
Release procedure
This document describes the procedure for releasing a new version of the revm
project. The repository is hosted on github and the published to the crates. Every published crate is part of one tag (currently tag v55) that contains all crates versions. The versions depending on the change can be major, minor or patch, we dont have one version for all packages.
Link of tag to the particular version of the crate can be found in CHANGELOG file.
CI/CD
On every pull request all statetest are run.
revme
Is a binary crate that is used for running Ethereum state tests json and it has few other utilities.
It can be downloaded from crates as crates install revme
.
Test can be found here tests
or from the ethereum tests repository.
Contact
Git repo can be found https://github.com/bluealloy/revm/
For questions please open github issue or join public telegram group: https://t.me/+Ig4WDWOzikA3MzA0
Licence
Licensed under MIT Licence.
unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions.
Security
If there is security question/findings please contact me directly on email atdragan0rakita@gmail.com
or on keybase @draganrakita.