Skip to main content

Fees

Introduction

Liquidity Book introduces dynamic fees to allow for surge pricing during high market volatility.

Traders pay a swap fee to liquidity providers when performing a swap. The total swap fee (fsf_s) will have two components: a base fee (fbf_b) and a variable fee (fvf_v), which is a function of instantaneous price volatility. The fee rate will be applied to the swap amount in each liquidity bin and distributed proportionally to the liquidity providers in that bin.

Fees will be held separate from liquidity and claimable by liquidity providers.

Base Fee

The base fee of a market is configured by the protocol owner and determined by the base factor (BB) and the bin step (ss):

fb=Bsf_b = B \cdot s

Variable Fee

The variable fee on the other hand depends on the volatility of the market. It will be affected by the frequency of the swaps, but doing large swaps accross many bins (on large price movements) will also increase it. Fees are calculated and distributed per bin, to allow a fair distribution of the fee to the liquidity providers of the bin crossed.

Fees are calculated iteratively as each bin is crossed (if the swap is large enough). In other words, if a large swap crosses nn bins, then the total swap fee is calculated per bin kk (such that 0kn0 \leq k \leq n), where kk is the difference in bin IDs from the initial bin where the swap originated and the current bin in which it is being calculated.

Example - take MAS/USDC. The active bin before swap is $1. A large buy order is made that pushes the price up to $1.3. The values of kk for each bin is listed below (note: bin prices are simplified for this example):

$1 bin - ID = 1844; kk = 0

$1.1 bin - ID = 1845; kk = 1

$1.2 bin - ID = 1846; kk = 2

$1.3 bin - ID = 1847; kk = 3

kk can also be negative if it pushes the price downwards.

The variable fee for a bin fv(k)f_v(k) will be calculated using the variable fee control parameter (AA), bin step (ss) and the volatility accumulator (va(k)v_a(k)):

fv(k)=A(va(k)s)2f_v(k) = A(v_a(k) \cdot s) ^ 2

Volatility Accumulator

The volatility accumulator (va(k)v_a(k)) is the witness of the current volatility of the pair. This value will be kept in memory between each calculation step. It will be calculated during a swap and will depend on two factors: the volatility reference (vrv_r) from the previous swaps, and the introduced volatility (ir(activeId+k)|i_r - (activeId + k)|):

va(k)=vr+ir(activeId+k)v_a(k) = v_r + |i_r - (activeId + k)|

(Note: activeIdactiveId is the ID of the active bin before the swap is made.)

The volatility reference (vrv_r) depends on the time elapsed since the last transaction (tt). We define a window which has an upper and lower bound. If tt is smaller than the lower bound defined by filter period (tft_f) (i.e. high frequency of transactions occurring), then vrv_r stays the same. If tt is greater than the upper bound defined by decay period (tdt_d) (i.e. low frequency of transactions occurring), then vrv_r is reset to 0. If tt is within the window, then it takes the previous vav_a decayed by a factor RR.

vr={vr,t<tfRva,tf<=t<td0,td<=tv_r = \begin{cases} v_r, & t < t_f \\ R \cdot v_a, & t_f <= t < t_d \\ 0 , & t_d <= t \end{cases}

This means that high frequency trades will stack up volatility, while low frequency trades will slowly reduce the volatility, or even reset it after a long moment has passed without any trade.

Now that the volatility reference is calculated, it is time to calculate the volatility introduced by the trade. Another variable, the index reference (iri_r), is introduced. In most cases, iri_r will simply be the ID of the active bin before the swap is made. But in times of high frequency transactions, iri_r will keep its old value instead. This is to prevent people from manipulating fees by making small lots of small transactions that increase and decrease price.

ir={ir,t<tfactiveId,tf<=ti_r = \begin{cases} i_r, & t < t_f \\ activeId, & t_f <= t \end{cases}

The volatility accumulated for the bin kk will then be used to calculate the fees generated by swapping through this bin and be allocated to the liquidity providers of the bin.

The final fee for the bin kk will be: f ⁣ee=(swap  amount)k(fb+fv)kf\!ee = (swap\;amount)_k \cdot (f_b + f_v)_k

Volatility Accumulator Example

All that was probably extremely confusing so we outline an example of how the volatility accumulator will look as swaps are made.

Let tft_f = 1 sec, tdt_d = 5 secs, RR = 0.5 secs and active bin ID is 100.

Swap 1

You make a trade that crosses +3 bins to 103. So 0k30\leq k \leq 3:

ir=100i_r = 100
vr=0v_r = 0
va(0)=0+100(100+0)=0v_a(0) = 0 + |100 - (100 + 0)| = 0
va(1)=0+100(100+1)=1v_a(1) = 0 + |100 - (100 + 1)| = 1
va(2)=0+100(100+2)=2v_a(2) = 0 + |100 - (100 + 2)| = 2
va(3)=0+100(100+3)=3v_a(3) = 0 + |100 - (100 + 3)| = 3

Swap 2

Alice makes a trade 4 secs later that crosses +5 bins to 108. So 0k50\leq k \leq 5:

ir=103i_r = 103
vr=0.53=1.5v_r = 0.5 \cdot 3 = 1.5
va(0)=1.5+103(103+0)=1.5v_a(0) = 1.5 + |103 - (103 + 0)| = 1.5
va(1)=1.5+103(103+1)=2.5v_a(1) = 1.5 + |103 - (103 + 1)| = 2.5
va(2)=1.5+103(103+2)=3.5v_a(2) = 1.5 + |103 - (103 + 2)| = 3.5
......
va(5)=1.5+103(103+5)=6.5v_a(5) = 1.5 + |103 - (103 + 5)| = 6.5

Swap 3

Bob makes a trade 0.3 secs later that crosses -2 bins to 106. So 2k0-2\leq k \leq 0:

Note: vrv_r and iri_r do not update as the transaction was less than the filter period.

ir=103i_r = 103
vr=1.5v_r = 1.5
va(0)=1.5+103(108+0)=6.5v_a(0) = 1.5 + |103 - (108 + 0)| = 6.5
va(1)=1.5+103(1081)=5.5v_a(-1) = 1.5 + |103 - (108 - 1)| = 5.5
va(2)=1.5+103(1082)=4.5v_a(-2) = 1.5 + |103 - (108 - 2)| = 4.5

Notice that the volatility accumulator is decreasing despite high frequency of transactions.

Protocol Fees

It is expressed as a variable, protocolShare, which is a percentage of the total swap fee. The maximum possible is 25%.