Skip to content

feat: index-vault core — iPOT liquid index token, NAV engine, redeem queue, keeper cranks - #79

Open
YD811 wants to merge 4 commits into
mainfrom
feat/index-vault-core
Open

feat: index-vault core — iPOT liquid index token, NAV engine, redeem queue, keeper cranks#79
YD811 wants to merge 4 commits into
mainfrom
feat/index-vault-core

Conversation

@YD811

@YD811 YD811 commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

The flagship DeFi index-vault layer: deposit USDC → mint a liquid index token (iPOT) at NAV → capital deploys into configured index legs under on-chain caps → instant redemptions from an idle buffer, bigger ones through an escrowed queue.

On-chain (all additive, layout-compatible):

  • StrategyConfig (["strategy", pot]) — weights (≤10 legs, Σ=100%), idle buffer, TVL/deposit caps, NAV guards, keeper identity
  • TokenAllowlist (["allowlist"]) — global mint allowlist, 100 slots, 3 classes
  • StrategyPosition + position escrow — per-leg cost basis; the exact seam Kamino/Meteora CPI adapters plug into (Phase 2)
  • RedeemRequest — escrowed redemption queue, priced at settlement NAV, permissionless settle, cancellable
  • PotAccount tail carve (reserved 128→70): index_mint, is_flagship, Option<NavSnapshot> — old accounts decode unchanged
  • 15 instructions; NAV snapshot guarded by slot monotonicity + deviation cap; exits never pause-gated

Custody invariant: funds only in vault-PDA-owned token accounts; the keeper cannot pay any wallet except a redeeming member's own ATA.

Off-chain mirror: SDK (PDAs + builders for the full surface, tsc clean) · keeper NAV crank (60s, book-value) + redeem settler · web (token registry, iPOT deposit/redeem panel with instant/queued fallback, flagship pin) · deterministic IDL patcher (scripts/patch_idl_index.py) since anchor 0.30.1 IDL-gen is broken on modern rustc.

Notes for review

  • One init per instruction: two inits in one Accounts struct blow the 4KB BPF stack frame on current platform-tools — hence the split bootstrap (init_index_mint → init_strategy_config; init_position → init_position_vault) and client-created vault ATAs.
  • Legacy plain struct StrategyConfig (strategy_vault.rs) renamed LegacyStrategyConfig — not an account, no discriminator/layout impact.
  • update_strategy_config loosening changes are NOT timelocked yet — flagged in docs as a pre-mainnet TODO to wire into PendingRiskParams.

Tests

Full suite 30 passing (18 existing + 12 new) against localnet (solana-test-validator --bpf-program GJap9… pot_vault.so): bootstrap, NAV repricing, deposit caps, instant + queued redeem, idle-buffer floor, keeper auth, deviation guard, pause semantics (deposits blocked, exits open).

Deploy

Devnet redeploy pending (upgrade authority = deployer 9HCK3…, program account already extended; blocked on ~0.6 faucet SOL). Mainnet: gated on devnet e2e + YD sign-off — runbook in the follow-up docs PR.

🤖 Generated with Claude Code

YD811 and others added 4 commits July 5, 2026 04:07
…t, NAV snapshot, redeem queue, deploy seam

- New accounts: StrategyConfig (["strategy", pot]), TokenAllowlist (["allowlist"], 100 mints,
  3 classes), StrategyPosition (["position", pot, mint, route]), RedeemRequest (["redeem",
  pot, member, id]).
- PotAccount tail carve: index_mint + is_flagship + Option<NavSnapshot> (reserved 128→70,
  layout-compatible — old accounts decode as default/None).
- 15 new instructions: allowlist init/set, index bootstrap (init_index_mint +
  init_strategy_config + init_position + init_position_vault — one init per ix, the 4KB BPF
  stack frame does not fit two), deposit_base, redeem_instant, request_redeem/settle_redeem/
  cancel_redeem, deploy_to_strategy/withdraw_from_strategy, update_nav_snapshot,
  set_strategy_paused, update_strategy_config.
- Guards: deposit min/max, TVL cap, NAV staleness (slots) + deviation cap, idle-buffer floor
  on deploys, keeper allowlist, weights sum=100%, global mint allowlist. Redemptions are
  never pause-gated.
- Custody: funds only in vault-PDA-owned token accounts; keeper cranks can never pay
  anyone but the requester's own ATA.
- Legacy strategy_vault StrategyConfig renamed LegacyStrategyConfig (plain struct, no
  layout/discriminator impact).
- IDL: scripts/patch_idl_index.py (deterministic, idempotent, self-checking) — 53 ix,
  14 accounts, 100 errors; copies refreshed in sdk/web/keeper.
- Tests: tests/index_vault.test.ts — 12 cases (bootstrap, NAV repricing, caps, instant +
  queued redeem, buffer floor, keeper auth, pause semantics). Full suite 30 passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- pda.ts: getStrategyConfigAddress / getAllowlistAddress / getIndexMintAddress /
  getStrategyPositionAddress / getPositionVaultAddress / getRedeemRequestAddress.
- index-vault.ts: builders for the full surface (bootstrap, deposit, instant+queued
  redeem, settle/cancel, deploy/withdraw, NAV crank, pause, config update), ATA
  helpers (idempotent create — vault ATAs are client-created by design),
  fetchStrategyConfig/fetchPositions/fetchPendingRedeems, getNavPerShare,
  computeBookNav. tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…settler

- index-crank.ts: discovers StrategyConfigs served by this keeper key, writes
  book-value NAV (idle buffer + Σ position cost bases; exact while routes hold
  base at book — market pricing per route plugs in with the protocol adapters),
  settles pending RedeemRequests the buffer can serve (rate-limited per tick).
- Idempotent (non-overlapping ticks), retries with exponential backoff,
  per-tick settle cap, structured logs, metrics export.
- Keeper key via KEEPER_KEYPAIR_PATH / KEEPER_KEYPAIR_JSON (secret manager) —
  crank-only identity, cannot route funds anywhere but a requester's own ATA.
- Wired into index.ts behind KEEPER_ENABLE_INDEX_CRANK (default on, no-op
  without a key). .env.example documents the new knobs. tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, flagship pin

- lib/token-registry.ts: curated client registry (verified liquid mints only —
  USDC/USDT + SOL/JitoSOL/mSOL/bSOL/jupSOL), 3 classes, per-token defiRoutes,
  composition validator mirroring on-chain guards. Must stay ⊆ on-chain allowlist.
- hooks/useIndexVault.ts: NAV/price/idle reads (30s), previewShares/previewPayout,
  useDepositBase (1% min-shares floor), useRedeemIndex (instant → queue fallback).
- components/IndexVaultPanel.tsx: price/share + NAV + instant liquidity, deposit
  with mint preview, redeem with instant/queued state; renders only when the pot
  has a StrategyConfig — classic SOL flow untouched, mock mode unaffected.
- Flagship pin: lib/flagship.ts (env NEXT_PUBLIC_FLAGSHIP_POT → on-chain flag →
  mock name fallback) wired into / grid and /leaderboard (pins above any sort).
- tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
potbot-v2 Ready Ready Preview, Comment, Open in v0 Jul 7, 2026 6:16pm

Request Review

@supabase

supabase Bot commented Jul 7, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project iybzibvnzgxqwhgmkopf because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant