Skip to Content
Supra Layer 1SupraEVMDifferences from Ethereum

Differences from Ethereum

A Supra node serves the Ethereum JSON-RPC API at /rpc/v1/eth, with Ethereum’s transaction envelopes, address format and log format; on Devnet that is https://rpc-devnet.supra.com/rpc/v1/eth. Compilers, ABIs and signing libraries carry over unchanged, and so does a contract unless it reads one of the block values or system contracts that differ. This page states what changes for existing contracts and tooling.

The node describes every method, its parameters and its errors on its /docs page, generated from the version it runs; Devnet’s is https://rpc-devnet.supra.com/docs. Per-method parameter rules, debug_traceCall’s options, and each method’s answer for a pruned height or a height above the tip are stated there. Gas, fees, transaction types and the EVM version are in Gas and Fees.

Block values and system contracts

OpcodeSolidityOn SupraEVMOn Ethereum
COINBASEblock.coinbasethe zero address; no fee is paid to it (Where the fee goes)the block’s fee recipient
PREVRANDAO (DIFFICULTY)block.prevrandao, block.difficulty0; for randomness, use the randomness precompilethe beacon chain’s RANDAO value
GASLIMITblock.gaslimitthe epoch’s block gas budget plus its per-transaction gas cap, in a block and under eth_call, eth_estimateGas and debug_traceCall; the block header’s gasLimit adds the gas the block’s system pseudo-transactions used (GASLIMIT)the block header’s gasLimit
TIMESTAMPblock.timestampseconds, truncated from the block’s microsecond timestamp (Block Timestamp)seconds
BLOCKHASHblockhash(n)the hash eth_getBlockByNumber returns for block n, for the 256 blocks before the current onethe same
BLOBHASHblobhash(i)0the versioned hash of the transaction’s ith blob
BLOBBASEFEEblock.blobbasefee1the block’s blob base fee

GASLIMIT

GASLIMIT (block.gaslimit) returns the block gas limit of the epoch the block belongs to: the epoch’s block gas budget plus its per-transaction gas cap. It returns that value to every transaction a block executes, submitted and system alike, and to eth_call, eth_estimateGas and debug_traceCall simulated in that block, whatever gas limit the request is simulated with.

A block header’s gasLimit is that value plus the gas the block’s block-metadata transaction, automated transactions and automation records used, which is known only once the block has executed. The two differ by that gas.

Blob transactions (type 3) are refused at submission; the transaction types accepted are in Gas and Fees.

Ethereum’s system contracts are not deployed. There is no code at the EIP-2935 block-hash history contract (0x0000F90827F1C53a10cb7A02335B175320002935), the EIP-4788 beacon-root contract (0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02), the EIP-7002 and EIP-7251 request contracts (0x00000961Ef480Eb55e80D19ad83579A64c007002, 0x0000BBdDc7CE488642fb579F8B00f3a590007251), or the deposit contract (0x00000000219ab540356cBB839Cbe05303d7705Fa). A block hash older than 256 blocks cannot be read on chain. The contracts that are deployed at fixed addresses are listed in Predeployed Contracts.

A block’s hash is the hash the consensus layer certified, not keccak256 of the RLP-encoded header, and the header’s stateRoot, transactionsRoot, receiptsRoot and sha3Uncles are zero. A client cannot recompute a block hash from its header or verify a Merkle proof against a header root, and eth_getProof is not served.

The node keeps current state only

The node holds the state at the chain’s head and no earlier state. A balance, code, a storage slot or a call simulated as of a past height is not available from any method, so code that depends on one has to be changed rather than pointed at another endpoint. Blocks, transactions, receipts and logs are served for every height the node retains.

The wallet-integration endpoint

/rpc/v1/eth/wallet_integration serves the methods /rpc/v1/eth serves except debug_traceCall, which it answers with -32601. For eth_call, eth_estimateGas, eth_getBalance, eth_getCode, eth_getStorageAt and eth_getTransactionCount it accepts any block parameter, for wallet software that sends one /rpc/v1/eth refuses. The parameter is accepted, not honoured: the answer describes the head whatever height was named, with one exception. eth_estimateGas given a height or earliest runs in that block’s environment — its number, timestamp, base fee and randomness seed, and its epoch’s EVM version and per-transaction gas cap — against the latest state, because EVM state is kept for the latest block only. Given a block hash, it is answered for the head.

A 200 from this endpoint carries the height it was answered from in the x-supra-block-height response header, as a decimal string; for a batch it is a lower bound on the height each method saw. The header is omitted when the node has no executed block, and /rpc/v1/eth does not send it.

Block tags and finality

Every tag but earliest resolves to the newest executed block. earliest resolves to the oldest block the node still retains, which is genesis only on a node that has not pruned.

The methods that name a block to read (eth_getBlockByNumber, eth_getBlockTransactionCountByNumber, eth_getTransactionByBlockNumberAndIndex, eth_getLogs, eth_feeHistory) accept every tag and a height. An eth_getLogs range whose fromBlock is above the head, or above toBlock, is answered with an empty list rather than an error. For the methods that read or simulate against state, a block parameter naming exactly the state the node would return is accepted; one naming a different state is refused with -39001 (“Unknown block”). safe and finalized resolve to the head, so their answer is byte-identical to the latest answer, while a height and earliest name a state this node does not keep. pending is answered from committed state; eth_getTransactionCount adds the sender’s accepted-but-unexecuted transactions to it, and eth_getBalance, eth_getCode and eth_getStorageAt refuse it.

safe and finalized resolve to the newest executed block because that block is already final: a block is executed only after consensus has committed it. A client whose confirmation rule reads finalized is given the same block, with the same guarantee, as one reading latest.

A height below the node’s retention floor is answered with -32002 and the floor in data.oldestBlock. Devnet’s retention window is in Devnet.

Following logs

The filter API is not served. Poll eth_getLogs over a height range, advancing fromBlock with eth_blockNumber, or subscribe with eth_subscribe ["logs", <filter>] over WebSocket. A library helper that watches events through eth_newFilter has to be configured for one of these instead.

Methods not served

A method the node does not serve is answered with -32601 and geth’s wording, the method <name> does not exist/is not available. The six filter methods also carry the supported alternative in data.alternative; no other unsupported method carries data:

{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32601, "message": "the method eth_newFilter does not exist/is not available", "data": { "alternative": "Poll eth_getLogs over a height range, advancing fromBlock with eth_blockNumber, or subscribe with eth_subscribe [\"logs\", filter] on the WebSocket endpoint." } } }
Not servedUse instead
debug_traceTransaction, trace_*The receipt, which states why a transaction failed, and its logs. No method reports an executed transaction’s internal calls; debug_traceCall runs against the head, not the past block.
txpool_*, eth_subscribe ["newPendingTransactions"]Nothing enumerates the pending pool. eth_getTransactionByHash answers for an accepted, unexecuted transaction with blockNumber null; supra_executedTransactions streams transactions once executed.
The six filter methods (eth_newFilter, eth_newBlockFilter, eth_newPendingTransactionFilter, eth_getFilterChanges, eth_getFilterLogs, eth_uninstallFilter)Following logs, and newHeads for new blocks.

eth_subscribe ["newPendingTransactions"] is answered with -32602 and Unsupported subscription type.

Methods that need state proofs, an unlocked account or a multi-block simulation are not served either, among them eth_getProof, eth_createAccessList, eth_simulateV1, eth_accounts, eth_sign, eth_signTransaction, eth_sendTransaction, eth_coinbase, eth_mining, eth_blobBaseFee, the eth_getUncle* methods, net_listening, net_peerCount and web3_sha3. Sign transactions in the client and submit them with eth_sendRawTransaction.

eth_call and eth_estimateGas refuse state and block overrides (their third and fourth parameters) with -32602, unless the override is null or {}.

eth_syncing, web3_clientVersion, and the block transaction-count and by-index methods are served. net_version returns the chain ID as a decimal string.

debug_traceCall implements callTracer and prestateTracer, and is served on /rpc/v1/eth and the WebSocket endpoint. Its options and bounds are on the /docs page.

Transaction and log indices

transactionIndex is a transaction’s position among the block’s EVM transactions, 0..n in execution order, as listed by eth_getBlockByNumber, eth_getBlockByHash and eth_getBlockReceipts. logIndex is block-wide over the block’s EVM logs only.

A Supra block also carries Move transactions. The REST endpoints GET /rpc/v4/block/height/{height}?with_finalized_transactions=true and GET /rpc/v4/block/{block_hash}/transactions list every transaction of the block across both virtual machines, so an EVM transaction’s position there is not its transactionIndex. The transaction hash is the join key between the two.

System pseudo-transactions

Four kinds of transaction that no user signed appear in blocks, receipts and logs, and in the supra_executedTransactions and logs subscriptions:

  • Block-metadata: the first transaction of every block, one per block.
  • Settlement credits: a cross-VM crossing into SupraEVM, directly after block-metadata.
  • Automated transactions: the execution of a due automation task.
  • Automation records: the automation registry’s per-cycle bookkeeping, and the removal of faulty tasks and of tasks a change of the EVM gas config no longer admits.

Each uses the EIP-1559 (type 0x2) envelope with v, r and s all 0, and a real from: the automation task’s sender for an automated transaction, the node’s system-account address for the other three. Block-metadata and automation records carry the to and input executed; a settlement credit’s to is the recipient and its input is empty. Each carries a top-level supraTxKind field, "blockMetadata", "settlement", "automated" or "automationRecord", absent on user transactions. A block’s gasUsed includes them, and its gasLimit includes the gas its block-metadata, automated transactions and automation records used; see The block gas budget. GASLIMIT does not include that gas; see GASLIMIT.

A settlement credit’s receipt describes its EVM leg only, and carries one log naming the crossing’s settlement id (the credit log); the rest of the crossing is traced as in Tracing Cross-VM Transfers.

Why a transaction failed

The receipt of a transaction whose status is 0x0, from eth_getTransactionReceipt or eth_getBlockReceipts, carries fields beside the standard ones:

  • error: execution reverted for a revert, the reason for a halt (out of gas, invalid opcode, …), or the rejection message, which begins with geth’s string where geth reports the same rejection.
  • revertReason: for a revert, the decoded Error(string), Panic(uint256) or UTF-8 reason. Absent when none decodes or it is empty.
  • output: for a revert, the raw returndata as hex, from which a custom error is decoded.
  • outputTruncated, revertReasonTruncated: true when the field holds the first 4096 bytes of a longer value.

A successful receipt carries none of them. Replaying a mined transaction with eth_call at its block does not work here, since eth_call answers from the head.

WebSocket subscriptions

The WebSocket endpoint is at /rpc/v1/eth, reached with a GET upgrade, text frames only; on Devnet it is wss://rpc-devnet.supra.com/rpc/v1/eth. It serves every method the HTTP endpoint serves, and its answers carry no HTTP status.

  • eth_subscribe ["newHeads"]: the EVM block header of each executed block.
  • eth_subscribe ["logs", <filter>]: logs matching an address and topics filter; all logs if it is omitted.
  • eth_subscribe ["supra_executedTransactions", {"hashesOnly": <bool>}]: each executed block’s EVM transactions in block order, pseudo-transactions included. The default, false, delivers {"transaction": {…}, "tx_output_info": {…}}.
  • eth_unsubscribe ["<subscription-id>"]: answers true or false.

A subscription id is a UUID string, not a hex quantity. eth_subscribe ["syncing"] is not supported.

Notifications are eth_subscription messages whose params hold subscription and result. Connection and subscription caps are in Devnet.

Error codes

CodeMeaningRaised for
3Execution revertedA reverting eth_call or eth_estimateGas; data holds the returndata.
-32601Method not foundA method not served; debug_traceCall on the wallet-integration endpoint.
-32602Invalid parametersA malformed or refused parameter; newPendingTransactions.
-32002Resource unavailableA height below the retention floor, with data.oldestBlock; a node still starting, without data.
-32005Limit exceededAn eth_getLogs range or result set, or a debug_traceCall frame count, over the node’s bound.
-39001Unknown blockA height or earliest sent to a method that reads current state; an eth_feeHistory newestBlock above the tip, with data.latestBlock; an eth_getLogs blockHash the node holds no block for.
-32000Server errorA transaction refused at submission, with the reason in the message; an eth_call or eth_estimateGas that halts rather than reverts.
-32001Resource not foundA named resource that does not exist, or a block in an epoch in which SupraEVM was not active.
-32603Internal errorA fault on the node.
-32700Parse errorA request body that is not JSON.
-32600Invalid requestA JSON body that is not a JSON-RPC request.
Last updated on