--- title: Curve Magic description: Why Curve Works image: https://i.imgur.com/EpRuWmo.png tags: Curve, Curve V1, Curve V2, Curve Finance, math explained, whitepaper explained, wp explained, concentrated liquidity, Stableswap, invariant, CRV, crvUSD, crypto, defi, defi terms explained, Ethereum, L2, --- # Curve Magic [Philip Lu](https://twitter.com/_alltold), [Curve Research](https://www.curveresearch.org/) Original Work by Michael Egorov, [Curve Finance](https://curve.fi) Thank you to [Chanho Suh](https://github.com/chanhosuh), my colleague at Curve Research, for the peer review This Edition May 25^th^, 2023; 1^st^ Edition Mar. 17, 2023 # Abstract We consolidate Curve's V1 and V2 whitepapers and elaborate on concepts introduced in the original papers' corresponding sections. # Introduction Welcome! First things first: I assume that you have high school-level math knowledge, with only a little 1^st^-year university math required. You’ll also want to have a basic understanding of DeFi and DEXes. If you’ve completed at least a math-heavy Bachelor’s degree, I highly recommend you reason through the [Curve V1](https://classic.curve.fi/files/stableswap-paper.pdf) whitepaper (6 pages) and afterward the [Curve V2](https://classic.curve.fi/files/crypto-pools-paper.pdf) whitepaper (5 pages) on your own, only referring to this paper when you want more thorough explanation. If this writeup’s length discourages you, read anyway: you may find that you’re the kind of twisted person who enjoys a challenge. If you aren’t eager to learn about Curve but are invested in StakeDAO, REDACTED, yearn, Convex, or Curve itself, you may be putting money in what you don’t understand. Not that I fault you for it; you’re just good at aping. Please view this as your chance to mitigate risk by knowing what Curve’s value proposition is. All journeys feel hard to start, but you often find that you were always capable. Again, refer to this paragraph’s first sentence for good measure. Necessary DeFi and math concepts have been compiled in the Glossary. We go over the following terms: Automated Market Maker (AMM), Concentrated Liquidity, Derivative, Equilibrium, Exponential Moving Average (EMA) Oracle, Hypersurface, Impermanent Loss (IL), Invariant (Liquidity Equation, Bonding Curve), Mean-Reversion, Monotonic, and Newton’s Method. If you’re using LLMs to summarize this paper, you’d need to cross-check the output, which might defeat the purpose of using the LLM. # <img src="https://i.imgur.com/jPABKfm.png"> Curve V1 Let’s first discuss where Curve began—Stableswap. Think “**stable** prices after **swap**ping”. ## Stableswap As we’ve seen, exchanges like Uniswap V2 use the $x \cdot \ y\ = \ k$, or constant-product, invariant to maintain liquidity even if prices shift significantly. Before concentrated liquidity, however, stablecoins were facing price stability and liquidity issues; in addition, stablecoin LPs earned few fees. That’s why, in 2019, Curve founder Michael Egorov sought to build “Stableswap”, an efficient, stablecoin-oriented AMM with lower slippage than Uniswap at the time (V2). ### The Constant-Price Invariant Imagine a constant-price system. We can swap stablecoins $1$-for-$1$ with no price impact. We generalize this behaviour for any number of tokens, giving us a “linear” constant-price invariant. For example, we get $x + y = k$ for two tokens. Let $x_{i}$ denote the balance of token $i$ deposited: $$\sum_{}^{}x_{i} = k$$ For any two stablecoins, the exchange rate between both tokens would be $1$, equal to the derivative $\frac{dy}{dx}$, where $dy = - dx$. However, we can’t maintain a price of exactly $1$ if the reserves of any of the tokens start to run out. ### The Constant-Product Invariant We generalize the constant-product equation $x \cdot \ y\ = \ k$ for any number of tokens: $$\prod_{}^{}x_{i} = k$$ ## Finding a Middle Ground ![](https://i.imgur.com/kW3r8sL.png) Figure 1: Stableswap (Blue) in Between Constant-Price and Uniswap Invariants ([Curve](https://classic.curve.fi/files/stableswap-paper.pdf)) Stableswap is a “middle ground” between having perfectly constant prices and having slippage in exchange for adaptable liquidity. In the figure above, the desired Stableswap invariant is “flat” when the reserves of X and Y are balanced, meaning the price remains constant at close to 1.0. If reserves go out of balance, there is still liquidity offered with slippage. ![](https://i.imgur.com/tQ15WlB.png) Figure 2: Price Slippage Under Uniswap and Stableswap ([Curve](https://classic.curve.fi/files/stableswap-paper.pdf)) As we swap more of one token for the other, both invariants experience considerable slippage due to providing liquidity while the pool is heavily imbalanced. However, as figure 2 above tells us, Stableswap's slippage outside of the 1.0 price zone, having a steeper slope, is initially worse than Uniswap's before it improves. Visually, the longer the straight line part in figure 3 below, the harder the graph has to curve under imbalance, which results in a wider depeg. ## The Stableswap Invariant Inspired by both graphs above, we want a “straight-line" constant-price part to have more influence when reserves are balanced, but as the portfolio becomes more imbalanced, we want the curved constant-product part to take over. Assume we start a pool with $n$ stablecoins with equal balances in it. *If and only if the pool is balanced*, do the following two statements hold: $$\sum_{i = 1}^{n}x_{i} = k_1 = D,$$ (Balanced Constant-Price Invariant) $$\prod_{i = 1}^{n}x_{i} = k_2 = \left( \frac{D}{n} \right)^{n},$$ (Balanced Constant-Product Invariant) where the invariant $D$ is the total balance of the pool *when all the coins’ prices are equal at* $1. If each coin has equal reserves, each reserve is equal to the average amount $\left( \frac{D}{n} \right)$, so the constant-product invariant is the product of $\left( \frac{D}{n} \right)$ multiplied by itself $n$ times. But what happens when the reserves become imbalanced? That’s where we introduce an “amplification coefficient” parameter $A$. A higher $A$ extends the range where Stableswap looks like the straight-line constant-price invariant above for longer. A lower $A$ means Stableswap looks more like the curved Uniswap invariant in figure 1 above. <img src="https://i.imgur.com/7dqCQKW.gif" style="width:2.63433in;height:2.65375in"/> Figure 3: Stableswap (Red) Approximating a Straight Line as $A$ Approaches $\infty$ and a Curve as $A$ Approaches $0$ ([Balancer](https://docs.balancer.fi/concepts/math/stable-math)) We say that our constant-price invariant that experiences close to zero slippage corresponds to having infinite leverage because it's like there's an infinite reserve of coins that keep replenishing the token balances after swaps such that there is no price impact. On the other hand, $0$ leverage gives us our regular constant-product invariant that experiences significant slippage but offers liquidity when there is imbalance. Let $\chi$ (“chi”) denote the leverage we apply to our Stableswap invariant. As such, we want the constant-price invariant as $\chi\ \ \rightarrow \ \infty$ and the constant-product invariant when $\chi\ = 0$. We add the Balanced Constant-Price and the Balanced Constant-Product Invariants to each other to reflect Stableswap’s two parts. We apply leverage to the constant-price part to help “flatten” the graph by multiplying by $\chi\ D^{n - 1}$. $$\chi\ D^{n - 1} \cdot \sum_{}^{}x_{i} + \prod_{}^{}x_{i} = \chi\ D^{n - 1} \cdot (D) + \left( \frac{D}{n} \right)^{n} = \chi\ D^{n} + \left( \frac{D}{n} \right)^{n}$$ (Leveraged Invariant) We multiply the constant-price term by $\chi\ D^{n - 1}$ to also get two terms with $D^{n}$ in them because we want to account for the fact that $\prod_{}^{}x_{i} = ({D/n)}^{n}$ could be much larger than $\sum_{}^{}x_{i} = D$. As planned, if our leverage $\chi\ = 0$, $\chi\ D^{n} = 0$, and we only have the constant-product term $({D/n)}^{n} = \prod_{}^{}x_{i}$. In contrast, as $\chi\ \rightarrow \infty$, $\chi\ D^{n} \rightarrow \infty$, and $({D/n)}^{n}$ is very small in comparison since the number of stablecoins $n$ does not grow when $\chi$ grows, which makes the constant-price invariant $\chi\ D^{n - 1} \cdot \sum x_{i}$ more dominant. However, this invariant relies on the fact that the reserves of each token are equal, and liquidity is only supported close to the ideal price of $1.0$. We alter $\chi$ to make it dynamic: when the portfolio is perfectly balanced, $\chi$ is equal to the amplification coefficient $A$; however, when the portfolio becomes imbalanced, $\chi$ starts to fall off to $0$. $$\chi\ = \frac{A \cdot \prod x_{i}}{\left( \frac{D}{n} \right)^{n}}$$ (Dynamic Leverage Coefficient) $\prod_{}^{}x_{i}$ and $\left( \frac{D}{n} \right)^{n}$ cancel each other out when the token reserves are balanced, leaving only $A$, but how do we know that this new $\chi$ decreases towards $0$ as the pool becomes imbalanced? When the pool is balanced, all token balances $x_{i} = x = \frac{D}{n}$ are the same, so $\left( \frac{D}{n} \right)^{n} = x^{n}$. Assuming you can swap stablecoins 1:1, say that a balanced pool is started with $x$ of token 1 and $x$ of token 2. If you deposit 5 of token 1 and take out 5 of token 2, we have that $$\prod_{}^{}x_{i} = (x + 5) \cdot (x - 5) = x^{2} - 25$$ In this case, $n = 2$, so $\left( \frac{D}{n} \right)^{n} = x^{2}$. Clearly, $x^{2} > x^{2} - 25$ for any $x > 0$, so $\left( \frac{D}{n} \right)^{n} > \prod_{}^{}x_{i}$ here. We can mathematically describe imbalance using the ratio $\frac{x_{i}}{x_{j}}$ for any two tokens $i$ and $j$: the closer $\frac{x_{i}}{x_{j}}$ is to 1, the more balanced the pool is, and the further away $\frac{x_{i}}{x_{j}}$ is from 1 towards either 0 or ∞, the less balanced the pool is. Let’s plug some numbers. We have three scenarios where both token 1 and token 2 have starting balances of 20, 10, and 6; we deposit 5 of token 1 and take out 5 of token 2. | | $$x = 20$$ | $$x = 10$$ | $$x = 6$$ | |------------------|------------------|------------------|------------------| | $$\prod_{}^{}x_{i}$$ | $$(25) \cdot (15) = 375$$ | $$(15) \cdot (5) = 75$$ | $$(11) \cdot (1) = 11$$ | | $$\left( \frac{D}{n} \right)^{n}$$ | $${(20)}^{2} = 400$$ | $${(10)}^{2} = 100$$ | $${(6)}^{2} = 36$$ | | $$\chi\ = \frac{A \cdot \prod_{}^{}x_{i}}{\left( \frac{D}{n} \right)^{n}}$$ | $$\frac{A \cdot 375}{400} = \mathbf{0.9375}\mathbf{A}$$ | $$\frac{A \cdot 75}{100} = \mathbf{0.75}\mathbf{A}$$ | $$\frac{A \cdot 11}{36} \approx \mathbf{0.3056}\mathbf{A}$$ | | $$\frac{x_{1}}{x_{2}}$$ | $$\frac{25}{15} \approx \mathbf{1.67}$$ | $$\frac{15}{5} = \mathbf{3}$$ | $$\frac{11}{1} = \mathbf{11}$$ | We see that as the imbalance represented by $\frac{x_{1}}{x_{2}}$ increased, $\chi$ got closer to 0 since $\left( \frac{D}{n} \right)^{n}$grew relative to $\prod_{}^{}x_{i}$, so $\chi$ is working as intended. In fact, $\chi$ going to 0 implies that the slippage outside our invariant's flat region is at first faster than in Uniswap's, as Uniswap's $k$ doesn't reach 0 unless all deposits are removed from the pool. We sub in $\chi\ = \frac{A \cdot \prod_{}^{}x_{i}}{\left( \frac{D}{n} \right)^{n}} = \frac{A \cdot \prod_{}^{}x_{i} \cdot n^{n}}{D^{n}}$ into our leveraged invariant: $$\chi\ D^{n - 1} \cdot \sum_{}^{}x_{i} + \prod_{}^{}x_{i} = \chi\ D^{n} + \left( \frac{D}{n} \right)^{n}$$ $$\rightarrow \frac{A \cdot \prod_{}^{}x_{i} \cdot n^{n}}{D^{n}} \cdot D^{n - 1} \cdot \sum_{}^{}x_{i} + \prod_{}^{}x_{i} = \frac{A \cdot \prod_{}^{}x_{i} \cdot n^{n}}{D^{n}} \cdot D^{n} + \left( \frac{D}{n} \right)^{n}$$ Divide both sides by $\prod x_{i} \neq 0$, and then multiply both sides by $D$, and we’re done: $$\rightarrow An^{n} \cdot \sum_{}^{}x_{i} + D = ADn^{n} + \frac{D^{n + 1}}{n^{n} \cdot \prod x_{i}}$$ (The Stableswap Invariant) In the first term on the left-hand side of the equation, we got rid of $\prod x_{i}$ and $D$ because they were working against our amplification coefficient $A$ that keeps prices constant. And there we have it. Our Stableswap invariant, using $A$, maintains stable prices when reserves are reasonably balanced, otherwise providing liquidity under the constant-product curve with slippage proportional to $A$. During trades, we solve for the output amount net of a flat fee, and after deposits or withdrawals, we charge a small LP token rate. Existing LPs profit from both fees. Sharing a common result, swaps, deposits, and withdrawals all cause us to iteratively recalculate [prices](https://twitter.com/0xa9a/status/1514192791689179137?s=20) $\frac{dx_{j}}{dx_{i}}$. However, swaps, ignoring the slight fee, mostly keep $D$ constant, while adding or removing liquidity have considerable impact on $D$. Since $D$ governs liquidity depth, we need both higher and balanced $D$ to allow larger swaps without slippage. Take the 4pool, composed of DAI, USDC, USDT, and Terra’s depegged UST, as a cautionary tale. [On May 7, 2022](https://twitter.com/CurveSwaps/status/1523059517486891008?s=20), an $84.5M USDC swap and withdrawal imbalanced the share of UST to kick off UST’s then-1.5% depeg to \$0.985. UST then went on to make up [over 99% of remaining 4pool reserves](https://curve.fi/#/ethereum/pools/ust/deposit/), trading for \~\$0.02-\$0.03 as of the time of writing. So to drive the point home, $A$'s leverage comes with risk: the higher $A$ is, the faster slippage works once we exit the straight part of the curve. Imagine the market panics and values USDC/USDT at 0.90, but we value it at 1.0. If the pool then becomes heavily imbalanced but we increase $A$, we're doubling down on mean-reversion around a 1:1 exchange rate. Given that arbitrageurs barely maintain a \$1 price at the edge of the flat region, a pool with a higher $A$—a longer flat part—requires greater LP deposits to reachieve balance. Who would cover the difference if there's no more easy arbitrage to commit? Thus, when the peg rapidly slips and doesn't return, we might throw in the towel by decreasing $A$, marking-to-market our assets to reflect loss. Our paper profit shifts accordingly with $A$, so we've essentially made impermanent loss permanent. Thankfully, it then becomes easier for 1. the peg to recover, and 2. the pool to eventually balance, undoing part of the IL caused by imbalance, including reductions in $D$. Wow, that was a long ride. Don’t worry, we’re done with the math now. Sike! We haven’t even touched upon Curve V2’s invariant, which includes non-stablecoin and non-pegged assets! # <img src="https://i.imgur.com/jPABKfm.png">Curve V2 ## Transformed Pegged Invariants To enable greater liquidity, Curve V2 pools store volatile tokens which aren’t necessarily “pegged” to each other at a strict ratio like USDT, ETH, and WBTC, which compose the tricrypto2 pool. We track a balances vector $\mathbf{b}\ = \ (b_{0},b_{1},...)$, where $b_{i}$ is the balance of token $i$ with $N$ different tokens in the pool. We maintain a price scaling vector $\mathbf{p}\ = \ (p_{0},p_{1},...)$, where $p_{i}$ is token $i$’s market price relative to token $0$’s, with $p_{0} = 1$ regardless of swapping activity. If we let $p_{0} = 1$ denote the USD, then all other $p_{i}$ will track token $i$'s price in USD, so if token $i$ starts at \$50 and its price increases 10% afterwards, $p_{i} = 50 \rightarrow \ \approx 55$. V2's dynamic price scale thus differs from Stableswap's, where we almost always assume that all $p_i = 1$. From the whitepaper, we’re given a way to convert "transformed balances” $\mathbf{b}$ into “real balances” $\mathbf{b'}$ through a transformation $T$: $$\mathbf{b} = T\left( \mathbf{b'}\mathbf{,\ p} \right) = \left( \frac{{b'}_{0}}{p_{0}},\ \frac{{b'}_{1}}{p_{1}},\ \ldots \right);{\forall i,\ p}_{i} \neq 0.$$ (Real Balances) Each transformed balance $b'_{i}$ gets divided by $p_{i}$ to give the real balance $b_{i}$, or the current amount of token $i$ in the pool. $$\mathbf{b'} = T^{- 1}\left( \mathbf{b,\ p} \right) = \left( b_{0}p_{0},\ b_{1}p_{1},\ \ldots \right).$$ (Transformed Balances) We take a real balance $b_{i}$ and scale it by $p_{i}$ to give $b'_{i}$, the value of the token $i$ present denominated in token $0$. All $b'_{i}$ should be approximately equal for a pool in equilibrium, which means having roughly equal USD amounts of each token deposited since the USD is crypto’s de facto unit of account. For instance, each of the three [tricrypto2 pool](https://curve.fi/#/ethereum/pools/tricrypto2/swap) assets makes up a third of dollar-denominated liquidity, establishing equilibrium. We represent our desired invariant as the hypersurface $$I(\mathbf{b}\mathbf{'})\ = \ 0.\ $$ After swaps, deposits and withdrawals, pools will resist causing massive price movements while aiming to periodically align the dollar value—or token 0 value—of respective token deposits to be equal. In addition, using $\mathbf{b'}$ implies there’s ~0 price deviation if you deposited or withdrew assets at a dollar-wise balanced ratio. For consistency, say our transformed balances vector $\mathbf{b'}$ represents the equalized dollar-amount deposits of each token during pool balance. During and after the pool’s creation, let $$\mathbf{b'} =\mathbf{x}_{\mathbf{eq}} = \left(x_{eq},x_{eq},\ldots \right).$$ We peg $\mathbf{p}$ to the pool’s initial state $\mathbf{x}_{\mathbf{eq}}$ where each token starts out with $x_{eq}$ dollars’ worth deposited, so our pool knows how much each token is initially worth relative to the others. We want that for any value of $x_{eq},$ $$I\left( x_{eq},\ x_{eq},\ \ldots \right) = 0,$$ signifying that our current liquidity curve should barely shift after swaps *if deposits remain constant and balanced*. We see this price-preserving property in Stableswap thanks to its dynamic leverage coefficient $\chi$. V2 redefines imbalance as having unequal dollar amounts of each token in between each price update. Every price "repeg" equalizes the dollar balances of each token, creating a new liquidity curve with a new, balanced equilibrium point. The invariant $D$ is constant for a particular liquidity curve, being equal to the sum of all transformed deposits in a state of equilibrium. $N$ is the number of different tokens in the pool. $$D = Nx_{eq},$$ $$I\left( \mathbf{x}_{\mathbf{eq}},D \right) = I(\mathbf{x}_{\mathbf{eq}},\ Nx_{eq}) = \ 0.$$ Since $D$ is expressed in terms of $x_{eq}$, finding a solution $x_{eq}$ to the invariant above becomes trivial. ## The Cryptoswap Invariant It’s time to explicitly define our liquidity equation! We repurpose the Stableswap invariant: $$KD^{N - 1}\sum_{}^{}x_{i} + \prod_{}^{}x_{i} = KD^{N} + \left( \frac{D}{N} \right)^{N}$$ (The Cryptoswap Invariant) However, we slightly modify our leverage coefficient $K$: $$K_{0} = \frac{\prod x_{i}N^{N}}{D^{N}},\ \ \ \ \ \ \ \ K = AK_{0}\frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}.$$ (Decaying Dynamic Leverage Coefficient) If Stableswap is a combination of constant-price and constant-product invariants, then Cryptoswap is a combination of Stableswap and constant-product invariants. $K_{0}$ denotes how imbalanced the pool is, for $\prod x_{i}$ becomes smaller relative to $\left( \frac{D}{N} \right)^{N}$as the pool grows imbalanced. $A$ is our regular amplification coefficient. $\gamma$ ("gamma") controls the length of flat zone, which is inverse to how tightly our part-Stableswap, part-constant product invariant hugs a purely constant-product curve that uses the same equilibrium point—more on that later. If the reserves are balanced: $$\left( \frac{D}{N} \right)^{N} = \prod x_{i} \rightarrow K_{0} = 1;$$ $$K = A \cdot 1 \cdot \left( \frac{\gamma^{2}}{(\gamma + 1 - 1)^{2}} \right) = A,$$ giving us our Stableswap invariant. If the reserves are imbalanced: $$K_{0} \rightarrow 0,\ K \rightarrow 0 \cdot A \cdot \frac{\gamma^{2}}{(\gamma + 1 - 0)^{2}} \rightarrow 0,$$ causing our invariant to adopt constant-product behaviour with worse slippage than pure constant-product. As $\prod x_{i}$ becomes smaller relative to $\left( \frac{D}{N} \right)^{N}$as the pool grows imbalanced, $K_{0}$ decreases as imbalance increases. Thus, $$\frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}$$ decreases due to having a bigger denominator. $\gamma + 1 - K_{0}$ has a linear relationship with $K_{0}$, so $\left( \gamma + 1 - K_{0} \right)^{2}$ essentially has a square relationship with $K_{0}$. Therefore, $\frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}$ decreases by a square factor as $K_{0}$ decreases due to greater imbalance, since $\gamma$ is a constant. Furthermore, $K = A \cdot K_{0} \cdot \frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}$ drops off even faster. Therefore, the “leverage” factor $K$ is more sensitive to reserve imbalances, causing a quicker exit from the stable price zone in Cryptoswap than in Stableswap. Cryptoswap compensates for the fact that it is working with assets more volatile than stablecoins. The constant $\gamma$ is also meant to help compensate for volatility: $\gamma$ shortens our invariant's flat region in exchange for easing $\mathbf{p}$'s slippage outside of it. To visualize $\gamma$'s role, we might imagine Cryptoswap contained within a miniscule range between two constant-product invariants. *When reserves become imbalanced* from trading or LP volume, we repeg $\mathbf{p}$, which shifts our invariant while transforming its curvature. The rebalanced result lies inside the boundaries. ![](https://i.imgur.com/wDJxzC8.png) Figure 4: Cryptoswap (Orange) Given Room to Shift in Between Two Constant-Product Invariants (Dashed) While Approximating Stableswap (Blue) ([Curve](https://classic.curve.fi/files/crypto-pools-paper.pdf)) Thus, the smaller $\gamma$ is— that is, the closer our imagined boundaries are—the smaller $\frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}$ is, and the faster $K = A \cdot K_{0} \cdot \frac{\gamma^{2}}{\left( \gamma + 1 - K_{0} \right)^{2}}$ decreases, and the faster we emulate the constant-product invariant to provide liquidity. In this sense, a lower $\gamma$ expresses that we give up on a stable $\mathbf{p}$ more quickly so that our curve doesn't snap back to constant-product as hard. A lower $\gamma$ diminishes IL by pacifying our post-flat region slippage whenever we fail to mean-revert to the current price scale. <img src="https://i.imgur.com/MWO5yKt.png" style="width:4.75in;height:4.75in"/> Figure 5: $\gamma$ Enabling Cryptoswap (Red) to Offer Stable Prices for a Volatile Asset for a Shorter Range Compared to Stableswap (Green) ([Kurt Barry](https://twitter.com/Kurt_M_Barry/status/1404496498335830027?s=20&t=KIiuWGW7e5Vi8GiZyYMAuQ)) We'd then repeg the price scale, creating a new liquidity curve. We distinguish the two user activities that affect $\mathbf{p}$: swapping, and adding or removing liquidity. To change our liquidity curve, we solve the Cryptoswap equation $I(\mathbf{x_{eq}}, D) = 0$ for $x_i$ after swaps for token $i$ and for $\mathbf{x_{eq}}$ and $D = Nx_{eq}$ after repegs, deposits, or withdrawals. ### Solving the Invariant We define Cryptoswap as $F(\mathbf{x},\ D) = \ 0$ and express the dynamic leverage coefficient $K$ as a function $K(\mathbf{x},\ D)$. After rearranging the terms to be on one side of an equation, we have $$F\left( \mathbf{x},D \right) = K\left( \mathbf{x},D \right) \cdot D^{N - 1} \cdot \sum_{}^{}x_{i} + \prod_{}^{}x_{i} - K\left( \mathbf{x},D \right) \cdot D^{N} - \left( \frac{D}{N} \right)^{N} = 0$$ (Solvable Cryptoswap Form) At regular intervals, we solve $F(\mathbf{x},\ D)\ = \ 0$ against either $x_j$ or $D$ using Newton's method. The "best" starting points for $D_{0}$ and $x_{i,0}$ are included below: $$D_{0} = N\left( \prod x_{i} \right)^{\frac{1}{N}},$$ $$D_{k + 1} = D_{k} - \frac{F\left( \mathbf{x},\ D_{k} \right)}{F_{D}^{'}\left( \mathbf{x},\ D_{k} \right)}.$$ $$x_{i,0} = \frac{D^{N - 1}}{\prod_{k \neq i}^{}{x_{k} \cdot N^{N - 1}}},$$ $$x_{i,\ k + 1} = x_{i,k} - \frac{F\left( x_{i,k},\ldots,\ D \right)}{F_{x_{i}}^{'}\left(x_{i,k},\ldots,\ D \right)}.$$ However, beware: $F\left(\mathbf{x},D\right)$ isn’t monotonic, so it could “change direction”, thereby creating a potentially unlimited number of suboptimal solutions that would be gas-costly to calculate and store. Or, the curve could become flat at any point, causing Newton's method to fail to proceed. According to Curve contributor [Fiddy](https://twitter.com/fiddyresearch), Curve’s math functions usually require fewer than 10 Newton’s method iterations because they estimate optimal $D_{0}$ and $x_{i,0}$. However, the number of iterations can vary widely, sometimes being as high as 24+. We find solutions that deviate from the previous iteration within only two decimal places ([Curve’s Math contract, line 121](https://etherscan.io/address/0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5#code)), but if we can’t after 255 iterations, we give up to limit gas costs (lines 160 and 194). With that in mind, we’re motivated to initialize $x_{i, 0}$ and $D_{0}$ so that Newton’s method can reliably find solutions to $F(\mathbf{x},\ D)\ = \ 0$, taking ~60k gas per $D$ or $x_{i}$ solved (line 102) not \~35k like the whitepaper states. For reference, that’s about three times the 21k gas base cost of sending someone ETH. #### Computing D With Leverage We solve for $D$ when repegs, deposits, and withdrawals occur, updating $\mathbf{p}$ if a deposit or withdrawal is imbalanced dollar-wise. Our new $D$ is based on the rebalanced equilibrium point characterized by each updated $b'_i = b_ip_i$. We illustrate solving for new $D$ below. You might need to zoom in. ![](https://i.imgur.com/xWzwr5x.jpg) Figure 6: Solving $\left|F\left( \mathbf{x},\ D \right)\right|\ = \ 0$ Against $D$ Using Newton’s Method, Given $D_{0}$ (Curve) Starting from $D_{0}$ at the orange cross, we steadily iterate towards the solution, marking each step with a green dot. As we can see, we usually need three iterations at most to find a sufficiently precise answer, but we can end up taking many more steps, as shown in the bottom two graphs. While holding $\mathbf{x}$ and $\mathbf{p}$ constant, we start solving from the “best” $D_{0}$: $$D_{0} = N\left( \prod x_{i} \right)^{\frac{1}{N}}.$$ $$K_{0} = \frac{\prod x_{i}N^{N}}{D_{0}^{N}} = \frac{\prod x_{i}N^{N}}{\left( N\left( \prod_{}^{}x_{i} \right)^{\frac{1}{N}} \right)^{N}} = \frac{\prod x_{i}N^{N}}{\prod x_{i}N^{N}} = 1,$$ $$K\left( \mathbf{x},D_{0} \right) = A.$$ $K = A$, our maximum leverage. If current $\mathbf{x}$ is balanced enough given $\mathbf{p}$, we can satisfy $F = 0$ while our new invariant upholds the widest flat part possible. If not, we iteratively reduce $K_0$ and $K$. The token $i$ vs. token $j$ vs. token ... graph incrementally "unflattens", shortening its stable region, but adapting pure constant-product's gentler slippage at the edges. Think of it this way: if we make an imbalanced deposit prevalued at \$1M, we want our solved $D$ to be as close to 1M higher as possible after price slippage. We stop solving when $D$ converges, setting a rebalanced equilibrium point $\mathbf{x_{eq}}$. $D$ counts profit in V1 where $\mathbf{p} = (1,1,...)$, but when $\mathbf{p}$ bounces around in V2, $D$ might not decrease to mark IL. Not a good sign. We'll come up with a precise profit measure in *Quantification of a Repegging Loss* below. The above aside, we’ve tested and confirmed that this $D_{0}$ is safe for convergence. #### Computing $x_{i}$ Without Leverage As opposed to what affects $D$, $j$-$i$ swaps involve adding the user's token $j$ input to $x_j$, calculating the exchange rate $\frac{\partial x_i}{\partial x_j}$, solving for a new $x_i$ that keeps $D$ constant with $\frac{\partial F}{\partial x_i}$, and outputting an amount of token $i$ net of a fee. We then feed the trade price to our oracle, which affects all $p_i$ down the line. Again, we must navigate $F$ cautiously. If we didn’t initialize $x_{i,0}$ properly in Figure 7 below, we may have ended up crossing that “mountain”. In that case, we likely would've failed to find a solution after iterating too many times, marked by the red triangles. Otherwise, we could've found a suboptimal solution far away from the optimal $x_{i}$ marked by the purple arrows, which would incur excessive slippage. ![](https://i.imgur.com/qAYLuLv.png) Figure 7: Fickle $F$ Landscape Necessitating Intelligent Initialization of $D_{0}$ and $x_{i,0}$ ([George Ovchinnikov, Filipp Skomorokhov](https://github.com/curvefi/tricrypto-ng/blob/extended-readme/docs/tricrypto_optimisation.pdf)) Therefore, while holding $D$ constant, we want to begin solving from the "best" $x_{i,0}$: $$x_{i,0} = \frac{D^{N - 1}}{\prod_{k \neq i}^{}{x_{k} \cdot N^{N - 1}}},$$ $$K_{0}\ = \frac{\prod x_{k}N^{N}}{D^{N}} = \frac{\prod_{k \neq i}^{}x_{k} \cdot x_{i,0} \cdot N^{N}}{D^{N}} = \frac{{(D}^{N - 1} \cdot N^{N})}{(D^{N} \cdot N^{N - 1})} = \frac{N}{D},\ $$ where $\frac{N}{D} \approx 0$ because $D$ far outweighs $N$. $$K\left( x_{i,0},\ldots,D \right) = \ A \cdot \left( \frac{N}{D} \right) \cdot \frac{\gamma^{2}}{\left( \gamma\ + \ 1\ –\frac{N}{D} \right)^{2}\ } \approx 0.\ $$ We initially apply close to no leverage. In this sense, solving for $x_i$ is "opposite" to solving for $D$. Keeping $D$ the same, $F(x_{i,0}, ..., D) \approx \prod x_i - \left(\frac{D}{N}\right)^N \leq 0$. Therefore, starting from small $x_{i,0}$, $x_{i,k}$ increases every iteration to bring $F$ up from the negatives to $0$, reaching our swap-reduced solution $x_i$. We correspondingly increment $K_0$ higher until the curvature fits our altered balance. After you add token $j$, $\frac{\partial x_i}{\partial x_j}$ dictates based on balance how much $x_i$ changes relative to $x_j$. Even though $D$ stays mostly constant, our post-swap $x_j$ and $x_i$ alter where we are on the current curve. Generally, if the swap made all $x_i$ get closer to $\frac{D}{N}$, the exchange rate stabilizes as we enter the flat part, and vice versa. When swaps further imbalance, slippage compounds. Fortunately, slippage works both ways: for a short region containing the flat zone and its curving edges, inputting low-supply tokens improves balance a lot faster. Each time liquidity transforms our curve, Stableswap gets recentered around the *balanced region*, while bootleg constant-product governs the *imbalanced region*—revisit figure 5. So, when we calculate new curves, the degree of balance within price-determined $\mathbf{b'}$ dictates how the liquidity curve behaves locally, with total liquidity determining the depth of said behaviour. To visualize recentering, have a fun [table surfing video](https://youtu.be/NY1EGJN5faE) (Figure 8: A Visual Representation of Stableswap Recentering): the students on the floor constantly “recenter” around the girl on the table, who represents pool prices, to keep her stable but mobile for consecutive short distances. Of course, we need dollar-denominated balance to offer stable prices, and we suffer IL whenever we recenter. #### Safe Parameters To find out the limits of our invariant, Curve’s team used fuzzing, which is an automated way to test software by throwing extreme, invalid, or random data at a program to see how it performs or breaks, and test results validated our mathematical reasoning. For safe convergence of $x_{i}$: $$0.1 \leq D \leq 10^{15} \space \mathrm{USD}$$ $10^{15}$ USD is 1 quadrillion, or 1,000 trillion, dollars—more than the entire wealth of the world. $$5 \cdot 10^{- 3} < x_{i}/D\ < 200.$$ While not likely, a newly calculated $x_{i}$ can outsize total deposits $D$ by up to 200 times if total liquidity is growing quickly, like when apes are piling into a pool that has just been deployed. For safe convergence of $D$: $$1 \leq A \leq 10000.$$ As a convention, V2 pool smart contracts store "$A$" as $10,000 \cdot A \cdot N^N$. $$10^{- 9} \leq x_{0} \leq 10^{15}.$$ We don’t want our deposits $D$ to grow too big. $$10^{- 5} \leq x_{i}/x_{0}\ \leq 10^{15}.$$ In this case, it’d be hard to maintain liquidity with such extreme imbalance between token $i$ and token $0$; plus, deposits $D$ could also become too large. For safe convergence of both $x_{i}$ and $D$: $$10^{- 8} \leq \gamma \leq 10^{- 2}.$$ Again, this sets the range our invariant can bend in. ## Quantification of a Repegging Loss In V2, $\mathbf{p}$ is dynamically volatile, so we want a dynamic mean-reversion strategy in order to make profit. To enact such, pools regularly concentrate, or "flatten", liquidity around every new price scale. Realistically, concentrated liquidity is a bet: by briefly offering zero slippage, LPs earn consistent fees IL-free when prices mean-revert to a stable average. But, when imbalance forces recentering, LPs uniformly take amplified IL from subpar constant-product's slippage. We illustrate the curve-warping repegging effect below. ![](https://hackmd.io/_uploads/BkMFkR-Bh.jpg) Figure 9: Repegging Process in a Two-Coin Pool ([Leo Lau, Boo/Guangwu](https://medium.com/anchordao-lab/automated-market-maker-amm-algorithms-and-its-future-f2d5e6cc624a#bbd7)) Pre-swap, we have $y = x = 1000$, where $p_0 = p_1 = 1$, and $D = y + x = 2000$. Assuming no frontrunning or arbitrage, we swap \$400 of $x$ for ~\$343 of $y$ and nuke $x$'s price down to 0.6. We travel along the green curve to reach the orange recentered $\mathbf{x_{eq}}$. Reflecting heavy imbalance, it lies distant from the old blue $\mathbf{x_{eq}}$ inside the stable zone where the green curve hugs the dashed blue line. Only by covering the repegging loss with external deposits could we return to the blue point where $p_1 = 1$ *and* $D = 2000$. To envision curve warping, let's say that each particular $\mathbf{p}$ creates a "$\mathbf{p}$-family" of curves that share flat and curved parts. These parts are respectively parallel to each other and distinct from—e.g. non-parallel to—those of other $\mathbf{p}$-families. We shift between curves in a family by depositing or withdrawing at a dollar-balanced ratio. In that case, $D$ then increases or decreases without affecting the curvature. In V1, almost any increase to $D$ creates profit. Stableswap rarely morphs because all $p_i$ normally stay at 1. However, Figure 9's crisscrossing straight lines demonstrate that, in V2, the flat part will relocate nonparallel to the previous flat part and adjust length, switching the invariant's family. Therefore, since constant-sum $D$ creates all flat parts, comparing $D$ across $\mathbf{p}$-families to measure profit is, geometrically, comparing apples to oranges. This is why $D$ doesn't accurately track repegging loss from curve to curve. As such, we want a unique measure of pool value that accounts for V2's particular form of IL. We quantify pool value using a simple constant-product invariant. We disregard “noise” from any differences between $\mathbf{p}$ and the market price of each token. The one-dimensional value of our pool $X_{cp}$ is given as the geometric average of the real balances: $$X_{cp} = \left( \prod \frac{D}{Np_{i}} \right)^{\frac{1}{N}}$$ $$\rightarrow X_{cp} = \left( \prod \frac{b'_{i}}{p_{i}} \right)^{\frac{1}{N}} = \left( \prod b_{i} \right)^{\frac{1}{N}}.$$ (Pool Value Without Noise) Overall, curvy $\prod b_i$ hugs Cryptoswap better and replicates its transformations better than $D$, flat as a board and short. Hence, comparing $X_{cp}$ across $\mathbf{p}$-families is the geometrical apples-to-apples comparison that we need to make to quantify pool value. $\prod b_i$ and Cryptoswap share $\mathbf{x_{eq}}$, where $\prod b_i$ and $X_{cp}$ are lower at any other point along $\prod b_i$ due to $p_i$ slippage. The $\frac{1}{N}$ exponent restrains $X_{cp}$'s volatility. ## Algorithm for Repegging ### Profit Measure To quantify profit, we first track $X_{cp}$ at every repeg. After depositing into a new, empty pool, we initialize the LP token supply as $X_{cp}$. The proportion of LP tokens you own determines the proportion of liquidity you can withdraw. On each deposit, we grow the LP token supply by nearly the same percentage that deposits $D$ grew by, after deducting a deposit fee. To measure the value of an LP token independent of when an LP joined the pool, we introduce the virtual price: $$virtual\ price = \ \frac{X_{cp}}{LP\ token\ supply}.\ $$ (Virtual Price) In other words, a pool’s virtual price is the pool value available per LP token. We incorporate the virtual price to measure LP profit, which we label $xcp\_profit$. When a pool receives liquidity for the first time, we initialize the virtual price and $xcp\_profit$ as 1.0, denoting neither profit nor loss. $xcp\_profit$ increases from virtual price increases, when LPs own more tokens worth more money than before. $$new\ xcp\_ profit = \ old\ xcp\_ profit\ \cdot \ \frac{new\ virtual\ price\ \ }{old\ virtual\ price}\ $$ $$= old\ xcp\_ profit \cdot \left\lbrack \left( \frac{X_{cp,new}}{new\ LP\ token\ supply} \right) \div \left( \frac{X_{cp,old}}{old\ LP\ token\ supply} \right) \right\rbrack$$ (Profit Measure) Creating profit, $X_{cp}$ could increase disproportionately high relative to the LP token supply through swap and deposit fees and external liquidity incentives. We profit only if we reasonably preserve balance, though. The more concentrated the swap or deposit is in token $j$, the higher the fee taken in token $i$ or LP tokens, respectively. The older the LP, the longer their ownership share "compounds" due to fees, so older LPs receive a bigger proportion of the fees than newer LPs. Naturally, we need a placeholder $xcp\_profit\_real$ to mark losses to $xcp\_profit$ from repegs, admin fees, and $A$ or $\gamma$ changes. If a price update causes $xcp\_profit\_real - 1$ to fall below half of $xcp\_profit - 1$, wiping out half or more of accumulated profit, we revert it to preserve the remainder. As a result, our leftover transformed balances will stay at the same price. This impedes potential cascading losses by momentarily allowing withdrawals at stable prices. The lower profit goes, the lower the threshold to temporarily suspend $\mathbf{p}$, which bolsters this line of defense. Doubly, price manipulation becomes more expensive, taking more trade volume over a longer period. This buys time for arbitrageurs to narrow spreads between Curve pools and external exchanges, which tames further arbitrage via mean-reversion and thus blunts losses. Countering the loss, all resultingly heightened activity generates greater fees. We might compare arbitrageurs to a mafia protecting the businesses that it extorts. Nonetheless, we should diminish the "noise" between $\mathbf{p}$ and the market, lest we invite recurring "leveraged" losses. Two ways we can do so are: 1. attracting deep liquidity with \$CRV; and 2. "optimising" pool parameters like $A$, $\gamma$, the oracle time, or the admin fee. Also, under imbalance, we raise fee rates to offset repegging loss while aiming to slow the frequency of further-destabilizing trading. ### Internal Oracle To log price movement, pools take an internal exponential moving average (EMA) of price points over a specified period. Informed by trades or imbalanced withdrawals or deposits, the latest prices influence the EMA value the most, but we still end up with smoothed-out data that’s more reliable. Let $\mathbf{p}_{last}$ be the last reported $N$-coin price vector from $t$ seconds ago. Our weight factor $\alpha$ has a half-time of $T_{1/2\ }$ seconds, [typically 600](https://etherscan.io/address/0xd51a44d3fae010294c616388b506acda1bfaae46#readContract#F26), and the oracle price $\mathbf{p}^{*}$ is given as: $$\alpha = 2^{- \frac{t}{T_{1/2}}},$$ $$\mathbf{p}^{*} = \mathbf{p}_{last}(1 - \alpha) + \alpha\mathbf{p}_{prev}^{*},$$ (N-Price EMA Oracle) where $\mathbf{p}_{prev}^{*}$ was the most recent *average* that we replaced. We store the oracle price $\mathbf{p}^{*}$ and the price peg $\mathbf{p}$ on-chain, while we calculate the last reported price $\mathbf{p}_{last}$ after swaps, deposits, and withdrawals. First, we derive $\mathbf{p}_{last}$ from $\frac{\partial x_i}{\partial x_j}$, which our *current* $\mathbf{p}$-family's curvature determines. Then, we incorporate $\mathbf{p}_{last}$ into the latest $\mathbf{p}^{*}$ EMA. Lastly, we shift *current* $\mathbf{p}$ toward $\mathbf{p}^{*}$ to create *new* $\mathbf{p}$, which updates $\mathbf{b'}$. Every time $\mathbf{p}$ repegs, we increase or decrease each $p_{i}$ toward $p_{i}^{*}$ by multiplying it by a value slightly above or below 1.0; however, for simplicity, the difference won’t be exactly ($\mathbf{p}^{*} - \mathbf{p}$). We move prices in increments of $s$, the price change step: $$\frac{p_{i}}{p_{i,prev}} = 1 + \frac{\left( \frac{p_{i}^{*}}{p_{i,prev}} - 1 \right)}{\sqrt{\sum\left( \frac{p_{j}^{*}}{p_{j,prev}} - 1 \right)^{2}}} \cdot s$$ (Price Adjustment in Log Space) Well, that looks scary as hell. Let's break it down. The percentage difference between the latest token $i$ oracle reading $p_{i}^{*}$ and the price scale $p_{i,prev}$ that we're replacing makes up a fraction of how far every oracle price has deviated from every previous price in absolute terms, given by the distance formula $\sqrt{\sum\left( \frac{p_{j}^{*}}{p_{j,prev}} - 1 \right)^{2}}$. We multiply that fraction by our step $s$ and add 1 to get a multiple above or below 1 that we should adjust $p_{i}$ up or down by, relative to all token price changes. Obviously, pools will aim to readjust to prices that accommodate high-liquidity regions of the curve without creating losses, as the [Curve docs](https://resources.curve.fi/base-features/understanding-crypto-pools) state. ## Concentrated Liquidity Let's piece together Cryptoswap's concentrated liquidity design. Most crucially, we leverage $D$, centering a no-slippage zone around $\mathbf{x_{eq}}$. Adding deposits deepens liquidity net of the curve transformation's IL because Newton's method solves $D$ to differ as little as possible from its ideal result. Because imbalance is inevitable, we allow a dynamic fee, elaborated below, to both cushion profit and slow departure from the flat part. Placing another backstop, we repeg only if $xcp\_profit$ is more than double the IL. We thus want to subdue repegging cost beforehand, so we lower noise with $CRV incentives and pool parameter optimization. Moreover, our oracle averages prices out for greater stickiness within consistent ranges. As a result, Curve concentrates liquidity around the current price. ## Dynamic Fees Finally, some money-making talk. LPs charge a swap fee so that there's enough profit to cover IL. Intuitively, the higher the imbalance, the higher the fee; greater loss needs greater fees to offset! The swap fee $f$ ranges between two constants $f_{mid}$ and $f_{out}$, with $f_{mid} < f_{out}$. In the "middle" of the stable zone, $f$ starts at $f_{mid}$ and increases “out” to $f_{out}$ after imbalance. $$g = \frac{\gamma_{fee}}{\gamma_{fee} + 1 - \frac{\prod x_{i}}{\left( \sum x_{i}/N \right)^{N}}}$$ $$f = g \cdot f_{mid} + (1 - g) \cdot f_{out}$$ (Dynamic Fee Within a Range) If transformed reserves are balanced dollar-wise: $$\prod_{}^{}x_{i} = \left( \frac{\sum x_{i}}{N} \right)^{N} \rightarrow \ \frac{\prod x_{i}}{\left( \frac{\sum x_{i}}{N} \right)^{N}} = 1$$ $$\rightarrow g = \frac{\gamma_{fee}}{\gamma_{fee} + 1 - 1} = \frac{\gamma_{fee}}{\gamma_{fee}} = 1$$ $$\rightarrow f = f_{mid}$$ If transformed reserves become imbalanced dollar-wise: $$\frac{\prod x_{i}}{\left( \frac{\sum x_{i}}{N} \right)^{N}} \rightarrow 0$$ $$\rightarrow g \rightarrow \frac{\gamma_{fee}}{\gamma_{fee} + 1 - 0} = \frac{\gamma_{fee}}{\gamma_{fee} + 1} \approx \gamma_{fee},$$ given that $\gamma_{fee}$ is similarly close to $0$ like the $\gamma \in \lbrack 10^{- 8},10^{- 2}\rbrack$ in our Cryptoswap invariant. For example, $\frac{10^{- 2}}{10^{- 2} + \ 1}\ \ \approx \ 10^{- 2}$ within a $1$% margin of error. Thus, as $g \cdot f_{mid} \rightarrow \gamma_{fee} \approx 0$, $f \rightarrow (1 - g) \cdot f_{out} \rightarrow f_{out}$. When imbalance persistently worsens, $\left( \frac{\sum x_{i}}{N} \right)^{N}$ grows faster than $\prod x_{i}$ decreases by at least a power of $N$. Consequently, $g$ near-parabolically drops to $\gamma_{fee} \approx 0$, bringing the fee $f$ up to $f_{out}$ with haste. ![](https://hackmd.io/_uploads/B1d4oZoS2.png) Figure 10: Near-Parabolic Fee Rise in a Two-Token Pool ([Leo Lau, Boo/Guangwu](https://medium.com/anchordao-lab/automated-market-maker-amm-algorithms-and-its-future-f2d5e6cc624a#32fc)) Another way to think about it: the fee grows based on how far the internal oracle is from $\mathbf{p}$. If the internal price has "run away" from where we recentered too fast, we stand to face major repegging loss, so we jack up fees to defend our profits. In contrast to the swap fee, the deposit-withdrawal fee only applies if a deposit or withdrawal is imbalanced in dollar terms. It's intended to equal the swap fee under the assumption that the pool is balanced at time of deposit and at time of withdrawal. # V1 vs. V2 At the end of this long journey, weary traveler, I hope the following ideas were “the friends you made along the way”. Regarding Stableswap: we concentrate liquidity around a 1:1 peg, usually at a price of \$1. We maintain it until extreme imbalance occurs, during which we depeg under subpar constant-product's slippage. Said slippage scales with our leverage $A$, and changing $A$ lowers our profit, which constant-price $D$ counts because Stableswap's so flat. Regarding Cryptoswap: we concentrate liquidity around the current price scale, albeit for necessarily shorter regions. As a result, $\prod b_i$ approximates our curvier invariant better than $D$ does, which is why we track profit with $X_{cp}$. That is, $X_{cp}$ better measures the repegging loss linked to curve warping, which changes in $A$, $\gamma$, or $\mathbf{p}$ produce. Our moving average oracle smoothes out $\mathbf{p}$ and can suspend it to preserve $xcp\_profit$; separately, we scale fees after imbalance. To rebalance, our invariant equalizes all $x_{eq}$, but liquidity concentration depth persists through the curve's transformation because we initialize Newton's method well when solving for $D$. We’re done. Whether you read linearly or in scrambled fashion, thank you for your attention. I hope, by exploring concepts deeper, readers gleaned the subtle magic behind Curve’s system. Another fruit bundled in your mind’s handbasket: savour it well! # Glossary #### Automated Market Maker (AMM) The set of smart contracts Curve V1 and V2 use to algorithmically pool liquidity, calculate prices, minimize slippage, route multi-step trades, and, for V2, to ensure LPs are exposed to all assets equally under equilibrium. #### Concentrated Liquidity A mechanism that adds depth to liquidity around a price range such that it takes sustained trade volume in said price range to cause slippage by shifting equilibrium. When mean-reversion occurs, *concentrated liquidity* means no slippage for traders, and no IL for LPs—a win-win. The downside is: *concentrated liquidity* amplifies slippage when we run out of it. [Further reading](https://uniswap.org/whitepaper-v3.pdf) (Section 2 and Figure 3) #### Derivative If you were to draw a line in the direction a tiny point on a curve was heading in, the slope of that line would be the *derivative*. In an AMM, its invariant’s *derivative* at the current equilibrium point tells where the exchange rate between two tokens is and where it’s “going to go” after a trade involving given amounts of both tokens occurs. Further reading: [V1 Formula](https://twitter.com/0xa9a/status/1514192791689179137?s=20), V2 formula not yet public #### Equilibrium In general, *equilibrium* point is the variable price an AMM enforces between a pair of tokens based on current reserves of each. For Curve V1, *equilibrium* will usually reside around \$1 despite considerable imbalance. For V2, *equilibrium* is the “balance” denoted by a pool having equal dollar amounts of each token, achieved by changing prices, altering the true amount of any token stored, or by combining these two events to a variable degree. #### Exponential Moving Average (EMA) Oracle Curve V2’s internal oracle takes an average of a fixed number of the most recent price data points. Each point in this “moving” average has half as much weight every half-time—as in chemistry’s half-life—occurring every $T_{1/2}$ seconds, where the scaling factor $\alpha$ will *exponentially* reduce an observation’s weight through repeated multiplication as time goes on. We then end up with smoother price data that still emphasizes the most recent prices. If the most recent price $\mathbf{p}_{last}$ was reported $t$ seconds ago, we update the current *EMA* $\mathbf{p}_{prev}^{*}$: $$\alpha = \left( \frac{1}{2} \right)^{\frac{t}{T_{1/2}}},$$ $$\mathbf{p}^{*} = \mathbf{p}_{last}(1 - \alpha) + \alpha\mathbf{p}_{prev}^{*}$$ [Further reading](https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/ema) #### Hypersurface In a Curve V2 pool holding $N$ tokens, our invariant is geometrically represented by a *hypersurface*, an $N$-dimensional surface in ($N + 1$)-dimensional price space formed by the $N$ dimensions of our token balances vector $\mathbf{x}$ plus one dimension of our invariant function $F$. *Hypersurfaces* like V2’s invariant are implicitly defined by single equations such as $F\left( x_{1},\ldots,x_{n} \right) = 0$. [Further reading](https://mathworld.wolfram.com/Hypersurface.html) #### Impermanent Loss (IL) LPs face *impermanent loss* at any time if their AMM liquidity is worth less money, even including rewards, than what it would’ve been if they had just held their tokens. Note the difference between a real paper loss, where the deposits are worth less than what the LP bought them for, and *IL*, where the LP had worse returns by providing liquidity rather than simply holding. Generally, after an LP deposits assets at a given exchange rate among them, they face worse *IL* the further prices deviate from said exchange rate. Further reading: [formula](https://medium.com/auditless/how-to-calculate-impermanent-loss-full-derivation-803e8b2497b7), [in-depth](https://chainbulletin.com/impermanent-loss-explained-with-examples-math) #### Invariant (Liquidity Equation, Bonding Curve) An *invariant* formula always satisfies some mathematical property. AMMs like Uniswap originally used the constant-product *invariant* $x \cdot y = k$, where $x$ and $y$ are the balances of two tokens and $k$ is a constant. The ratio between balances determines the exchange rate at equilibrium, and the *invariant*’s derivative smoothly determines how the exchange rate will change after swaps, deposits, or withdrawals. ![](https://i.imgur.com/mCZmccI.png) Constant-Product Invariant (Gnosis DAO) However, this *invariant* incurs slippage no matter how small the trade, so Curve’s V1 and V2 *invariants* seek to enable less slippage, incorporating the constant-product *invariant* when necessary. [Further reading](https://ethresear.ch/t/improving-front-running-resistance-of-x-y-k-market-makers/1281) #### Mean-Reversion In liquid markets, asset prices tend to average out by stabilizing into a range or reversing course after a strong move in either direction. Such *mean-reversion* allows AMMs to organically "undo" some imbalance—and thus IL—while collecting fees in both directions. [Further reading](https://www.cmcmarkets.com/en/trading-guides/mean-reversion) #### Monotonic A function that either doesn’t increase or doesn’t decrease at all is *monotonic*. Respectively, its first derivative is strictly $\leq 0$ or $\geq 0$, and it doesn’t change sign over the function’s entire domain. Curve’s multidimensional invariant isn’t *monotonic*, meaning any of its partial first derivatives can become $0$ several times as it changes sign several times. Newton’s Method doesn’t work if the first derivative is $0$, which can stop us from finding roots to Curve’s hypersurface as we lack perfect formulas for every situation. [Further reading](https://en.wikipedia.org/wiki/Monotonic_function) #### Newton’s Method A method to iteratively approximate a root $x_{i}$ to $F\left( x_{1},\ldots,x_{n} \right) = 0$ in the $i$th dimension without needing an exact solution to the equation. Starting from a point, we take the tangent line at that point using the derivative, intersect it with the $i$th axis, and repeat the process with the new $F$ value at $x_{i}$ until we find a sufficiently precise root. However, *Newton’s Method* can fail in several ways: first, if $F$ is “flat” at any $x_{i}$ such that $F_{x_{i}}^{'}\left( x_{1},\ldots,x_{n} \right) = 0$ but $F \neq 0$, the iterative process stops as the tangent can’t intersect the $i$th axis. Second, we can approach a suboptimal root, which could cause excessive slippage in our invariant. Third, we can end up in a loop where we alternate our search among multiple roots, but never reach any of them due to $F$’s “shape”. Further reading: [definition](https://math.libretexts.org/Bookshelves/Calculus/Calculus_(OpenStax)/04%3A_Applications_of_Derivatives/4.09%3A_Newtons_Method), [failures](https://en.wikipedia.org/wiki/Newton's_method#Failure_analysis)