Skip to content

EVM#5410

Open
mpapierski wants to merge 15 commits into
casper-network:devfrom
mpapierski:evm
Open

EVM#5410
mpapierski wants to merge 15 commits into
casper-network:devfrom
mpapierski:evm

Conversation

@mpapierski
Copy link
Copy Markdown
Collaborator

@mpapierski mpapierski commented May 21, 2026

Summary

This PR adds a proof-of-concept EVM execution path to casper-node. It proves that Casper can accept, validate, execute, account for, and persist Ethereum-shaped transactions while keeping the execution and storage model rooted in Casper: global state, transaction flow, account/purse accounting, fee/refund policy.

The companion casper-sidecar changes in casper-network/casper-sidecar#468 provide the Ethereum JSON-RPC surface for this PoC. Sidecar currently implements eth_chainId, eth_blockNumber, eth_getBlockByNumber, eth_getTransactionCount, eth_sendRawTransaction, eth_getTransactionReceipt, eth_getLogs, eth_newFilter, eth_getFilterChanges, eth_getFilterLogs, eth_uninstallFilter, eth_call, and websocket log subscriptions. It uses node binary-port APIs to submit signed EVM transactions, run speculative EVM calls, read blocks and transaction execution info, and project Casper EVM receipts/logs into Ethereum-compatible JSON-RPC responses.

What Changed

On the node side, this branch introduces:

  • Transaction::Evm and TransactionHash::Evm.
  • Casper-owned EVM types for addresses, hashes, transactions, accounts, config, receipts, logs, topics, and Ethereum-style U256 JSON quantities.
  • A new casper-executor-evm crate backed by revm.
  • EVM global-state keys for account identity, nonce, code hash, bytecode, and storage.
  • ExecutionResult::Evm, carrying EVM receipt data plus Casper accounting fields.
  • Transaction acceptor support for EVM enablement, signature validation, chain ID, gas limit, base fee, priority fee, balance, and nonce checks.
  • Contract-runtime routing for finalized EVM transactions.
  • Casper fee/refund handling for EVM transactions.
  • Binary-port speculative execution support for read-only eth_call.
  • Native Casper transfers to 20-byte EVM addresses when EVM is enabled.
  • EIP-7702 set-code transaction support.

What Works

The current PoC supports signed Ethereum RLP ingestion through sidecar, conversion into Transaction::Evm, node-side validation, execution through revm, persistence of EVM state, and Ethereum-compatible receipt projection.

Tested flows include contract deployment, contract calls, native EVM value transfer, event logs in receipts, simple ERC20/ERC721-style behavior, speculative eth_call, native Casper funding of EVM addresses, and EIP-7702 delegated-code execution using Foundry.

The PoC supports the Ethereum transaction envelopes needed for the current tooling flow:

  • Legacy transactions, with EIP-155 chain ID replay protection.
  • EIP-2930 access-list transactions, only when the access list is empty.
  • EIP-1559 dynamic-fee transactions, only when max_priority_fee_per_gas == 0.
  • EIP-7702 set-code transactions, with non-empty authorization lists, empty access lists, and zero priority fee.

Prague/Pectra Compatibility

The executor is configured with a Prague-capable EVM spec, and this branch implements the main PoC execution path needed for EIP-7702. In that sense, the exercised EVM path is Prague-compatible.

It is not yet a complete Prague/Electra network implementation. The canonical Prague/Electra meta EIP is EIP-7600. Remaining Prague/Pectra work includes:

  • EIP-2537: BLS12-381 precompiles.
  • EIP-2935: historical block hash system contract.
  • EIP-6110: validator deposit requests.
  • EIP-7002: withdrawal request predeploy.
  • EIP-7251: consolidation request predeploy.
  • EIP-7623: calldata floor-cost accounting.
  • EIP-7685: execution-layer requests and requests_hash.
  • EIP-7691: Prague/Electra blob throughput parameters.
  • EIP-7549: consensus-layer change; no execution-layer work expected here.

Blob transactions are still rejected. Full blob support requires EIP-4844 sidecars, KZG data, blob gas accounting, and the Prague blob parameter updates from EIP-7691. Client configuration should also eventually account for EIP-7840.

Current Limitations

EVM is disabled by default in chainspecs and must be explicitly enabled.

The sidecar RPC surface is enough for the PoC Foundry flow, transaction submission, receipts, calls, logs, filters, and log subscriptions. Some Ethereum RPC methods are still future work, including eth_estimateGas, eth_getBalance, eth_getCode, and eth_getTransactionByHash.

eth_getBlockByNumber currently returns transaction hashes only; full transaction objects are explicitly rejected for now. Block and receipt projection still needs to mature around complete Ethereum roots, bloom handling, gas-used accounting, and historical query performance.

Access lists are decoded but non-empty lists are rejected. Priority fees are also rejected because Casper does not currently prioritize transactions using Ethereum fee-market tips.

Future Work

Next steps are to move this from PoC towards a spec-complete feature:

  • Add Prague/Pectra predeploy and system-contract handling.
  • Implement EIP-7685 request collection and block/header commitments.
  • Add blob transaction support, blob gas accounting, and blob schedule config.
  • Complete EIP-7623 calldata floor-cost accounting.
  • Define the long-term Casper policy for EVM base fee movement, priority fees, refunds, and fee distribution.
  • Add indexed EVM logs for efficient historical queries.
  • Expand sidecar RPC coverage and remove local patching once node-side types are released.
  • Add conformance tests for Prague precompiles, EIP-7702 edge cases, blob rejection/support, and gas accounting boundaries.

Not every Ethereum feature maps cleanly onto Casper’s existing execution, storage, accounting, and consensus model. For those cases, the plan is to make a best-effort compatibility layer, keep the Casper-side semantics explicit, and document where behavior intentionally differs from Ethereum mainnet.

Validation

This branch adds unit and integration coverage for EVM transaction decoding, approval handling, executor behavior, account/state storage, receipts, native transfers to EVM addresses, nonce validation, binary-port speculative EVM calls, Casper fee/refund handling, and EIP-7702 delegation behavior.

The manual Foundry validation flow is documented in EVM.md.

mpapierski added 15 commits May 21, 2026 17:00
Add shared EVM-native types, global-state keys and stored values,
chainspec configuration, and a new casper-executor-evm crate backed by
revm. The executor runs against a caller-provided TrackingCopy so callers
can decide whether to commit effects or discard a forked view execution.

This introduces typed EVM account, bytecode, and storage records so
contract state can be queried and pruned by address prefix. EVM balances
are backed by deterministic Casper main purses, with balance reads and
writes reconciled through existing purse balance storage.

Signed Ethereum RLP decoding and sender recovery are added to
casper-types for legacy, EIP-2930, and EIP-1559 transactions. Blob
transactions and EIP-7702 set-code transactions return explicit
unsupported errors in this first pass.

The node and storage layers learn the new transaction/hash/initiator
shapes without routing EVM transactions through existing Casper
transaction execution yet. Chainspecs now include disabled-by-default
EVM configuration with CSP namespace chain IDs.

Solidity fixtures, Makefile targets, and integration tests cover
deployment, calls, ERC20/ERC721 behavior, storage deletion,
selfdestruct semantics, and native EVM purse-balance reconciliation.
Require signed EVM transactions to carry the configured chain ID so
legacy pre-EIP-155 transactions cannot bypass the Casper EVM replay
domain. Reject non-empty Ethereum access lists until the executor maps
them into revm transaction environments.

Add explicit validation modes for unsigned call requests so simulation
calls remain available while commit-capable calls can opt into revm
balance, nonce, chain-id, base-fee, and gas-limit checks.

Add a block hash provider abstraction for the EVM BLOCKHASH opcode,
including an LMDB-backed provider for future node wiring and tests for
the 256-block lookup window. Complete selfdestruct cleanup by pruning
the deterministic main purse balance alongside the EVM account and
storage.# Please enter the commit message for your changes. Lines starting
Bump the pinned stable Rust toolchain from 1.85.1 to 1.91.0 so the workspace
can use dependencies that require the newer compiler.

Keep the existing Makefile lint gate on -D warnings while allowing lint
categories that were introduced or tightened by newer clippy versions and
would otherwise force unrelated API churn. Apply small mechanical updates
and targeted dead-code annotations needed for the 1.91.0 lint run.
Allow native transfer targets to be encoded as 20-byte EVM addresses when
EVM support is enabled. Resolve those targets to existing EVM account
purses or create deterministic EVM account records on first funding, while
preserving the native transfer record schema.

Stop seeding EVM accounts at genesis and require explicit funding through
native transfers. Reject EVM address transfer targets when EVM is disabled,
add the binary-port error code, and cover the genesis and transfer behavior
with tests.

Document the explicit EVM funding flow and add CL typing/schema support for
EVM addresses.
EVM addresses and Casper account hashes come from different preimages, so using
the same signing key currently gives users two separate identities. This change
adds a small identity record under `EvmAddr::Account` so an EVM address can
point either at an existing Casper account or at an EVM-native purse.

The old EVM account blob is split into separate records for identity, nonce,
code hash, bytecode, and storage. Runtime and transaction validation now resolve
the EVM sender before balance and nonce checks, while the executor only reads
and writes the new layout.

When an EVM transaction is signed by a key that already has a Casper account,
the runtime links the EVM sender address to that account. When no Casper account
exists yet, it creates one using the deterministic EVM purse as the main purse.
EVM-native accounts and contract-created accounts stay purse-backed and are not
forced into Casper account identities.

Native transfers to EVM addresses now follow the same identity model: linked
accounts credit the Casper main purse, EVM-native identities credit their purse,
and missing targets create the deterministic purse-backed identity first.

This also removes the unreleased `EvmValue::Account` and `EvmValue::ByteCode`
storage forms, storing bytecode as `StoredValue::ByteCode` instead.
Introduce type 0x04 EVM transaction decoding, serialization, signing,
verification, config checks, and executor translation. Store signed
authorization-list items as transaction data while keeping Casper approvals
limited to the outer Ethereum signature.

Pass EIP-7702 authorization lists through to revm so Prague execution handles
authority recovery, delegation writes, invalid-entry skipping, nonce updates,
and delegation clearing. Keep existing Casper policies for blob transactions,
non-empty access lists, and non-zero priority fees. Normalize missing dynamic
priority fees to zero in the executor to match validation.

Update sidecar dependency patches, receipt projection, raw transaction tests,
and JSON schema snapshots for type 0x04 transactions.

Document EIP-7702 support and devnet verification steps, and add coverage for
type-4 decoding, round trips, config compliance, executor semantics, and
sidecar raw transaction handling.
Remove the binary-port EVM call simulation command and route sidecar
read-only EVM calls through TrySpeculativeExec. Add an unsigned EVM call
marker transaction that carries chain ID and gas price so normal EVM
config compliance still applies before execution.

Return EVM speculative execution data through a dedicated binary-port
result type, and keep unsigned call marker transactions rejected by
transaction acceptance so they cannot be submitted as normal network
transactions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant