Stable pool
SyncSwap stable pool implements the Stableswap AMM curve. A significant amount of time of our review was dedicated to comparing SyncSwap against other Stableswap implementations used as reference. The code bears much similarity to Trident HybridPool
; we found SyncSwap to be an equivalent but generally more gas-efficient implementation.
Stableswap primer
The Stableswap AMM curve was initially introduced by Curve Finance and is designed for increasing capital efficiency in pools containing assets that are intended to maintain a stable price. This is achieved by reducing price slippage compared to other AMM models such as constant product, thus encouraging more and bigger swaps and collecting more fees overall.
The Stableswap invariant is as follows:
Where are the amount of assets in the pool, is the number of assets in the pool, and is a constant needed to balance both sides of the equation.
The curve behavior is a hybrid between the well-known constant product and the constant sum curves, which can be tuned via the parameter. For increasing values of , the behavior of Stableswap approaches that of the constant sum curve, whereas for , the equation is equivalent to the constant product curve.
SyncSwap implementation of Stableswap is optimized for a pool with two assets and a hardcoded , reducing the invariant to
For more information on Stableswap, refer to the original paper describing the curve at https://classic.curve.fi/files/stableswap-paper.pdf↗.
Note: To simplify the exposition, all amounts will be considered normalized to the same amount of decimal digits.
Swap
To perform a swap, users must send the amount to be used as input and call swap
(since this must be performed in a single transaction, it is normally delegated to the router contract).
The following calculations assume a swap from the first to the second asset of the pair that makes up the pool. The calculations in the reverse direction are specular and omitted.
In order to compute the amount of tokens obtained from the swap, the constant is first obtained from the curve equation via iterative approximation. The recurrence relation is defined as
Once has been determined, the net amount of input tokens is computed by subtracting the protocol fees from the input amount. The amount of output tokens is then computed by another iterative approximation process using the recurrence relation
Recurrence relation analysis
The above recurrence relations appear to implement a slight variant of Newton's root finding method. Both iterative computations are continued until they converge (e.g., ), and up to a maximum of 256 iterations.
During our review we observed that the recurrence relation used to calculate appears to be slightly different from the one that would be obtained by applying the textbook Newton's method. Given the invariant expressed as a function of ,
Newton's method would define as
which is slightly different from the recurrence relation used by the implementation that is equivalent to
Numerical experimentation showed that the two equations converge to the same value.
Further investigation also confirmed that the equation used by SyncSwap is equivalent to the implementation used by Trident and even to the original Curve Finance implementation of Stableswap. To the best of our knowledge, no official documentation exists regarding the derivation of the formulas used by the original Curve Finance implementation. Since all implementations exhibit the same behavior, we consider it the de facto standard and the desired behavior.
Mint
The liquidity used to perform swaps is provided by liquidity providers who deposit liquidity in exchange for LP tokens. Liquidity providers must send the liquidity they want to provide to the pool and call mint
. This is normally performed by the router contract.
The amount of LP tokens minted to the user is equal to
where computes the parameter by iterative approximation as described in the previous section.
The parameters represent swap fees charged to the user if the liquidity sent to the pool was imbalanced with respect to the current exchange rate, calculated with the same formula used by the swap process.
The parameter represents the total supply of LP tokens, including the newly minted LP tokens minted as protocol fees. Protocol fees can vary depending on the value returned by the pool master getProtocolFee()
function, which for the purposes of this exposition we will treat as a number between zero and one. If enabled, protocol fees cause the minting of additional LP tokens that are sent to an address responsible of collecting them. The amount to be minted is computed as
where is the value of the invariant saved from the previous execution, and . Note that protocol fees are minted only if
Burn
Opposite to minting, burning allows to get back liquidity in exchange for LP tokens. Users must send LP tokens to the pool before calling burn
(within the same transaction), normally by using the router contract.
The amount of assets returned to the user is calculated by
Unilateral burn
SyncSwap also allows to burn LP tokens in exchange for one of the two assets of a pool. This is equivalent to burning LP tokens for the pair and swapping the unwanted asset for the desired one.
The amounts of assets gained by burning LP tokens is computed identically to the regular burn functionality, and the conversion rate between the pair matches the amount that would be obtained by a regular swap operation.