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
- 1Discover the relayerRead
relayer.addressandrelayer.feeBpsfromGET /api/config. - 2Bind the proofBuild the witness with
relayerset to that address andfeeset accordingly; prove. - 3SubmitPOST the proof to
/api/relayer/withdraw. The relayer adds its address and broadcasts. - 4SettleThe contract pays
denomination − feeto the recipient andfeeto 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 itself | Proof binds recipient → verification fails. |
| Inflate the fee | Proof binds fee → verification fails. |
| Replay a seen proof elsewhere | Bound parameters + spent nullifierHash → rejected. |
| Refuse to submit | Possible — 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.