Common Vault Operations

Day-to-day vault management — roles, contracts, guards, and recommended multisig thresholds

Overview — Day-to-day vault management flow
DAY-TO-DAY VAULT MANAGEMENT FLOW FUNDVAULT Holds idle assets • enforces caps releaseAssets() called internally by AssetVault STRATEGY Deploys capital • earns yield bounded by strategyCap ASSETVAULT User-facing • redeem claims fulfillRedeem pulls from FundVault allocate deallocate fulfillRedeem CURATOR 2/3 CURATOR 2/3 OPERATOR 2/3 FUNDNAVFEED Off-chain NAV categories VAULTMANAGER Computes NAV • validates PPS • persists state syncNavValue OPERATOR 2/3 updateNav OPERATOR 2/3 PPS UPDATED persists PPS, totalDenomination FUNDVAULT strategyCap enforced on allocate setStrategyCap CURATOR 2/3 STRATEGY bounded by strategyCap TIMELOCKED TYPICAL SEQUENCE 1 · SET CAP Curator • timelocked 2 · ALLOCATE Curator • bounded by cap 3 · SYNC NAV Operator • strategy value 4 · UPDATE NAV Operator • validates PPS 5 · FULFILL Operator • from FundVault PRE-STEP · DEALLOCATE Curator • if idle too low syncNavValue before updateNav • updateNav after allocate/deallocate to keep PPS in sync • deallocate before fulfillRedeem if idle insufficient
Operation Details
allocate(strategy, amount)
Move idle assets from FundVault to a whitelisted strategy
CURATOR — 2/3 MULTISIG
Property Detail
Contract FundVault.allocate(strategy, amount)
Role CURATOR_ROLE — 2/3 multisig (Frank, Bean, Khiem)
Timelock NONE — operational frequency, bounded by cap
Guards strategy.totalAssets() + amount ≤ strategyCap • strategy must be whitelisted • idleAssets ≥ amountisNotPausednonReentrant
Effect Transfers asset to strategy via safeTransfer • increments totalAllocated[strategy]
Risk High — moves real assets out of FundVault, but capped
deallocate(strategy, amount)
Pull assets from a strategy back to FundVault
CURATOR — 2/3 MULTISIG
Property Detail
Contract FundVault.deallocate(strategy, amount)
Role CURATOR_ROLE — 2/3 multisig (Frank, Bean, Khiem)
Timelock NONE — needed frequently for rebalancing & pre-fulfill
Guards Strategy must be whitelisted • amount > 0isNotPausednonReentrant
Effect Calls strategy.withdraw(amount) which transfers assets back to FundVault • increments totalDeallocated[strategy]
Risk High — triggers strategy withdrawal; may cause slippage if strategy holds illiquid positions
setStrategyCap(strategy, cap)
Set the maximum amount that can be allocated to a strategy
CURATOR — 2/3 MULTISIG
Property Detail
Contract FundVault.setStrategyCap(strategy, cap)
Role CURATOR_ROLE — 2/3 multisig (Frank, Bean, Khiem)
Timelock TIMELOCKED — cap changes affect risk exposure, requires delay
Guards Strategy must be whitelisted • calls _timelocked()
Effect Sets strategyCap[strategy] = cap • enforced as hard ceiling in allocate()
Risk High — raising cap exposes more capital; setting to 0 effectively blocks all future allocations
fulfillRedeem(totalAmount, controllers)
Fulfill pending redeem requests — pull assets from FundVault and mark requests claimable
OPERATOR — 2/3 MULTISIG
Property Detail
Contract AssetVault.fulfillRedeem(totalAmount, controllers[])
Role OPERATOR_ROLE — 2/3 multisig (Frank, Bean, Max)
Timelock NONE — frequent ops; PPS guard protects against stale fulfills
Guards isNotPausednonReentrant • FundVault must have idleAssets ≥ totalAmount for releaseAssets()
Effect 1. Calls FundVault.releaseAssets(totalAmount) — pulls assets into AssetVault
2. Calls AsyncRequestManager.fulfillRedeem(controllers) — marks each request as fulfilled
3. Users can now call redeem() or withdraw() to claim
Risk Medium — moves assets to user-claimable state; bounded by existing request amounts
syncNavValue(asset, description, nav)
Update off-chain NAV for a specific category on FundNavFeed — e.g. the current value held by a strategy
OPERATOR — 2/3 MULTISIG
Property Detail
Contract FundNavFeed.syncNavValue(asset, description, nav)
Role OPERATOR_ROLE — 2/3 multisig (Frank, Bean, Max)
Timelock NONE — frequent updates; bounded by PPS deviation guard in updateNav()
Guards Category must exist for the asset (_getCategoryIndex) • category must be registered via addNavCategory()
Effect Sets _categories[asset][index].nav = nav • emits NavUpdated(asset, nav, description)
Risk High — directly affects totalNAV and PPS calculation; bad values caught by PPS deviation guard on next updateNav()
When to call Before updateNav() — sync the current value of assets held by each strategy so NAV reflects real positions
updateNav()
Recompute protocol-wide NAV, validate PPS deviation, persist new price-per-share
OPERATOR — 2/3 MULTISIG
Property Detail
Contract VaultManager.updateNav()
Role OPERATOR_ROLE — 2/3 multisig (Frank, Bean, Max)
Timelock NONE — frequent ops; PPS deviation guard is the safety net
Guards isValidPps check — reverts with InvalidPricePerShare if new PPS deviates beyond deviationPps threshold
Effect 1. Calls navAggregateModel.computeNav() across all registered assets
2. Persists per-asset NAVs, navDenomination, effNavDenomination, globalRedeemShares
3. Updates pricePerShare and lastNavUpdated timestamp
4. Emits PricePerShareUpdated(oldPps, newPps)
Risk Medium — bounded by deviation guard; stale inputs from syncNavValue are the real risk vector
When to call After every allocate / deallocate / syncNavValue — keeps PPS accurate for deposits, redeems, and fee calculations
Operational checklist:
Before first allocate — Curator must setStrategyCap() (timelocked) and strategy must be whitelisted via addStrategy()
Before updateNav — Operator must call syncNavValue() on FundNavFeed for each strategy whose position value has changed
After allocate / deallocate — Operator must call syncNavValue() then updateNav() to keep PPS in sync
Before fulfillRedeem — ensure FundVault has sufficient idle assets. If not, Curator must deallocate() from a strategy first
Cap = 0 blocks future allocations but does not force an automatic deallocate — existing positions remain until explicitly withdrawn
Suggested multisig key owners:
CURATOR_ROLE (2/3) — Frank, Bean, Khiem (or other wallets owned by Frank or Bean as alternates)
OPERATOR_ROLE (2/3) — Frank, Bean, Max