Skip to main content

Standard Ethereum RPC (eth_*)

Use your base library for all eth_* methods. The client.zks surface only covers ZKsync-specific RPC (zks_*). For standard Ethereum JSON-RPC (e.g., eth_call, eth_getLogs, eth_getBalance), call them through your chosen library (ethers or viem).

zks_ Interface

interface ZksRpc {
  getBridgehubAddress(): Promise<Address>;
  getL2ToL1LogProof(txHash: Hex, index: number): Promise<ProofNormalized>;
  getReceiptWithL2ToL1(txHash: Hex): Promise<ReceiptWithL2ToL1 | null>;
}

Methods

getBridgehubAddress() → Promise<Address>

Fetch the on-chain Bridgehub contract address.
const addr = await client.zks.getBridgehubAddress();

getL2ToL1LogProof(txHash: Hex, index: number) → Promise<ProofNormalized>

Return a normalized proof for the L2→L1 log at index in txHash.
const proof = await client.zks.getL2ToL1LogProof(l2TxHash, 0);
/*
{
  id: bigint,
  batchNumber: bigint,
  proof: Hex[]
}
*/
If a proof isn’t available yet, this method throws a typed STATE error. Poll based on your app’s cadence.

getReceiptWithL2ToL1(txHash: Hex) → Promise<ReceiptWithL2ToL1 | null>

Fetch the transaction receipt; the returned object always includes l2ToL1Logs (empty array if none).
const rcpt = await client.zks.getReceiptWithL2ToL1(l2TxHash);
console.log(rcpt?.l2ToL1Logs); // always an array

Types (overview)

type ProofNormalized = {
  id: bigint;
  batchNumber: bigint;
  proof: Hex[];
};

type ReceiptWithL2ToL1 = {
  // …standard receipt fields…
  l2ToL1Logs: unknown[];
};

Usage

import { JsonRpcProvider, Wallet } from 'ethers';
import { createEthersClient } from '@dutterbutter/zksync-sdk/ethers';

const l1 = new JsonRpcProvider(process.env.ETH_RPC!);
const l2 = new JsonRpcProvider(process.env.ZKSYNC_RPC!);
const signer = new Wallet(process.env.PRIVATE_KEY!, l1);

const client = createEthersClient({ l1, l2, signer });

// Public RPC surface:
const bridgehub = await client.zks.getBridgehubAddress();