Introduction

On September 8th, 2025, Lighter tasked zkSecurity with auditing its Plonky2 circuits. The audit lasted three weeks with two consultants. During the engagement, the team was granted access to the relevant parts of the Lighter codebase via a custom repository. Additionally, a whitepaper and online documentation was shared, outlining various aspects of the protocol.

Scope

The primary scope of this audit was Lighter’s Block, Delta, and Wrapper layers. More specifically, it served as a follow-up to an engagement conducted just one month earlier. The previous audit focused extensively on Lighter’s top-level circuits in the Prover’s circuit/src/ directory, as well as all files in circuit/src/types/ and circuit/src/transactions/. The low-level circuit at circuit/src/bigint/unsafe_bit/mod.rs was also reviewed.

This audit, in contrast, concentrated on changes introduced by the Lighter team since that engagement. Specifically, the scope includes:

  • The changes between commit 4876a50 and b119f03, which primarily is the account delta tree feature.
  • src/delta folder.
  • src/recursion folder.
  • src/bigint folder.
  • src/hints folder.
  • src/comparison folder.

Overview

The reports from our two previous audit engagements already provide extensive explanations of Lighter’s protocol. To avoid redundancy, we will not repeat those details here. Instead, we refer the reader to the first and second (to be published) report, as well as the whitepaper and documentation, for an introduction to the protocol.

Accordingly, this report does not include a general overview. Rather, we briefly highlight the circuit layers that were the focus of this particular audit and summarize the changes made to them.

Transaction Layer

  • Changes to public data handling and tree structure: account tree moved under validium; metadata tree removed.
  • Introduction of an account public data tree that aggregates deltas since genesis.
  • Introduction of a per-batch delta tree that resets to an empty tree at the start of each batch.

Recursion Layer

  • A cyclic aggregator that linearly accumulates proofs, verifying itself and a given group of block proofs.
  • Produces a “segment” as output, with 1–8 segments expected per batch, to be consumed by the wrapper layer.

Delta Layer

  • Rebuilds the delta tree of a given batch from scratch by inserting all non-empty delta leaves, in order.
  • Verifies that the reconstructed delta root matches the root published at the transaction layer, ensuring the same data was issued on different layers.
  • Evaluates a polynomial from the fields of delta leaves, on a pseudo-random point.

Wrapper Layer

  • Verifies the segment proofs to connect them, and extracts the generated batch data.
  • Consumes the blob array (i.e., the compressed, byte-serialized delta leaves), decompresses it, and performs polynomial evaluation on them at the same point, ensuring the blob data really corresponds to fields of the delta tree.
  • Proves commitment equivalence on blob data to show the constructed blob data is the same as the one published on Ethereum.

Note: At the time of the engagement, updates to the wrapper layer were still in progress. Consequently, its review has been deferred to a future audit once those changes are complete.

Account Delta Tree

The account delta Merkle tree records the state changes for all accounts within a batch. It shares the same depth as the main account tree, with each leaf representing the delta for the account at that index. If an account’s state (such as its position) is updated during the batch, the corresponding leaf is populated with an AccountDeltaFullLeaf; otherwise, the leaf remains empty.

tree

All non-empty leaves are collected and serialized into blob data for further comparison and verification.

Within the delta constraints, the circuit performs the following steps: - Computes the Merkle root by processing non-empty leaves from left to right. - Serializes the non-empty leaves into a blob array. - Evaluates the blob as a polynomial at a pseudo-random point x, treating each byte as a coefficient: a0+a1x+a2x2+.

Finally, the blob circuit need to witness Ethereum’s published blob data, performs the same polynomial evaluation, and checks that the results match. This ensures that all account deltas are correctly published and linked between layers.