Curve pricefeed

Curve price feed

The Curve price feed returns the USD price for a single Curve LP share. The price is computed as ICurvePool.get_virtual_price() multiplied by the USD price of the cheapest asset in the Curve pool currently.

The intuition behind this is that it is more profitable to withdraw the asset with the largest balance in the pool (since otherwise the user will suffer imbalancing fees), which will be the cheapest asset. Therefore, a fair price for a Curve LP share is based on the price of the cheapest asset.

To avoid get_virtual_price() manipulation affecting Gearbox, the price feed checks the get_virtual_price() returned value against preset lower and upper bounds. If the value falls outside the bounds, the function reverts.

The bounds are configured by the governance and the upper bound is typically set to the current value +2%.

Math proof

Beyond the intuition, we also want to show that the defined calculation cannot overestimate the value of a Curve LP, since otherwise the discrepancy can be exploited to steal money from LPs.


Curve's invariant is defined as

Annxi+D=ADnn+Dn+1nnxi,An^n\sum x_i + D = ADn^n + \frac{D^{n+1}}{n^n \prod x_i},

where xix_i is balance for the i-th token in pool, nn is the number of tokens, AA is the amplification parameter and DD is a constant representing the virtual price of the LPLP token.

Curve price oracle equation

We want to prove that

pjmini1,..,npijxi,p_j \ge \min\limits_{i \in 1,..,n} p_{ij} \sum x_i,

is true for any Curve pool. pjp_j is price of Curve LP token nominated in jj-th coin.


Real curve LP price is equal to

pj=xixixj,p_j = \sum x_i \frac{\partial x_i}{\partial x_j},

where xi/xj\partial x_i/\partial x_j by definition is the price of ii-th coin nominated in jj-th coin (or pijp_{ij}). Substituting, we get:

xipijmini1,..,npijxi,\sum x_i p_{ij}\ge \min\limits_{i \in 1,..,n} p_{ij} \sum x_i,

which is always true by definition of min\min.

Curve LP's ICurvePool.get_virtual_price() is calculated as xi\sum x_i. So the price oracle value calculated as ICurvePool.get_virtual_price()*min(p_i) corresponds to the right hand side in the inequality. Hence, Gearbox will always value Curve LP tokens conservatively as long as get_virtual_price() is not manipulated.

Last updated on December 25, 2022