Program ID:Documentation Index
Fetch the complete documentation index at: https://docs.x0protocol.dev/llms.txt
Use this file to discover all available pages before exploring further.
zQWSrznKgcK8aHA4ry7xbSCdP36FqgUHj766YM3pwre
x0-zk-verifier provides on-chain verification of zero-knowledge proofs generated by the x0-zk-proofs WASM library. It validates Groth16 proofs over the Ristretto255 curve for confidential token operations.
Problem Statement
Token-2022’s ConfidentialTransfer extension encrypts balances using Twisted ElGamal, but the protocol still needs to enforce correctness constraints:- Public key validity — The ElGamal public key is correctly derived from a secret scalar
- Zero balance — An encrypted balance is actually zero (required for account closure)
- Withdraw correctness — A withdrawal amount is valid against the encrypted balance
- Transfer correctness — Encrypted sender/receiver ciphertexts are consistent
Proof Types
PubkeyValidityProof
Proves that an ElGamal public key is correctly derived: where is the secret scalar and is the Ristretto255 generator. Size: 64 bytesZeroBalanceProof
Proves that an ElGamal ciphertext encrypts the value 0 without revealing the randomness. Size: 96 bytesWithdrawProof
Proves that withdrawing amount from encrypted balance is valid — i.e., the remaining balance is non-negative and bounded by . Size: 160 bytesTransferProof
Proves that a confidential transfer correctly re-encrypts the amount under the recipient’s public key, and the sender’s remaining balance is non-negative. Size: 288 bytesInstructions
verify_pubkey_validity
Verifies an ElGamal public key validity proof and stores the result in a ProofContext PDA.
verify_withdraw
Verifies a withdrawal proof and records the verified amount.
verify_zero_balance
Verifies that an encrypted balance is zero.
verify_transfer
Verifies a confidential transfer proof and records the amount and recipient.
State Account
ProofContext
Each verified proof creates aProofContext PDA that serves as an on-chain receipt:
["proof-context", owner, mint]
Proof Freshness
Proof contexts expire after 300 seconds (PROOF_CONTEXT_FRESHNESS_SECONDS). The is_fresh() method checks:
This prevents replay attacks — a proof verified 5 minutes ago cannot be used to authorize a new transfer.
Amount Bounds
All proof amounts are bounded by: This constraint comes from the Token-2022 ConfidentialTransfer extension’s use of 48-bit range proofs.Verification Flow
Error Codes
| Code | Name | Description |
|---|---|---|
0x1700 | ProofVerificationFailed | ZK proof did not verify |
0x1701 | InvalidProofData | Proof data format invalid |
0x1703 | InvalidProofType | Unknown proof type |
0x1704 | ProofExpired | Proof context older than 300s |
0x1710 | AmountTooLarge | Amount exceeds |
0x1711 | InvalidElGamalPubkey | ElGamal public key invalid |
0x1713 | ProofSizeMismatch | Proof data wrong length |
0x1720 | ArithmeticOverflow | Integer overflow in verification |