Documentation Index
Fetch the complete documentation index at: https://mintlify.com/collinsville22/Sable/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Shielded Pool V4 enables private WBTC deposits with:- Groth16 ZK proofs for deposit/withdrawal unlinkability
- Variable batch sizes (3, 5, or 7 deposits per batch)
- Auto-deploy to ERC-4626 vaults when batch threshold is reached
- Merkle tree commitment tracking (depth 10, capacity 1,024)
- BN254 Poseidon hash function (Garaga-compatible)
Privacy Properties
Hidden
- Depositor address (relayer submits)
- Deposit amount (fixed denomination)
- Depositor-withdrawer link (ZK proof)
Unpredictable
- Batch boundaries (variable sizes)
- Anonymity set per batch (3-7 users)
Architecture
Core Functions
deposit
Deposit exactlydenomination WBTC with a commitment hash. Relayer-only.
BN254 Poseidon hash of (secret, nullifier, leafIndex)
Original depositor address (WBTC source)
- Transfer
denominationWBTC from depositor to pool - Insert commitment into Merkle tree at next available leaf index
- Mark commitment as used (prevent duplicates)
- Auto-deploy batch of 3 if threshold reached (when auto-deploy enabled)
Auto-deploy is enabled by default. Batches of 3 are automatically deployed to the vault when 3+ undeployed deposits accumulate.
deploy_batch
Manually deploy a batch of pending deposits to the vault.Batch size: must be 3, 5, or 7
- Validate count is 3, 5, or 7
- Check enough undeployed deposits exist
- Transfer
count * denominationWBTC to vault viavault.deposit() - Record batch ID, start index, deposit count, and shares per deposit
- Emit
BatchDeployedEventwith batch metadata
deploy_partial_batch
Deploy a partial batch (any count ≥ 1) for timeout scenarios.withdraw
Withdraw using a Groth16 ZK proof with 7 public inputs.Garaga Groth16 proof blob with embedded public inputs
| Index | Field | Type | Description |
|---|---|---|---|
| 0 | root | u256 | Merkle root (must be in recent history) |
| 1 | nullifierHash | u256 | Unique spend tag (prevents double-spend) |
| 2 | recipient | u256 | Withdrawal recipient address |
| 3 | relayer | u256 | Relayer address (fee recipient) |
| 4 | fee | u256 | Relayer fee in WBTC sats |
| 5 | batchStart | u256 | First leaf index of batch |
| 6 | batchSize | u256 | Number of deposits in batch |
- Verify Groth16 proof via Garaga BN254 verifier
- Check nullifier hasn’t been spent
- Verify Merkle root is known (within last 30 roots)
- Verify fee ≤ max_fee_bps of denomination
- Look up batch_id from batchStart
- Validate batch parameters (start, size) match stored batch
- Redeem exact
batch_shares[batch_id]from vault - Send (payout - fee) to recipient, fee to relayer
- Mark nullifier as spent
Storage
Merkle Tree
Tree Depth: 10 levels (max 1,024 deposits per pool)Hash Function: BN254 Poseidon(2) via Garaga, matching circomlib
Batch Tracking
View Functions
Events
DepositEvent
BatchDeployedEvent
WithdrawalEvent
Configuration
Constructor
Parameters
Curator Functions
Security Model
Privacy Guarantees
Privacy Guarantees
- Depositor anonymity: Relayer submits all deposits
- Amount privacy: Fixed denomination per pool
- Unlinkability: Groth16 proof breaks depositor-withdrawer link
- Anonymity set: 3-7 users per batch (variable)
ZK Proof Requirements
ZK Proof Requirements
- Prove knowledge of secret + nullifier preimage
- Prove commitment exists in Merkle tree at claimed root
- Prove nullifier derives from same secret as commitment
- Prove batch membership (batchStart, batchSize)
Economic Security
Economic Security
- Max fee cap prevents relayer extraction
- Root history (30) tolerates network delays
- Nullifier registry prevents double-spend
- Vault shares locked until withdrawal