Core Security Mechanisms
Double-Spend Protection
Nullifier Validation
Every transaction creates unique nullifiers that prevent the same UTXO from being spent twice.
How it works: Each input note generates a nullifier. The protocol attempts to create a nullifier account using
init (not init_if_needed). If the nullifier already exists, the transaction automatically fails with a system error, preventing double-spends.Reference: lib.rs:598-622, lib.rs:674-710Zero-Knowledge Proof Verification
Groth16 ZK-SNARK
Every transaction requires a valid zero-knowledge proof using the Groth16 proving system.
- Valid proof structure (lib.rs:226-233)
- Correct public inputs (groth16.rs:89-109)
- Pairing equation verification (groth16.rs:127-146)
- Field element bounds checking (groth16.rs:149-152)
Merkle Root Validation
Historical Root Checking
Transactions must reference a known historical Merkle tree root.
merkle_tree.rs:79-105
Financial Safety Features
Deposit Limits
Configurable Deposit Caps
Maximum deposit amounts protect against large-scale attacks and ensure system stability.
- Default limit: 1,000 SOL (1,000,000,000,000 lamports)
- Authority-controlled: Only the program authority can update limits
- Per-token limits: Separate limits for SOL and each SPL token
lib.rs:78, lib.rs:105-112, lib.rs:191-206
Fee Validation
Dynamic Fee Verification
Fees are validated against configurable rates with error margins.
- Deposit fee rate: 0% (free deposits)
- Withdrawal fee rate: 0.25% (25 basis points)
- Error margin: 5% (500 basis points)
- All rates enforced within 0-10000 basis points
lib.rs:91-93, lib.rs:250-257, utils.rs:148-212
Public Amount Verification
Amount Consistency Checks
The relationship between deposit/withdrawal amounts and fees is cryptographically verified.
- Public amount = ext_amount - fee (for deposits)
- Public amount = -(|ext_amount| + fee) (for withdrawals)
- Prevents fee manipulation attacks
utils.rs:92-128
Data Integrity Features
External Data Hash Verification
Transaction Data Binding
All transaction metadata is cryptographically bound to the zero-knowledge proof.
- Recipient address
- Transfer amount
- Encrypted outputs (privacy data)
- Fee and fee recipient
- Token mint address
lib.rs:217-240, utils.rs:276-311
Token Account Validation
SPL Token Account Checks
SPL token operations validate account ownership and mint addresses.
lib.rs:375-397
Arithmetic Safety
Overflow Protection
Checked Math Operations
All arithmetic operations use checked math to prevent overflows and underflows.
lib.rs:290-349, merkle_tree.rs:67-68
Merkle Tree Capacity
Tree Full Protection
The Merkle tree has a maximum capacity of 2^26 (67,108,864) leaves.
merkle_tree.rs:33-39, lib.rs:23
Access Control
Authority-Gated Operations
Administrative Controls
Critical operations require valid authority signatures.
- Initialize trees: Create new Merkle trees for tokens (lib.rs:151-185)
- Update deposit limits: Modify maximum deposit amounts (lib.rs:105-112)
- Update fee configuration: Change fee rates and margins (lib.rs:117-143)
- Mainnet:
AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM(multisig) - Devnet:
97rSMQUukMDjA7PYErccyx7ZxbHvSDaeXp2ig5BwSrTf - Localnet: No authority required (testing)
lib.rs:25-32, lib.rs:804-829
Token Allowlist
Approved Tokens Only
Only explicitly approved SPL tokens can use the privacy protocol.
- USDC:
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - USDT:
Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - ORE:
oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp - ZEC:
A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS - stORE:
sTorERYB6xAZ1SSbwpK3zoK2EEwbBrc7TZAzg1uCGiH - jlUSDC:
9BEcn9aPEmhSPbPQeFGjidRiEKki46fVQDyPpSQXPA2D - jlWSOL:
2uQsyo1fXXQkDtcpXnLofWy88PxcvnfH2L8FPSE62FVU
lib.rs:40-60, lib.rs:394-397