vault-strategy: curated whitelist, dynamic assets, oracle-bounded slippage#81
Merged
Merged
Conversation
Persona-driven 5-10 minute script explaining the vault-strategy example through Maria (manager), Alice and Bob, with per-step state-transition and token-movement ledgers and verified arithmetic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
Map the vault to a mutual fund / actively managed ETF (units, NAV pricing, expense ratio, in-kind redemption), name current Solana peers (Drift Vaults, Symmetry, Kamino), and contrast what actually differs onchain. Introduce the cast as each actor first appears instead of upfront. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
Lead with the concept (an onchain mutual fund / actively managed ETF) instead of granular outcome numbers, drop numbered Step headings for descriptive ones, gloss USDC on first use, and note the vault passes through losses as well as gains. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
Standardize on 'shares' (the program's term) throughout, define net asset value and its 'net', restate custody as program-controlled with no manager access, drop the dead Drift peer for Symmetry/Kamino/Meteora, and cut the obvious oracle and bug asides. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
A vault is one single-asset token account (a Solana token account holds one mint); the whole construct is the strategy or the fund. Reserve 'vault' for the three per-asset accounts throughout, name which vault each token movement touches, and explain the term where it first appears, matching the production pattern (one token vault per asset plus a shares mint). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
Define vault as a single-asset account vs the multi-asset strategy (ERC-4626 sense), define the two target weights and the fixed two-asset limit, detail exactly what the manager can and cannot do, clarify a share mint's address is a PDA (a derived public key), contrast fee-by-minting-shares with offchain expense ratios, and write the split as 40/60. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
…ppage Add a Registry plus per-mint WhitelistEntry accounts curated by a protocol authority (separate from managers), binding each approved mint to its official Pyth feed. Strategies grow their portfolio with add_asset, which registers a whitelisted mint at the next index as an AssetConfig PDA and creates its vault; deposit and withdraw validate the complete 0..asset_count set via remaining accounts so NAV and in-kind payouts always cover every asset. Replace caller-supplied swap minimums with an oracle-anchored bound: invest and rebalance compute each leg's minimum output from the Pyth price and a strategy-level max_slippage_bps (capped in code). Also fix the example's clean-checkout build: box the mock-swap-router swap account structs (4096-byte SBF stack overflow) and document the per-manifest build that avoids stripping the router entrypoint. Update README and CHANGELOG; rewrite the test suite (15 tests) for the new API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
…ippage Add Victor (registry authority) and the whitelist/add_asset steps, describe the oracle-computed slippage floor in invest/rebalance, correct the PDA wording (a PDA is an off-curve address with no private key, not a public key), and replace the stale two-asset and caller-slippage footnotes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5vHRAwvmnXhz8tzcq3xHX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Hardens the
vault-strategyexample along three lines that came out of reviewing the program with depositor-vs-manager trust in mind, and fixes its clean-checkout build. All changes are on thevault-strategyexample only.Curated asset registry (anti-fraud)
A
Registryplus per-mintWhitelistEntryaccounts, maintained by a protocol authority that is deliberately not the strategy manager. Each entry binds an approved mint to its official Pyth feed. New instructions:initialize_registry,whitelist_asset. This closes the two fraud vectors a manager-curated list leaves open: listing a token the manager mints themselves, and pairing a real mint with a feed the manager controls.Dynamic assets
Strategies grow their portfolio with
add_asset, which registers a whitelisted mint at the next index as anAssetConfigPDA (["asset", strategy, index]) and creates its vault. Assets occupy the contiguous range0..asset_count(up toMAX_ASSETS= 8), which letsdepositandwithdrawre-derive and require the complete set via remaining accounts — so NAV and in-kind payouts can never silently omit an asset. Replaces the previous fixed two-asset layout.Oracle-bounded slippage
investandrebalanceno longer trust a caller-supplied minimum. They compute each swap leg's minimum output from the Pyth price and a strategy-levelmax_slippage_bps(set at creation, capped in code at 10%), and revert any fill that deviates beyond it.Build fixes (needed for a clean checkout)
mock-swap-routerswap account structs, which overflowed the 4096-byte SBF stack frame under current platform-tools.cpifeature into the router build and strips its entrypoint.Testing
cargo test— 15 LiteSVM tests pass, covering the full lifecycle (registry → whitelist → strategy → add-asset → deposit → invest → rebalance → fees → in-kind withdraw) and rejection paths: non-whitelisted asset, weight overflow, over-cap fee and slippage, oracle-bounded swap slippage, unregistered router, and incomplete asset accounts on deposit.Docs
README and CHANGELOG updated for the new design. A walkthrough video script (
VIDEO_SCRIPT.md) is included and is being updated to match.🤖 Generated with Claude Code
Generated by Claude Code