Concentrated Liquidity

To address the lazy liquidity problem, Gnoswap leverages a novel architecture called Concentrated Liquidity Pools (CLPs). CLPs allow liquidity providers to set a minimum and maximum price range, in which their liquidity will be active. This ensures that liquidity is concentrated around a specific price range, improving capital efficiency and reducing slippage for traders.

As liquidity in CLPs only requires each amount of x and y within the designated range (Pa, Pb), its behavior can be plotted into a graph as the following:

The real reserve curve is a parallel translation of the virtual reserve curve by the number of x tokens in price b (xb) towards the y-axis and the number of y tokens in price a (ya) towards the x-axis, giving the following equation:

k=(x+xb)(y+ya)k = (x+x_b)(y+y_a)

Although the real reserve curve represents the actual amount of tokens deposited by a liquidity provider, the liquidity pool must track two values to compute the virtual reserve curve that the pool behaves as: liquidity L and the square root of price √P.

We define L as √k, a geometric mean of the quantity of two tokens in a pool, and also a constant that reflects the liquidity of the pool. We can solve for L using k = xy:

L=k=xyL = \sqrt{k} = \sqrt{xy}

Similarly, we can solve for √P by simply square-rooting the price equation:

P=y/x\sqrt{P} = \sqrt{y/x}

Using the above formulas, we can compute the virtual reserves by solving for x and y respectively:

Solving for x:

x=y/P\sqrt{x}=\sqrt{y/P}
x=xy/P=L/Px=\sqrt{xy}/\sqrt{P}=L/\sqrt{P}

Solving for y:

y=Px\sqrt{y}=\sqrt{Px}
y=xyP=LPy=\sqrt{xy}*\sqrt{P}=L*\sqrt{P}

If we substitute these values for xb and ya for the initial formula, we arrive at the concentrated liquidity formula (the real reserve curve):

k=L2=(x+L/Pb)(y+LPa)k = L^2 = (x+L/\sqrt{P_b})(y+L\sqrt{P_a})

Output Calculation

Based on the formulas derived in the previous section, we can calculate the output of a swap.

When trading y for x (calculating ∆x with ∆y), we first calculate √P using the first equation, then use the value to calculate ∆x:

∆√P=y/L∆√P = ∆y /L
x=(1/P)L∆x=∆(1/\sqrt{P})*L

Similarly, we can also calculate ∆y when we trade x for y:

(1/P)=x/L∆(1/\sqrt{P})=∆x/L
y=PL∆y=∆\sqrt{P}*L

Price Tick

Since the price range of each LP Token in a pool is unique, we need a mechanism to uniformly divide the price units of a pool to merge the liquidity of tokens provided at the same price within a single liquidity pool. The boundaries that partition the range are called ticks. The default tick spacing for pools is 1 basis point, meaning that liquidity is divided into intervals of 0.01%.

The pricing mechanism and the fee distribution mechanism remain the same as regular CPMM pools within a single tick. After a tick's liquidity is drained, the remaining input rolls over to the following tick to be swapped at a different rate.

Price at tick i can be expressed as the following formula:

p(i)=1.0001ip(i)=1.0001^i

Since prices are stored as a square root in Gnoswap's contracts, we use the following formula to calculate the square root of the price at tick i:

p(i)=1.0001i/2\sqrt{p}(i)=1.0001^{i/2}

As the logarithmic calculation to derive i from a select price doesn't always end up as an integer, once a user inputs a value as a price, the contract automatically finds the nearest tick out of lower ones. For example, the exact value of the price at a tick index of 50,000, can be calculated as:

1.000150,000=148.3760629231.0001^{50,000} = 148.376062923

As the next highest tick (50,001) would result in a value of 148.383481541, a lower price range of 148.37 would translate into a lower tick of 50,000.

Last updated