Gas costs

Let's walk through the factors determining the end-to-end gas costs for a ZK app using NEBRA UPA. There are three on-chain steps that can consume gas:

  1. Submitting proofs

    • on-chain (~23-100k gas per proof- depends on submission size)

    • off-chain (0 gas per proof)

  2. Verifying the aggregated proof (~18k gas per proof)

  3. Querying the verification result (~25k gas per proof)

Summing up these costs, we find that in total:

  • Applications submitting their proofs on-chain can save as much as 184k gas (~75%) per proof.

  • Applications submitting their proofs off-chain can save upwards of 207k gas (~85%) per proof.

You can estimate your application's gas savings using our gas calculator at For simplicity we show gas estimates for an application with four public inputs, but the actual costs for each step will vary a bit depending on the number of public inputs per proof.

Step 1: Proof Submissions

NEBRA UPA collects submissions of one or more proofs and places them in a queue to be aggregated. Note that UPA does not aggregate submission-by-submission. Instead, aggregated batches are chosen independently of the way the proofs were submitted.

Applications will have two options for proof submissions: on-chain and off-chain. On-chain submissions cost gas in exchange for censorship-resistance (an aggregator that skips verifying a valid proof can be slashed). Off-chain submissions have no gas cost, but offer weaker censorship resistance.

The current UPA release (v1.1) supports on-chain submission. Off-chain submission will be available soon.

Cost of on-chain submission

Due to per-transaction storage costs, using a whole Ethereum transaction to submit a single proof is relatively expensive. Instead, we recommend that apps take advantage of multi-proof submissions.

The contracts currently deployed to the Sepolia testnet are initial implementations with large scope for gas optimization, but they serve to illustrate the approximate cost model. Currently, the fixed cost per submission is about 100k gas. The marginal cost of each additional proof in a submission is about 20k gas (for processing the additional proof and public input data).

Therefore the per-proof gas cost for an on-chain submission of MM proofs is approximately:

100000/M+20000100000/M + 20000

The table below shows the measured cost of submissions of different sizes.

Submission Batch SizeTotal Gas CostPer-proof Gas Cost









As we iterate the contracts and introduce more optimizations, we expect to significantly reduce the costs shown here.

Cost of off-chain submission

Off-chain submissions have no associated gas cost, but a weaker censorship resistance mechanism: In response to a submission, the aggregator sends back a confirmation that they will aggregate the proof before a certain deadline. If this aggregator misses this deadline then they are subject to slashing.

Step 2: Verifying the aggregated proof

The current version of NEBRA UPA aggregates proofs into a Halo2-KZG proof. The cost of verifying such a proof in isolation is about 350k gas, and is roughly independent of batch size. In addition, the UPA contract emits an event and updates its storage to mark each application proof in the batch as verified. This incurs a marginal per-proof cost of about 7k gas.

Therefore the per-proof gas cost for verifying one batch of NN proofs and storing the result is approximately:

350000/N+7000350000/N + 7000

The current configuration of NEBRA UPA sets the batch size to N=32N=32. With this batch size the aggregated verification cost comes out to ~18k gas per proof (Etherscan).

Step 3: Query of the verification result

Once a proof has been verified by the UPA contract, the app contract may query the UPA contract to confirm that the associated public inputs are valid. This typically looks like:

require(upaVerifier.isVerified(circuitId, publicInputs, "Not verified");

The gas cost of this external contract call is about 25k gas per proof.

In the near future, apps will be able to amortize this cost by checking that a whole multi-proof submission has been verified instead of checking each of its proofs individually.

Calculation of end-to-end gas savings

Without UPA

The total cost for an app to verify an individual Groth16 proof is about 250-270k gas, which can be broken down into:

  1. Submitting and verifying the proof (~250k gas)

  2. Retrieving the verification result

    • from an external contract (~10-20k gas)

    • from within the app contract (0 gas)

Using UPA with on-chain submission

With UPA, assuming submissions of size $M$ and proof aggregations of size $N$, the total end-to-end per-proof gas cost with on-chain submissions comes out to about:

100000/M+350000/N+52000100000/M + 350000/N + 52000

Concretely, with submissions of M=32M=32 proofs and aggregations of N=32N=32 proofs, this per-proof gas cost comes out to

100000/32+350000/32+5200066000100000/32 + 350000/32 + 52000 \approx 66000

which represents a savings of about 184k gas per proof (~75%).

Using UPA with off-chain submission

The end-to-end gas cost with off-chain submissions will be approximately:

350000/N+32000350000/N + 32000

With the current UPA configuration of N=32N=32, the per-proof cost comes out to

350000/32+3200043000350000/32 + 32000 \approx 43000

which represents a savings of about 207k gas per proof (~85%).

Last updated