A zk-rollup (zero-knowledge rollup) executes transactions off the base chain, compresses the resulting state changes, and posts a cryptographic validity proof that the base-chain contract verifies before accepting a new state root. This article explains the mechanism end to end: sequencer batching, state commitments, proof systems, data availability, and finality. It then provides a runnable RPC-based procedure for observing batch submissions and confirming that a rollup's on-chain state root matches the proof-verified transition. The focus is on reproducible verification methods rather than endorsing a specific rollup or endpoint provider.
Scope and the core mental model
A zk-rollup is a layer-2 construction in which transaction execution happens away from the base chain, but correctness is enforced on-chain by a succinct proof. The rollup contract on the base chain stores a state root. To advance that root, an operator submits a batch commitment plus a validity proof; the contract verifies the proof and, if valid, updates the root. Because the proof is checked by the base chain, users do not need to trust the operator's honesty for state correctness, only for liveness and censorship behavior.
This article treats zk rollups as an architecture rather than a single product. Different zk-rollups vary in proof system (SNARK or STARK), data availability strategy (calldata, blobs, or a separate DA layer), and virtual machine (EVM-equivalent or custom). The verification workflow below is written so it can be adapted to any rollup that exposes standard JSON-RPC and a base-chain contract address.
The practical question this guide answers is: given a rollup RPC endpoint and a base-chain RPC endpoint, how do you observe a batch, confirm the proof was accepted, and reconcile the rollup's reported state with the base-chain contract?
- Execution: off-chain, performed by a sequencer or prover network.
- Settlement: on the base chain, via a verifier contract.
- Data availability: transaction data published so state can be reconstructed.
- Finality: achieved when the validity proof is verified on-chain.
Prerequisites and assumptions
You need two RPC endpoints: one for the rollup network and one for its base chain (for example, Ethereum mainnet). You also need the rollup's settlement contract address and, ideally, the ABI for its batch-submission event. These are published in each rollup's documentation; this guide does not assume a specific rollup.
The procedures use curl and Python with only standard libraries plus an HTTP call. Replace RPC_URL, BASE_RPC_URL, and ROLLUP_CONTRACT with values from the network you are inspecting. Never paste a private key into a shell history; for read-only verification no key is required at all.
If you are choosing an endpoint rather than verifying one, the concrete provider decision belongs in RPC Assistant; this page stays on methodology. For a broader endpoint selection framework, see the guide to RPC endpoints and the multi-chain RPC endpoints overview.
- Rollup RPC URL (read-only is sufficient).
- Base-chain RPC URL.
- Settlement contract address and batch event topic.
- A block range that contains at least one known batch submission.
How a zk-rollup batch moves from execution to finality
The lifecycle has five stages. First, users submit transactions to the rollup, where a sequencer orders them. Second, the sequencer executes the batch against the current state, producing a new state root and a list of state diffs. Third, a prover generates a validity proof attesting that executing the batch on the prior state yields the new root. Fourth, the operator publishes compressed transaction data and the proof to the base chain. Fifth, the verifier contract checks the proof and, on success, writes the new root.
The distinction between zk-rollups and optimistic rollups is at stage five. Optimistic rollups accept the root immediately and rely on a fraud-proof window during which anyone can challenge. Zk-rollups accept the root only after proof verification, so withdrawals do not need a challenge period once the proof lands. That is why zk-rollups are sometimes called validity rollups.
Data availability is a separate axis from validity. A proof can be valid while the underlying transaction data is withheld, which would prevent users from reconstructing state or exiting independently. Mature zk-rollups publish enough data on the base chain (calldata or blobs) to reconstruct state. When evaluating a zk-rollup, check both the proof system and the DA commitment.
Observing batch submissions through the base-chain RPC
The most direct verification is to read the settlement contract's logs. Batch submissions typically emit an event containing the previous state root, the new state root, and a commitment to the batch data. The exact event signature differs per rollup, so fetch the ABI from the project's repository and compute the topic with keccak256.
The following Python script queries logs for a given contract and topic over a block range. It prints each matching log so you can inspect the state-root fields. It does not decode the payload, because decoding depends on the rollup's ABI; that is the next step.
import json, urllib.request
BASE_RPC_URL = "BASE_RPC_URL"
ROLLUP_CONTRACT = "ROLLUP_CONTRACT"
TOPIC0 = "BATCH_EVENT_TOPIC"
FROM_BLOCK = "0x0"
TO_BLOCK = "latest"
def rpc(method, params):
body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
req = urllib.request.Request(BASE_RPC_URL, data=body, headers={"Content-Type":"application/json"})
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())["result"]
logs = rpc("eth_getLogs", [{
"address": ROLLUP_CONTRACT,
"fromBlock": FROM_BLOCK,
"toBlock": TO_BLOCK,
"topics": [TOPIC0]
}])
for log in logs:
print(log["transactionHash"], log["blockNumber"], log["data"][:130])Reconciling the rollup state root with the base chain
After you have a batch transaction hash, fetch the transaction receipt on the base chain and confirm status 0x1. Then read the rollup's current state root from the rollup RPC (many expose a method such as a state-root getter or a block tag) and compare it with the latest root recorded by the settlement contract. A mismatch means either you are reading different block heights or the rollup RPC is lagging.
The following curl calls illustrate the read pattern. The first fetches the receipt; the second calls a rollup RPC method. Replace the method name with the one your rollup documents.
curl -s -X POST "$BASE_RPC_URL" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["BATCH_TX_HASH"]}'
curl -s -X POST "$RPC_URL" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"ROLLUP_STATE_ROOT_METHOD","params":["latest"]}'A results table for recording verification runs
Record each verification run in a table so results are comparable across rollups and over time. Do not fill in numbers you have not measured; leave cells blank until the run completes. A suggested schema is below, followed by the procedure to populate it.
Procedure: (1) pick a batch transaction hash from the log query; (2) record the base-chain block number and receipt status; (3) record the rollup RPC block height at the same moment; (4) read the state root from both sources; (5) mark match or mismatch; (6) note the wall-clock time between batch inclusion and your read. Repeat at three different times of day to expose RPC lag patterns.
- | Run | Batch tx | Base block | Receipt status | Rollup height | Root match | Observed lag |
- |-----|----------|------------|----------------|---------------|------------|--------------|
- | 1 | | | | | | |
- | 2 | | | | | | |
- | 3 | | | | | | |
Expected verification result and what it tells you
A healthy run shows a successful base-chain receipt, a rollup RPC height at or above the batch's rollup height, and identical state roots from the rollup RPC and the settlement contract at the same height. If the roots match, the proof-verified transition is reflected consistently by both data sources.
If the receipt succeeds but the roots differ, first confirm you are comparing the same block height. Rollup RPCs and base-chain RPCs advance independently, and a lagging rollup node can report an older root. Re-read both at a pinned height before concluding there is a problem. Persistent mismatch at a pinned height is a serious signal and warrants checking the rollup's status page and the contract's event history.
If the receipt fails, the proof was rejected or the transaction reverted; the batch did not finalize. Inspect the revert reason and the prover's public status if available.
Troubleshooting common verification failures
Most failures are observational rather than protocol-level. The table below maps symptoms to likely causes and the next check to run.
For endpoint-level reliability issues, such as timeouts or inconsistent responses, the troubleshooting approach is the same as for any JSON-RPC workload: compare two independent endpoints, pin block heights, and log request IDs. If you need a concrete endpoint recommendation rather than a method, RPC Assistant covers that separately.
- Empty log result: wrong contract address, wrong topic, or block range outside the batch window.
- Receipt not found: transaction still pending or submitted to a different chain ID.
- Root mismatch: height mismatch, lagging rollup RPC, or a reorg on the base chain.
- Decode error: ABI does not match the deployed contract version.
- Timeout: endpoint rate limit or overload; retry with backoff and a second endpoint.
Limitations and tradeoffs of zk-rollups
Validity proofs give strong correctness guarantees, but they are not free. Proving is computationally heavy, and proving cost scales with batch complexity. For some workloads, the amortized cost per transaction is low; for others, especially small batches, it can dominate. This is a design tradeoff, not a defect, and it is why batch sizing and proof recursion matter.
EVM compatibility is another tradeoff. EVM-equivalent zk-rollups aim to run existing contracts unchanged but face higher proving costs; custom VMs can be more efficient but require porting. Data availability choices also matter: posting full calldata maximizes transparency but costs more than blobs or external DA layers.
Finally, zk-rollups still depend on the base chain for settlement and on the sequencer for liveness. A valid proof does not prevent censorship or downtime; those are operational properties you should evaluate separately, often by monitoring multiple RPC endpoints.
Next steps: from verification to production monitoring
Once you can reproduce a single verification run, automate it. Schedule the log query and root comparison at a fixed interval, store results in the table schema above, and alert on persistent mismatches or receipt failures. This turns a one-off check into a lightweight settlement monitor.
For production workloads that read rollup state frequently, consider a dedicated node so your reads are not subject to shared rate limits. OnFinality's dedicated node offering and API service are the infrastructure entry points; pricing details are on the RPC pricing page, and supported networks are listed in the networks directory.
If your next question is which endpoint to use for a specific rollup or base chain, hand that decision to RPC Assistant rather than guessing from this methodology page.