For the complete documentation index, see llms.txt. This page is also available as Markdown.

Architecture

How Rome's components fit together — EVM execution inside a Solana program.

Rome embeds an EVM bytecode interpreter inside a Solana on-chain program. Users talk to the Rome Proxy over standard Ethereum JSON-RPC, and the proxy submits their transactions straight to the Rome EVM program on Solana. There is no separate execution layer to keep in sync — EVM state is Solana state.

System overview

User to Rome Proxy to the Rome EVM program on Solana, with Hercules indexing back

Components

Rome EVM Program (on-chain)

The core of Rome — a Solana BPF program containing a full EVM bytecode interpreter (a fork of SputnikVM). It:

  • Receives serialized EVM transactions as Solana instructions

  • Executes Solidity bytecode inside the Solana runtime

  • Maps each Ethereum address (H160) to a Solana PDA

  • Exposes precompiles for calling into Solana (CPI, System, Helper, Withdraw) alongside the standard Ethereum precompiles

  • Stores EVM state (balances, nonce, code, storage) as Solana account data

Rome Proxy (JSON-RPC server)

A standard Ethereum JSON-RPC server on port 9090 — the entry point for the public chains. It translates Ethereum API calls into Solana activity:

  • eth_sendRawTransaction → serialize the EVM tx → submit a Solana instruction

  • eth_call → emulate execution off-chain via the Mollusk SVM emulator

  • eth_estimateGas → simulate for gas estimation

  • eth_getBalance, eth_getCode, eth_getBlockByNumber, receipts, logs → served from indexed state

It also exposes Rome extensions: rome_emulateTx, rome_emulateRegRollup, rome_mintId, rome_buildInfo, rome_getResources, and more.

Hercules (indexer)

Watches the Rome EVM program on Solana and reconstructs Ethereum-compatible blocks — transactions, receipts, logs, and state changes — backed by PostgreSQL. On the public chains it runs in slot-aligned mode, so a block number maps to a Solana slot and the same slot yields the same block on any indexer. The proxy serves these blocks to wallets and explorers.

Precompiles

Rome implements the standard Ethereum precompiles (ecrecover, SHA-256, RIPEMD-160, identity, modexp, the BN254 curve operations, blake2f) with mainnet-equivalent semantics, plus non-EVM precompiles that reach into Solana: CpiProgram (0xFF…08, arbitrary CPI), System (0xFF…07, PDA derivation and base58 helpers), HelperProgram (0xFF…09, ATA/PDA creation, SPL transfers, gas↔lamports), and Withdraw (0x42…16). See the Contract Addresses reference for the full table.

Execution modes

Rome executes an EVM transaction in one of two ways:

Atomic (VmAt)

A single Solana transaction. The whole EVM transaction executes within one Solana transaction's compute budget (~1.4M compute units). Used for most operations — transfers, ordinary contract calls, swaps.

Iterative (VmIt)

For work that exceeds a single transaction's budget. Execution is split across multiple Solana transactions:

  1. Each step (a Solana transaction) runs as many EVM opcodes as fit in its compute budget — the step size is adaptive, not fixed

  2. VM state is Borsh-serialized into a StateHolder account between steps

  3. Accounts are TTL-locked for a few seconds during execution

  4. Used for heavy operations such as BN254 pairing

Account mapping

Every Ethereum address maps deterministically to a Solana PDA derived from the chain ID and the address under the Rome EVM program. That PDA owns the account's balance (as SPL token accounts), contract code, storage slots, and nonce — all as Solana account data.

Holder accounts

Solana transactions are capped at 1,232 bytes, but EVM transactions (especially contract deployments) can be much larger. Rome stages large transactions into holder accounts: the transaction is split into chunks written sequentially into a holder (up to 80 KB), then assembled and executed on-chain. The Rome SDK manages this transparently.

Gas and pricing

Each chain has its own gas token — any SPL token. Gas pricing reads a Meteora DAMM pool (v1 or v2, configurable) to convert between the gas token and SOL for the underlying Solana transaction fees.

What's next

Last updated

Was this helpful?