Providing Liquidity To Classic Pools

Add/Remove Liquidity From Classic Pools

Pool creation

In some cases, your contract may be instantiating a new pool for a token pair. This can be done by calling the router's createPool function.

Example

Create a new DAI-USDC pool with amplification factor of 50. Refer to this section to understand more about the amplification factor.

poolAddress = dmmFactory.createPool(dai, usdc, 50000);

Kindly note the following:

  • The token addresses are interchangeable, ie. dmm.createPool(usdc, dai, 50000) yields the same result.

  • There can be at most 1 unamplified pool for a token pair, ie. only 1 pool can exist with ampBps = BPS (10000). Should there already be an existing unamplified pool, attempts to create another one will fail.

Adding liquidity

To safely add liquidity to a pool, we recommend using the router. There are different functions for adding liquidity to existing pools or creating a new pool, and if the token pair is ERC20-ERC20, or ETH-ERC20.

These methods both require committment to a belief about the current price, which is encoded in the amount*Desired parameters. While it is fairly safe to assume that the current fair market price is around what the current reserve ratio is for a pair due to arbitrage, it is dangerous to obtain this ratio within the same transaction as it can be easily manipulated.

In addition, the amount*Min and vReserveRatioBounds parameters should be utilised as a sanity buffer as the market price may shift drastically before the transaction is confirmed.

Determining the appropriate pool

See this section on pool selection.

Examples

  1. Create a new ERC20-ERC20 pool with amplification factor 100

  2. Add liquidity to an existing ERC20-ERC20 with FoT pool

Creation and liquidity provision to ERC20-ETH pools are similar, with the only difference being the functions to be called.

New ERC20-ERC20 pool via addLiquidityNewPool

For new ERC20-ETH pool creations, the equivalent function is addLiquidityNewPoolETH.

Example: Create a new pool with 100 USDC and 100 USDT

// Note: assume that usdc and usdt token approvals have been given to router
// and that transferFrom has been called to transfer tokens to contract from user
dmmRouter.addLiquidityNewPool(
    usdc,
    usdt,
    1000000, // amplification factor of 100
    100 * 1e6, // 100 usdc
    100 * 1e6, // 100 usdt
    100 * 1e6, // no slippage tolerance because it is a new pool
    100 * 1e6 // no slippage tolerance because it is a new pool
);

Add to existing ERC20-ERC20 (FoT) pool via addLiquidity

Although CORE is a Fee-on-Transfer (FoT) token, it utilises the same function as adding liquidity to an existing ERC20-ERC20 pool. However, it is likely that the slippage tolerance will have to be adjusted to account for the token fee.

For adding liquidity to existing ERC20-ETH pools, the the equivalent function is addLiquidityETH.

Example: Add 1 CORE and 1000 USDT

// Note: assume that core and usdt token approvals have been given to router
// and that transferFrom has been called to transfer tokens to contract from user

// the vReserveRatioBounds below is set to the absolute minimum and maximum values as an example
// it is recommended to read the virtual reserve ratio and set the appropriate values from that
vReserveRatioBounds = new uint256[2];
(vReserveRatioBounds[0], vReserveRatioBounds[1]) = (0, -1);
dmmRouter.addLiquidity(
    core,
    usdt,
    core-usdt-pool, // core-usdt pool address
    1 * 1e18, // 1 core
    1000 * 1e6, // 1000 usdt
    97 * 1e16, // 3% slippage tolerance (0.97 core / 1000 usdt)
    970 * 1e6, // 3% slippage tolerance (1 core / 970 usdt)
    vReserveRatioBounds
);

Removing liquidity

As is the case with Uniswap LP tokens, DMM-LP tokens implement meta-approvals to vastly help improve UX and save on gas costs. Hence, we recommend the usage of the removeLiquidity*withPermit* functions.

Removing LP tokens from ERC20-ERC20 pool

Removing 100 wbtc-usdt LP tokens via removeLiquidityWithPermit

Note: For FoT tokens like CORE, the same function can be used, but the minimum receivable of core tokens should be adjusted.

dmmRouter.removeLiquidityWithPermit(
    wbtc,
    usdt,
    wbtc-usdt-pool, // wbtc-usdt pool address
    100 * 1e8, // 100 wbtc-usdt LP tokens
    1 * 1e8, // Min receivable of 1 wbtc
    100 * 1e6, // Min receivable of 100 usdt
    msg.sender, // send assets to msg.sender
    block.timestamp, // deadline
    approveMax, // boolean flag if max token allowance approval
    v, // approve permit signature field
    r, // approve permit signature field
    s // approve permit signature field
);

Removing LP tokens from ERC20-ETH pool

Removing 100 core-eth LP tokens via removeLiquidityETHWithPermitSupportingFeeOnTransferTokens

dmmRouter.removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
    core,
    core-eth-pool, // core-eth pool address
    100 * 1e8, // 100 core-eth LP tokens
    1 * 1e18, // Min receivable of 1 core
    10 * 1e17, // Min receivable of 0.1 ether
    msg.sender, // send assets to msg.sender
    block.timestamp, // deadline
    approveMax, // boolean flag if max token allowance approval
    v, // approve permit signature field
    r, // approve permit signature field
    s // approve permit signature field
);

Last updated