pyrevm Python Bindings

repository·master·Indexed 41 days ago

https://github.com/paradigmxyz/pyrevm

High-performance Python bindings to the revm Ethereum Virtual Machine implementation written in Rust. Version 0.3.7 allows developers to simulate transactions, fork from remote nodes, manage state with snapshots and reverts, and configure EVM environments using Env, BlockEnv, and TxEnv.

Tokens
4.3K
Snippets
18
Records
22
Agent score
52%

What's inside pyrevm

  1. Manage state with checkpoints (snapshot and revert)

    master

    pyrevm supports state management through checkpoints. You can take a snapshot() of the current state and later revert(checkpoint) to that state. Alternatively, you can use commit() to clear all existing checkpoints.

    Note: Unlike the Rust implementation, the Python library does not automatically commit to the database.

    from pyrevm import EVM
    
    evm = EVM()
    checkpoint = evm.snapshot()
    evm.message_call(
        caller=...,
        to=...,
        value=...,
    )
    evm.revert(checkpoint)  # or: evm.commit() to clear all checkpoints
  2. Build pyrevm for development or production

    master

    The project uses Maturin for Rust/Python FFI. Use the following commands to build the library:

    • make build: Build for development.
    • make build-prod: Build for production (recommended to avoid performance degradation).
    • make test: Run the test suite.
    make build
    # or for production
    make build-prod
  3. Manage state with snapshots and reverts

    master

    The EVM class provides a mechanism to checkpoint the state and revert to it later using JournalCheckpoint objects.

    1. snapshot(): Creates a checkpoint of the current journaled state. Returns a JournalCheckpoint object.
    2. revert(checkpoint): Reverts the EVM state to the state captured in the provided checkpoint. Raises PyOverflowError if no checkpoint exists or PyKeyError if the checkpoint is invalid.
    3. commit(): Commits the current journaled state changes to the underlying database.
    # Example: Snapshot, execute, and revert
    checkpoint = evm.snapshot()
    
    # ... perform state-changing operations ...
    
    evm.revert(checkpoint)
    # State is now back to what it was at the snapshot
  4. Initialize a new EVM instance

    master

    Create a new EVM instance using the EVM() constructor. You can initialize it with a custom environment, fork from a remote node, or use an in-memory database.

    Parameters:

    • env (optional): An Env object to define the initial block and transaction environment.
    • fork_url (optional): A string URL to fork the state from a remote node.
    • fork_block (optional): A string representing the block number to fork from.
    • gas_limit (optional): A u64 representing the gas limit for calls and deployments (defaults to 18446744073709551615).
    • tracing (optional): A boolean to enable/disable execution tracing (defaults to false).
    • spec_id (optional): A string defining the EVM specification version (e.g., "LATEST").
    # Example: Initialize EVM with a remote fork
    evm = EVM(fork_url="https://eth-mainnet.g.alchemy.com/v2/your-api-key", fork_block="18000000", tracing=True)
    
    # Example: Initialize in-memory EVM
    evm = EVM(spec_id="LONDON")
  5. Simulate transactions by forking from a remote node

    master

    You can initialize an EVM instance by providing a fork_url to fork from a remote Ethereum node (e.g., Infura). This allows you to simulate transactions against real mainnet state. You can also configure the environment using Env and BlockEnv to set specific block parameters like timestamp.

    from pyrevm import EVM, Env, BlockEnv
    
    address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"  # vitalik.eth
    address2 = "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
    fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27"
    
    # set up an evm
    evm = EVM(
        fork_url=fork_url,
        tracing=True,
        env=Env(
            block=BlockEnv(timestamp=100)
        )
    )
    
    # Execute a transaction via message_call
    evm.message_call(
        caller=address,
        to=address2,
        value=10000
    )
  6. Configure the EVM environment with Env

    master

    The Env class is the top-level container for the EVM state, composing three distinct environment components: CfgEnv (configuration), BlockEnv (block parameters), and TxEnv (transaction parameters). You can initialize it by passing these components or use the default values.

    To create a new environment, use Env(cfg, block, tx) where each argument is optional.

    # Example of creating an Env with custom components
    cfg = CfgEnv(chain_id=1)
    block = BlockEnv(number=U256('12345'))
    tx = TxEnv(caller='0x...', value=U256('100'))
    env = Env(cfg, block, tx)
  7. Execute a message call

    master

    Perform a message_call to a specific address. This simulates a call from a caller to a to address with optional calldata, value, gas, and gas_price.

    Parameters:

    • caller: The address making the call.
    • to: The target address.
    • calldata (optional): The bytes to be sent.
    • value (optional): The amount of Ether to send.
    • gas (optional): The gas limit for the call.
    • gas_price (optional): The gas price.
    • is_static: Boolean indicating if the call should be treated as a static call.
    # Example: Call a function on a contract
    calldata = b"\x0a\x00\x00\x00..."
    result = evm.message_call(
        caller="0x1234567890123456789012345678901234567890",
        to="0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
        calldata=calldata,
        value=10**18,
        gas=100000
    )
  8. Query account and storage data

    master

    Use the following methods to inspect the state of the EVM:

    • basic(address): Returns an AccountInfo object for the given address.
    • get_code(address): Returns the contract bytecode at the address as bytes, or None if no code exists.
    • storage(address, index): Returns the U256 value stored at a specific storage slot (index) for the given address.
    • get_balance(address): Returns the U256 balance of the given address.
    • block_hash(number): Returns the hash of the block at the specified number as bytes.
    # Example: Check contract storage
    slot = 0x0
    value = evm.storage("0xContractAddress", slot)
    print(f"Value at slot {slot}: {value}")
    
    # Example: Get balance
    balance = evm.get_balance("0xUserAddress")
  9. Access data from a Log object

    master

    When a transaction emits events, you can inspect them using the Log class. Each Log object provides access to the event's metadata and payload.

    Available properties:

    • address: The address of the contract that emitted the log (as a String).
    • topics: A list of log topics (as Strings).
    • data: Returns a tuple containing (topics, data).
      • topics: A list of PyBytes objects representing the topics.
      • data: A PyBytes object representing the raw log data.
  10. Configure transaction settings with TxEnv

    master

    The TxEnv class defines the parameters for a specific transaction. It supports standard fields like caller, gas_limit, value, and data, as well as EIP-4844 features like blob_hashes and max_fee_per_blob_gas.

    Key Parameters:

    • caller: The address of the transaction sender (string).
    • gas_limit: Maximum gas allowed (u64).
    • to: The recipient address (string). If omitted, the transaction is treated as a contract creation. If a salt is provided, it defaults to a CREATE2 scheme.
    • value: The amount of Ether to send (U256).
    • data: The transaction payload (bytes).
    • access_list: A list of tuples containing (address, [nonce, ...]) for EIP-2930.
    • blob_hashes: A list of blob hashes for EIP-4844.
    • max_fee_per_blob_gas: Maximum fee per blob gas (U256).
    # Example: Creating a standard transfer transaction
    tx = TxEnv(
        caller='0x1234567890123456789012345678901234567890',
        to='0x0987654321098765432109876543210987654321',
        value=U256('1000000000000000000'),
        gas_limit=21000
    )