The five charging avenues
There is no other place the core can debit a vault:| Core instruction | Fee operation | Buckets it can populate |
|---|---|---|
process_deposits | Deposit | lp · manager · protocol (+ performance) |
process_withdrawals | Withdraw | lp · manager · protocol (+ performance) |
use_funds | UseFunds | lp · manager · protocol (+ performance) |
return_funds | ReturnFunds | lp · manager · protocol (+ performance) |
report_on_funds | Deposit (NAV update) | performance crystallization on the new NAV |
report_on_funds matters most: it’s where the oracle writes reported equity, so it’s where NAV-based performance fees crystallize.
The four buckets
Every fee splits into LP, manager, protocol, performance — each with its own verified recipient. The performance bucket is high-water-mark-gated: a calculator charges only on equity above the prior mark and returns the new mark, so the same gain is never taxed twice.Charge vs. claim
Charge
Called by the core on a fund op. Accrues into
unclaimed and total_collected. No tokens move.Claim
claim_fees(fee_type, amount) requires recipient == recipients.get_recipient(fee_type) and amount ≤ unclaimed, then moves the amount from unclaimed to total_claimed. The core executes the SPL transfer signing as vault_share_signer.The dispatcher ledger
total_collected / total_claimed ledger makes every fee ever charged independently verifiable.
Balance identity
A vault’s total is a signedi64:
Build a custom calculator
Implement calculate_fees with any fee model.