Add/Remove Liquidity

Introduction

Liquidity management is performed through LBRouter contract. This contract will abstract some of the complexity of the liquidity management, perform safety checks and will revert if certain conditions were to not be met.

  • Liquidity is added or removed to LBPairs.

  • Liquidity may be distributed to specific Bins, with different amounts per Bin.

:::note

  • The v2.2 LBRouter is not backwards compatible with v2.1 LBPairs, although ABI stays the same

  • The v2.1 LBRouter is not backwards compatible with v2.0 LBPairs.

  • The v2.0 LBRouter must be used to remove liquidity from v2.0 LBPairs and v2.1 LBRouter must be used to remove liquidity from v2.1 LBPairs :::

Adding Liquidity

To add liquidity, the LiquidityParameters struct is as input:

function addLiquidity(LiquidityParameters memory liquidityParameters)
    external
    returns (
        uint256 amountXAdded,
        uint256 amountYAdded,
        uint256 amountXLeft,
        uint256 amountYLeft,
        uint256[] memory depositIds,
        uint256[] memory liquidityMinted
    );

function addLiquidityNATIVE(LiquidityParameters memory liquidityParameters)
    external
    payable
    returns (
        uint256 amountXAdded,
        uint256 amountYAdded,
        uint256 amountXLeft,
        uint256 amountYLeft,
        uint256[] memory depositIds,
        uint256[] memory liquidityMinted
    );

Liquidity Parameters

The number of parameters are quite extensive. Here are a few pointers to understand how to construct them better:

  • The active bin ID may change from the time you decided to add liquidity to when it is actually added. Therefore, you define activeIdDesired and idSlippage to account for when the price moves.

  • deltaIds define which bins liquidity will be added to relative to activeId, 0 being the active bin. All positive values are bins with only X and all negative values are bins with only Y.

  • distributionX (or distributionY) is the percentages of amountX (or amountY) you want to add to each bin.

    • Sum of all values should be less than or equal to 1. If less than, the remaining is refunded back to the user.

    • Trying to add X to a bin below the active bin or Y to a bin above the active bin will cause a revert.

  • Maximum number of bins, that can be populated at the same time is around 80 on Sei C-chain due to block gas limit (8M). Multiple transactions can be used to add liquidity to more bins.

Code Example

In this example, we add 100 USDC and 100 USDT into three bins: active bin, bin below and bin above.

We define the distributions as follow:

  • For asset X (USDC), we add 50 USDC to the active bin and 50 USDC to the bin above.

  • For asset Y (USDT), we add 33.3 USDT to the active bin and 66.6 USDT to the bin below.

We also allow a bin ID slippage of 5 just in case bin moves in the time it takes to execute the transaction.

Removing Liquidity

There are some key differences between adding and removing liquidity:

  1. We don't use the LiquidityParameters struct.

  2. We use absolute bin IDs instead of relative bin IDs.

  3. Because we use absolute bin IDs, bin slippage is not possible.

  4. We define absolute LBToken balances to remove from each bin.

    • In bins below active bin, balances consist of only Y.

    • In bins above active bin, balances consist of only X.

    • In the active bin, the balance consists of a share of X and Y.

To remove liquidity, we use one of the router functions below:

Here are some pointer for using these functions:

  1. Lengths of ids and amounts must be the same.

  2. Values in amounts are LBToken amounts.

  3. Maximum number of bins that can be withdrawn at the same time is around 51 due to SEI C-chain block gas limit (8M). In this case, multiple transactions can be used to remove more liquidity.

:::note For tax tokens, removing liquidity with removeLiquidityNATIVE() is not possible, due to double tax accrual. This can be circumvented in two ways, depending on tax token implementation:

  1. Whitelisting LBRouter and/or LBPair.

  2. Removing native liquidity with removeLiquidity() function. This will return wrapped native token to user, instead of just native token. :::

Code Example

Last updated