Fee Module
Manages the discrete price points and liquidity distribution across the price curve.
Source: sources/libraries/fee_helper.move | sources/libraries/pair_parameter_helper.move
Modules: ferra_damm::fee_helper | ferra_damm::pair_parameter_helper
The Fee Module is the core fee calculation engine of the Ferra DAMM protocol. It combines two independent fee mechanisms — Fee Scheduler (time-based base fee) and Dynamic Fee (volatility-based variable fee) — to determine the total fee for each swap.
Fee Architecture Overview
┌──────────────────────────────────────────────────────────────────┐
│ Total Fee │
│ │
│ total_fee = base_fee + variable_fee │
│ capped at MAX_FEE (50% = 500,000,000) │
│ │
│ ┌────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ Base Fee │ │ Variable Fee │ │
│ │ (Fee Scheduler) │ │ (Dynamic Fee) │ │
│ │ │ │ │ │
│ │ If scheduler enabled: │ │ If dynamic fee enabled: │ │
│ │ Linear or Exponential│ │ Based on volatility │ │
│ │ decay from cliff_fee │ │ accumulator × tick_spacing │ │
│ │ │ │ │ │
│ │ If scheduler disabled: │ │ If dynamic fee disabled: │ │
│ │ Static fee_rate │ │ 0 │ │
│ └─────────────────────────┘ └────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘PairParameters
The PairParameters struct is stored in each Pool and holds all fee state.
Static Fee Fields
fee_rate
u64
Base fee rate when scheduler is disabled. Precision: 10^9 (e.g., 2,500,000 = 0.25%)
current_sqrt_price
u128
Current pool sqrt price (Q64.64 format)
current_tick_index
I32
Current pool tick index
tick_spacing
u32
Pool tick spacing
activation_timestamp
u64
When pool/fee scheduler activates (ms)
Fee Scheduler Fields
fee_scheduler_mode
u8
0 = Linear, 1 = Exponential
enabled_fee_scheduler
bool
Whether fee scheduler is active
cliff_fee_numerator
u64
Initial maximum fee. Must be > 0, max 500,000,000 (50%)
number_of_period
u16
Total number of reduction periods
period_frequency
u64
Duration of each period (ms)
fee_scheduler_reduction_factor
u64
Linear: absolute reduction per period. Exponential: decay factor in basis points
Dynamic Fee Config Fields
enabled_dynamic_fee
bool
Whether dynamic fee is active
filter_period
u16
Seconds before updating volatility reference. Must be <= decay_period
decay_period
u16
Seconds for full volatility reset. Max: 4095. Must be > 0
reduction_factor
u16
Decay rate in basis points (1-10000). Used to reduce volatility_reference
variable_fee_control
u32
Scaling factor for variable fee. Max: 2,000,000
max_volatility_accumulator
u32
Cap on volatility accumulator. Max: 1,048,575 (0xFFFFF)
Dynamic Fee State Fields (Updated on Every Swap)
volatility_accumulator
u32
Current accumulated volatility level
volatility_reference
u32
Reference volatility from previous period
id_reference
I32
Reference tick index for delta calculation
time_of_last_update
u64
Timestamp of last volatility update
Fee Scheduler (Base Fee)
The Fee Scheduler provides time-based fee reduction from an initial cliff fee down to the base fee rate.
How It Works
Pool is created with
activation_timestampandcliff_fee_numeratorBefore activation: fee =
cliff_fee_numerator(maximum fee)After activation: fee decreases over
number_of_periodperiodsAfter all periods complete: fee =
fee_rate(base fee)
get_total_fee_rate
Returns the total fee rate combining base fee and variable fee.
Returns: Total fee rate, capped at MAX_FEE (500,000,000 = 50%)
get_base_fee
Returns the current base fee based on the fee scheduler state.
Logic:
If scheduler disabled or
activation_timestamp == 0: returns staticfee_rateIf before activation or at max period: returns
fee_rateor cliff fee accordinglyOtherwise: calculates fee based on mode (linear or exponential)
Linear Mode (fee_scheduler_mode = 0)
Fee decreases by a fixed amount each period.
Formula:
Example:
cliff_fee_numerator = 100,000,000(10%)fee_scheduler_reduction_factor = 9,000,000(0.9% per period)number_of_period = 10Result: Fee decreases from 10% → 9.1% → 8.2% → ... → 1% over 10 periods
Validation: Total reduction (reduction_factor × number_of_period) must not exceed cliff_fee_numerator
Exponential Mode (fee_scheduler_mode = 1)
Fee decays exponentially using a compound decay factor.
Formula:
Uses Q64.64 fixed-point arithmetic for precision.
Example:
cliff_fee_numerator = 100,000,000(10%)reduction_factor = 2000(20% decay per period)number_of_period = 10Result: 10% → 8% → 6.4% → 5.12% → ... asymptotically approaching 0
Validation: reduction_factor must be > 0 and < 10000 (basis_point_max)
get_current_number_period
Calculates which period we are currently in.
Logic:
Before activation: returns
number_of_period(maximum penalty = cliff fee)After activation:
period = (elapsed_time + period_frequency - 1) / period_frequencyCapped at
number_of_period
Fee Scheduler Query Functions
is_fee_scheduler_enabled(params)
bool
Whether fee scheduler is active
get_cliff_fee_numerator(params)
u64
Initial cliff fee
get_scheduler_number_of_period(params)
u16
Total periods
get_scheduler_period_frequency(params)
u64
Period duration (ms)
get_scheduler_reduction_factor(params)
u64
Reduction per period
get_activation_timestamp(params)
u64
Activation time (ms)
get_fee_scheduler_mode(params)
u8
0 = Linear, 1 = Exponential
Dynamic Fee (Variable Fee)
The Dynamic Fee mechanism automatically adjusts fees based on real-time market volatility. During high volatility (large price movements), fees increase to protect LPs. During calm markets, fees decay back to zero.
How It Works
Each swap updates the volatility accumulator based on price movement
Variable fee is calculated from the volatility accumulator
After
filter_period, the reference volatility decays byreduction_factorAfter
decay_period, volatility reference resets to zero
get_variable_fee
Calculates the current variable fee from volatility state.
Formula:
Example:
volatility_accumulator = 100tick_spacing = 60variable_fee_control = 1000prod = 100 × 60 = 6000variable_fee = (6000 × 6000 × 1000 + 99) / 100 = 360,000,000(36%)
Volatility Update Flow
On each swap, the following functions are called in sequence:
update_volatility_parameters
Entry point called on every swap to update volatility state.
Flow:
update_references(params, timestamp)— handles time-based decayupdate_volatility_accumulator(params, active_id)— adds new volatility
update_references
Handles time-based volatility decay.
Logic:
update_volatility_accumulator
Adds new volatility based on price movement since reference.
Formula:
The × 10 factor is the volatility per bin constant.
get_delta_id
Calculates the absolute tick distance from the reference, normalized by tick spacing.
Formula: |active_id - id_reference| / tick_spacing
Dynamic Fee Query Functions
is_dynamic_fee_enabled(params)
bool
Whether dynamic fee is active
get_dynamic_filter_period(params)
u16
Filter period (seconds)
get_dynamic_decay_period(params)
u16
Full decay period (seconds)
get_dynamic_reduction_factor(params)
u16
Decay rate in basis points
get_dynamic_variable_fee_control(params)
u32
Scaling factor
get_dynamic_max_volatility_accumulator(params)
u32
Max volatility cap
get_volatility_accumulator(params)
u32
Current volatility level
get_volatility_reference(params)
u32
Reference volatility
get_id_reference(params)
I32
Reference tick index
get_time_of_last_update(params)
u64
Last update timestamp
get_active_id(params)
I32
Current tick index
Fee Helper (Validation & Calculation)
The fee_helper module provides fee parameter validation and fee amount calculation utilities.
validate_dynamic_fee_parameters
Validates dynamic fee configuration.
Validation Rules:
filter_period <= decay_period0 < decay_period <= 40950 < reduction_factor <= 10000variable_fee_control <= 2,000,0000 < max_volatility_accumulator <= 1,048,575
validate_base_fee
Validates fee scheduler configuration to ensure the minimum fee after all periods is above the threshold.
Validation Rules:
fee_rate <= MAX_FEE_RATE(10%)cliff_fee_numerator > 0and<= MAX_FEE(50%)number_of_period > 0period_frequency > 0Linear mode:
reduction_factor × number_of_period <= cliff_fee_numeratorExponential mode:
0 < reduction_factor < 10000Minimum fee after all periods must be >=
MIN_FEE_NUMERATOR(100,000 = 0.01%)
Fee Amount Calculation Functions
get_fee_amount_inclusive
Extracts fee from an amount that already includes fees.
Formula: fee = amount_with_fees × total_fee_rate / PRECISION (rounds up)
Example: 1% fee on 10,000 → fee = 100
get_fee_amount_exclusive
Calculates fee to add on top of an amount.
Formula: fee = amount × total_fee_rate / (PRECISION - total_fee_rate) (rounds up)
Example: 1% fee on 9,900 → fee = 100 (total becomes ~10,000)
get_composition_fee
Calculates composition fee using a quadratic formula for balanced liquidity incentives.
Formula: fee = amount × total_fee_rate × (total_fee_rate + PRECISION) / PRECISION²
get_protocol_fee_amount
Calculates the protocol's share of a fee amount.
Formula: protocol_fee = fee_amount × protocol_share / BASIS_POINT_MAX (rounds down)
Example: 25% protocol share on 100 fee → protocol_fee = 25
General Query Functions
get_tick_spacing(params)
u32
Pool tick spacing
get_fee_rate(params)
u64
Static base fee rate
get_current_sqrt_price(params)
u128
Current sqrt price
get_current_tick_index(params)
I32
Current tick index
Constants Reference
PRECISION
1,000,000,000 (10^9)
Fee precision denominator
SQUARED_PRECISION
10^18
Precision squared for composition fee
MAX_FEE_RATE
100,000,000 (10%)
Maximum base fee rate
MAX_FEE
500,000,000 (50%)
Maximum total fee (base + dynamic)
MIN_FEE_NUMERATOR
100,000 (0.01%)
Minimum fee after scheduler
BASIS_POINT_MAX
10,000
Basis point denominator
MAX_VARIABLE_FEE_CONTROL
2,000,000
Max scaling factor
MAX_DECAY_PERIOD
4,095 (0xFFF)
Max decay period in seconds
MAX_VOLATILITY_ACCUMULATOR
1,048,575 (0xFFFFF)
Max volatility level
FEE_SCHEDULER_MODE_LINEAR
0
Linear fee scheduler mode
FEE_SCHEDULER_MODE_EXPONENTIAL
1
Exponential fee scheduler mode
COLLECT_FEE_MODE_ON_BOTH
0
Collect fee on input token
COLLECT_FEE_MODE_ON_QUOTE
1
Collect fee on quote token
Error Codes
fee_helper
502
E_FEE_TOO_HIGH
Fee rate exceeds maximum
505
E_INVALID_DECAY_PERIOD
Decay period is 0 or exceeds max
506
E_INVALID_REDUCTION_FACTOR
Reduction factor is 0 or exceeds basis point max
507
E_INVALID_VARIABLE_FEE_CONTROL
Variable fee control exceeds max
508
E_INVALID_MAX_VOLATILITY_ACCUMULATOR
Max volatility is 0 or exceeds max
509
E_INVALID_PARAMETER
Filter period > decay period
510
E_INVALID_FEE_SCHEDULER
Invalid scheduler config (zero values)
511
E_LINEAR_REDUCTION_TOO_HIGH
Linear total reduction exceeds cliff fee
512
E_MIN_FEE_TOO_LOW
Minimum fee after scheduler below threshold
pair_parameter_helper
900
E_INVALID_PARAMETER
Invalid volatility parameter (exceeds 20 bits)
Usage Examples
Reading Current Fee State
Fee Scheduler Timeline
Dynamic Fee Response to Volatility
Last updated