Appearance
Smart Contracts
Cairo contracts on Starknet handling on-chain state and verification.
Architecture
src/
├── lib.cairo # Entry points
├── clmm/
│ ├── swap.cairo # Swap engine
│ ├── liquidity.cairo # Position management
│ └── math/ # Q128.128 arithmetic
├── privacy/
│ ├── merkle_tree_bn254.cairo
│ └── nullifier.cairo
└── verifier.cairo # Garaga interfaceEntry Points
deposit
Shield tokens with a commitment:
cairo
fn deposit(
token: ContractAddress,
amount: u256,
commitment: u256,
) -> u32 // leaf indexswap_shielded_v2
Private swap with ZK proof:
cairo
fn swap_shielded_v2(
full_proof_with_hints: Span<felt252>,
public_inputs: WithdrawPublicInputsV2,
swap_params: SwapParams,
)Flow:
- Verify proof (Garaga)
- Check nullifier unused
- Validate Merkle root
- Execute CLMM swap
- Create output commitment
- Mark nullifier spent
mint_shielded
Add liquidity privately:
cairo
fn mint_shielded(
full_proof_with_hints: Span<felt252>,
public_inputs: MintPublicInputsV2,
tick_lower: i32,
tick_upper: i32,
liquidity_delta: u128,
owner_commitment: felt252,
)Position key: poseidon(owner_commitment, tick_lower, tick_upper)
burn_shielded / collect_fees_shielded
Remove liquidity or claim fees by proving knowledge of owner_secret.
CLMM Module
Swap Loop
Start → [Compute step in tick] → Hit boundary?
↓ Yes
[Cross tick, update liquidity]
↓
[Continue until done]Tick System
- Prices discretized:
price = 1.0001^tick - Positions define
[tick_lower, tick_upper]range - Tick bitmap for O(1) next-tick lookup
Fee Accumulation
cairo
fee_growth_global_0: u256 // Token0 fees per liquidity
fee_growth_global_1: u256 // Token1 fees per liquidityPrivacy Module
BN254 Merkle Tree
- Depth: 20 (~1M leaves)
- Hash: BN254 Poseidon (Garaga compatible)
- Root history for stale proof tolerance
Nullifier Registry
cairo
nullifiers: Map<(u128, u128), bool> // nullifier_hash → spentProof Verification
Garaga Groth16 verifier validates:
- 7 public inputs
- ~200 byte proof
- ~3ms verification time
Storage
cairo
struct Storage {
// Pool
sqrt_price: u256,
current_tick: i32,
liquidity: u128,
// Privacy
merkle_root: u256,
nullifiers: Map<(u128, u128), bool>,
// Positions (commitment-keyed)
positions: Map<felt252, PositionInfo>,
// Ticks
ticks: Map<i32, TickInfo>,
tick_bitmap: Map<i16, u256>,
}Errors
cairo
INVALID_PROOF // ZK proof failed
NULLIFIER_SPENT // Double-spend attempt
INVALID_ROOT // Stale Merkle root
SLIPPAGE_EXCEEDED // Output below minimum
INSUFFICIENT_LIQUIDITY