Ronin RPC After the Move to Ethereum L2: A Developer's Guide (Chain ID 2020)

By John Sullivan · October 3, 2026 · 6 min read · #ronin #ronin rpc #op stack #layer 2 #gaming #developer guide

Ronin spent four years as Sky Mavis's gaming sidechain, home of Axie Infinity. On May 12, 2026 it hard-forked into an Ethereum layer 2 built on the OP Stack, with Conduit running the migration and EigenDA providing data availability. The chain ID is still 2020, the token is still RON, and existing contracts kept their addresses. Almost everything an RPC client cares about changed anyway: block cadence, fees, finality, log limits and, most surprisingly, how far back you can read.

Most Ronin RPC guides were written for the sidechain. This one was measured on October 3, 2026 against the live chain, through the same endpoint you get from SwiftNodes.

The endpoint

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

const ronin = defineChain({
  id: 2020,
  name: "Ronin",
  nativeCurrency: { name: "RON", symbol: "RON", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.swiftnodes.io/rpc/ronin?key=YOUR_API_KEY"] } },
});

const client = createPublicClient({ chain: ronin, transport: http() });
console.log(await client.getBlockNumber());

web3_clientVersion returns conduit-op-reth, the same client family as Katana. Our Ronin route is HTTP only for now, so poll for new blocks instead of subscribing; at a 2-second cadence, polling every 2 seconds misses nothing.

What we measured

Property Value
Chain ID 2020 (0x7e4)
Block time 2.00 s (1,000-block average)
Gas limit 60,000,000
Base fee 20 gwei, unchanged across 2,000 sampled blocks
eth_gasPrice 21 gwei (base fee + 1 gwei tip)
safe lag ~252 blocks (~8.5 min)
finalized lag ~701 blocks (~23 min)
eth_getLogs max span 200 blocks
Earliest block served 55,577,500 (2026-05-12 22:09:47 UTC)
debug_traceTransaction / trace_block both available
eth_getBlockReceipts available

Two of those numbers will break code written for the old Ronin, and one will surprise anyone used to Ethereum.

Gotcha 1: no history before the migration

Ask the public RPC for block 50,000,000, or for block 1, and you get null. The first block it serves is 55,577,500, timestamped May 12, 2026; reports put the fork at 55,577,490, and the ten blocks in between aren't served either. State reads follow the same line: eth_getBalance at any earlier height returns no state found for block.

The layer 2's history simply begins at the fork. For an indexer this matters a lot:

  • Backfills that start at block 0 fail immediately. Start your cursor at 55,577,500 if you only need post-migration data.
  • Sidechain-era events (four years of Axie, Katana DEX and bridge history) are not reachable through this endpoint at any price tier. If you need them, you need an archive that preserved the old chain, and you should confirm that with your provider before you build on it.
  • Block numbers did not reset. The layer 2 continued the old numbering, so a stored block number from 2025 still means something; you just can't fetch it here.

Gotcha 2: eth_getLogs is capped at 200 blocks

The cap is exact: a 199-block span succeeds and 200 fails with

requested block range 201 exceeds the limit of 200; narrow your fromBlock/toBlock

At 2 seconds per block that's under seven minutes of chain time per call, one of the tightest limits we've measured; our getLogs range-cap survey shows most chains allow thousands of blocks. A day of Ronin is 43,200 blocks, so catching up one day takes 216 calls. Page deliberately:

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

Filter by address (and topics) wherever you can. The block span is the limit, but narrow filters keep each response small and quick.

Gotcha 3: the base fee doesn't move

Every block we sampled had a base fee of exactly 20 gwei, including a block that used 0.7% of its 60M gas limit. On Ethereum, a near-empty block would push the base fee down; here it sits at what behaves like a configured floor. eth_feeHistory agrees, returning the same 0x4a817c800 (20 gwei) for every block.

In practice:

  • maxFeePerGas of 21 to 25 gwei is plenty; eth_maxPriorityFeePerGas returns 1 gwei.
  • Don't build fee logic that expects the base fee to fall when the chain is quiet. It won't.
  • The 20 gwei is RON, not ETH. Gas is still paid in RON, so a simple transfer costs about 21,000 × 21 gwei = 0.00044 RON plus the L1 fee below.

Gotcha 4: every receipt carries an L1 fee

As an OP Stack chain, Ronin charges each transaction for its share of the cost of posting data to Ethereum, and receipts now include the OP Stack fee fields:

"l1Fee": "0x2aa7f2b4",
"l1GasUsed": "0xa0a",
"l1GasPrice": "0x3ec4efa",
"l1BaseFeeScalar": "0x558",
"l1BlobBaseFee": "0x3954d9",
"l1BlobBaseFeeScalar": "0xc3c9d"

If you compute a transaction's cost as gasUsed × effectiveGasPrice, you're now undercounting by l1Fee. Our guide to reading transaction receipts covers the standard fields; on Ronin, add l1Fee to get the full cost.

Each block also starts with a type 0x7e deposit transaction: the system transaction OP Stack chains use to carry L1 attributes. Code that iterates block transactions and assumes every one is type 0 or 2 should skip type 0x7e, or at least not crash on it. Coinbase is now 0x4200000000000000000000000000000000000011, the sequencer fee vault, not a validator address.

Finality: latest, safe and finalized are different now

The sidechain finalized under its own validator set. As a layer 2, Ronin's three block tags mean three different things:

  • latest is the sequencer's head, 2 seconds old at most.
  • safe (about 8.5 minutes back) is data that has been posted to the data-availability layer and derived by the node.
  • finalized (about 23 minutes back) follows Ethereum's own finality.

For game state and UI, latest is fine. For deposits, withdrawals and anything you credit to a user, wait for safe at least. Our 62-chain finality measurement and the soft vs hard finality explainer explain why rollups split these tags, and what a sequencer does covers what latest actually trusts.

Migration checklist for existing Ronin code

  • Start backfills at 55,577,500, or point historical queries at a sidechain archive.
  • Page eth_getLogs in 200-block windows.
  • Treat the base fee as a constant 20 gwei; set maxFeePerGas a little above it.
  • Add l1Fee to per-transaction cost accounting.
  • Skip or handle type 0x7e deposit transactions when walking blocks.
  • Use safe or finalized for anything that moves money.

Summary

Ronin is the same chain ID and the same token on a completely different engine: an OP Stack layer 2 with 2-second blocks, a fixed 20 gwei base fee, L1 fees on every receipt, and an 8.5-minute safe and 23-minute finalized lag. For RPC clients, the two things that bite are the 200-block eth_getLogs cap and the hard floor at block 55,577,500: nothing from the sidechain era is served.

Ronin endpoints and live chain status are on our Ronin RPC page, alongside 127 other chains on one key. SwiftNodes has a free tier if you want to try it.

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 →