Base Fee
The base fee follows one of five modes. Fee numerators are over1,000,000,000, so a numerator of 1,000,000 is 0.1%. Every fee a schedule can reach must be between 0.01% and 99%.
Schedulers exist for launches. A new pool can open with a high fee that taxes the first buyers and snipers, then falls to a normal fee as time passes or as the price climbs.
- A time scheduler counts periods (in slots or seconds, per the pool’s activation type) from the activation point. After the last period the fee stays at its settled value.
- A market cap scheduler counts how many steps the square-root price has risen above its initial value, so the fee only falls if buyers push the price up. The step count is recomputed from the current price on every swap, so the fee rises again if the price falls back. It also has an expiration, in slots or seconds per the activation type: after that much time from activation, the fee settles regardless of price.
Base Fee Parameters and Limits
All numerators are over1,000,000,000, so 1 bp is 100,000. Every mode needs its highest fee at or below 990,000,000 (99%) and its lowest fee at or above 100,000 (0.01%), or creating the config or pool fails with InvalidParameters.
For a linear mode
reduction_factor is a fee numerator taken off each period, and the cliff fee must be large enough that cliff_fee_numerator - reduction_factor × number_of_period stays at or above 100,000. For an exponential mode it is in basis points, and each period multiplies the fee by 1 - reduction_factor / 10,000. A factor of 10,000 or more fails with MathOverflow.
Worked Schedules
A time scheduler that starts at 20% and ends at 1% over 10 periods of 60 seconds, activated at time 1000. The SDK’sbaseFeeParameters with startingBaseFeeBps 2000, endingBaseFeeBps 100, numberOfPeriod 10 and totalDuration 600 gives a cliff of 200,000,000, a period frequency of 60, and a linear reduction of 19,000,000 or an exponential reduction of 2,588 bps:
The exponential fee by period is
200,000,000, 148,240,000, 109,875,487, 81,439,711, 60,363,114, 44,741,140, 33,162,133, 24,579,773, 18,218,527, 13,503,572 and 10,008,848. The last is above 1% because the SDK picks the largest factor whose settled fee does not fall below the ending fee.
A market cap scheduler with the same fees, priceMultiple 4 and schedulerExpirationDuration 86,400 seconds. The SDK gives sqrt_price_step_bps of ⌊(√4 - 1) × 10,000 / 10⌋ = 1,000, so one period passes for every 10% the square-root price rises above its initial value. The linear reduction is 19,000,000 per period and the exponential reduction is 2,588 bps:
The expiration check is strict. At exactly activation time plus 86,400 the fee still follows the price, and one unit later it settles.
Dynamic Fee
The dynamic fee adds a surcharge that rises when the price moves and decays when it stops. It measures how far the price has moved from a reference price, in 1 bp ticks, and charges more the further it has gone.- Swaps close together in time (within the filter period) keep the same reference, so a burst of trades in one direction keeps raising the fee.
- After a quieter gap (between the filter and decay period), the reference moves to the current price and part of the accumulated volatility carries over, set by the reduction factor.
- After the decay period with no significant swap, the volatility resets to zero.
getDynamicFeeParams builds these settings from a base fee: the surcharge is capped at 20% of the base fee, reached at a 15% price move, with a 10 second filter period, 120 second decay period and 50% reduction factor.
Dynamic Fee Parameters
The surcharge at the cap,
⌈variable_fee_control × max_volatility_accumulator² / 10^11⌉, must be at most 990,000,000. Any failed rule fails with InvalidParameters. The dynamic fee is optional and is set only when the pool or its config is created.
The fee is ⌈variable_fee_control × volatility_accumulator² / 10^11⌉, with the accumulator equal to the tick distance from the reference price times 10,000, plus the carried volatility, capped at the maximum. A swap pays the fee for the volatility at the price when it starts, so the swap that moves the price is not charged for its own move. On a new pool the stored reference time is zero, so the first swap resets the reference to the current price.
With a 0.25% base fee, getDynamicFeeParams(25, 10) gives max_volatility_accumulator 14,470,000, variable_fee_control 238, filter 10, decay 120 and reduction 5,000. The surcharge by price move from the reference:
Walk-through with those parameters, a 0.25% base fee, the reference set at time 1000 at the pool’s price, and the square-root price after each swap at 1.004, 1.012, 1.030, 1.035 and 1.036 times the starting value. Square-root prices are stored as integers and round down, so each of the first three moves measures one tick less than the exact ratio (79, 239 and 599 ticks):
Every swap here moves the price by at least 10 ticks, so each counts as significant and restarts the timer. At time 1030 the 24 seconds fall between the filter and decay periods, so the reference moves to the current price and
5,990,000 × 5,000 / 10,000 = 2,995,000 carries over, and the fee is ⌈238 × 2,995,000² / 10^11⌉ = 21,349 on top of the base. At time 1200 the 170 seconds pass the decay period, so nothing carries over. The SDK’s quoteExactIn reproduces the fee numerators of the swaps at times 1003, 1006, 1030 and 1200.
Fee Token
The collect fee mode decides which token the fee is taken in.OnlyY means LPs and the protocol only ever earn token Y. Pools that use it must have SOL, USDC or a token with a token badge as token Y.
A pool with the OnlyY mode that is created with a token Y that is not SOL, USDC or badged fails with InvalidTokenBadge.
With a 0.30% fee, a pool holding 1,000,000,000,000 liquidity at price 1 and a swap of 1,000,000,000 atoms:
The fee in each row is split 90% to LPs and 10% to the protocol, for example 2,697,303 and 299,700 in the first row. In the
OnlyY buy row, the fee comes off the input first, so only 997,000,000 Y trades. The fee is always rounded up, so the swapper pays the extra atom.
Where the Fee Goes
In each step of a swap, the fee is first split between LP liquidity and limit orders in proportion to how much of that step each one filled.
Notes on the split:
- Referral host. Any token account that holds the fee token can be passed as the referral, including the swapper’s own. For the limit-order part, the host’s 20% is worked out as if the protocol took the LP rate, not 50%.
- Partner. Only pools created from a dynamic config have a partner: the config’s pool creator authority. The partner fee bps comes from the config, and an operator can change it on a pool later.
- Rounding. Shares are rounded so the pool never pays out more than it collected.
- The total fee is rounded up, and the swapper pays the difference.
- The LP part of the fee is rounded up and the limit-order part is the remainder.
- The protocol’s cut of the LP part and of the limit-order part is rounded down, and LPs or makers keep the remainder.
- The host fee and the partner fee are rounded down, and the protocol keeps the remainder.
- Each position’s fee, each maker’s fee share and each reward is rounded down when it is credited.
Rows with a partner fee apply to dynamic-config pools, the only pools that have a partner. A launch pool never has one.
The protocol’s gross share in the first normal row is
1,496,181 + 54,253 from the two LP parts and 7,500 from the order. With a referral, the host’s 20% applies to 1,496,181 + 54,253 + 1,500, where 1,500 is 10% of the 15,000 limit-order fee, not the 7,500 the protocol actually took. That gives ⌊1,551,934 × 0.2⌋ = 310,386. The partner’s share then applies to what is left after the host: ⌊1,247,548 × 0.2⌋ = 249,509.
Who collects each part: LPs with claim_fee on their position, makers when the order is canceled, the host in the swap itself, the pool partner with claim_partner_fee and Meteora with its protocol fee claim. claim_partner_fee takes max_amount_x and max_amount_y, caps on the accrued fee before any transfer fee, and min_amount_x and min_amount_y, minimums after it that fail with ExceededSlippage. It sends nothing and returns when both amounts are zero. An operator can set the partner fee bps to any value from 0 to 5,000 on a pool that has a partner.
Related
Pool Creation and Activation
Which configs fix the fee schedule, and when schedulers start counting.
Formulas
Fee schedules, the dynamic fee and the fee split as equations.

