Revm

CI License Chat

Revm is a highly efficient and stable implementation of the Ethereum Virtual Machine (EVM) written in Rust.

banner

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:

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

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

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 on secp256k1 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:

  1. Include Revm
  2. Add main Evm type MyEvm and give it a Context, Precompile, Instructions and optionally Inspector.
  3. Implement EvmTr for MyEvm.
  4. Create a empty MyEvmHandler type and implementHandler for it. Override any logic that you want.
  5. Now you can use MyEvmHandler to run your own MyEvm instance. Other steps are more for agronomics and easier usage.
  6. Create a MyContextBuilder trait that will build your context with default types you want to use.
  7. Create a MyEvmBuilder trait that will build your Evm with default instructions and precompiles.
  8. 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.