AMM Swap

One can think of the AMM as a standard UniV3 range order, where sqrtPriceLowX96 and sqrtPriceHighX96 represent the upper and lower bounds of the range. These ranges are determined and actively managed by the liquidityProvider, to provide the best risk-adjusted returns to its users.

The parameters for an incoming AMM swap can look like the following Solidity example:

SovereignPoolSwapContextData memory data;
SovereignPoolSwapParams memory params = SovereignPoolSwapParams({
    isSwapCallback: false,
    isZeroToOne: true,
    amountIn: 1e18,
    amountOutMin: 0,
    recipient: address(this),
    deadline: block.timestamp + 2,
    swapTokenOut: address(token1),
    swapContext: data
});

Note: It is important to leave the swapContext field empty because the HOT differentiates between an HOT swap and an AMM swap by checking if the length of the swapContext.externalContext and the swapContext.swapFeeModuleContext is 0 or not.

Effective Liquidity

AMM swaps can only trade against the liquidity stored in the _effectiveAMMLiquidity variable. The remaining part of the reserves are considered passive ( more about this later ). So there might be cases where the reserves available to the the AMM are low, even though the total reserves deposited in the pool are high. This is intentional since _effectiveAMMLiquidity requires careful security checks before it can be updated, as described below.

Effective AMM Liquidity

HOT assumes that at any point of time reserves can be in any arbitrary composition. This is because incoming HOT swaps can trade at any price and amounts (restricted by some configurable bounds), hence creating a misalignment of reserve amounts that would otherwise be implied by a standard UniV3 range order. Consequently, the fundamental invariants of CPMMs do not hold for the reserves.

To make sure that the AMM works correctly no matter what the reserve composition looks like, we decouple the reserves into 2 categories:

  1. Active Reserves - These are balanced reserves that adhere to the xy=k invariant, and can be utilized by both the AMM and HOT swaps.

  2. Passive Reserves - Any unbalanced reserves that are not part of the active reserves are considered passive. Only HOT swaps can access the passive reserves.

Design Goals:

  1. Minimize the amount of passive reserves in the system, by rebalancing into active reserves at any opportunity we get.

  2. Make sure that the liquidity remains constant (_effectiveAMMLiquidity) before and after any AMM swap.

  3. Utilize the maximum possible amount of active reserves.

We achieve these design goals by calling the _updateAMMLiquidity internal function after any interaction that could potentially change the reserve composition, and if said interaction contains the appropriate number of invariant checks to mitigate the damage from AMM spot price manipulation.

More about the risks, and protections around _updateAMMLiquidity in a separate document.

Last updated