Skip to content
0xMC
Go back

From Uniswap v3 to crvUSD LLAMMA

Original paper: 《From Uniswap v3 to crvUSD LLAMMA.pdf》

By 0xmc,0xjezex,0xstan, paco0x

Preface: The most difficult part of Curve’s stablecoin design is LLAMMA, an AMM for continuous liquidation and deliquidation. LLAMMA builds on several ideas from Uniswap v3, but the price definitions in the Curve whitepaper differ from those used in the Uniswap v3 whitepaper. This article reconciles the two frameworks and uses that comparison to explain the intuition behind the LLAMMA algorithm.

Relation to Uniswap v3

The price definition used in this article is the reciprocal of the one used in Uniswap v3. Therefore, we rewrite the relevant formulas from the Uniswap v3 whitepaper so they are consistent with this article. In short, LLAMMA makes several Uniswap v3 parameters dynamic in order to offer better prices to both crvUSD borrowers and liquidators.

Comparing the Constant Product Formulas

Formula (2.2) from the Uniswap v3 whitepaper:

(x+LPb)(y+LPa)=L2\begin{aligned} (x+\dfrac{L}{\sqrt{P_b}})(y+L\sqrt{P_a})=L^2 \end{aligned}

Uniswap v3 Simulation of Virtual Liquidity

Formula (1) in the Curve stablecoin whitepaper:

I=(x+f)(y+g)\begin{aligned} I = (x + f) (y + g) \end{aligned}

AMM with an external price source

Here, PcdP_{cd} means Pcurrent_downP_{current\_down} and PcuP_{cu} means Pcurrent_upP_{current\_up}.
The corresponding relationships are:

Pb=1Pcd,Pa=1Pcu,L=IP_{b} = \dfrac{1}{P_{cd}}, P_{a} = \dfrac{1}{P_{cu}}, L=\sqrt{I}

The corresponding constant product formula is:

(x+Ipcd)(y+Ipcu)=I\begin{aligned} (x+\sqrt{I}\sqrt{p_{cd}})(y+\dfrac{\sqrt{I}}{\sqrt{p_{cu}}})=I \end{aligned}

where:

f=Ipcd,g=Ipcuf=\sqrt{I}\sqrt{p_{cd}}, g=\dfrac{\sqrt{I}}{\sqrt{p_{cu}}}

Correspondence in Liquidity Calculation

Formula (6.7) from the Uniswap v3 whitepaper:

L=ΔyΔp\begin{aligned} L=\dfrac{\Delta{y}}{\Delta{\sqrt{p}}} \end{aligned}

Because the two price definitions are reciprocals, this corresponds to:

I=ΔyΔ1p\begin{aligned} \sqrt{I} = \dfrac{\Delta{y}} {\Delta{\sqrt{\dfrac{1}{p}}}} \end{aligned}

One specific application of this formula is:

I=(y00)(1pcd1pcu)=pcdpcupcupcdy0\begin{aligned} \sqrt{I} = &\dfrac{(y_0-0)}{(\dfrac{1}{\sqrt{p_{cd}}}-\dfrac{1}{\sqrt{p_{cu}}})} \\ = &\dfrac{\sqrt{p_{cd}p_{cu}}}{\sqrt{p_{cu}}-\sqrt{p_{cd}}} y_0 \end{aligned}

Expanding the square gives:

I=pcdpcupcu+pcd2pcdpcuy02\begin{aligned} I= \dfrac{{p_{cd}p_{cu}}}{p_{cu}+p_{cd}-2\sqrt{p_{cd}p_{cu}}} y_0^2 \end{aligned}

From the formulas above, when y0y_0 remains constant, the closer pcdp_{cd} and pcup_{cu} are to each other, the larger the corresponding liquidity II becomes.

In other words:

limpcdpcuI=+\lim\limits_{p_{cd} \to p_{cu}} \sqrt{I}= +\infty

Liquidity cannot be infinite. In Uniswap v3, the minimum tick spacing limits the size of LL.

By analogy, LLAMMA also needs an indicator that measures the minimum price difference.

Correspondence in the Minimum Price Difference

pp=A1A\dfrac{p\downarrow}{p\uparrow} = \dfrac{A-1}{A}

From the definition of AA, the closer pp\downarrow and pp\uparrow are to each other, the larger AA becomes and the more concentrated the liquidity is:

A=pppA = \dfrac{p\uparrow}{p\uparrow - p\downarrow}

In Uniswap v3, only ticks whose indexes are divisible by tickSpacing can be initialized. Thus, tickSpacing determines the minimum price range in which LPs can allocate their liquidity. The smaller the tickSpacing, the tighter and more precise the price ranges. In Uniswap v3, different fee tiers correspond to different tickSpacing values.

However, crvUSD LLAMMA does not need many different tickSpacing values. Since LLAMMA is designed for ETH-crvUSD, each band can use a tickSpacingtickSpacing of 100 basis points. Formula (6.1) from Uniswap v3:

pi=1.0001ip_i=1.0001^i

In LLAMMA, A=100A=100. Formula (11) from the Curve stablecoin whitepaper is:

p(n)=(A1A)npbase\begin{aligned} p\uparrow (n) = (\dfrac{A-1}{A})^n p_{base} \end{aligned} p(n)=(A1A)n+1pbase\begin{aligned} p\downarrow (n) = (\dfrac{A-1}{A})^{n+1} p_{base} \end{aligned}

Setting n=in = -i and A=100A=100, we get:

p(i)=(1001001)ipbase    \begin{aligned} p\uparrow (-i) = (\dfrac{100}{100-1})^i p_{base}\ \ \ \ \end{aligned}

Design pcdp_{cd} and pcup_{cu}

We want LLAMMA to have the following behavior: when the ETH price rises, the pool buys ETH; when the ETH price falls, the pool sells ETH. Given this goal, we define pcdp_{cd} and pcup_{cu} as functions of pop_o that are steeper than linear functions, so their growth rates are faster than that of pop_o. At the same time, the figure shows that the two curves pcup_{cu} and pcdp_{cd} pass through (p,p)(p\downarrow,p\downarrow) and (p,p)(p\uparrow,p\uparrow), respectively. Many possible curves can satisfy these requirements. The general form is:

pcd=pon+1pn,pcu=pom+1pmp_{cd} = \dfrac{p_o^{n+1}}{p\uparrow^n}, p_{cu} = \dfrac{p_o^{m+1}}{p\downarrow^{m}}

where m<nm<n.

Let’s start with the simplest case:

pcd=po2p,pcu=po2pp_{cd} = \dfrac{p_o^2}{p\uparrow}, p_{cu} = \dfrac{p_o^2}{p\downarrow}

Substituting pcup_{cu} and pcdp_{cd} into the expanded formula for II gives:

I=pcdpcupcu+pcd2pcdpcuy02=po2ppo2py02po2p+po2p2po2ppo2p=po2y02p+p2pp=po2y02(pp)2\begin{aligned} I= &\dfrac{{p_{cd}p_{cu}}}{p_{cu}+p_{cd}-2\sqrt{p_{cd}p_{cu}}} y_0^2 \\ = &\dfrac{\dfrac{p_o^2}{p\uparrow}\dfrac{p_o^2}{p\downarrow} y_0^2}{\dfrac{p_o^2}{p\uparrow} + \dfrac{p_o^2}{p\downarrow} - 2\sqrt{\dfrac{p_o^2}{p\uparrow}\dfrac{p_o^2}{p\downarrow}}}\\ =&\dfrac{p_o^2 y_0^2}{p\downarrow+p\uparrow - 2\sqrt{p\downarrow p\uparrow}}\\ =&\dfrac{p_o^2 y_0^2}{(\sqrt{p\uparrow}-\sqrt{p\downarrow})^2} \end{aligned}

Then f2f^2 can be calculated as:

f2=Ipcd=po2y02(pp)2po2p\begin{aligned} f^2=&Ip_{cd}\\ =&\dfrac{p_o^2 y_0^2}{(\sqrt{p\uparrow}-\sqrt{p\downarrow})^2}·\dfrac{p_o^2}{p\uparrow} \end{aligned}

Under this assumption, f2f^2 is difficult to interpret and calculate. Now consider the case where pcdp_{cd} and pcup_{cu} are cubic functions of pop_o:

pcd=po3p2,pcu=po3p2p_{cd} = \dfrac{p_o^3}{p\uparrow^2}, p_{cu} = \dfrac{p_o^3}{p\downarrow^2}

Substituting pcup_{cu} and pcdp_{cd} into the expanded formula for II gives:

I=pcdpcupcu+pcd2pcdpcuy02=po3p2po3p2y02po3p2+po3p22po3p2po3p2=po3y02p2+p22pp=po3y02(pp)2\begin{aligned} I= &\dfrac{{p_{cd}p_{cu}}}{p_{cu}+p_{cd}-2\sqrt{p_{cd}p_{cu}}} y_0^2 \\ = &\dfrac{\dfrac{p_o^3}{p\uparrow^2}\dfrac{p_o^3}{p\downarrow^2} y_0^2}{\dfrac{p_o^3}{p\uparrow^2} + \dfrac{p_o^3}{p\downarrow^2} - 2\sqrt{\dfrac{p_o^3}{p\uparrow^2}\dfrac{p_o^3}{p\downarrow^2}}}\\ =&\dfrac{p_o^3 y_0^2}{p\downarrow^2+p\uparrow^2-2p\downarrow p\uparrow}\\ =&\dfrac{p_o^3 y_0^2}{(p\uparrow-p\downarrow)^2} \end{aligned}

Recalculating f2f^2:

f2=Ipcd=po3y02(pp)2po3p2=po6y02(pp)2p2\begin{aligned} f^2=&Ip_{cd}\\ =&\dfrac{p_o^3 y_0^2}{(p\uparrow-p\downarrow)^2}·\dfrac{p_o^3}{p\uparrow^2}\\ =&\dfrac{p_o^6 y_0^2}{(p\uparrow-p\downarrow)^2 p\uparrow^2} \end{aligned}

When pcdp_{cd} and pcup_{cu} are cubic functions of pop_o, the mathematical form becomes much simpler. The square-root term disappears, making the calculation more convenient. If we use a higher-order function, the AMM price and pop_o will diverge more significantly. As a result, the cost of buying ETH when the price rises becomes much higher, leading to greater liquidation losses. Therefore, defining pcdp_{cd} and pcup_{cu} as cubic functions of pop_o is a better choice.

Derivation of Other Parameters

Assuming that pcdp_{cd} and pcup_{cu} are cubic functions of pop_o, take the special case po=pp_o=p\uparrow. In this case, we get y=y0y=y_0 and x=0x=0, so:

I=po3y02(pp)2=poy02po2(pp)2=poy02(ppp)2=poy02A2\begin{aligned} I=&\dfrac{p_o^3 y_0^2}{(p\uparrow-p\downarrow)^2}\\ =&p_o y_0^2 · \dfrac{p_o^2}{(p\uparrow-p\downarrow)^2}\\ =&p_o y_0^2 · (\dfrac{p\uparrow}{p\uparrow-p\downarrow})^2\\ =&p_oy_0^2A^2 \end{aligned}

Given the formula for II, we can calculate ff and gg:

f=Ipcd=poy02A2po3p2=po2pAy0\begin{aligned} f=&\sqrt{I}\sqrt{p_{cd}} \\ =&\sqrt{p_oy_0^2A^2}\sqrt{\dfrac{p_o^3}{p\uparrow^2}}\\ =&\dfrac{p_o^2}{p\uparrow}Ay_0 \end{aligned} g=Ipcu=poy02A2po3p2=ppoAy0=ppo(A1)y0\begin{aligned} g =& \dfrac{\sqrt{I}}{\sqrt{p_{cu}}}\\ =& \dfrac{\sqrt{p_oy_0^2A^2}}{\sqrt{\dfrac{p_o^3}{p\downarrow^2}}}\\ =&\dfrac{p\downarrow}{p_o}Ay_0\\ =&\dfrac{p\uparrow}{p_o}(A-1)y_0 \end{aligned}

From this, we obtain the complete constant product formula:

(po2pAy0+x)(ppo(A1)y0+y)=poA2y02(\dfrac{p_o^2}{p\uparrow}Ay_0 + x)(\dfrac{p\uparrow}{p_o}(A-1)y_0 + y) = p_oA^2y_0^2

Transforming the equation above into a quadratic equation in y0y_0 gives:

poAy02y0(ppo(A1)x+po2pAy)xy=0p_oAy_0^2- y_0(\dfrac{p\uparrow}{p_o}(A-1)x + \dfrac{p_o^2}{p\uparrow}Ay) - xy = 0

Solving this quadratic equation for y0y_0 gives:

y0=(ppo(A1)x+po2pAy)+(ppo(A1)x+po2pAy)2+4poAxy2poAy_0 = \dfrac{(\dfrac{p\uparrow}{p_o}(A-1)x + \dfrac{p_o^2}{p\uparrow}Ay)+\sqrt{(\dfrac{p\uparrow}{p_o}(A-1)x + \dfrac{p_o^2}{p\uparrow}Ay)^2+4p_oA·xy}}{2p_oA}

If the price moves slowly enough for the oracle price pop_o to follow it, then given xx and yy, we can use the Uniswap v3 formulas to calculate how much ETH, denoted by yy\uparrow, will eventually remain in the band if the price rises, or how much USD, denoted by xx\downarrow, will eventually remain in the band if the price falls:

y=y+Δy=y+I(1p1p)=y+IpIppp=y+(f+x)fpp=y+xpp\begin{aligned} y\uparrow =& y + \Delta y \\ =& y + \sqrt{I}(\dfrac{1}{\sqrt{p\uparrow}} - \dfrac{1}{\sqrt{p}}) \\ =& y + \dfrac{\sqrt{I}\sqrt{p} - \sqrt{I}\sqrt{p\uparrow}}{\sqrt{p\uparrow p}} \\ =& y + \dfrac{(f +x) - f}{\sqrt{p\uparrow p}} \\ =& y + \dfrac{x}{\sqrt{p\uparrow p}} \end{aligned} x=x+I(pp)=x+I(1p1p)pp=x+((g+y)g)pp=x+ypp\begin{aligned} x\downarrow =& x + \sqrt{I}(\sqrt{p\downarrow}- \sqrt{p}) \\ =& x + \sqrt{I}(\dfrac{1}{\sqrt{p}} - \dfrac{1}{\sqrt{p\downarrow}})\sqrt{p\downarrow p}\\ =& x + ((g+y) - g)\sqrt{p\downarrow p}\\ =& x + y\sqrt{p\downarrow p} \end{aligned}

Reference

[1] Adams, Hayden, et al. “Uniswap v3 Core.” Technical report, Uniswap, 2021. https://uniswap.org/whitepaper-v3.pdf

[2] Egorov, Michael, and Curve Finance. “Curve Stablecoin Design.” Technical report, Curve Finance, 2022.
https://github.com/curvefi/curve-stablecoin/blob/master/doc/curve-stablecoin.pdf


Share this post on: