Guides
Vault Router
Vault Router — Multi-Vault Deposits
The VaultRouter contract enables optimal vault selection and multi-vault deposits in a single transaction. Instead of manually comparing APYs and approving tokens for each vault, VaultRouter handles routing, approval, and deposit atomically.
How It Works
User calls VaultRouter.deposit_to_best_vault(amount, token)
→ Router queries all registered vaults
→ Selects vault with best APY + available capacity
→ Handles token approval internally
→ Deposits into selected vault
→ Returns LST shares to user
→ Resets approval to zero (safety)Architecture
VaultRouter sits between users and VaubanVault instances:
┌──────────┐ ┌──────────────┐ ┌────────────────┐
│ User │────►│ VaultRouter │────►│ VaubanVault │
│ │ │ │ │ (vaSTRK) │
│ │ │ - routing │ ├────────────────┤
│ │ │ - approval │ │ VaubanVault │
│ │ │ - deposit │ │ (vawBTC) │
└──────────┘ └──────────────┘ └────────────────┘Contract Interface
#[starknet::interface]
trait IVaultRouter<TContractState> {
// Deposit to the best vault for a given token
fn deposit_to_best_vault(
ref self: TContractState,
amount: u256,
token: ContractAddress,
receiver: ContractAddress
) -> (ContractAddress, u256); // (vault, shares)
// Deposit to a specific vault
fn deposit_to_vault(
ref self: TContractState,
vault: ContractAddress,
amount: u256,
receiver: ContractAddress
) -> u256; // shares
// Admin: register/remove vaults
fn register_vault(ref self: TContractState, vault: ContractAddress);
fn remove_vault(ref self: TContractState, vault: ContractAddress);
// View: get registered vaults
fn get_vaults(self: @TContractState) -> Array<ContractAddress>;
}Security
- CEI pattern: All state updates before external calls
- Approval reset: Token approvals set to zero after each deposit (prevents leftover allowance attacks)
- Owner-only registration: Only contract owner can register/remove vaults
- Zero-address validation: All address inputs validated
- Reentrancy safe: No state dependencies across external calls
Integration
Frontend (Starknet.js)
import { Contract } from 'starknet';
const router = new Contract(VAULT_ROUTER_ABI, VAULT_ROUTER_ADDRESS, account);
// Approve router to spend tokens
await account.execute([
{ contractAddress: STRK_TOKEN, entrypoint: 'approve', calldata: [VAULT_ROUTER_ADDRESS, amount, 0] },
{ contractAddress: VAULT_ROUTER_ADDRESS, entrypoint: 'deposit_to_best_vault', calldata: [amount, 0, STRK_TOKEN, userAddress] }
]);Backend API
GET /api/vaults/recommendation?token=STRK&amount=1000
→ { vault: "vaSTRK", apy: "12.5%", capacity: "80%", shares_estimate: 995 }Related
- Native Staking Guide — Direct vault deposits
- LST Staking Guide — Liquid staking tokens
- Architecture: Contracts — Full contract reference