The two-hop call path
The three conditions
1
Match the discriminator
Expose an instruction whose 8-byte discriminator equals
CALCULATE_FEES_DISCRIMINATOR = [140,235,78,9,249,8,129,101]. In Anchor, just name it calculate_fees — the generated discriminator matches by construction.2
Read the input, treat account[0] as the vault
Take a
FeeCalculationInput argument; account[0] is the read-only vault, any further accounts are your own config PDAs.3
Return output via return-data
Write a
FeeCalculationOutput with set_return_data.The wire types
A minimal calculator
The four buckets and the HWM
Every fee splits into four buckets — LP, manager, protocol, performance — each with its own verified recipient. The performance bucket is high-water-mark-gated: charge only on equity above the prior mark and returnnew_high_water_mark = Some(balance), which the dispatcher persists. The same gain is never taxed twice.
Prebuilt calculators to reference
Attaching it
PointVaultFees.fee_calc_program at your program id via set_fee_calc_program.