System Overview
An Earn Vault has three layers:- Loopscale layer. Lists vaults, indexes onchain state into snapshots and per-wallet positions, computes APY and allocation, and builds deposit and withdrawal transactions.
- Vault program (
sVau1tXvayVWfotzm9Ahcv2qfnnfRWttt78BCnNC6dD). Tracks NAV, mints and burns shares, processes the withdrawal queue, runs governance, and validates every manager action against vault-level invariants. - Custody. Capital sits in a Squads Smart Account that the vault controls. The manager never holds depositor funds directly. Every strategy action is a Squads transaction that must match a pre-approved policy.
Onchain Accounts
The core account. Stores the underlying mint, the share (LP) mint, the Squads addresses, the list of token entries, the list of strategy positions, role assignments, fee and withdrawal configuration, governance configuration, and the vault’s financials (idle AUM, deployed AUM, LP supply, pending withdrawals, instant-withdrawal window state). Derived from
["vault", seed_id].SPL token representing proportional ownership of the vault. Minted on deposit and burned on withdrawal at the current NAV per share. Queued and vote-staked shares sit in the vault’s LP escrow account.
Each token the vault can hold (its underlying plus any other accepted tokens) has an entry with a mint, a price ID into
ExponentPrices, a token account owned by the Squads vault (where deposits land and capital is deployed from), and a token account owned by the vault (where withdrawal fills are staged). Deposits and withdrawals can only use tokens that have an entry.Every non-token position the vault tracks for NAV: Loopscale loans, strategies, and vault stakes; Kamino obligations and farms; Exponent yield, CLMM, and orderbook positions; Orca Whirlpool positions; and tracked token accounts such as PTs or tranche tokens. A position must be registered before the vault can value it, and the vault won’t let the manager trade into an unregistered one.
A global price account. Each price ID resolves to a feed (Pyth, Scope, Chainlink, stake-pool rate, PT/YT pricing, TWAP, Kamino vault share price, Loopscale vault LP price, and others), or to a product of feeds, e.g.
JitoSOL/SOL × SOL/USD. All values are converted into the vault’s underlying.One account per queued withdrawal request. Records the owner, the shares requested and still remaining, and the fills made against it (which token entry, what share of the request). Its address is the
requestId returned by the Loopscale API.Governance state for a proposed change, plus one vote account per LP holder voting on it. See Governance.
Roles
Each role holds one or more keys.
On Loopscale-curated vaults the Overview tab shows the curator, the strategist (allocator), the sentinel, and the Squads vault address.
How Manager Actions Are Constrained
Manager discretion is limited by two independent checks on every strategy transaction. 1. Squads policies (what can be called). AProgramInteraction policy whitelists a target program, the instructions allowed on it, and constraints on accounts and instruction data, e.g. only these Kamino markets, only this Loopscale strategy, only senior-tranche deposits. Squads rejects any instruction that doesn’t match an approved policy.
2. The vault’s post-hook (what the result is allowed to be). Every policy attaches a post-hook that calls the vault program’s validate_interaction_hook after the instruction runs. The hook sees exactly which instructions executed and re-checks the vault’s invariants:
Policies can only be added or changed directly while the vault is empty. Once it holds depositor capital, policy changes must go through governance.
NAV, Pricing, and AUM Refresh
refresh_aum instruction. That instruction walks every token entry and strategy position and values each through ExponentPrices. Price checks are same-slot strict: each price, and each Kamino reserve the vault touches, must have been updated in the slot where it’s read, otherwise the program throws StalePriceData (6080). Any instruction that changes vault configuration or positions also sets an AUM_REFRESH_REQUIRED flag. Until a fresh refresh clears it, deposits and withdrawals fail with AumRefreshRequired (6123).
That’s why every Earn transaction from the Loopscale API comes as two transactions sent as one Jito bundle:
- AUM refresh. Price updates, Kamino/Scope reserve refreshes, then
refresh_aum. - Action. The deposit, withdrawal, claim, or cancel, plus the Jito tip.
Deposits
deposit_liquidity(amount, min_lp_out) transfers a token-entry token from the user into the Squads vault and mints shares:
min_lp_out shares would be minted (MinLpOutNotMet, 6016) or if it would push the vault past its deposit cap, max_aum_supply (LpSupplyMaximumExceeded, 6015).
Withdrawals
Withdrawals take one of two paths, depending on the vault’s configuration and current liquidity.- Queued
- Instant
- Request.
queue_withdrawalmoves the user’s shares into escrow and creates a withdrawal account. No funds move yet. - Fill. The manager unwinds positions as needed and calls
fill_withdrawal, through a Squads policy, choosing which token entries pay out and how much of the request each covers. A request can be filled in several partial fills. The standard withdrawal fee (normal_withdrawal_cut_bp) applies. - Claim. Once the request is filled and the vault’s withdrawal period has unlocked, the user calls
execute_withdrawalto receive the tokens.
withdrawal_cancel_cooldown_seconds) has passed. The payout token is the manager’s choice at fill time. A preference passed through the Loopscale API is recorded and honored where possible, but isn’t enforced onchain.Withdrawal period
Each vault sets a withdrawal period that controls when queued requests can be claimed and when the instant-withdrawal window resets:- Interval: a fixed lock time after the request (between 12 hours and 30 days).
- Weekly schedule: specific UTC weekdays, optionally every Nth week. For example, a vault might process withdrawals on Tuesdays and Fridays.
Fees
There is no performance fee. All fee parameters can only change through governance once the vault holds AUM.
Raw values in the vault account use different precisions:
management_fee_bps is in millionths (1,000,000 = 100%/yr, so 3000 = 0.30%), while the withdrawal cuts use standard basis points (10,000 = 100%). The Loopscale app converts these for display.Governance
Once a vault holds depositor capital, the manager can only change settings, roles, fees, deposit caps, positions, or policies through an onchain proposal:- Rejection-based voting. Proposals pass by default. Share holders can stake shares to vote Reject, or Opt Out, which queues their shares for withdrawal if the proposal passes. If rejections reach the vault’s rejection threshold (a share of LP supply snapshotted when voting starts), the proposal fails.
- Timelock. An approved proposal can only execute after the timelock, so depositors always get a window to exit before a material change takes effect.
- Defaults. Exponent’s defaults are a 48-hour voting period (configurable from 1 hour to 7 days), a 24-hour timelock, and a 33% rejection threshold. Each vault can set its own, and the live values appear under Governance on the vault’s Overview tab.
- Finalizing and executing a proposal are permissionless. Anyone can call them once the period has passed.
Supported Venues
Policies can whitelist any of the integrations the vault program knows how to value:The Loopscale Layer
Loopscale reads everything from chain and adds no custody or onchain permissions of its own.- Registry. Each listed vault is registered with its provider, share mint, accepted asset, display metadata, and a status:
Draft(shown, deposits paused),Active,Paused, orDeprecated. Flags record which withdrawal paths the vault offers and whether depositors must accept terms first. - Indexing. Loopscale streams the vault program’s accounts and transactions. It keeps a decoded copy of each vault account, tracks every withdrawal request and its fills, and writes a per-wallet event ledger (deposit, instant withdraw, request, cancel, fill, claim) used for cost basis and PnL.
- Snapshots. Every 15 minutes, Loopscale snapshots share supply, NAV per share, AUM, pending withdrawals, and utilization (deployed AUM ÷ total AUM).
- Yield figures.
- APY (
displayApyBps) is forward-looking: each position’s current rate (lending, borrowing cost, PT yield, LP fees) weighted by its value, netted across lend and borrow legs. - Realized return (
realizedReturnBps24h/7d/30d) is backward-looking: the simple annualized change in NAV per share over the window. - Rewards APY annualizes active reward emissions against AUM.
- Headline APY (
headlineApyBps) is the APY, or the 7-day realized return when no APY is available, plus rewards APY.
- APY (
- Allocation. Each refresh splits AUM into unallocated liquidity (idle token-entry balances) and deployed positions grouped by venue, each with its share of AUM and APY. This feeds the Allocation tab.
- Transactions. The Pandora API wraps the provider’s SDK to build deposit, withdraw, claim, and cancel transactions, prepends the AUM-refresh transaction, and attaches the address lookup tables. See Integrate Earn Vaults.