SDK & Integration

The relayer

Gasless withdrawals without trusting the submitter. The proof binds the recipient and fee, so a relayer can only refuse service — never re-aim funds or skim more than the agreed fee.

A fresh withdrawal address has no ETH to pay gas — which is exactly the address a private withdrawal wants to use. The relayer pattern solves this: someone else submits the transaction and takes a fee out of the withdrawn amount.

How a relayed withdrawal flows

  1. 1
    Discover the relayerRead relayer.address and relayer.feeBps from GET /api/config.
  2. 2
    Bind the proofBuild the witness with relayer set to that address and fee set accordingly; prove.
  3. 3
    SubmitPOST the proof to /api/relayer/withdraw. The relayer adds its address and broadcasts.
  4. 4
    SettleThe contract pays denomination − fee to the recipient and fee to the relayer.

Why the relayer is untrusted

Both circuits bind the withdrawal parameters into the proof: the Privacy Pool binds recipient, relayer, fee, refund; the Shielded Pool binds the whole extDataHash. A relayer that tampers with any of these produces a proof that fails on-chain verification.

Relayer tries to…Outcome
Redirect funds to itselfProof binds recipient → verification fails.
Inflate the feeProof binds fee → verification fails.
Replay a seen proof elsewhereBound parameters + spent nullifierHash → rejected.
Refuse to submitPossible — but the user can self-submit instead.

Censorship & metadata

A relayer can censor by declining specific withdrawals; running multiple relayers or self-submitting mitigates this. Note that metadata privacy (IP, timing) is out of scope at the protocol layer — relayer and client behavior must address it. See the Threat model.