Introduction

As part of our ongoing effort to optimize AMM design, we have developed a new version of Proteus, our AMM engine, which increases precision and gas efficiency (Github).

Please see our previous white papers (first paper, second paper) for a review of our prior work. Briefly, our objective is to create an “AMM engine” that can replicate any bonding curve. To that end, we developed a method that could use any polynomial equation as an invariant (provided the segment in question was positive and monotonically decreasing). In our first paper, we used generalized conic sections as a proof of concept. The drawback to conic sections is that they are difficult to parameterize due to the nonlinear relationship between their algebraic coefficients and their geometry. Therefore, in our second paper, we used a piece-wise function of modified constant product curves. This strategy gave us both flexible geometry and could be easily parameterized. This third paper describes an implementation that is mathematically equivalent to the second iteration, but is more precise and gas efficient (approximately 90k-110k gas for a swap).

This approach allows for extremely precise liquidity concentration across multiple price ranges and fungible LP tokens. The first application will be stablecoin liquidity pools. We will branch out to other use cases over time.

Design Constraints

Our motivation is to create an algorithm that bonding curve that can replicate any bonding curve. This allows for both ****liquidity concentration and fungible LP tokens. This algorithm must meet the following design constraints in order to be viable:

  1. Curves are monotonically decreasing and continuous at all points
  2. Curves are simple to calculate mathematically on-chain, thus eliminating polynomials higher than degree 2.
  3. Prices are gas-efficient to compute in solidity
  4. Equation is precise
  5. The generator is able to replicate most shapes
  6. The generator is intuitive and flexible to use: i.e. users can either provide a shape they desire or simply provide the liquidity distribution they desire.

Prior Work

The proteus curve is a composite function; that is, a curve made up of smaller functions scaled up and ‘stitched’ together in a stepwise fashion. The curve sections we use are all of hyperbolic form: $(x+a)(y+b)=1$ as seen below. The curves are constrained such that the boundaries between curve sections each represent a single price so that there are no discontinuities in the curve and its first derivative. When each segment is scaled appropriately, this stepwise function of curve segments generates a composite function as shown below:

Figure 1: A composite bonding curve created from discrete curve segments

Figure 1: A composite bonding curve created from discrete curve segments

Further Innovation

After implementing this stepwise function in Solidity and deploying it to Ethereum test nets, we concluded the following about this composite curve:

  1. The composite curve represents the bonding curve at a single pool utility $u$.
  2. In order to scale all curve segments appropriately, the individual scale factors $\lambda _i$ varied.
  3. Therefore, we introduced a new variable Kappa, $\kappa _i$, such that $\lambda _i = u\kappa_i$.
  4. In qualitative terms, kappa ($\kappa$) is an individual scale modifier that influences the degree that a curve segment scales at a given utility with respect to other curve segments. For instance, in the diagram below, the purple curve segment scales by a factor of 4x at the given utility. The orange segment, however, has only scaled by a factor of 2x at that same utility. Therefore, the Kappa values for the purple and orange segments are valued at 4 and 2 respectively.

Figure 2: A section’s kappa value influences the degree to which its curve segment scale in the composite curve

Figure 2: A section’s kappa value influences the degree to which its curve segment scale in the composite curve

To generate the composite function, the utility and kappa are represented in each segment i of the stepwise function with n segments, numbered from 1..n starting with the bottom-most segment (the segment adjacent to the x-axis), and increasing counter-clockwise. as follows:

$$ \Big(\dfrac {x}{u\kappa _i} + a_i\Big)\Big(\dfrac {y}{u\kappa _i} + b_i\Big) = 1 $$

Deriving segment parameters

There are three arrays (vectors) that determine the shape of the curve: