Ethereum JSON-RPC API: Complete Guide for ZKsync Era

·

ZKsync Era is a cutting-edge Layer 2 scaling solution designed to bring high throughput and low-cost transactions to Ethereum while maintaining security and decentralization. One of its key features is full compatibility with the standard Ethereum JSON-RPC API, enabling developers to seamlessly port Ethereum dApps to ZKsync with minimal changes.

However, due to architectural differences between Ethereum Layer 1 and ZKsync’s optimistic rollup design, there are important distinctions you must understand when interacting with the network via RPC calls.

👉 Discover how ZKsync Era enhances Ethereum scalability and unlocks new development possibilities.


Key Differences in ZKsync Era’s JSON-RPC Implementation

While ZKsync supports most Ethereum-standard RPC methods, two notable deviations affect block data retrieval and transaction handling:

1. Block Data Retrieval Methods

Methods that return block information — such as eth_getBlockByHash, eth_getBlockByNumber, and Geth’s eth_subscribe with the newHeads parameter — do not provide actual values for receiptsRoot, transactionsRoot, and stateRoot.

Instead, these fields contain zero (0x0) values. This occurs because ZKsync’s L2 blocks do not maintain a state root; only L1 batches (aggregated L2 data published on Ethereum) include this concept.

This architectural difference reflects ZKsync’s rollup model, where final state commitments occur periodically on Layer 1 rather than per-block on Layer 2.

2. Unsupported Transaction Method

The method eth_sendTransaction is intentionally not supported in ZKsync. Unlike Ethereum, where nodes can sign and broadcast transactions directly, ZKsync requires all transactions to be pre-signed and submitted using eth_sendRawTransaction.

This ensures greater control over transaction flow and aligns with secure wallet integration patterns.


Core Ethereum JSON-RPC Methods on ZKsync Era

Below is a comprehensive overview of essential JSON-RPC methods supported by ZKsync Era, complete with parameters, return types, and example usage.

eth_chainId

Retrieves the current chain ID in hexadecimal format.

{
  "jsonrpc": "2.0",
  "result": "0x144",
  "id": 1
}

This value helps identify the network (e.g., mainnet vs. testnet) and prevents cross-chain replay attacks.


eth_call

Executes a read-only smart contract function call without broadcasting a transaction.

Useful for querying token balances, contract states, or simulating interactions before sending real transactions.


eth_estimateGas

Estimates the gas required to execute a transaction or contract interaction.

Note: The from address cannot be a non-SmartAccount smart contract, or an exception will be thrown.

👉 Learn how gas optimization boosts performance and reduces costs on Layer 2 networks.


eth_gasPrice

Returns the current average gas price in gwei.

This value helps dynamically set gas fees based on real-time network conditions, improving transaction inclusion speed.


Event Filtering & Log Retrieval

ZKsync supports Ethereum-style event filtering for real-time dApp updates:

These tools are essential for building responsive frontends and backend monitoring systems.


Account & Balance Queries

eth_getBalance

Fetches an account’s balance at a specific block.

Ideal for tracking wallet balances or historical token holdings.

eth_getTransactionCount

Gets the number of transactions sent from an address (nonce).

Used primarily for constructing valid transactions with correct nonce values.


Block Information Methods

eth_getBlockByNumber / eth_getBlockByHash

Retrieve full block details including:

Despite zeroed-out roots, these methods offer valuable insights into block composition and timing.

eth_getBlockTransactionCountByNumber / ...ByHash

Returns the number of transactions in a block — useful for analyzing block congestion or validator activity.


Smart Contract Interaction

eth_getCode

Fetches deployed bytecode at a contract address.

Helpful for verifying contract existence or inspecting proxy implementations.

eth_getStorageAt

Reads raw storage value at a given position (slot) in a contract.

Used in advanced debugging, forensics, or storage layout analysis.


Transaction Lifecycle Management

eth_getTransactionByHash

Retrieve detailed transaction data:

Critical for tracking user actions and debugging failed transactions.

eth_getTransactionReceipt

Returns post-execution receipt:

Always check the receipt to confirm transaction success and extract emitted events.

eth_sendRawTransaction

Submits a signed transaction to the mempool.

This is the only way to send transactions on ZKsync Era.


Fee & Client Metadata

eth_feeHistory

Fetches historical base fees and rewards across recent blocks.

Enables EIP-1559-aware fee estimation strategies for better UX.

web3_clientVersion / eth_protocolVersion

Returns client software and protocol version strings (e.g., "ZKsync/v2.0").

Useful for diagnostics and compatibility checks.


Frequently Asked Questions (FAQ)

Q: Why are stateRoot and receiptsRoot always zero?

A: Because ZKsync uses a rollup architecture where state commitments are batched and posted to Ethereum Layer 1 periodically. Individual L2 blocks don’t store full state roots — only L1 batches do.

Q: Can I use MetaMask or Ethers.js with ZKsync?

A: Yes! Standard Ethereum libraries work seamlessly. Just ensure your provider points to a ZKsync RPC endpoint (like https://mainnet.era.zksync.io/) and use eth_sendRawTransaction for sending transactions.

Q: Is eth_call accurate on ZKsync?

A: Absolutely. Read operations reflect the true state of contracts on ZKsync and are fully consistent with Ethereum semantics.

Q: How do I handle nonces on ZKsync?

A: Use eth_getTransactionCount with the "latest" tag for pending nonce tracking, just like on Ethereum.

Q: What tools support ZKsync RPC?

A: Hardhat, Foundry, Ethers.js, Web3.js, The Graph, and many indexers support ZKsync through standard RPC interfaces.

Q: Are there rate limits on public RPC endpoints?

A: Public nodes may apply throttling under heavy load. For production apps, consider using dedicated RPC providers or running your own node.


👉 Explore advanced developer tools and resources to build powerful dApps on ZKsync Era.