Abstract RPC: A Developer's Guide (Chain ID 2741)

By John Sullivan · October 7, 2026 · 5 min read · #abstract #abstract rpc #zk stack #zksync #layer 2 #developer guide

Abstract is an Ethereum ZK rollup built on ZKsync's ZK Stack, aimed at consumer apps: games, NFTs and social products, most of them used through the Abstract Global Wallet. It speaks Ethereum JSON-RPC, so viem and ethers connect without special setup. But the chain underneath is the ZKsync VM, not the EVM, and that shows up in gas numbers, transaction types and finality.

This guide is measured against the live chain on October 7, 2026, through the same endpoint SwiftNodes customers use.

The endpoint

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

const abstract = defineChain({
  id: 2741,
  name: "Abstract",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.swiftnodes.io/rpc/abstract?key=YOUR_API_KEY"] } },
});

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

viem also ships an abstract chain definition in viem/chains, and its viem/zksync extensions add the ZKsync-specific actions; swap in the URL above as the transport.

What we measured

Property Value
Chain ID 2741 (0xab5)
Block time 0.58 s (0.588 s over 100,000 blocks, 0.565 s over 10,000)
Gas limit 1,125,899,906,842,624 (2^50) per block
Base fee / eth_gasPrice 0.04525 gwei, flat
eth_maxPriorityFeePerGas 0
Plain ETH transfer, gas used 94,647 (sampled transaction)
Same sender, eth_estimateGas 200,894
Fee for that transfer ~0.0000043 ETH
safe behind head ~23 minutes
finalized behind head ~3.8 hours
eth_getLogs capped at 10,000 results per call, not by block range
Historical state back to block 1 (October 25, 2024)

Gas: don't hardcode Ethereum numbers

The gas limit is 2^50, which is effectively unbounded. It tells you nothing about what a transaction can use. The real limit on ZK Stack is the batch, and zks_getFeeParams shows its parameters: 200 million gas and 700,000 bytes of pubdata per batch, and a minimum L2 gas price of 45,250,000 wei. That minimum is exactly the base fee every block reported, so on a quiet chain the fee doesn't move.

A plain ETH transfer is not 21,000 gas here. The one we sampled used 94,647, because ZKsync charges for account validation and for the state diff it publishes to Ethereum. eth_estimateGas for the same sender returned 200,894, more than twice what the transfer used. That is normal on ZK Stack: estimates include a pubdata allowance, and unused gas is refunded, so the cost is the 94,647 actually used, about 0.0000043 ETH at that gas price. Use the estimate as the limit and don't treat it as the cost.

zks_estimateFee returns the same gas limit plus gas_per_pubdata_limit, which you need when building EIP-712 (type 0x71) transactions yourself:

const fee = await client.request({
  method: "zks_estimateFee" as any,
  params: [{ from: sender, to: recipient, value: "0x1" }],
});
// { gas_limit, gas_per_pubdata_limit, max_fee_per_gas, max_priority_fee_per_gas }

Estimating from an address with no account behind it fails with invalid sender. can't start a transaction from a non-account. Use a real sender, not a zero or placeholder address.

Most transactions come from smart accounts

In a 100-transaction sample of recent blocks, 72 were type 0x71 (ZKsync's EIP-712 transaction), 21 were EIP-1559 type 2 and 7 were legacy. The sender of the plain transfer we measured returned bytecode from eth_getCode: it is a smart contract account, not an externally owned key. That is the Abstract Global Wallet at work. ZK Stack has native account abstraction, so any account can be a contract with its own validation logic, no ERC-4337 bundler needed.

Two practical consequences for indexers and wallets:

  • Don't assume "has code" means "is a contract someone deployed as an app". On Abstract most active users have code.
  • Signature checks for off-chain messages should use ERC-1271 (isValidSignature) rather than ecrecover, or smart-account users can't sign in.

Blocks, batches and finality

Abstract produces a block about every 0.58 seconds, and blocks carry two extra fields, l1BatchNumber and l1BatchTimestamp. Blocks are grouped into L1 batches; a recent batch spanned 1,300 blocks (about 12.5 minutes), and another held 2,078 L2 transactions. zks_getL1BatchDetails shows each batch's lifecycle on Ethereum:

Stage Batch 92,904 (October 3, 2026)
Committed to L1 12:13:39 UTC
Proven 12:32:43 UTC (+19 min)
Executed 15:32:04 UTC (+3 h 18 min after commit)

That gap between proof and execution is why finalized trails the head by about 3.8 hours, while safe trails by about 23 minutes. Our finality survey across 62 chains puts that in context. Show users latest for UX, and wait for finalized before crediting withdrawals or deposits that can't be reversed. More on that split in soft vs hard finality on L2s.

Logs and history

eth_getLogs here limits results, not block ranges. Every query that would return more than 10,000 logs failed with Query returned more than 10000 results. Try with this block range [...], and the error hands you a range that fits. A filter on one token contract returned 6,923 logs over 10,000 blocks (about 1.6 hours). Wider windows hit the result cap, not a range cap. On busy contracts, page by result count: start wide, and when the error comes back, retry with the suggested range. Method details are on eth_getLogs on Abstract.

Historical state reads worked at every depth we tried, down to block 1, from October 25, 2024. Tracing is partial: debug_traceTransaction and debug_traceBlockByNumber with callTracer returned full call trees (including the system-contract calls ZKsync makes on every transaction), but the trace_* namespace is not available. eth_getBlockReceipts works.

ZKsync methods

The zks_ namespace is partly available:

Method Result
zks_L1BatchNumber, zks_getL1BatchDetails, zks_getL1BatchBlockRange work
zks_getBlockDetails, zks_getFeeParams, zks_estimateFee work
zks_getMainContract, zks_L1ChainId, zks_getBaseTokenL1Address work
zks_getBridgecontracts refused (not whitelisted on Abstract's own RPC either)
txpool_*, eth_sendRawTransactionSync not available

zks_getBaseTokenL1Address returns 0x…0001, the ZK Stack marker for ETH as the base token.

WebSocket

eth_subscribe with newHeads and logs works on the WebSocket URL above, which streams Abstract's official node. At 0.58 s blocks expect close to two heads a second; a logs subscription filtered to your contracts is usually cheaper than polling eth_getLogs.

Summary

  • ZK Stack rollup on Ethereum, chain ID 2741, ETH for gas, 0.58 s blocks.
  • Flat 0.04525 gwei gas price; transfers use ~95k gas and estimate ~200k. Always estimate.
  • Most senders are smart accounts: verify signatures with ERC-1271.
  • safe ~23 min, finalized ~3.8 h behind the head.
  • eth_getLogs caps results at 10,000 and suggests a range; history goes back to block 1.

Abstract endpoints, live gas and method support are on our Abstract RPC page and Abstract gas tracker, alongside 127 other chains on one key. SwiftNodes has a free tier 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 →