Revenue Pool
This page describes Velocity’s current, redesigned fee/revenue flow (the fee redesign). It replaces the older Drift model where all protocol revenue routed through the Insurance Fund and protocol-owned IF shares — see Trading Fees for the full per-fill split.
Each spot market’s revenue pool (SpotMarket.revenuePool, a Deposit-type pool balance) has exactly one purpose: staging the insurance fund’s cut of protocol fees before it settles to the Insurance Fund vault. It is not where the protocol’s own share of fees lands — that goes straight to a separate, directly-withdrawable protocol_fee_pool instead (see Protocol fee custody and withdrawal).
The revenue pool increases from various portions of the protocol:
-
borrow interest (
InsuranceFund.ifFeeFactor) -
perpetual and spot liquidations (the insurance-fund cut,
if_liquidation_fee) -
perpetual market trading fees (the insurance-fund cut of the per-fill split,
FeeStructure.ifFeeNumerator)
and ultimately funds:
-
the Insurance Fund vault (100% staker-owned — see below)
-
perpetual market AMMs (conditionally, via revenue withdraws)
Insurance Fund
Any account can call the permissionless settle_revenue_to_insurance_fund instruction to settle a portion of the revenue pool to the Insurance Fund vault:
If the Insurance Fund has users staked, each individual settlement is capped to min(1/10 of the revenue pool, MAX_APR cap) (halved at high utilization) —
-
thus an astronomically large inflow into the revenue pool (relative to user insurance staked amounts) results in revenue that trickles into the fund over a longer period rather than immediately
- this encourages more insurance fund stakers (who require a medium horizon of insurance offering) to join during the high annualised cap inflow
The Insurance Fund is 100% staker-owned. There are no protocol-owned IF shares, no settlement-time protocol/staker split, and no admin_withdraw_from_insurance_fund_vault — every dollar that settles into the fund accrues to stakers as share-price appreciation. Insurance Fund Stakers must adhere to the cooldown period for withdrawals (see Insurance Fund Staking).
Protocol Fee Custody and Withdrawal
The protocol’s own cut of trading fees, liquidation fees, and lending yield is not routed through the revenue pool or the Insurance Fund at all. Each market (perp and spot) has its own withdrawable protocol_fee_pool, funded by:
- Trading fees: the residual of the per-fill fee split (
FeeStructure.ammFeeNumerator/ifFeeNumerator— the protocol gets whatever’s left). - Liquidations:
protocol_liquidation_fee, split IF-first against the existing insurance-fee budget (see Liquidations). - Lending:
SpotMarket.protocolFeeFactoron deposit-interest gains.
It exits only via withdraw_protocol_fees_perp / withdraw_protocol_fees_spot, gated by the FeeWithdraw hot key and recipient-locked to State.protocolFeeRecipientPerp / protocolFeeRecipientSpot (each settable only by cold_admin). A withdrawal is always capped to the pool’s own balance and can never dip into user deposits.
Spot Markets
Spot Markets allow for swaps between tokens and interest payments between depositors and borrowers (there is no spot order book — see Order Types). These flows are parameterised to split fee collection between the revenue pool (insurance) and the protocol’s own withdrawable pool.
Within the program, its parameterised by the following in bold:
| Field | Description |
|---|---|
InsuranceFund.if_fee_factor | fraction of borrow interest reserved for the revenue pool (100% staker-owned) |
SpotMarket.protocol_fee_factor | fraction of borrow interest reserved for the protocol’s withdrawable protocol_fee_pool |
if_liquidation_fee | the insurance-fund cut of a spot liquidation, credited to the revenue pool directly |
protocol_liquidation_fee | the protocol cut of a spot liquidation, credited to protocol_fee_pool directly |
Lenders receive the remainder after both if_fee_factor and protocol_fee_factor are taken — set both via update_spot_market_if_factor.
The following instructions interact w/ the insurance fund:
resolve_spot_bankruptcy(gated byState.solvencyStatus— see Liquidations)
Perpetual Markets
Perpetual Markets are bootstrapped by the Velocity AMM, which — depending on market-making performance — can draw funds from the revenue pool to cover asymmetric funding shortfalls and PnL settlement, subject to the caps below.
Within the program, its parameterized by the following in bold:
| Field | Description |
|---|---|
max_revenue_withdraw_per_period | the market’s max revenue pool draw per period (doesn’t include bankruptcy resolution) |
revenue_withdraw_since_last_settle | revenue pool draws on behalf of user pnl since the last settle (doesn’t include bankruptcy resolution) |
last_revenue_withdraw_ts | the last timestamp of a revenue withdraw (tracked in order to reset the period) |
A perpetual market may draw up to max_revenue_withdraw_per_period from the revenue pool every period.
Additionally, for direct draws from the insurance fund, it’s parameterized by the following in bold:
| Field | Description |
|---|---|
quote_settled_insurance | settled funds from the insurance fund since inception |
quote_max_insurance | max funds it can settle from insurance fund since inception |
unrealized_pnl_max_imbalance | max amount of pnl the net users can be owed within a market before: 1. draws from insurance are allowed 2. initial asset weights for this pnl get discounted |
Unlike spot markets, perp markets are capped by the max draw from insurance via quote_max_insurance.
quote_settled_insurance tracks the insurance fund draw amount since inception. Once this threshold is reached or the insurance fund is depleted, the market resorts to its own AMM Fee Pool as a clawback of last resort. For any remaining losses not covered, the market performs socialized losses in bankruptcy events — see How Perp Bankruptcy Resolution Works.
The following instructions interact w/ the insurance fund:
-
resolve_perp_pnl_deficit -
resolve_perp_bankruptcy
notes:
resolve_perp_pnl_deficit can only be resolved by insurance fund deposits (within the market’s constraints), not by social loss with other users. Both instructions are gated by State.solvencyStatus — see Liquidations.