ZETHProtocol Spec
Landing page

ZETH: A Shielded Pool for Confidential ETH Transfers

A zero-knowledge protocol for unlinkable value transfer on Ethereum.

Version 1.0

Abstract

Abstract

ZETH is a shielded-pool protocol that lets a user deposit ETH, transfer value privately within the pool, and withdraw to an unrelated address such that no on-chain observer can link the withdrawal to the originating deposit. Privacy is enforced cryptographically rather than by trust: every state transition is accompanied by a zero-knowledge succinct non-interactive argument of knowledge (zk-SNARK) that the transition is valid, while revealing nothing about the sender, recipient, or amount beyond what is structurally public.

The construction follows the commitment/nullifier accumulator model pioneered by Zerocash and refined by subsequent shielded systems, instantiated over the BN254 curve with Poseidon hashing and Groth16 proofs for on-chain verification efficiency. This document specifies the cryptographic primitives, the note and accumulator structure, the circuit constraint system, the on-chain verification logic, and, critically, the precise boundaries of the privacy guarantee, including the leakage that the protocol does not eliminate.

01

Introduction

Ethereum's base layer is fully transparent: every transaction exposes sender, recipient, and value. Pseudonymity offers weak protection, because chain analysis routinely deanonymizes addresses through clustering, timing, and value correlation. For a class of legitimate uses, such as payroll confidentiality, competitive business transactions, donation privacy, and personal financial privacy, this transparency is a defect rather than a feature.

ZETH addresses one specific, well-scoped problem: breaking the on-chain link between the address that funds the system and the address that later receives funds, while keeping intermediate transfers confidential. It does not attempt to be a general anonymity network, nor does it claim to defeat a global adversary with full network-level surveillance. Section 8 is explicit about what falls outside the guarantee.

The remainder of this document assumes familiarity with elliptic-curve cryptography, Merkle accumulators, and the SNARK proving model.

02

Preliminaries and Notation

Let $\lambda$ denote the security parameter. We work over the BN254 (alt-bn128) pairing-friendly curve, whose scalar field $\mathbb{F}_r$ has prime order

$$r = 21888242871839275222246405745257275088548364400416034343698204186575808495617.$$

All field elements, commitments, and hashes are members of $\mathbb{F}_r$ unless stated otherwise. EVM precompiles at addresses 0x06, 0x07, and 0x08 provide BN254 addition, scalar multiplication, and pairing checks, making on-chain Groth16 verification economically feasible.

We use the following primitives:

  • $H : \mathbb{F}_r^* \to \mathbb{F}_r$ is the Poseidon hash, a SNARK-friendly algebraic hash with low multiplicative complexity. Poseidon is used for all in-circuit hashing because its constraint count per invocation is roughly two orders of magnitude below that of a bit-decomposed Keccak.
  • A Merkle accumulator $\mathsf{MT}$ of fixed height $d = 20$, supporting up to $2^{20}$ leaves, with $H$ as the compression function.
  • A Groth16 proving system $(\mathsf{Setup}, \mathsf{Prove}, \mathsf{Verify})$ over BN254.

Notation: $x \,\|\, y$ denotes ordered concatenation of circuit inputs to $H$; $\mathbf{a} \mathrel{\overset{\$}{\leftarrow}} \mathbb{F}_r$ denotes uniform sampling.

03

Notes, Commitments, and Nullifiers

The unit of value in ZETH is a note. A note is a tuple

$$\mathsf{note} = (v, \mathsf{pk}, \rho)$$

where $v \in [0, 2^{248})$ is the value in wei, $\mathsf{pk}$ is the owner's spending public key, and $\rho \mathrel{\overset{\$}{\leftarrow}} \mathbb{F}_r$ is a blinding factor (also serving as the note's uniqueness nonce).

Spending keys.

A user samples a private key $\mathsf{sk} \mathrel{\overset{\$}{\leftarrow}} \mathbb{F}_r$ and derives the public key as

$$\mathsf{pk} = H(\mathsf{sk}).$$

This one-way derivation means the public key can appear in a note commitment without exposing the spending authority.

Commitment.

The on-chain representation of a note is its commitment

$$\mathsf{cm} = H(v \,\|\, \mathsf{pk} \,\|\, \rho).$$

Only $\mathsf{cm}$ is published. Because $H$ is collision-resistant and $\rho$ is high-entropy, $\mathsf{cm}$ is binding (the owner cannot later equivocate on $v$) and hiding (an observer learns nothing about $v$ or $\mathsf{pk}$).

Nullifier.

To spend a note, its owner publishes a nullifier

$$\mathsf{nf} = H(\mathsf{cm} \,\|\, \mathsf{sk}).$$

The nullifier is deterministic in the note and the spending key, so a given note yields exactly one valid nullifier; yet because it is a hash under the secret $\mathsf{sk}$, it is computationally unlinkable to $\mathsf{cm}$ without knowledge of $\mathsf{sk}$. The contract maintains a set $\mathcal{N}$ of seen nullifiers; a spend is rejected if its nullifier is already in $\mathcal{N}$. This is the double-spend prevention mechanism, and it leaks nothing about which commitment was consumed.

04

The Accumulator

All commitments are inserted, in order of creation, as leaves of an incremental Merkle tree $\mathsf{MT}$ of height $d=20$. The tree's root $\mathsf{rt}$ is a succinct binding commitment to the entire set of notes ever created.

The contract retains a rolling window of the most recent $K = 30$ roots, $\mathcal{R} = \{\mathsf{rt}_{t-K+1}, \ldots, \mathsf{rt}_t\}$. A spend proof is validated against any root in $\mathcal{R}$, not only the latest. This window decouples proof generation from block-to-block tree mutation: a user can build a proof against a recent root without it being invalidated by an unrelated deposit landing in the interim. Roots older than the window are no longer accepted, bounding the contract's storage and the staleness an adversary can exploit.

Empty subtrees are filled with a fixed sequence of "zero values" $Z_0, \ldots, Z_d$, where $Z_0$ is a domain-separated constant and $Z_{i+1} = H(Z_i \,\|\, Z_i)$. These are precomputed and must be regenerated if either $H$ or the domain constant changes.

05

Protocol Operations

ZETH exposes three operations. Each is a single circuit, the transaction circuit, parameterized by the number of input and output notes; deposit and withdraw are special cases of the general transfer where value crosses the public boundary.

Let the public boundary value be $v_{\text{pub}} \in \mathbb{Z}$, interpreted as a signed quantity: positive for a deposit (public ETH entering the pool), negative for a withdrawal (ETH leaving), zero for a purely internal transfer.

5.1 Shield (deposit)

The user constructs one or more output notes whose total value equals the ETH sent with the transaction. The contract:

  1. Receives $v_{\text{pub}} > 0$ wei of ETH.
  2. Verifies the transaction proof (Section 6) with no input notes (or dummy inputs) and the new output commitment(s).
  3. Inserts each output commitment into $\mathsf{MT}$, updating $\mathsf{rt}$.

The depositing address is public, which is unavoidable since ETH must come from somewhere, but it is linked only to the commitment, not to any future spend.

5.2 Transfer (internal, private)

The user proves ownership of input notes already in the tree, nullifies them, and creates new output notes (one for a recipient, one for change) with $v_{\text{pub}} = 0$. The contract verifies the proof, checks input nullifiers are unseen, records them in $\mathcal{N}$, and inserts the new output commitments. No address or amount appears on-chain. The recipient learns their note out-of-band via an encrypted payload emitted as an event (Section 7).

5.3 Unshield (withdraw)

The user proves ownership of input notes, sets $v_{\text{pub}} < 0$ equal to the amount to release, and specifies an arbitrary recipient address $\mathsf{addr}$ as a public input. The contract verifies the proof, records nullifiers, inserts any change commitment, and transfers $|v_{\text{pub}}|$ wei to $\mathsf{addr}$. Because the proof reveals only nullifiers, which are unlinkable to the original commitments, $\mathsf{addr}$ carries no on-chain relationship to the depositing address.

06

The Transaction Circuit

The circuit enforces a relation $\mathcal{C}$ over public and private inputs. We specify it for the $n_{\text{in}} = 2$, $n_{\text{out}} = 2$ instantiation; other arities are structurally identical.

Public inputs.

$$\big(\mathsf{rt},\; v_{\text{pub}},\; \mathsf{addr},\; \{\mathsf{nf}_i\}_{i=1}^{2},\; \{\mathsf{cm}^{\text{out}}_j\}_{j=1}^{2}\big)$$

Private witness.

$$\big(\{\mathsf{sk}_i, v_i, \rho_i, \mathsf{path}_i, \mathsf{idx}_i\}_{i=1}^{2},\; \{v^{\text{out}}_j, \mathsf{pk}^{\text{out}}_j, \rho^{\text{out}}_j\}_{j=1}^{2}\big)$$

The relation $\mathcal{C}$ holds iff all of the following constraints are satisfied:

(C1) Input key derivation. For each input $i$: $\;\mathsf{pk}_i = H(\mathsf{sk}_i)$.

(C2) Input commitment reconstruction. For each input $i$: $\;\mathsf{cm}_i = H(v_i \,\|\, \mathsf{pk}_i \,\|\, \rho_i)$.

(C3) Membership. For each input $i$ with $v_i \neq 0$: the Merkle path $\mathsf{path}_i$ with index bits $\mathsf{idx}_i$ authenticates $\mathsf{cm}_i$ to the public root $\mathsf{rt}$. Each index bit is constrained boolean: $\;\mathsf{idx}_{i,k}(1 - \mathsf{idx}_{i,k}) = 0$. Inputs with $v_i = 0$ are dummy inputs and bypass membership; this allows transactions with fewer real inputs than the fixed arity.

(C4) Nullifier integrity. For each input $i$: $\;\mathsf{nf}_i = H(\mathsf{cm}_i \,\|\, \mathsf{sk}_i)$, and $\mathsf{nf}_i$ equals the corresponding public input. This binds the published nullifier to a note the prover demonstrably owns.

(C5) Output commitment integrity. For each output $j$: $\;\mathsf{cm}^{\text{out}}_j = H(v^{\text{out}}_j \,\|\, \mathsf{pk}^{\text{out}}_j \,\|\, \rho^{\text{out}}_j)$, matching the public output commitment.

(C6) Range constraints. For each output $j$: $\;v^{\text{out}}_j \in [0, 2^{248})$, enforced by bit-decomposition. This prevents field-overflow value forgery, in which a sum wraps the modulus to manufacture value.

(C7) Value conservation.

$$\sum_{i=1}^{2} v_i \; + \; v_{\text{pub}} \;=\; \sum_{j=1}^{2} v^{\text{out}}_j.$$

No value is created or destroyed; the public boundary term accounts for deposits and withdrawals.

(C8) Address binding. $\mathsf{addr}$ is included as a public input and bound into the proof (e.g. as a constrained no-op multiplication) so that a withdrawal proof cannot be replayed with a substituted recipient, a malleability defense.

The constraint that most often fails to be specified correctly in naive implementations is C6 together with C7: without range checks, conservation can be satisfied modulo $r$ by an adversary who wraps the field, minting value from nothing. The bit-decomposition is therefore not optional.

07

Note Discovery

A recipient must learn the opening $(v, \mathsf{pk}, \rho)$ of a note created for them. ZETH attaches to each output an encrypted payload, encrypted to the recipient's viewing key using an ephemeral-static ECDH scheme, emitted as a contract event. Recipients trial-decrypt events with their viewing key; successful decryption yields the note opening. The viewing key is separate from the spending key, enabling disclosure for audit or compliance without granting spend authority.

08

Security Model and Limitations

This section states what ZETH guarantees and, equally important, what it does not. A privacy system that overstates its guarantees endangers its users.

Cryptographic guarantees, under standard assumptions (collision-resistance of Poseidon over $\mathbb{F}_r$, knowledge-soundness of Groth16 under the BN254 algebraic-group/knowledge-of-exponent assumptions, and a sound trusted setup):

Balance integrity.
No PPT adversary can withdraw or transfer more value than they own, except with negligible probability. (Follows from C2–C7 and knowledge-soundness.)
Double-spend resistance.
Each note can be nullified at most once. (Follows from C4 and the on-chain nullifier set.)
Transaction confidentiality.
Internal transfers reveal no sender, recipient, or amount. (Follows from the hiding property of commitments and the zero-knowledge property of the proof.)
Deposit–withdrawal unlinkability.
Holds within the anonymity set, defined below.

The anonymity set.

A withdrawal is unlinkable only among the set of deposits that are plausibly its source. This set is bounded by everyone who has deposited and not yet withdrawn. Its effective size, and therefore the actual privacy delivered, depends on usage. A pool with few participants provides weak privacy regardless of the cryptography. The protocol's math is necessary but not sufficient for privacy; the anonymity set is the operative variable.

Leakage the protocol does NOT eliminate.

Value fingerprinting.
Depositing 13.37 ETH and later withdrawing 13.37 ETH is self-linking. Privacy is strongest with standardized denominations or when amounts are split/merged across many transactions.
Timing correlation.
A deposit immediately followed by the only withdrawal of similar size narrows the set to one. Temporal diffusion is a user responsibility.
Funding/draining heuristics.
If the address that funds a deposit and the address that receives a withdrawal share an off-chain relationship (same exchange account, same KYC identity, immediate sweep to a known wallet), external analysis can re-link them. ZETH breaks the on-chain link; it cannot break links the user reintroduces.
Network-level adversary.
An observer of the RPC/relayer layer who can associate proof submission with an IP gains metadata outside the protocol's scope. Use of a relayer or anonymizing transport is recommended and is not provided by the contract.
Trusted-setup compromise.
Groth16 requires a per-circuit structured reference string. If the setup's toxic waste is not destroyed by at least one honest participant in the generating ceremony, an adversary could forge proofs, i.e., mint value. The integrity of the multi-party ceremony is a load-bearing assumption, not a detail.

Composition with regulation.

Confidentiality technology does not alter a user's legal obligations. Nothing in this design constitutes advice that any particular use is lawful in any jurisdiction; that determination rests with the user.

09

Parameters

ParameterValue
CurveBN254 (alt-bn128)
In-circuit hashPoseidon over $\mathbb{F}_r$
Proof systemGroth16
Tree height $d$20 ($2^{20}$ notes)
Root window $K$30
Note value range$[0, 2^{248})$
Default arity2 inputs / 2 outputs
10

References

The construction draws on the Zerocash protocol (Ben-Sasson et al., 2014); the Groth16 proving system (Groth, 2016); the Poseidon hash (Grassi et al., 2019); the Sapling shielded-pool design (Hopwood et al., Zcash Protocol Specification); and the variable-amount shielded-transfer model explored by later EVM-based pools. Full citations accompany the published source.

This document describes a cryptographic protocol. It is a technical specification, not an offering, solicitation, or assurance of fitness for any purpose. The security properties stated in Section 8 hold only under the assumptions listed there, including a sound trusted setup and an adequate anonymity set.