Sable — Permissionless BTC Yield Vaults on StarkNet
Multi-strategy BTC yield aggregator with ZK privacy, Smart DCA, CDPs, cross-chain bridging, and direct staking — all on StarkNet L2.
Next.js 16 · React 19 · Cairo · StarkNet · Groth16 · Tailwind v4
Live App · Documentation · Demo Video
Watch the full demo on YouTube
┌─────────────────────────────────────────────────────────────────────────┐
│ USER BROWSER │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────┐ ┌───────────────┐ │
│ │ Argent │ │ Braavos │ │ WalletCo- │ │ Local Note │ │
│ │ Wallet │ │ Wallet │ │ nnect │ │ Storage │ │
│ └──────┬───────┘ └──────┬───────┘ └─────┬─────┘ └───────┬───────┘ │
│ └──────────────────┴───────────────┬┘ │ │
│ │ │ │
│ ┌─────────────────────────────────────────┴─────────────────┴───────┐ │
│ │ NEXT.JS 16 FRONTEND (App Router) │ │
│ │ │ │
│ │ Pages: / /vault/[id] /privacy /dca /cdp /stake /bridge │ │
│ │ /portfolio │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ REACT HOOKS LAYER │ │ │
│ │ │ │ │ │
│ │ │ use-vault-data use-vault-contract use-shielded-vault │ │ │
│ │ │ use-dca use-cdp use-staking │ │ │
│ │ │ use-bridge use-private-swap │ │ │
│ │ └──────────────────────────┬──────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────────────┴──────────────────────────────────┐ │ │
│ │ │ LIB / API LAYER │ │ │
│ │ │ │ │ │
│ │ │ api/vaults api/vesu api/avnu api/price │ │ │
│ │ │ api/onchain api/oneclick api/defillama │ │ │
│ │ │ privacy/note privacy/prover privacy/merkle │ │ │
│ │ │ constants format rpc abi/ │ │ │
│ │ └──────────────────────────┬──────────────────────────────────┘ │ │
│ └─────────────────────────────┼─────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────┴──────────────────────────────────────┐ │
│ │ NEXT.JS API ROUTES (Server-Side) │ │
│ │ /api/curator /api/relayer/* /api/dca/* /api/shielded-deposit │ │
│ │ /api/staking /api/execute-outside │ │
│ └─────────────────────────────┬──────────────────────────────────────┘ │
└────────────────────────────────┼────────────────────────────────────────┘
│
┌────────────┴────────────┐
│ STARKNET MAINNET │
│ │
┌─────────────────┼─────────────────────────┼──────────────────────┐
│ │ SABLE CONTRACTS │ │
│ ┌──────────┐ │ ┌──────────────────┐ │ ┌───────────────┐ │
│ │ Sentinel │ │ │ Shielded Pool V4 │ │ │ DCA │ │
│ │ Citadel │ │ │ (Groth16 ZK) │ │ │ Contract │ │
│ │ Trident │ │ ├──────────────────┤ │ ├───────────────┤ │
│ │ Delta │ │ │ Swap Pool │ │ │ CDP │ │
│ │ Turbo │ │ │ (Private Swaps) │ │ │ Contract │ │
│ │ Apex │ │ ├──────────────────┤ │ ├───────────────┤ │
│ │ │ │ │ Stablecoin Vault │ │ │ Groth16 │ │
│ │ (ERC4626)│ │ │ (Private USDC) │ │ │ Verifier │ │
│ └────┬─────┘ │ └──────────────────┘ │ └───────────────┘ │
│ │ │ │ │
└───────┼────────┼──────────────────────────┼──────────────────────┘
│ │ │
┌───────┴────────┴──────────────────────────┴──────────────────────┐
│ EXTERNAL PROTOCOLS │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Vesu │ │ Ekubo │ │ Endur │ │ Nostra │ │
│ │ Lending │ │ AMM/LP │ │ Staking │ │ CDP Lending │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ AVNU │ │ Pragma │ │ Garaga │ │ NEAR 1-Click │ │
│ │ DEX Agg │ │ Oracle │ │ ZK Proof │ │ Bridge/Intents │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
User Wallet ──► Frontend (React) ──► Hooks ──► StarkNet RPC ──► Smart Contracts
│ │
│ └──► External APIs (Vesu, AVNU, CoinGecko, DefiLlama)
│
└──► API Routes (Server) ──► Relayer / Curator / Keeper
Layer
Technology
Version
Framework
Next.js (App Router, Turbopack)
16.1.6
UI
React
19.2.3
Language
TypeScript
5.x
Styling
Tailwind CSS
4.x
Animations
Motion (Framer Motion)
12.6.3
Charts
Recharts
2.15.3
Smart Contracts
Cairo (Scarb)
2.14.0 / 2.13.1
Blockchain
StarkNet Mainnet
—
StarkNet Client
starknet.js
8.1.2
Wallet Integration
@starknet-react/core
5.0.3
ZK Proofs (Groth16)
snarkjs + circomlibjs
0.7.6 / 0.1.7
ZK Proofs (UltraHonk)
@aztec/bb.js + @noir-lang/noir_js
0.82.2 / 1.0.0-beta.15
On-chain ZK Verify
Garaga
1.0.1
Wallets
Argent X, Braavos
—
{
"starknet" : " ^8.1.2" ,
"@starknet-react/core" : " ^5.0.3" ,
"@starknet-react/chains" : " ^4.1.0" ,
"snarkjs" : " ^0.7.6" ,
"circomlibjs" : " ^0.1.7" ,
"@aztec/bb.js" : " 0.82.2" ,
"@noir-lang/noir_js" : " 1.0.0-beta.15" ,
"garaga" : " ^1.0.1" ,
"recharts" : " ^2.15.3" ,
"motion" : " ^12.6.3" ,
"clsx" : " ^2.1.1"
}
1. Vaults (/ and /vault/[id])
The core product: 6 distinct BTC yield strategies deployed as ERC-4626 tokenized vaults on StarkNet. Users deposit WBTC and receive share tokens representing their proportional claim on the vault's growing assets.
Vault
Strategy
Risk
Cairo Contract
Description
Sable Sentinel
Pure Lending
1 (Low)
sentinel.cairo
Supply WBTC to Vesu PRIME pool. Simplest, safest strategy.
Sable Citadel
Staked BTC + Lending
2 (Low-Med)
citadel.cairo
WBTC → Endur xWBTC liquid staking → supply to Vesu for dual yield.
Sable Trident
Recursive Staking
3 (Med)
trident.cairo
3x recursive WBTC staking loop on Endur for amplified staking rewards.
Sable Delta Neutral
BTC-USDC Spread
4 (Med-High)
delta_neutral.cairo
Deposit WBTC as collateral → borrow USDC → deploy USDC to yield → earn spread.
Sable Turbo
USDC Leverage Loop
5 (High)
btcvault.cairo
Leverage-loop WBTC collateral on Vesu: deposit → borrow USDC → swap to WBTC → re-deposit.
Sable Apex
Multi-Strategy Max Yield
5 (High)
apex.cairo
40% leverage lending + 35% Ekubo LP + 25% Endur staking. Maximum diversified yield.
Every Sable vault implements the ERC-4626 tokenized vault standard:
┌──────────────────────────────────────────────────┐
│ ERC-4626 VAULT │
│ │
│ deposit(assets) ──► mint(shares) │
│ withdraw(assets) ◄── redeem(shares) │
│ │
│ share_price = total_assets() / total_supply() │
│ │
│ As strategy earns yield: │
│ total_assets ↑ → share_price ↑ │
│ Each share redeems for more WBTC over time │
└──────────────────────────────────────────────────┘
DEPOSIT:
User ──► approve(WBTC, vault, amount)
──► vault.deposit(amount, receiver)
◄── vault mints share tokens to receiver
──► curator.deploy_idle() deploys WBTC into strategy
WITHDRAW:
User ──► vault.withdraw(assets, receiver, owner)
──► vault unwinds strategy positions (may use flash loans)
◄── WBTC transferred to receiver
──► share tokens burned
The curator (owner) manages strategy execution. Idle WBTC sitting in the vault is deployed to yield protocols via the /api/curator endpoint:
Curator calls deploy_idle():
1. Read idle WBTC balance in vault
2. Execute strategy-specific deployment:
- Sentinel: supply to Vesu PRIME
- Citadel: stake on Endur → supply xWBTC to Vesu
- Trident: recursive stake loop (3 iterations)
- Delta Neutral: supply collateral → borrow USDC → deploy USDC
- Turbo: leverage loop (deposit → borrow → swap → re-deposit)
- Apex: split across lending + LP + staking
3. All yield accrues to the vault → share price increases
Source
Vaults Using It
Description
Vesu Lending APY
Sentinel, Citadel, Trident, Turbo, Apex
Interest from borrowers on Vesu
Endur xWBTC Staking
Citadel, Trident, Apex
Liquid staking yield on BTC
BTCFi Season STRK
All
100M STRK incentive program rewards
Ekubo LP Fees
Apex
Concentrated liquidity market making fees
Borrowing Spread
Delta Neutral, Turbo
Earn more on deployed capital than borrowing cost
Leverage Amplification
Trident, Turbo
Multiply base yield via recursive positions
File
Purpose
src/app/page.tsx
Vault listing with filtering (Conservative/Moderate/Aggressive) and sorting (APY/TVL)
src/app/vault/[id]/page.tsx
Vault detail page: strategy breakdown, APY analysis, metrics, deposit/withdraw
src/components/vault-card.tsx
Summary card with APY, TVL, risk level, allocation bars
src/components/deposit-withdraw.tsx
Deposit/withdraw modal with WBTC/USD toggle, max buttons
src/hooks/use-vault-data.ts
Fetch vault metadata, APY breakdown, performance history
src/hooks/use-vault-contract.ts
Read on-chain state: balance, share price, min deposit, strategy info
src/lib/api/vaults.ts
Vault data fetching, APY calculation from multiple sources
src/lib/api/onchain.ts
Call total_assets() on vault contracts via RPC
src/lib/api/vesu.ts
Fetch Vesu pool APY, utilization, vToken data
src/lib/api/defillama.ts
Historical APY/TVL charts from DefiLlama
src/components/performance-chart.tsx
Historical APY/TVL chart (Recharts)
2. Privacy / Shielded Vaults (/privacy)
Zero-knowledge shielded deposits that break the on-chain link between depositor and withdrawer using Groth16 BN254 proofs verified on StarkNet via Garaga.
Tab
Pool Type
Token
Description
Lending
Sentinel Vault
WBTC
Private deposits into Sable Sentinel (lending yield)
Yield
Delta Neutral Vault
WBTC
Private deposits into Sable Delta Neutral (spread yield)
Stables
Stablecoin Vault
USDC
Private USDC deposits into Vesu RE7 USDC Core
Swap
Swap Pool
WBTC→ETH/USDC/STRK
Private token swaps via pool-to-pool transfers
How Shielded Deposits Work
DEPOSIT FLOW:
1. User generates a random NOTE locally:
┌──────────────────────────────────────┐
│ Note = { │
│ secret: random 31 bytes │
│ nullifier: random 31 bytes │
│ commitment: Poseidon(secret, │
│ nullifier) │
│ } │
└──────────────────────────────────────┘
2. User sends TX: approve(WBTC, pool, denomination) + pool.deposit(commitment)
- Fixed denomination amounts (e.g., 0.0002 BTC, 0.0004 BTC)
- Commitment is added to pending batch
3. Relayer batches 3 deposits together:
pool.process_batch([commitment_1, commitment_2, commitment_3])
- All 3 commitments inserted into Merkle tree
- Batch start index recorded
4. Note saved to browser localStorage (CRITICAL: losing = losing funds)
WITHDRAWAL FLOW:
1. User generates Groth16 proof locally (in browser via snarkjs WASM):
┌──────────────────────────────────────────────────────────┐
│ Proof inputs: │
│ Private: secret, nullifier, pathElements, pathIndices │
│ Public: root, nullifierHash, recipient, relayer, │
│ fee, batchStart, batchSize │
└──────────────────────────────────────────────────────────┘
2. Proof submitted to relayer API (/api/relayer/withdraw)
3. Relayer calls pool.withdraw(proof, publicInputs)
- On-chain Groth16 verification via Garaga verifier contract
- Nullifier hash recorded (prevents double-spend)
- Funds sent to recipient address
- Relayer fee deducted
4. Recipient receives funds with NO on-chain link to depositor
ROOT
/ \
/ \
H(0,1) H(2,3)
/ \ / \
L0 L1 L2 L3 ◄── Leaf = Poseidon(commitment)
│ │ │ │
Note0 Note1 Note2 Note3
- Tree depth: 20 levels (supports ~1M deposits)
- Hash function: Poseidon (StarkNet-native, efficient in-circuit)
- Batch size: 3 deposits per batch
- Each withdrawal proves membership via Merkle path
Fixed Denominations (V4 Pools)
Sentinel (Lending):
Pool Key
Denomination
Pool Address
sentinel_1x
0.0002 BTC
0x002bdb9769851d0307e812351cc1eb31b617951fba786cfd5d58baff36589a33
sentinel_2x
0.0004 BTC
0x02a94630f46bcf7362c12ed5b0163b4dd7644eb923aaada61ffb858d7912e03d
sentinel_3x
0.0006 BTC
0x038224d3966b850913cfc4dd610032d8082e14c90fce91819a0fb994b1cc63f3
sentinel_4x
0.0008 BTC
0x06de0d6c46431628f0cd257aa4384125b2380a7c5362aab2b146283181c2dff3
Delta Neutral (Yield):
Pool Key
Denomination
Pool Address
dn_1x
0.00036 BTC
0x07298d2765e1dc61dae0f5d8c70b86e1857b038ab7a1f7c473111321aaac51aa
dn_2x
0.00072 BTC
0x059511116f7e1877fc9e3d26a2b9165d02cc367414c009c94b7b76f6d1e4c929
dn_3x
0.00108 BTC
0x01191727f6135bb878e9771066b0c6bcc18faed9146eb0a04eabb83190b90ce3
dn_4x
0.00144 BTC
0x040babfa49b967c7873e3b275b7f8d6bea88028854f5b5923c2de5af76d78c56
Stablecoin (Private USDC):
Pool Key
Denomination
Pool Address
stable_10
10 USDC
0x04f4af2cf01a1cf28f424ce2ce3d7fed7f11792c88e5ce7a3eedd21cea24a5eb
stable_25
25 USDC
0x05aa66a4541caf4d43a526edd89c0285a671e0be0024ae5f8ca9f6734f4b7c89
stable_50
50 USDC
0x03226cbb8976f41eddf88c2871cf4d04653a1b6415dee7037a1ceaf641e977a9
stable_100
100 USDC
0x06348e9e2db703841bed848146ef895c8aed4f3c143e76bd145d9b3c544cea68
Swap Input Pools:
Pool Key
Denomination
Pool Address
swap_1x
0.0002 BTC
0x0a9ca1d554d7ef360e47de70f89fefcb571b568c8dd049de96fa181e1c69c60
swap_2x
0.0004 BTC
0x06729a96665ddffa05443774414e550d95d473e87874b273f2ed7ae03bda5dca
swap_3x
0.0006 BTC
0x07f6e657c2cbe03a233890a7cda6d65f8d7dec65b7973ea9f3ef1f7307ffe1d8
swap_4x
0.0008 BTC
0x01046244f84287eaa49b06263739ac21a26b9e144db4e6799f571e0ce4141c46
PRIVATE SWAP (WBTC → ETH/USDC/STRK):
1. Deposit WBTC into swap input pool (shielded deposit)
2. Generate withdrawal proof targeting the swap pool contract
3. Swap pool receives WBTC, swaps via AVNU DEX
4. Output token sent to recipient address
5. No link between depositor and output recipient
┌──────────┐ ┌───────────────┐ ┌──────────┐ ┌──────────────┐
│ Depositor│───►│ Swap Input │───►│ Swap Pool│───►│ AVNU Router │
│ (hidden) │ │ Pool (ZK) │ │ Contract │ │ (DEX swap) │
└──────────┘ └───────────────┘ └────┬─────┘ └──────┬───────┘
│ │
│ ┌────────────┘
▼ ▼
┌──────────────┐
│ Recipient │
│ (different │
│ address) │
└──────────────┘
Version
Proof System
Verifier
Status
V1
UltraHonk (Noir)
@aztec/bb.js
Legacy
V2
Groth16 BN254
snarkjs + Garaga
Legacy
V3
Groth16 BN254 (6 public inputs)
Garaga verifier 0x0410...
Legacy
V4
Groth16 BN254 (7 public inputs)
Garaga verifier 0x0332...
Current
File
Purpose
src/app/privacy/page.tsx
Privacy page with 4 tabs (Lending, Yield, Stables, Swap)
src/components/shielded-form.tsx
Multi-pool shielded deposit form
src/components/private-swap-form.tsx
Private swap execution interface
src/components/private-yield.tsx
Yield pool info panel
src/components/private-stables.tsx
Stablecoin pool info panel
src/components/private-swap.tsx
Swap pool info panel
src/hooks/use-shielded-vault.ts
Note generation, deposit, withdrawal, proof gen
src/hooks/use-private-swap.ts
Private swap execution logic
src/lib/privacy/note.ts
Shielded note: Poseidon hashing, nullifiers, commitments
src/lib/privacy/prover.ts
Groth16 proof generation (snarkjs WASM)
src/lib/privacy/merkle.ts
Merkle tree management
src/lib/privacy/calldata.ts
Proof calldata serialization
contracts/src/shielded_pool_v4.cairo
Current shielded pool contract
contracts/src/shielded_swap_pool.cairo
Private swap pool contract
3. Dollar-Cost Averaging (DCA) (/dca)
Automated recurring BTC purchases with an intelligent Mayer Multiple strategy that adjusts buy amounts based on whether BTC is historically undervalued or overvalued.
CREATE ORDER:
User selects:
- Sell token (USDC, USDT, ETH, STRK)
- Amount per order (e.g., 10 USDC)
- Frequency (Daily / Weekly / Bi-weekly / Monthly)
- Number of orders (e.g., 4)
- Strategy: Standard (fixed amount) or Smart (Mayer Multiple adjusted)
For Smart DCA:
- Total deposit = amount_per_order × num_orders × 1.5
- The 1.5x buffer covers worst-case (all orders at max multiplier)
- Unused funds refunded on completion or cancellation
EXECUTE ORDER (Keeper Bot):
Every interval, the keeper bot:
1. Checks which orders are due (block timestamp ≥ next_execution)
2. For Smart DCA, queries Pragma Oracle for:
- Current BTC price
- 200-day TWAP (Time-Weighted Average Price)
- Calculates Mayer Multiple = price / twap_200d
3. Applies multiplier to base amount
4. Fetches AVNU swap quote (sell token → WBTC)
5. Calls dca.execute_order(order_id, routes, ...)
6. Contract verifies timing, executes AVNU swap, records execution
Smart DCA — Mayer Multiple Strategy
The Mayer Multiple is the ratio of BTC's current price to its 200-day moving average. When the multiple is low, BTC is historically cheap — buy more. When high, it's overheated — buy less.
Mayer Multiple
Market Signal
Buy Multiplier
Example (10 USDC base)
< 0.8
Deeply undervalued
1.5x
15 USDC
0.8 – 1.0
Undervalued
1.25x
12.50 USDC
1.0 – 1.5
Fair value
1.0x
10 USDC
1.5 – 2.0
Overvalued
0.75x
7.50 USDC
> 2.0
Extremely overvalued
0.5x
5 USDC
Smart DCA deposits amount × orders × 1.5 upfront because:
Worst case: every single order executes at MM < 0.8 (1.5x multiplier)
Total spent = amount × orders × 1.5
If market stays fair value (1.0x), total spent = amount × orders
Remaining amount × orders × 0.5 is refunded on completion
Example: 10 USDC × 4 orders × 1.5 = 60 USDC deposited
Order 1: MM=0.76 → 15 USDC spent (1.5x) │ Running: 15/60
Order 2: MM=1.12 → 10 USDC spent (1.0x) │ Running: 25/60
Order 3: MM=0.95 → 12.50 USDC spent (1.25x)│ Running: 37.50/60
Order 4: MM=1.80 → 7.50 USDC spent (0.75x) │ Running: 45/60
──────────────────────────────────────────────
Total spent: 45 USDC Refunded: 15 USDC
┌──────────┐ approve + create_order ┌─────────────┐
│ User │ ──────────────────────────────► │ DCA Contract │
│ │ │ │
│ │ cancel_order (refunds) │ Orders[] │
│ │ ◄────────────────────────────── │ Executions[]│
└──────────┘ └──────┬───────┘
│
execute_order(routes) │
┌──────────┐ ────────────────────────────────────────┘
│ Keeper │ │
│ Bot │ ▼
│ │ ┌─────────────┐ ┌──────────────┐
│(off-chain│ │ Pragma │ │ AVNU Router │
│ cron job)│ │ Oracle │ │ (DEX swap) │
└──────────┘ │ (BTC/TWAP) │ │ │
└─────────────┘ └──────────────┘
File
Purpose
src/app/dca/page.tsx
DCA page with order creation form + active orders display
src/components/dca-form.tsx
Order creation UI (token select, amount, frequency, strategy toggle)
src/hooks/use-dca.ts
Order fetching, creation, display helpers (formatTokenAmount, getTokenSymbol)
scripts/dca_keeper.mjs
Off-chain keeper bot: checks due orders, fetches AVNU quotes, executes
contracts/src/dca.cairo
On-chain DCA contract: order storage, execution logic, Mayer Multiple calc
src/lib/api/avnu.ts
AVNU DEX quote/build API integration
4. Collateralized Debt Position (CDP) (/cdp)
Borrow USDC against WBTC collateral via Nostra lending protocol. Users maintain a health factor above 1.0 to avoid liquidation.
Parameter
Value
Collateral Token
WBTC (8 decimals)
Debt Token
USDC (6 decimals)
Max LTV
70%
Liquidation Threshold
~75% (Nostra parameter)
Backend Protocol
Nostra Finance
Collateral Token (Nostra)
iWBTC-c (0x05b7...f0c)
Debt Token (Nostra)
dUSDC (0x063d...a51)
OPEN POSITION:
1. User approves WBTC to CDP contract
2. CDP.deposit_collateral(amount)
├── Transfers WBTC from user
├── Approves WBTC to Nostra CDP Manager
└── Deposits as iWBTC-c collateral on Nostra
3. CDP.borrow(amount)
├── Borrows USDC from Nostra against collateral
└── Transfers USDC to user
MANAGE POSITION:
Health Factor = (collateral_value × liquidation_threshold) / debt_value
┌────────────────────────────────────────────────┐
│ Health Factor │ Status │
│ > 2.0 │ Very Safe (green) │
│ 1.5 – 2.0 │ Safe (green) │
│ 1.0 – 1.5 │ Caution (yellow) │
│ < 1.0 │ LIQUIDATION RISK (red) │
└────────────────────────────────────────────────┘
REPAY + WITHDRAW:
1. CDP.repay(amount)
├── User approves USDC to CDP contract
├── Repays USDC debt on Nostra
└── Reduces outstanding debt
2. CDP.withdraw_collateral(amount)
├── Withdraws iWBTC-c from Nostra
└── Returns WBTC to user
CLOSE POSITION (Atomic):
CDP.close_position()
├── Calculates total debt (principal + accrued interest)
├── User approves USDC to cover full debt
├── Repays 100% of debt to Nostra
├── Withdraws 100% of collateral from Nostra
└── Returns all WBTC to user
(Single transaction, no partial state)
Liquidation Price Calculation
liquidation_price = (debt_usdc × 100) / (collateral_wbtc × max_ltv)
Example:
Collateral: 0.001 WBTC
Debt: 50 USDC
Max LTV: 70%
Liquidation price = (50 × 100) / (0.001 × 70) = $71,428
If BTC drops below $71,428, position can be liquidated
File
Purpose
src/app/cdp/page.tsx
CDP page with position management
src/components/cdp-form.tsx
Deposit, borrow, repay, withdraw, close position UI
src/hooks/use-cdp.ts
Fetch CDP positions, protocol stats, health factor calc
contracts/src/cdp.cairo
On-chain CDP contract (Nostra integration, close_position)
src/lib/abi/cdp.ts
CDP contract ABI
Direct WBTC staking into Vesu lending pools for yield + STRK rewards.
Pool
Vesu Pool ID
vToken
Yield Source
Vesu PRIME
0x0451fe...c3b5
vWBTC (0x04ecb0...f56c)
Base lending APY + BTCFi STRK
Re7 xBTC
0x03a841...8ecf
vWBTC-Re7xBTC (0x0131cc...52a0)
Endur staking + lending APY + STRK
STAKE:
1. User approves WBTC to Vesu Singleton
2. Vesu Singleton.supply(pool_id, WBTC, amount)
3. User receives vToken (interest-bearing)
4. vToken balance grows over time as interest accrues
UNSTAKE:
1. User calls Vesu Singleton.withdraw(pool_id, vToken, amount)
2. vToken burned, WBTC returned (more than originally deposited)
File
Purpose
src/app/stake/page.tsx
Pool listing with APY and TVL
src/app/stake/[pool]/page.tsx
Individual pool management
src/components/staking/pool-card.tsx
Pool summary card
src/components/staking/stake-form.tsx
Stake/unstake interface
src/hooks/use-staking.ts
Fetch pool data and user positions from Vesu API
src/lib/abi/vesu-singleton.ts
Vesu Singleton ABI
6. Cross-Chain Bridge (/bridge)
Bridge assets to/from StarkNet via NEAR Intents / 1-Click protocol. Supports Solana, Ethereum, Base, Arbitrum, NEAR, and other chains.
BRIDGE IN (External Chain → StarkNet):
┌──────────┐ deposit ┌──────────────┐ intents ┌──────────┐
│ Solana / │ ─────────────► │ NEAR 1-Click │ ────────────► │ StarkNet │
│ Ethereum │ (SOL/ETH) │ Protocol │ (swap + │ Wallet │
│ Base ... │ │ (Intents) │ bridge) │ (STRK) │
└──────────┘ └──────────────┘ └──────────┘
BRIDGE OUT (StarkNet → External Chain):
┌──────────┐ STRK transfer ┌──────────────┐ intents ┌──────────┐
│ StarkNet │ ────────────────► │ NEAR 1-Click │ ──────────► │ Solana / │
│ Wallet │ to deposit │ Protocol │ (swap + │ Ethereum │
│ │ address │ (Intents) │ bridge) │ etc. │
└──────────┘ └──────────────┘ └──────────┘
1. User selects source chain + token, destination chain + token
2. Frontend fetches 1-Click quote (dry run) for estimated output
3. User confirms → non-dry quote → deposit address generated
4. Bridge IN: User sends tokens to deposit address on source chain
Bridge OUT: Frontend submits STRK transfer to 1-Click deposit address
5. Frontend polls 1-Click status endpoint for completion
6. On completion: tokens arrive at destination
File
Purpose
src/app/bridge/page.tsx
Bridge page
src/components/bridge/bridge-form.tsx
Bridge direction toggle, chain/token selectors, amount input
src/components/bridge/bridge-tracker.tsx
Step-by-step bridge status tracker
src/components/bridge/chain-token-selector.tsx
Chain and token picker UI
src/hooks/use-bridge.ts
Bridge logic: quotes, execution, polling, session persistence
src/lib/api/oneclick.ts
1-Click / NEAR Intents API integration
7. Portfolio (/portfolio)
Unified dashboard showing all user positions across every Sable product.
Category
Data Shown
Vault Positions
Share balance, current value, unrealized PnL per vault
Staking Positions
vToken balance, staked amount, earned rewards
CDP Positions
Collateral value, debt value, health factor, liquidation price
DCA Orders
Active orders, executed count, total bought, refundable amount
Shielded Notes
Number of active notes (from localStorage), denomination, pool
File
Purpose
src/app/portfolio/page.tsx
Unified portfolio dashboard
Smart Contracts Deep Dive
All contracts are written in Cairo and compiled with Scarb 2.13.1+ targeting Cairo 2.14.0 .
Contract
File
LOC (approx)
Purpose
Sentinel Vault
sentinel.cairo
~500
Pure Vesu PRIME lending
Citadel Vault
citadel.cairo
~600
Endur staking + Vesu lending
Trident Vault
trident.cairo
~700
3x recursive staking loop
Delta Neutral Vault
delta_neutral.cairo
~800
Collateral → borrow USDC → deploy yield
Turbo Vault (Base)
btcvault.cairo
~900
Leverage loop (WBTC → borrow → swap → repeat)
Apex Vault
apex.cairo
~1000
40% lending + 35% Ekubo LP + 25% Endur
DCA
dca.cairo
~600
Recurring orders with Mayer Multiple
CDP
cdp.cairo
~500
Nostra-backed WBTC→USDC borrowing
Shielded Pool V4
shielded_pool_v4.cairo
~800
Groth16 ZK deposits/withdrawals
Shielded Pool V3
shielded_pool_v3.cairo
~700
Previous version (batched deposits)
Shielded Pool V2
shielded_pool_v2.cairo
~600
Fixed denomination pools
Shielded Pool V1
shielded_pool.cairo
~500
Legacy (Noir + UltraHonk)
Shielded Swap Pool
shielded_swap_pool.cairo
~400
Pool-to-pool private swaps
Stablecoin Vault
stablecoin_vault.cairo
~400
USDC yield via Vesu RE7 USDC
Strategy Interface
strategy.cairo
~200
Shared strategy trait
Interfaces
interfaces.cairo
~300
Shared interface definitions
Lib
lib.cairo
~50
Module re-exports
[package ]
name = " sable"
version = " 0.1.0"
edition = " 2024_07"
cairo-version = " 2.14.0"
[dependencies ]
starknet = " 2.14.0"
openzeppelin = " ..." # ERC20, ERC4626, Ownable, Upgradeable
garaga = " ..." # Groth16 BN254 verification
ERC-4626 (Vault Contracts):
All 6 vault contracts implement the ERC-4626 standard with:
deposit(assets, receiver) / mint(shares, receiver)
withdraw(assets, receiver, owner) / redeem(shares, receiver, owner)
total_assets() — returns total WBTC managed including deployed capital
convert_to_shares(assets) / convert_to_assets(shares)
Ownable + Upgradeable:
owner() — curator/deployer address
upgrade(new_class_hash) — replace contract implementation
All strategy execution is owner-gated
Flash Loan Unwind:
Complex strategies (Turbo, Trident, Apex) may require flash loans for withdrawal:
Borrow WBTC → repay debt → withdraw collateral → repay flash loan
Ensures atomic unwinding of leveraged positions
Vesu V2 — Lending/Borrowing
Sable's primary yield source. Vesu is a modular lending protocol on StarkNet.
Integration
Usage
Supply WBTC
Sentinel, Citadel (via xWBTC), Turbo leverage
Supply USDC
Stablecoin Vault (RE7 USDC Core pool)
Borrow USDC
Delta Neutral, Turbo (leverage loop)
vTokens
Interest-bearing receipts for staking page
Pool API
APY, utilization, TVL data for frontend
Contract: Vesu Singleton 0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160
Integration
Usage
DCA Execution
Keeper swaps sell token → WBTC via AVNU routes
Turbo Loop
Swap borrowed USDC back to WBTC
Private Swap
Swap WBTC → output token in swap pool
API
Quote + build swap calldata
Contract: AVNU Router 0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
Ekubo — Concentrated Liquidity
Integration
Usage
Apex Vault
35% allocation to WBTC-ETH or WBTC-USDC LP
LP Fees
Market making revenue
Integration
Usage
Citadel Vault
Stake WBTC → receive xWBTC (liquid staking token)
Trident Vault
3x recursive stake loop
Apex Vault
25% allocation to Endur staking
Integration
Usage
CDP Contract
Backend for WBTC→USDC borrowing
iWBTC-c
Collateral token on Nostra
dUSDC
Debt token on Nostra
Contract: Nostra CDP Manager 0x073f6addc9339de9822cab4dac8c9431779c09077f02ba7bc36904ea342dd9eb
Integration
Usage
DCA Smart Orders
BTC spot price + 200-day TWAP for Mayer Multiple
CDP
BTC price for health factor / liquidation price display
Contract: 0x2a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b
Integration
Usage
Shielded Pools
On-chain Groth16 BN254 proof verification
Poseidon Hashing
StarkNet-native hash for note commitments
Verifier Contracts:
V3: 0x041011d7912b6759f2fe3cc66a1f746b81ec012c2774adabc77eecc299e0878d
V4: 0x03329c4d5c2e37dfd20d46c3c20be9230b2152c71947ead441c342d989d52ffa
NEAR Intents / 1-Click — Cross-Chain Bridge
Integration
Usage
Bridge IN
External chain → STRK on StarkNet
Bridge OUT
STRK on StarkNet → external chain
Supported Chains
Solana, Ethereum, Base, Arbitrum, NEAR, Polygon, Avalanche
Contract Addresses (Mainnet)
Contract
Address
Voyager
Sentinel Vault
0x04ec7fdb1679450fb88eae9facc439a46be4ddeba628211e269a7467f6e0971b
View
Citadel Vault
0x077ad8d0fe4b946cedc02eb8eb61a64e85bcde802a83e879e8c68fed8b9b130e
View
Trident Vault
0x058aadc9db62700de03d89a7c8f2952851d94e75f854cc6a340ef92d00cd3fb8
View
Delta Neutral Vault
0x06c8779ee7ed14b35ac5c6eae5dc721cc3e8104a65ffef4b5252babc407a1012
View
Turbo Vault
0x05f3d02005027296ccfb90574544b941d9ddc55c673e6fe0e92cb6f07e68d1f7
View
Apex Vault
0x071eb7fc3a912c0ee85b1dc795e29fd77ff4203a33384a1171dd4fcb7c7b3df9
View
DCA
0x0730f5de50171590132ff9238859d7eccbfa8359393f52083b3b88b397955e56
View
CDP
0x042f0f1cbb5ce44cc411f608d3c8295f3816ef7c3b6764cd6e46463efc7ca499
View
Stablecoin Vault
0x070fc554c4a9714646c5f53aea26611a70c529133a34c00f2b8f95fd2cba742d
View
Shielded Swap Pool
0x059abf82e0bc584a3b4e94fcc5aa4b5f7e9ea946b5fbe236cdecf491ad0b2c72
View
Token
Address
Decimals
WBTC
0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac
8
ETH
0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7
18
USDC
0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8
6
USDT
0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8
6
STRK
0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d
18
Pool
Pool ID
PRIME
0x0451fe483d5921a2919ddd81d0de6696669bccdacd859f72a4fba7656b97c3b5
Re7 xBTC
0x03a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf
Re7 USDC Core
0x03976cac265a12609934089004df458ea29c776d77da423c96dc761d09d24124
External Protocol Addresses
Protocol
Contract
Address
Vesu Singleton
Lending Pool Manager
0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160
AVNU Router
DEX Aggregator
0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
Nostra CDP Manager
Lending Backend
0x073f6addc9339de9822cab4dac8c9431779c09077f02ba7bc36904ea342dd9eb
Pragma Oracle
Price Feed
0x02a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b
Groth16 Verifier V4
ZK Proof Verifier
0x03329c4d5c2e37dfd20d46c3c20be9230b2152c71947ead441c342d989d52ffa
Groth16 Verifier V3
Legacy ZK Verifier
0x041011d7912b6759f2fe3cc66a1f746b81ec012c2774adabc77eecc299e0878d
All API routes are implemented as Next.js Route Handlers (server-side).
Route
Method
Purpose
/api/curator
POST
Curator deploys idle vault funds into yield strategies
/api/shielded-deposit
POST
Submit shielded deposit with Groth16 proof to pool
/api/dca/quote
GET
Get AVNU swap quote for DCA execution
/api/dca/build
POST
Build DCA swap transaction calldata
/api/relayer/fee-estimate
GET
Estimate relayer fee for private withdrawal
/api/relayer/pool-status
GET
Get shielded pool Merkle tree status (root, size)
/api/relayer/withdraw
POST
Submit private withdrawal with Groth16 proof
/api/relayer/deploy-batch
POST
Deploy batch of pending shielded deposits
/api/relayer/private-swap
POST
Execute private swap between pools
/api/staking
GET
Fetch staking pool data from Vesu API
/api/execute-outside
POST
Execute outside transactions (utility)
On-Chain Testing Evidence
All features have been tested on StarkNet Mainnet from the following wallet:
Address: 0x0362A762F25f0aa9C3935D4D11D5d5099262E4fF59f5D360d37BD157fBC3ABbc
Account Type: Argent X
Total Transactions: 98+
Sable Trident (0x058aadc9db...)
Action
TX Hash
Voyager
Deposit
0x63956529fd2a628b14e495cd41fc3d549874578ffc3613e8f22fd2914dff2ca
View
Deposit
0x2752d9b62f3018abc665fa7a657517e5622ac80071dbb78cfddee3530e6b08b
View
Deposit
0x931d14aea50bdded3932ce27338776421029a65d7895a65a2b2c39ac6bdb96
View
Deposit
0x4e5382f310d35dbdf83b6f25200f3ca2a8486ed3c2fb75b59ad8f4e0daec1d9
View
Withdraw
0x3469f3cc5a2c9cd70b6e4917bf93e4887738fe21ae5ced1f2fa3750bb2a3d1a
View
Withdraw
0xea31a445785525edf6e88db39970bc33c67ffcfe5e33099b7dff266d49b18b
View
Withdraw
0x226bdf395d1583c1037ed9c30c719672d570f95e3467936991ed1c4983272a4
View
Withdraw
0x2000617912e63a01b1eee025a4b1e7af7faca2816d8a4e96a285800ff46b546
View
Withdraw
0x724110ca31468d5bdfbf303d7abd6ce7ae087c23ba131cbebc500e03a7c13c5
View
Sable Citadel (0x077ad8d0fe...)
Action
TX Hash
Voyager
Deposit
0x30e3f2b57afee22c47df45c1841d379d736bf01962a813c79fa55d113f6d166
View
Deposit
0x7b1f475268fce4487490c250be68d10c22878086c890e6454abdff3a3f15ba3
View
Deposit
0x250e748bf6ff67f2e0ea2453235abccb6311f57dce5f8906a3b486a194434ea
View
Withdraw
0x640f97cc1ca4d8e547518e6e52ffa5ccdd01a170a8bfca8a2e8ca2c90e99f74
View
Withdraw
0x360efe165b08f72343142e2d2c9294086130125e143cdd3222d5bc8a5781774
View
Sable Turbo (0x05f3d02005...)
Action
TX Hash
Voyager
Deposit
0x7886dd70b823481d91cc8545f3092596f215cec8a7b26cc7f3260ddac47a4f
View
Deposit
0xf8b68d9735f2b668e08eb8ce237a36bc847c90dd2eea60cbd81efd9486c5e8
View
Deposit
0x50fb6cf22f7dac6c94c26f1c1b1f3b7265073828fa71fb05abc91365837884d
View
Deposit
0x78298f47a1bf0787d6cafe9d25a274d7e82ffd48b02aaf0db11a7dcbf6d86f9
View
Deposit
0x6abe965bdc657df2ffd5f932742da844acd8f15ceb0dd2fc763ceeba24f889f
View
Withdraw
0x4f18fec0125aafb635288c9ff80daf7c9a8ac642db315a03907f9de3a82c868
View
Withdraw
0x7507bea73cf503eac93d58870d33cec4923f9886d7cc6a72c6e795b1b9ffb7d
View
Withdraw
0x5cb3acf6463e064e06a50010c14b4f1ceabd02bbdfd864c2cec15aa7aaa5a5c
View
Withdraw
0x6d99b72eea9a6d6f9bef57096952e7a74035eeb8eb2d844a9a395da24e8ec50
View
Withdraw
0x4f6538863ede80861f1419c0d47652d557472ccac85d53a63dc4d0ab0c0454d
View
Sable Apex (0x071eb7fc3a...)
Action
TX Hash
Voyager
Deposit
0x7cb531ec72ae7d2967c46e2b9e4f1617021b24cce3923041dd9449875e2fb33
View
Deposit
0x361444553f157da29b3cfdd95f4625bb4880455151e762153634ea15a89d857
View
Withdraw
0x489523c49a24cc3e5c45438c39caaf1ee06358217464540c06e7d71bb31ea96
View
Withdraw
0x35d936ce731b9661ed1800f62ccb38e62526e4356c420e5fac1b479b06759cc
View
Withdraw
0x23cbfbaa54f5e83bfb904afcbc8ce3288e7c01bf154491567282df226c4f193
View
Sable Sentinel (0x04ec7fdb16...)
Action
TX Hash
Voyager
Deposit
0x274bbea8239ed28b9b1d717d485bac6cbf45e929e3fecdd01fa7c0f4a0bde9b
View
Deposit
0x24b5eacf53c9ff8f2638c78a38dacec2443735cbd1365a45cfb8c4bdf0827ae
View
Deposit
0x585846d1623c1f072f656ca8e54f6d7bd91c95d8bf9620d9ee38f13992915b5
View
Withdraw
0x278caa569b6835676371db7dea08a9bf418015833eb3507856fae21da053d3f
View
Withdraw
0x480714ba02d56dd0ac609a20fc1a1773d0b78f1660dc1914b645d9fa30af6e9
View
Withdraw
0x7e69158b4f33cf43062a56584ce60a98df8ff96c306073ea2f60f4baebe724c
View
Sable Delta Neutral (0x06c8779ee7...)
Action
TX Hash
Voyager
Deposit
0x5560c97ee17d49bba4b93bf1acfbc324bd25cab33051a6b90cc18249b3b517f
View
Deposit
0x6e4566cd90cbe44771441722f82b8c5d8778b3da047c3a00746c15c6f8dfbea
View
Deposit
0x5efbec7187a30fcfeb9248cfbaaf9b73f8e469103605c58e1b041b3507a8ac2
View
Withdraw
0x39ca51bfa3db16483f91fa171b29ee97a78e9b757e3026cb69e0914fb61cb1
View
Withdraw
0xafb521bacc40e445308191cfe4065de0b61ff600e739e2b1ea1d80e1b92481
View
Withdraw
0x5b7574b4cf306abe90e446d3cbed25a44fea78c9580bd25ba67e7b76f4ae040
View
Staking Transactions (Vesu vTokens)
Vesu PRIME vWBTC (0x04ecb0667...)
Action
TX Hash
Voyager
Stake (Deposit)
0x21e9d013b70cd1e185173a7409d47bf902efbdf9d69e60f9ab87d5bcde3b2af
View
Stake (Deposit)
0x4b24b9dbbdc400f9b6fa8ca740c72b9a647d3267b622af8a93ceac1d6cfcdbb
View
Unstake (Redeem)
0x21088e22c1edb28a51ccda531ef4b18f4eee56a19dca66ae6c8b56ec4d529d9
View
Unstake (Redeem)
0x31a46ae3d007e2d44c721b5b68dd7843c54b9f1977a0425c28efcef9b42fffd
View
Vesu Re7 xBTC vWBTC (0x0131cc091...)
Action
TX Hash
Voyager
Stake (Deposit)
0x2fa9a54b15c8b01122d6a4662b2050e70ab33cb2672675f3f7bee1bea9ba81
View
Stake (Deposit)
0x51d5a16e5ecd769f3f665db00efe95d8396482bb96fedee2f8e451a3af3f35a
View
Unstake (Redeem)
0x39bf229249211ea96c6213c7e67901b573116788ef98534013acbe30b3ee672
View
Unstake (Redeem)
0x6d7c0faf1570a808ffed9ea92096944f95489c128a6a5b8c60e0be445a5f4e6
View
Action
TX Hash
Voyager
Deposit Collateral + Borrow
0x67333902d51b445787f71927b65846b178522eb259f2cbc9e661cd9bd3c7386
View
Repay + Withdraw
0x2dc374d5bd8efa4c0284fa94c9c3e790180f62cca86122345e3423dcdf16bdd
View
Action
TX Hash
Voyager
Create Order (approve USDC + create_order)
0x633aa87c3038b8090573d58f66284504dc6c097422b73702e885cf899974d6c
View
Cancel Order
0x47c7df3fdd91a9f3c5f37327beb791dbcfc195828deda9e09adfc1da98261fc
View
AVNU Swap Transactions (Sample)
The tester wallet executed 19+ swaps via the AVNU Router for token conversions:
TX Hash
Voyager
0x4686d85a958637c01731577f5f0b315d384b416ffa1655c2e2c3423dc75eb41
View
0x75356c745ec3fa51737ba4f9d8fe347bf44ed14ac621a7793e4c5ae3ddd7c74
View
0x65791bfe6ab019dbbf4ae5e1100f258000df36f34f0a1cc8462966f6c426b7e
View
0x56c5204f8c246cfc08d2455fd80f513b1567f932ed35297f82f965553a22e4f
View
0x6f539c05857b7086ab480d7f6025217f8d5cf655929abd91122e6e108078d27
View
... and 14 more
Address: 0x0007842590942b769a203cfcb07540299b86e22ba05b6708b516ec04ca044ef7
Total Transactions: 408+
Deploy Account TX: 0x3947977f87e6bf1bd79180d4a6c5278da151a3cc8dc2d92bc4e0be02537861b
btcvault/
├── contracts/ # Cairo smart contracts (Scarb project)
│ ├── src/
│ │ ├── lib.cairo # Module re-exports
│ │ ├── interfaces.cairo # Shared interface definitions
│ │ ├── strategy.cairo # Common strategy trait
│ │ ├── sentinel.cairo # Vault: Pure Vesu lending
│ │ ├── citadel.cairo # Vault: Endur staking + Vesu
│ │ ├── trident.cairo # Vault: 3x recursive staking
│ │ ├── delta_neutral.cairo # Vault: BTC-USDC spread
│ │ ├── btcvault.cairo # Vault: Turbo leverage loop
│ │ ├── apex.cairo # Vault: Multi-strategy max yield
│ │ ├── stablecoin_vault.cairo # Vault: Private USDC yield
│ │ ├── dca.cairo # DCA: Recurring orders + Mayer Multiple
│ │ ├── cdp.cairo # CDP: WBTC→USDC borrowing
│ │ ├── shielded_pool.cairo # Privacy V1: Noir + UltraHonk
│ │ ├── shielded_pool_v2.cairo # Privacy V2: Groth16 + fixed denom
│ │ ├── shielded_pool_v3.cairo # Privacy V3: Batched deposits
│ │ ├── shielded_pool_v4.cairo # Privacy V4: Current (7 public inputs)
│ │ └── shielded_swap_pool.cairo # Privacy: Pool-to-pool private swaps
│ ├── Scarb.toml # Cairo project config
│ ├── Scarb.lock # Dependency lock file
│ ├── scripts/ # Deployment & upgrade scripts
│ │ ├── deploy.mjs
│ │ ├── deploy.sh
│ │ ├── upgrade.mjs
│ │ ├── upgrade-cdp.mjs
│ │ └── declare_and_upgrade.py
│ └── target/ # Build artifacts (sierra, casm)
│
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── layout.tsx # Root layout (providers, header, styling)
│ │ ├── page.tsx # / — Vault listing
│ │ ├── globals.css # Tailwind v4 + custom styles
│ │ ├── vault/
│ │ │ └── [id]/
│ │ │ └── page.tsx # /vault/[id] — Vault detail
│ │ ├── privacy/
│ │ │ └── page.tsx # /privacy — Shielded vaults
│ │ ├── dca/
│ │ │ └── page.tsx # /dca — Dollar-cost averaging
│ │ ├── cdp/
│ │ │ └── page.tsx # /cdp — Collateralized debt
│ │ ├── stake/
│ │ │ ├── page.tsx # /stake — Pool listing
│ │ │ └── [pool]/
│ │ │ └── page.tsx # /stake/[pool] — Pool management
│ │ ├── bridge/
│ │ │ └── page.tsx # /bridge — Cross-chain bridge
│ │ ├── portfolio/
│ │ │ └── page.tsx # /portfolio — Unified dashboard
│ │ └── api/ # Next.js API route handlers
│ │ ├── curator/
│ │ │ └── route.ts # POST: Deploy idle funds
│ │ ├── shielded-deposit/
│ │ │ └── route.ts # POST: Shielded deposit
│ │ ├── dca/
│ │ │ ├── quote/route.ts # GET: AVNU quote
│ │ │ └── build/route.ts # POST: Build swap TX
│ │ ├── relayer/
│ │ │ ├── fee-estimate/route.ts
│ │ │ ├── pool-status/route.ts
│ │ │ ├── withdraw/route.ts
│ │ │ ├── deploy-batch/route.ts
│ │ │ └── private-swap/route.ts
│ │ ├── staking/
│ │ │ └── route.ts # GET: Vesu pool data
│ │ └── execute-outside/
│ │ └── route.ts
│ │
│ ├── components/ # React components
│ │ ├── header.tsx # Top navigation bar
│ │ ├── wallet-button.tsx # Argent/Braavos wallet connect
│ │ ├── vault-card.tsx # Vault listing card
│ │ ├── deposit-withdraw.tsx # Vault deposit/withdraw modal
│ │ ├── performance-chart.tsx # APY/TVL historical chart
│ │ ├── shielded-form.tsx # Shielded deposit form
│ │ ├── private-yield.tsx # Yield pool info
│ │ ├── private-stables.tsx # Stablecoin pool info
│ │ ├── private-swap.tsx # Swap pool info
│ │ ├── private-swap-form.tsx # Private swap execution
│ │ ├── dca-form.tsx # DCA order creation
│ │ ├── cdp-form.tsx # CDP position management
│ │ ├── bridge/
│ │ │ ├── bridge-form.tsx # Bridge direction, amount, chain select
│ │ │ ├── bridge-tracker.tsx # Step-by-step status tracker
│ │ │ └── chain-token-selector.tsx
│ │ ├── staking/
│ │ │ ├── pool-card.tsx # Staking pool card
│ │ │ └── stake-form.tsx # Stake/unstake interface
│ │ └── ui/
│ │ └── animated-number.tsx # Animated counter component
│ │
│ ├── hooks/ # React hooks (state + chain interaction)
│ │ ├── use-vault-data.ts # Vault metadata, APY, performance
│ │ ├── use-vault-contract.ts # On-chain vault state reads
│ │ ├── use-staking.ts # Vesu staking pools + positions
│ │ ├── use-dca.ts # DCA orders, creation, display
│ │ ├── use-cdp.ts # CDP positions, health factor
│ │ ├── use-shielded-vault.ts # ZK deposits, withdrawals, proofs
│ │ ├── use-private-swap.ts # Private swap execution
│ │ └── use-bridge.ts # Cross-chain bridge logic
│ │
│ ├── lib/
│ │ ├── constants.ts # All addresses, pool configs, tokens
│ │ ├── types.ts # TypeScript interfaces
│ │ ├── format.ts # Number/currency formatting
│ │ ├── rpc.ts # StarkNet RPC URL config
│ │ ├── data.ts # Hardcoded vault data (fallback)
│ │ ├── api/
│ │ │ ├── vaults.ts # Vault data + APY calculation
│ │ │ ├── onchain.ts # total_assets() RPC calls
│ │ │ ├── vesu.ts # Vesu API integration
│ │ │ ├── defillama.ts # DefiLlama historical data
│ │ │ ├── price.ts # CoinGecko BTC price (30s cache)
│ │ │ ├── avnu.ts # AVNU DEX router integration
│ │ │ └── oneclick.ts # 1-Click bridge API
│ │ ├── privacy/
│ │ │ ├── note.ts # Poseidon commitments, nullifiers
│ │ │ ├── prover.ts # Groth16 proof generation (WASM)
│ │ │ ├── merkle.ts # Merkle tree management
│ │ │ ├── calldata.ts # Proof calldata serialization
│ │ │ └── worker-threads-stub.ts # WASM worker stub (Turbopack)
│ │ └── abi/
│ │ ├── vesu-singleton.ts # Vesu contract ABI
│ │ ├── erc4626.ts # ERC-4626 vault ABI
│ │ └── cdp.ts # CDP contract ABI
│ │
│ └── providers/
│ └── starknet.tsx # StarknetConfig + wallet providers
│
├── scripts/ # Off-chain tooling
│ ├── dca_keeper.mjs # DCA keeper bot (execute due orders)
│ ├── deploy-account.mjs # Account deployment utility
│ ├── query_vaults.py # Vault query testing
│ └── ekubo_query*.py # Ekubo analytics scripts
│
├── public/ # Static assets
│ ├── logo-sable.png # Project logo
│ └── tokens/ # Token icons (SVG)
│
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript configuration
├── next.config.ts # Next.js config (WASM, Turbopack)
├── postcss.config.mjs # PostCSS with Tailwind v4
├── eslint.config.mjs # ESLint configuration
└── .env.local # Environment variables (not committed)
Node.js ≥ 20.x
npm ≥ 10.x
Scarb ≥ 2.13.1 (for Cairo contract compilation)
StarkNet wallet (Argent X or Braavos browser extension)
git clone < repo-url> btcvault
cd btcvault
npm install
Create .env.local:
# StarkNet RPC (optional — defaults to Lava free endpoint)
NEXT_PUBLIC_STARKNET_RPC=https://rpc.starknet.lava.build
STARKNET_RPC=https://starknet-mainnet.g.alchemy.com/starknet/version/rpc/v0_8/< your-key>
# Curator (for /api/curator endpoint)
CURATOR_PRIVATE_KEY=0x...
CURATOR_ADDRESS=0x...
# Keeper (for DCA keeper bot)
KEEPER_KEY=0x...
KEEPER_ADDR=0x...
Running the Development Server
npm run dev
# Opens http://localhost:3000 with Turbopack hot reload
Compiling Cairo Contracts
cd contracts
scarb build
# Outputs Sierra + CASM to contracts/target/
Running the DCA Keeper Bot
node scripts/dca_keeper.mjs
# Checks all due DCA orders, fetches AVNU quotes, executes on-chain
Contracts are deployed using starknet.js scripts in contracts/scripts/:
# Declare + deploy a new contract
node contracts/scripts/deploy.mjs
# Upgrade an existing contract
node contracts/scripts/upgrade.mjs
# Upgrade CDP specifically (with proper resource bounds)
node contracts/scripts/upgrade-cdp.mjs
Resource Bounds (StarkNet V3 Transactions)
All StarkNet V3 transactions require explicit gas bounds:
const resourceBounds = {
l1_gas : { max_amount : 100000n , max_price_per_unit : 100000000000000n } ,
l2_gas : { max_amount : 1000000000n , max_price_per_unit : 100000000000n } ,
l1_data_gas : { max_amount : 200000n , max_price_per_unit : 100000000000000n } ,
} ;
For gas-heavy operations (AVNU swaps, DCA execution), L2 gas may need up to 1.2 billion (max allowed: 0x47868C00).
Keeper Bot Production Deployment
The DCA keeper bot should run as a persistent service (cron job or systemd):
# Run every 6 hours via cron
0 * /6 * * * cd /path/to/btcvault && node scripts/dca_keeper.mjs >> /var/log/dca_keeper.log 2>&1
This project is licensed under the MIT License .
Built on StarkNet · Powered by Vesu, Ekubo, Endur, Nostra, AVNU, Pragma, Garaga, NEAR Intents