Program identifier
c1oak6tetxYnNfvXKFkpn1d98FxtK7B68vBQLYQpWKp
Instruction surface
-
User-facing:
0:Transact1:TransactSwap
-
Relay/ops-facing:
10:Initialize11:PrepareSwapSol12:ExecuteSwap13:CloseSwapState
Public input layout
Transact and TransactSwap both use a 264-byte public input blob:
root[32]publicAmount[8](i64, LE)extDataHash[32]mintAddress[32]inputNullifiers[64](2 x 32)outputCommitments[64](2 x 32)chainNoteHash[32]
Fees and amount semantics
FIXED_FEE_LAMPORTS = 5_000_000(0.005 SOL)- Variable fee:
amount * 3 / 1000(0.3%) MIN_DEPOSIT_LAMPORTS = 10_000_000(0.01 SOL)
gross = abs(publicAmount)fee = 5_000_000 + gross * 3 / 1000net = gross - fee
net > 0.
Merkle tree and nullifiers
- Tree height:
32 - Root history size:
100 - Nullifiers are PDA-backed for O(1) spent checks
- Pool:
["pool"] - Treasury:
["treasury"] - Merkle tree:
["merkle_tree"] - Nullifier:
["nullifier", nullifier_hash] - Swap state:
["swap_state", pool_pubkey, nullifier]
Execution model
Transact
- Verifies 256-byte Groth16 proof against transaction verifier key.
- Validates root exists in root history ring.
- Creates nullifier PDAs for non-zero input nullifiers (double-spend protection).
- Appends non-zero output commitments to Merkle tree.
- Applies external transfer based on
publicAmount:- positive: deposit from payer to pool
- negative: withdrawal from pool to recipient + fee to treasury
- zero: pure shield transfer (no external SOL movement)
- Deposit path can require risk-oracle quote accounts when configured.
TransactSwap
- Runs the same proof/nullifier/commitment checks as
Transact. - Requires negative
publicAmount(swap is a withdrawal path). - Creates
SwapStatePDA with output mint, recipient ATA, min output, timeout data. - Moves SOL into swap state path for follow-up execution.
PrepareSwapSol + ExecuteSwap
- Wraps SOL into wSOL context, executes swap CPI route, then settles output.
CloseSwapStatecloses state account once complete/eligible.
Circuit assumptions the program relies on
- Transaction circuit is fixed to 2 inputs / 2 outputs.
- Tree depth is fixed to 32 levels.
- Circuit enforces value conservation:
sum(inputs) + publicAmount = sum(outputs). - Circuit includes
chainNoteHashbinding constraints for chain-note integrity.
Error families
0x1000-0x1002: root management0x1010-0x1013: proof input/proof shape errors0x1020-0x1026: nullifier and signer checks0x1030-0x1039: output/conservation/fee constraints0x1050-0x105D: account validation0x1070-0x1076: Groth16 verifier failures0x1080-0x1082: Merkle tree bounds/hash errors0x10A0-0x10A1: risk-oracle checks
ShieldPoolErrors in Error Handling.
Common failure modes
0x1001 RootNotFound: proof used an old root no longer in ring history.0x1020/nullifier-already-used: input already spent (or reused test nullifier).- Invalid instruction data: wrong public input length (must be 264 bytes).