Fee & Treasury Patterns
Fee patterns skim basis points on actions, route to treasury PDAs or ATAs, and document rounding. Use checked math and cap configurable fee bps in admin config.
Recipe
let fee = amount.checked_mul(config.fee_bps)?.checked_div(10_000)?;
let net = amount.checked_sub(fee)?;When to reach for this:
- DEX protocol fee.
- NFT marketplace fee.
- Withdrawal fee covering rent.
Working Example
pub fn split_fee(amount: u64, bps: u16) -> Result<(u64, u64), ProgramError> {
if bps as u64 > 10_000 { return Err(ProgramError::InvalidArgument); }
let fee = amount.checked_mul(bps as u64)?.checked_div(10_000)?;
let net = amount.checked_sub(fee)?;
Ok((net, fee))
}What this demonstrates:
- Caps bps at 100%.
- Returns net and fee.
- All checked ops.
Deep Dive
Rounding
Floor fee favor protocol or user - document choice.
Treasury
Dedicated PDA ATA per mint.
Rust Notes
// u128 intermediate for large mul if needed.Gotchas
- Unchecked fee math - Wrap drain.. Fix: checked_* only.
- Unbounded bps in config - 100% steal.. Fix: Validate max on set_config.
- Fee on failed partial - Charge before success.. Fix: Take fee after success or on input.
- Wrong treasury ATA mint - Lost fees.. Fix: Verify mint.
- Hidden admin skim - Trust loss.. Fix: On-chain transparent bps.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Off-chain fee | Not enforceable | On-chain only |
| Jupiter referral | Partner fees | Your program fee separate |
| Donation optional | UX choice | Revenue |
FAQs
Basis points?
1 bp = 0.01%.
Fee on SOL?
Lamports same math.
Token-2022 transfer fee?
Additional layer.
Treasury withdraw?
Admin ix.
Immutable fee?
Fixed in program.
Dynamic fee?
Config account.
Round down?
Common favor user.
Multiple recipients?
Split fee vector - cap len.
Events?
Emit fee taken.
Audit?
Math + treasury access.
Sim?
Assert fee amounts.
Anchor?
Same math in handler.
Related
- Safe Arithmetic - Math
- Vault & Escrow - Custody
- Fee & Treasury in DeFi - Context
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.