Etherlink RPC: A Developer's Guide (Chain ID 42793)

By John Sullivan · October 20, 2026 · 7 min read · #etherlink #etherlink rpc #tezos #layer 2 #developer guide

Etherlink is an EVM rollup that settles on Tezos. You write Solidity, use viem or ethers, and pay gas in XTZ. The node software is not Geth: it is octez-evm-node, written in OCaml by the Tezos core developers. It answers the usual eth_ methods, but a few answers differ from what Ethereum tooling expects. The biggest difference is gas: a plain value transfer uses about 621,000 gas, not 21,000.

Everything below was measured against the live chain on October 20, 2026. We used the SwiftNodes endpoint, the official public node node.mainnet.etherlink.com, and dRPC.

The endpoint

https://rpc.swiftnodes.io/rpc/etherlink?key=YOUR_API_KEY
wss://rpc.swiftnodes.io/ws/etherlink?key=YOUR_API_KEY
import { createPublicClient, http, defineChain } from "viem";

const etherlink = defineChain({
  id: 42793,
  name: "Etherlink",
  nativeCurrency: { name: "Tez", symbol: "XTZ", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.swiftnodes.io/rpc/etherlink?key=YOUR_API_KEY"] } },
});

const client = createPublicClient({ chain: etherlink, transport: http() });

viem also ships etherlink in viem/chains, so you can import it and only override the RPC URL. XTZ has 18 decimals on Etherlink, so formatEther gives you XTZ.

What we measured

Property Value
Chain ID 42793 (0xa729)
Client octez-evm-node 0.67
Block 1 May 2, 2024
Average block interval 1.09 s over 100,000 blocks, 1.52 s over the last 1,000
Transactions per block 1.7 on average; no empty blocks in 300
Block gas limit 1,125,899,906,842,624 (2^50)
Base fee 1 gwei in every block sampled
eth_maxPriorityFeePerGas 0
eth_gasPrice 1 gwei
Plain XTZ transfer 621,000 gas used, 0.000621 XTZ
finalized tag 15 to 28 blocks behind the head
safe tag rejected
eth_getLogs range 500 blocks
Historical state full history, back to the first blocks

The 2^50 gas limit is a placeholder, not a real capacity figure. Etherlink limits throughput in ticks, its own unit of execution work, and not in block gas. Do not size batches from gasLimit.

Block timestamps have one-second resolution. In 300 consecutive blocks, 71 pairs had the same timestamp. If you compute rates from timestamp differences, average over many blocks.

A transfer is not 21,000 gas

This catches the most code. Etherlink charges two fees for every transaction:

  • The execution fee pays for running the transaction. It is gas used multiplied by the base fee, and it is burned.
  • The inclusion fee pays for writing the transaction to Tezos layer 1. It goes to the sequencer, and it grows with the size of the transaction.

The inclusion fee is collected as extra gas, so it shows up in gasUsed. We asked eth_estimateGas about the same transfer with more and more calldata:

Transaction eth_estimateGas
Plain transfer, no data 623,828
Transfer + 64 bytes of data 882,378
Transfer + 1 KB of data 4,761,546

That is about 4,000 gas for each byte of calldata, on top of the execution cost. Four plain transfers we sampled from the chain each used exactly 621,000 gas.

The rule is simple: call eth_estimateGas for every transaction, and never hardcode 21,000. A transfer capped at gas: 21000 runs out of gas: even eth_estimateGas with that cap answers -32005 The transaction failed: Halt { reason: OutOfGas(...) }. The estimate moved between our runs (624,852 in the morning, 623,828 later) because the inclusion fee follows the cost of data on layer 1. Estimate close to sending, and add a small margin.

const gas = await client.estimateGas({ account, to, value });
const gasLimit = (gas * 110n) / 100n; // 10% margin for inclusion-fee drift

Etherlink refunds unused gas, so a margin costs you nothing. More on the general pattern in estimating gas with eth_estimateGas.

Tips are ignored

The base fee was 1 gwei in all 20 blocks we sampled across the last 100,000. eth_maxPriorityFeePerGas returns 0, and Etherlink's documentation says the chain ignores maxPriorityFeePerGas and deducts only the execution and inclusion fees. A higher tip does not buy faster inclusion. The sequencer orders transactions as they arrive.

The fee can rise when demand for execution is high, so read eth_gasPrice rather than assuming 1 gwei forever. eth_feeHistory works, but it needs blockCount as a hex string:

eth_feeHistory(5, "latest", [25, 75])      -> Json_encoding.Cannot_destruct ... Unexpected number instead of string
eth_feeHistory("0x5", "latest", [25, 75])  -> ok, baseFeePerGas all 0x3b9aca00

viem and ethers already send hex, so this only affects hand-written requests. The gasUsedRatio values are around 0.000000002, because of the 2^50 placeholder limit. Any fee logic that reacts to block fullness sees an empty chain.

finalized works, safe does not

eth_getBlockByNumber("finalized") -> a block 15 to 28 behind the head
eth_getBlockByNumber("safe")      -> Json_encoding.Cannot_destruct ... Unexpected string instead of finalized

The error text lists the tags the node accepts: earliest, latest, pending and finalized. Code written for Ethereum that asks for safe gets a JSON decoding error, not a block. If your library defaults to safe, switch it to finalized.

finalized trailed the head by 15 to 28 blocks, 17 to 30 seconds, in our samples. That means the block's contents are final on Tezos layer 1. Withdrawals from Etherlink to Tezos are a different thing. A standard withdrawal waits out the rollup's challenge period, about two weeks. Etherlink is one of the chains in our survey of the finalized block tag across 62 chains.

Logs: 500 blocks at a time

Both public endpoints cap eth_getLogs at exactly 500 blocks. A 500-block range works and a 501-block range fails. The two endpoints fail with different errors:

Endpoint Error at 501 blocks
node.mainnet.etherlink.com -32062 Block range is too large
dRPC -32603 Error: Cannot request logs over more than 500 blocks

Adding an address filter does not lift the cap. A 5,000-block query for one contract fails the same way. If your error handling matches on message text, match both. Better, page at 500 blocks from the start:

const STEP = 500n;
for (let from = start; from <= end; from += STEP) {
  const to = from + STEP - 1n > end ? end : from + STEP - 1n;
  const logs = await client.getLogs({ address, fromBlock: from, toBlock: to });
  // handle logs
}

At about 1.1 seconds per block, 500 blocks is about 9 minutes of chain time, so a day of history is about 160 requests. Unfiltered, the chain emitted about 0.8 logs per block in our sample (414 logs in 500 blocks). See eth_getLogs range caps by provider for how other chains compare.

For live data, WebSocket newHeads works. The official node's WebSocket delivered a header every 0.7 seconds in our test, and the SwiftNodes WebSocket every 1.2 seconds.

Tracing: one endpoint has it, one does not

Method Official node SwiftNodes
eth_getBlockReceipts works works
eth_feeHistory works (hex count) works (hex count)
debug_traceTransaction (callTracer) refused works
debug_traceBlockByNumber refused works
debug_traceCall refused works
trace_block, trace_transaction refused not available
txpool_status disabled disabled
eth_getProof, eth_createAccessList not supported not supported

The official node refuses debug_ and trace_ with -32053 API key is not allowed to access method, even though you never sent a key. That message comes from Etherlink's node. It does not mean your SwiftNodes key lacks access. On SwiftNodes, debug_ calls go to an upstream that serves them, so callTracer works on paid plans. trace_ methods are not served by any Etherlink upstream we found.

txpool_status answers Method disabled, reason: restricted by blockchain schema. Etherlink has a central sequencer, so there is no public mempool to inspect.

Historical state is there

The official node keeps full history. We read contract code of Wrapped XTZ (0xc9B5…3EAb) at block 1,000,000, 5,000,000 and 20,000,000, and balances at old heights. Every call worked, and state before the contract existed came back empty, as expected. You do not need archive=1 on Etherlink for historical reads, but it works if your code always sends it. More on why this varies by chain in full node vs archive node.

Activity is concentrated. In 300 blocks, one contract (0x3d54…a3ab) received 384 of 512 transactions. If your app reads a chain-wide average, it mostly measures that contract.

Summary

  • EVM rollup on Tezos, chain ID 42793, gas in XTZ with 18 decimals, about one block per second.
  • A plain transfer uses about 621,000 gas, because the layer 1 data fee is charged as gas. Always estimate, add a margin, never hardcode 21,000.
  • Base fee 1 gwei, tips ignored. A transfer cost 0.000621 XTZ.
  • finalized works and trails by 17 to 30 seconds. safe returns a decoding error.
  • eth_getLogs is capped at 500 blocks on every endpoint, with two different error messages.
  • debug_ tracing is refused by the official node and works through SwiftNodes. No trace_ anywhere.

Etherlink endpoints and method support are on our Etherlink RPC page, with 126 other chains on the same key. Start free: the free tier needs no card.

J
John Sullivan
Infrastructure Writer, SwiftNodes

John Sullivan covers RPC infrastructure, node operations, and multi-chain development at SwiftNodes — what it actually takes to keep endpoints fast, fresh, and reliable across EVM and non-EVM networks.

Related posts

Try SwiftNodes free — multi-chain RPC across 83 networks, flat-rate pricing, pay by card or crypto, no KYC. Get an API key in 30 seconds →