revm Documentation

repository·main·Indexed 24 days ago

https://github.com/bluealloy/revm

A highly efficient and stable implementation of the Ethereum Virtual Machine (EVM) written in Rust. It functions as a standalone executor for processing transactions and a framework for building custom EVM variants. The project includes the revme binary for executing Ethereum state tests, a modular crate ecosystem for core execution, state management, and Ethereum compatibility, and high-level APIs such as ExecuteEvm, ExecuteCommitEvm, InspectEvm, and SystemCallEvm.

Tokens
94.6K
Snippets
117
Records
455
Agent score
80%

What's inside revm

  1. Understand the revm crate ecosystem

    main

    The revm project is modularized into several specialized crates. Depending on your needs, you can use the main revm crate which re-exports all other crates, or select specific components to minimize dependencies:

    • Core Execution: revm (main entry point), revm-interpreter (contains all instructions), and revm-handler (manages validation, pre/post execution, and call frames).
    • State & Data: revm-database-interface (traits for fetching state), revm-database (implementations of the database interface), revm-state (account and storage types), and revm-primitives (constants and primitive types).
    • Ethereum Compatibility: revm-precompile (Ethereum-defined precompiled contracts) and revm-bytecode (opcode tables, legacy analysis, and EOF validation).
    • Context & Tracing: revm-context-interface (traits for Block/Transaction/Cfg/Journal), revm-context (default implementations for those traits), and revm-inspector (supports inspectors and EIP-3155 tracer).
    • Testing: revm-statetest-types (structs for state testing).
  2. Understand the revm-ee-tests directory structure

    main

    The revm-ee-tests crate is organized as follows:

    • src/lib.rs: Contains snapshot comparison utilities, specifically TestdataConfig and compare_or_save_testdata.
    • src/revm_tests.rs: Contains integration tests for the mainnet revm implementation.
    • tests/revm_testdata/: Stores the golden JSON snapshots used for test comparisons.
    • eip8037.md: Documentation for the EIP-8037 / TIP-1016 State Gas test plan.

    Note on Snapshots: Snapshot files are automatically generated during the first test run and are compared against existing files on all subsequent runs.

  3. Explore Revm ecosystem resources

    main

    The Revm ecosystem includes various extensions, clients, tools, and tutorials for developers working with the Ethereum Virtual Machine in Rust. Use these resources to extend Revm functionality, integrate it into clients, or learn through practical examples.

    API Extensions

    • alloy-evm: An abstraction layer on top of revm providing common implementations of EVMs.
    • Trevm: A typestate API wrapper for revm.

    Clients and Tools

    • Reth: A modular, ultra-fast implementation of the Ethereum protocol.
    • Helios: A trustless, efficient, and portable multichain light client.
    • Foundry: A portable and modular toolkit for rapid Ethereum application development.
    • Hardhat: A comprehensive development environment for compiling, deploying, testing, and debugging.
    • OpTrace: A high-performance, GUI-based EVM debugger for deep-dive trace analysis.

    Frameworks and Libraries

    • revm-inspectors: Hooks for EVM execution.
    • Revmc: JIT and AOT compiler for the EVM, leveraging Revm.
    • mevlog-rs: A Rust-based CLI tool for querying and monitoring Ethereum transactions with EVM tracing capabilities.

    Learning and Tutorials

    • MyEvm: Example of a custom EVM implementation.
    • Uniswap Swap Example: Demonstrates a USDC swap on Uniswap V2.
    • revm-by-example: Practical examples using the Rust EVM.
    • Revm is All You Need: A guide on building simulated blockchain environments.
  4. What is the Inspector and how does it work?

    main

    The Inspector trait is REVM's mechanism for observing and tracing EVM execution. It provides hooks into every aspect of a transaction's lifecycle, allowing you to monitor state changes, trace calls, capture events, and even override execution behavior.

    It is primarily used for building debuggers, gas analyzers, security tools, and custom execution tracers. Because the trait provides default empty implementations, there is minimal overhead if you only implement the specific hooks you need.

    pub trait Inspector<CTX, INTR: InterpreterTypes> {
        // Opcode-level tracing
        fn step(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {}
        fn step_end(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {}
        
        // Call and creation tracing  
        fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> { None }
        fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {}
        fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> { None }
        fn create_end(&mut self, context: &mut CTX, inputs: &CreateInputs, outcome: &mut CreateOutcome) {}
        
        // Event tracing
        fn log(&mut self, context: &mut CTX, log: Log) {}
        fn log_full(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
            self.log(context, log)
        }
        fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {}
    }
  5. Extend the EVM using the EVM Framework API

    main
    The EVM Framework API is designed for advanced users who need to extend EVM logic, incorporate custom context types, or provide built-in support for inspection. While more complex than the standard Execution API, it allows for the implementation of different EVM variants (such as Optimism). For a practical implementation guide, refer to the my_evm example in the repository.
  6. Understand TIP-1016 State Gas accounting

    main

    TIP-1016 introduces a dual-limit gas accounting model. Instead of a single gas pool, gas is split into:

    1. Execution Gas (CPU work): Tracks the computational effort.
    2. State Gas: Tracks state-changing operations such as storage creation, account creation, and code deposits.

    This separation allows for a 'reservoir' model where execution gas can spill into a reservoir to accommodate state gas costs, provided the total gas limits are respected.

  7. How external state transitions work in REVM

    main

    External state transitions are updates to the Ethereum state that are not triggered by regular user transactions. Instead, they are initiated by the client (the application using REVM) at specific block boundaries (pre- or post-block hooks) using REVM's system_call mechanism.

    REVM does not automatically perform these transitions. If you are building an Ethereum client or a test harness, you are responsible for manually invoking these system calls at the appropriate block boundaries to ensure compliance with EIPs like EIP-4788 and EIP-2935.

  8. State Gas Propagation and Reservoir Refill

    main

    Propagation

    • Success: When a child (via CREATE or CALL) succeeds, its state_gas_spent and reservoir propagate to the parent.
    • Revert: If a child reverts, its state gas is consumed (not returned to the parent), but the parent's reservoir is refilled via handle_reservoir_remaining_gas to account for the state gas that was drawn from the regular gas budget.

    Reservoir Refill Mechanism

    When an execution result is HALT or REVERT (not OK), the reservoir is refilled using the formula: new_reservoir = reservoir + max(0, state_gas_spent - reservoir)

    This ensures that if state gas was deducted from the regular gas budget because the reservoir was empty, that amount is accounted for during the refill process.

  9. State Gas behavior for SSTORE, CREATE, and CALL

    main

    SSTORE

    • New Slot: Writing from zero to non-zero on a fresh slot charges sstore_set_state_gas.
    • Overwrite: Overwriting an existing non-zero slot does not charge additional state gas.
    • Zero to Zero: Writing zero to an already-zero slot charges no state gas.

    CREATE / CREATE2

    • Empty Code: Deploying 0-byte code charges create_state_gas.
    • With Code: Deploying code charges create_state_gas + (code_deposit_state_gas * number of bytes).
    • With SSTORE: If init code performs an SSTORE to a new slot, it charges create_state_gas + sstore_set_state_gas + code_deposit_state_gas.

    CALL

    • New Account: A CALL with value to a non-existent account charges new_account_state_gas.
    • Existing Account: A CALL to an existing account charges no state gas.
    • No Value: A CALL to a non-existent account without a value transfer charges no state gas.
  10. How `Inspector` logging works (v32.0.0 and v30.0.0)

    main

    The Inspector::log function was renamed to log to support different levels of detail.

    • log: Used when the Interpreter is not available.
    • log_full: Takes an Interpreter as input and provides more detailed logging. Its default implementation calls log.
  11. How `GasParams` works in revm v34.0.0

    main

    In version v34.0.0 (v103 tag), gas calculation logic was moved from revm-interpreter into a new GasParams struct. This struct allows you to set dynamic opcode gas parameters and is initialized within the cfg.

    Key changes:

    • Gas calculation functions are now part of GasParams.
    • Gas constants moved from revm_interpreter::gas to revm_context_interface::cfg::gas.