Zero-Knowledge Circuits
Withdraw Circuit
The withdraw circuit is written in Circom and compiled to a Groth16 ZK-SNARK.
Private Inputs
secret— random value known only to the depositornullifier— unique identifier to prevent double-spendingamount— deposit amountpathElements[20]— Merkle proof siblingspathIndices[20]— Merkle proof path (left/right)
Public Inputs
root— Merkle tree rootnullifierHash— Poseidon(nullifier)recipient— withdrawal recipient addresstoken— token address (0x0 for ETH)withdrawAmount— amount to withdrawrelayer— relayer addressfee— relayer feenewCommitment— commitment for change (partial withdrawal)changeAmount— amount returned to pool
What the Circuit Proves
- The prover knows
secretandnullifiersuch thatcommitment = Poseidon(secret, nullifier) - A leaf
Poseidon(commitment, token, amount)exists in the Merkle tree at the given root nullifierHash = Poseidon(nullifier)(for double-spend prevention)withdrawAmount + changeAmount + fee = amount(conservation)- If
changeAmount > 0, thennewCommitment ≠ 0(change must have a commitment)
Hash Function
All hashes use Poseidon — an arithmetic-friendly hash function optimized for ZK circuits. It's significantly cheaper in terms of constraints compared to SHA-256 or Keccak.