pyrevm: Python bindings for revm EVM

0.3.7 · active · verified Fri Apr 17

pyrevm provides Python bindings to revm, a high-performance Ethereum Virtual Machine (EVM) written in Rust. It enables Python developers to simulate Ethereum transactions, execute smart contracts, and interact with the EVM environment directly from Python, offering a fast and efficient way to prototype and test EVM-based logic. The current version is 0.3.7, and the project maintains an active development cadence, often mirroring the underlying revm library's updates.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to initialize an EVM instance, set up account states, and simulate both a contract call and a value transfer transaction using `pyrevm`. It requires `pyrevm` to be installed. Addresses and contract bytecode are provided as raw bytes for simplicity.

from pyrevm import EVM, CfgEnv, BlockEnv, TxEnv

# Example setup: a simple contract and an account
# Contract that returns 0 for a specific function call
CONTRACT_CODE = bytes.fromhex("6080604052348015600f57600080fd5b506004361060285760003560e01c806306fdde0314602d575b600080fd5b603a603c565b005b60005481565b")
CONTRACT_ADDRESS = bytes.fromhex("1234567890123456789012345678901234567890")
CALLER_ADDRESS = bytes.fromhex("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd")

# Function selector for the example contract (returns 0)
FUNCTION_SELECTOR = bytes.fromhex("06fdde03")

def run_evm_simulation():
    # 1. Initialize environment configurations
    cfg_env = CfgEnv(chain_id=1)
    block_env = BlockEnv(
        number=1, timestamp=1, gas_limit=1_000_000_000,
        miner=bytes.fromhex("0000000000000000000000000000000000000000"), basefee=1
    )
    tx_env = TxEnv(
        caller=CALLER_ADDRESS, gas_limit=1_000_000_000, gas_price=1, value=0,
        data=FUNCTION_SELECTOR, transact_to=CONTRACT_ADDRESS
    )

    # 2. Create an EVM instance
    evm = EVM(
        cfg=cfg_env,
        block=block_env,
        tx=tx_env # Initial transaction environment
    )

    # 3. Insert initial state (e.g., contract code and account balances)
    evm.insert_account_info(
        CONTRACT_ADDRESS,
        code=CONTRACT_CODE,
        balance=0,
        nonce=0
    )
    # Give caller some balance for transactions
    evm.insert_account_info(
        CALLER_ADDRESS,
        balance=1_000_000_000_000_000_000, # 1 ETH
        nonce=0
    )

    # 4. Perform a contract call
    call_result = evm.call_raw() # Uses tx_env set during EVM init
    
    print(f"--- Contract Call Simulation ---")
    print(f"Status: {call_result.status}")
    print(f"Gas Used: {call_result.gas_used}")
    print(f"Exit Reason: {call_result.exit_reason}")
    print(f"Output: {call_result.result.hex()}")

    # 5. Perform a simple value transfer transaction
    recipient_address = bytes.fromhex("feeefeeefeeefeeefeeefeeefeeefeeefeeefeee")
    transfer_amount = 1000 # wei

    # Update tx_env for the transaction
    tx_env.data = b'' # No data for simple transfer
    tx_env.transact_to = recipient_address
    tx_env.value = transfer_amount

    # Perform the transaction
    transact_result = evm.transact_raw() # Uses updated tx_env
    
    print(f"\n--- Value Transfer Simulation ---")
    print(f"Status: {transact_result.status}")
    print(f"Gas Used: {transact_result.gas_used}")
    print(f"Exit Reason: {transact_result.exit_reason}")
    print(f"Output: {transact_result.result.hex()}")

if __name__ == "__main__":
    run_evm_simulation()

view raw JSON →