ZPrivDEX — building a shielded AMM on Zcash

In any single-trade model you cannot simultaneously have all three of: public verifiability of the AMM invariant, hidden individual trade amounts, and no trusted intermediary. If trade amounts are hidden, pool state delta is not publicly derivable, so any node verifying the invariant must trust whoever published the pool state. If pool state is public, trade sizes are visible as the delta. The only escape from this trilemma requires batch processing with threshold encryption.

Penumbra’s zSwap solves this precisely by having users encrypt their swap amounts to a threshold key controlled by validators, aggregating the encrypted amounts homomorphically, decrypting only the batch total, and then computing the clearing price from that total — individual amounts are never revealed even to the validators, only the net batch flow.This is the correct architecture for a shielded DEX that achieves all three properties simultaneously.

Penumbra themselves could not ship individual trade amount privacy in their initial mainnet release because the threshold cryptography infrastructure required was not yet available.This is the state of the field, not a gap specific to this proposal.

Given this, I want to be precise about what ZPrivDEX v1 actually achieves and what it does not claim:

What it achieves:

Trader identity is private. Zcash’s Orchard note commitment and nullifier scheme means any full node can verify a valid trade occurred without learning who made it, what their balance is, or their transaction history. This is meaningful — on every transparent DEX today, trader identity and full history are public.

FROST custody removes single-party fund control. No single entity can move pool funds unilaterally. This is an improvement over every existing Zcash DEX integration regardless of the ZKP question.

The AMM invariant is publicly verifiable when pool state is public. Any full node can verify it without trusting anyone.

What it does not achieve in v1:

Individual trade size privacy. With public pool state, delta is visible. This is the honest limitation.

The path to full privacy:

Batch processing with threshold encryption over Zcash’s FROST infrastructure is the direction. Users submit encrypted trade intents. The FROST signer group aggregates the encrypted amounts homomorphically and decrypts only the batch total to compute the clearing price. Individual amounts remain hidden even from signers. This is architecturally aligned with how FROST is already used in this design and is the correct item for the research roadmap.

I should have stated these boundaries clearly from the beginning of this conversation. Thank you for the precision — this exchange has produced a more honest design document than what was originally proposed.

With public pool state, the ZKP’s role narrows to proving trader identity privacy — who traded, which note they owned, where the output goes — without revealing any of that to public observers. Trade size is visible as the pool delta. Identity is not. That is a narrower guarantee than originally described but it is real and it is what Orchard’s note model is designed to provide.
@hanh @zooko

Hmmm … Near intents or Maya both use a quorum of signers, and for Near trades are shielded. In any case, one can always shield before/after the swap. More importantly, the pool state isn’t verifiable publicly. This is the main problem that isn’t addressed.

Good luck with your project

1 Like

Thank you for the context on NEAR Intents and for the directness throughout this conversation.

You are right on the core point. Pool state verifiability on Zcash without an external chain or smart contract infrastructure is not solved by ZKPs alone. NEAR Intents handles this correctly by running swap logic on NEAR where state is publicly verifiable, while using ephemeral transparent Zcash addresses for the ZEC leg. That is a better architecture for cross-chain swaps than what was originally described here.

I want to be honest about what ZPrivDEX actually is after this conversation, because the design has changed substantially based on the technical exchange in this thread.

The genuine gap it fills is narrower than originally claimed: same-chain swaps between ZEC and ZSA assets, which NEAR Intents does not cover because NEAR does not have ZSA pools. Post-NU7, when ZIP-226 and ZIP-227 activate, ZEC holders will have no venue to trade against ZUSD, zBTC, or any other ZSA without routing through an external chain. That routing introduces the exact dependencies — external chain trust, transparent legs, cross-chain bridge risk — that make NEAR Intents unsuitable for Zcash-native asset pairs.

For that use case, the correct design based on this conversation is:

Pool state published publicly in each transaction. Any Zcash full node can verify the AMM invariant from public data. No ZKP needed for that verification. The ZKP proves trader identity — who spent which note, where the output goes — which Orchard handles natively and which is meaningfully different from every existing integration including NEAR Intents, which still uses transparent ephemeral addresses for the ZEC leg.

FROST custody removes the transparent vault entirely. Not for cross-chain swaps where NEAR has verifiable state, but for same-chain ZEC-ZSA pools where there is no external chain to anchor trust. The FROST threshold is a weaker guarantee than a smart contract but a stronger one than a single custodian or a transparent vault sweep.

Trade amount privacy in v1 is not achieved. The pool state delta is visible. That is consistent with what NEAR Intents reveals.

The design is more modest than originally proposed scope with additions

It correctly distinguishes the remaining gap. Same-chain ZEC-ZSA swaps post-NU7 are not served by NEAR Intents. That is a real gap.

It presents a stable, honest design that does not change again. Public pool state, ZKP for trader identity only, FROST custody.

Thank you for your time and efforts reviewing it.

The previous design tried to hide x and y entirely. You were right that this makes the ZKP’s verification role circular — only the FROST signers can verify pool state, which means verification is not trustless. That design was wrong.

The correct architecture is batch processing with threshold ElGamal flow encryption over Pallas. Here is how it resolves your specific concerns:

Pool state x and y are always public. Updated per batch with the publicly revealed batch total. Any full node verifies the AMM invariant from public data with simple arithmetic — no viewing key, no trust in signers.

Individual trade amounts are hidden within the batch. Each trader encrypts their amount using exponential ElGamal under the FROST group’s threshold public key. Any full node can verify the encryption is correctly formed via a sigma protocol proof that accompanies each trade. The FROST signers aggregate all ciphertexts homomorphically — without decrypting any individual amount — and threshold-decrypt only the batch total. The batch total is what updates x and y.

This is the same design Penumbra documented for their zSwap system. The reason Penumbra could not ship it initially was that their threshold decryption needed to happen inside block production and required ABCI 2.0 in Tendermint. Zcash does not have that constraint — the FROST signing ceremony happens off-chain between blocks, within the 75-second inter-block window. No consensus protocol changes required.

The remaining honest limitation: minimum batch size for privacy. If only one trade is in a batch, the batch total equals that trade’s amount. The protocol enforces a minimum batch size. Small pools with few active traders have weaker privacy guarantees — this will be documented precisely in the Milestone 1 architecture document.

Thank you for submitting your proposal. Following a thorough review by the ZCG and a period for community feedback on the forum, the committee has decided not to move forward with this proposal.

We sincerely appreciate the time and effort you invested in your application and encourage you to stay involved and continue contributing to the Zcash community. Further details will be available in the meeting minutes to be posted later this week.

1 Like