Liquidity and swap for concentrated liquidity pool
In this guide, We'll make use of periphery contracts from v4-periphery
- Liquidity operations with
NonFungiblePositionManager
- Swaps via
CLSwapRouter
Liquidity operations
Mint
Create a new position wrapped in a NFT. If you have minted previously, consider increaseLiquidity()
to add liquidity to the same NFT tokenId.
INonfungiblePositionManager.MintParams memory params = INonfungiblePositionManager.MintParams({
poolKey: key,
tickLower: tickLower,
tickUpper: tickUpper,
amount0Desired: amount0,
amount1Desired: amount1,
amount0Min: 0,
amount1Min: 0,
recipient: address(this),
deadline: block.timestamp
});
(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)
= nfp.mint(params);
Input:
poolKey
: struct which identify the pooltickLower | tickUpper
: add liquidity from tickLower to tickUpperamount0Desired | amount1Desired
: intended amt0 and amt1amount0Min | amount1Min
: minimum amt0 and amt1. transaction will revert if the amount is less than that. In the real-world, set a realistic amount instead of0
.recipient
: who to receive the NFT which represent ownership of this positiondeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
tokenId
: NFT tokenId mintedliquidity
: total liquidity mintedamount0
: amount for token0 taken for mintingamount1
: amount for token1 taken for minting
Decrease liquidity
Decreases the amount of liquidity in a position and accounts it to the position
INonfungiblePositionManager.DecreaseLiquidityParams memory params = INonfungiblePositionManager
.DecreaseLiquidityParams({
tokenId: tokenId,
liquidity: liquidity,
amount0Min: 0,
amount1Min: 0,
deadline: type(uint256).max
});
(uint256 amount0, uint256 amount1) = nfp.decreaseLiquidity(params);
Input:
tokenId
: the NFT tokenId, received when called .mint() earlierliquidity
: amount of liquidity to removeamount0Min | amount1Min
: minimum amt0 and amt1, transaction will revert if the amount is less than thatdeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
amount0
: amount for token0 received for decreasing liquidityamount1
: amount for token1 received for decreasing liquidity
Increase liquidity
Increases the amount of liquidity in a position, with tokens paid by the msg.sender
INonfungiblePositionManager.IncreaseLiquidityParams memory params = INonfungiblePositionManager
.IncreaseLiquidityParams({
tokenId: tokenId,
amount0Desired: amount0,
amount1Desired: amount1,
amount0Min: 0,
amount1Min: 0,
deadline: block.timestamp
});
(uint128 liquidity, uint256 amount0, uint256 amount1) = nfp.increaseLiquidity(params);
Input:
tokenId
: the NFT tokenId, received when called .mint() earlieramount0Desired | amount1Desired
: intended amt0 and amt1amount0Min | amount1Min
: minimum amt0 and amt1, transaction will revert if the amount is less than thatdeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
liquidity
: amount of liquidity addedamount0
: amount for token0 taken for increasing liquidityamount1
: amount for token1 taken for increasing liquidity
Burn
Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens
nfp.burn(uint256 tokenId);
Swaps
Exact Input Single
Swaps amountIn
of one token for as much as possible of another token
ICLSwapRouterBase.V4CLExactInputSingleParams memory params = ICLSwapRouterBase
.V4CLExactInputSingleParams({
poolKey: key1,
zeroForOne: true,
recipient: address(this),
amountIn: 1 ether,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0,
hookData: new bytes(0)
});
uint256 amtOut = router.exactInputSingle(params, block.timestamp);
Input:
poolKey
: struct which identify the poolzeroForOne
: if true swap token0 for token1, else swap token1 for token0recipient
: address to receive the output tokenamountIn
: desired amount inamountOutMinimum
: min amount out. transaction revert if amount out is lessersqrtPriceLimitX96
: limit for the price the swap will push the pool to. this help to reduce slippage.hookData
: if set, will be passed to hooks in both beforeSwap and afterSwapdeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
amountOut
: amount of token out from the swap
Exact Input
Swaps amountIn
of one token for as much as possible of another along the specified path
bytes32 params;
ISwapRouterBase.PathKey[] memory path = new ISwapRouterBase.PathKey[](2);
path[0] = ISwapRouterBase.PathKey({
intermediateCurrency: currency1,
fee: uint24(3000),
hooks: IHooks(address(0)),
hookData: new bytes(0),
poolManager: poolManager,
parameters: params.setTickSpacing(10)
});
path[1] = ISwapRouterBase.PathKey({
intermediateCurrency: currency2,
fee: uint24(3000),
hooks: IHooks(address(0)),
hookData: new bytes(0),
poolManager: poolManager,
parameters: params.setTickSpacing(10)
});
ICLSwapRouterBase.V4CLExactInputParams memory input = ICLSwapRouterBase
.V4CLExactInputParams({
currencyIn: currency0,
path: path,
recipient: address(this),
amountIn: 1 ether,
amountOutMinimum: 0
});
uint256 amountOut = router.exactInput(input, block.timestamp);
Input:
currencyIn
: input tokenpath
: Array ofPathKey[]
which describe the pool to hoprecipient
: address to receive the output tokenamountIn
: desired amount inamountOutMinimum
: min amount out. transaction revert if amount out is lesserdeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
amountOut
: amount of token out from the swap
Exact Output Single
Swaps as little as possible of one token for amountOut
of another token
ICLSwapRouterBase.V4CLExactOutputSingleParams memory input = ICLSwapRouterBase
.V4CLExactOutputSingleParams({
poolKey: key1,
zeroForOne: false,
recipient: address(this),
amountOut: 1 ether,
amountInMaximum: 1.1 ether,
sqrtPriceLimitX96: 0,
hookData: new bytes(0)
});
uint256 amountIn = router.exactOutputSingle
Input:
poolKey
: struct which identify the poolzeroForOne
: if true swap token0 for token1, else swap token1 for token0recipient
: address to receive the output tokenamountOut
: desired amount outamountInMaximum
: max amount in. transaction revert if amount out is lessersqrtPriceLimitX96
: limit for the price the swap will push the pool to. this help to reduce slippage.hookData
: if set, will be passed to hooks in both beforeSwap and afterSwapdeadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
amountIn
: amount of token in from the swap
Exact Output
Swaps as little as possible of one token for amountOut
of another along the specified path (reversed)
bytes32 params;
ISwapRouterBase.PathKey[] memory path = new ISwapRouterBase.PathKey[](2);
path[0] = ISwapRouterBase.PathKey({
intermediateCurrency: currency0,
fee: uint24(3000),
hooks: IHooks(address(0)),
hookData: new bytes(0),
poolManager: poolManager,
parameters: params.setTickSpacing(10)
});
path[1] = ISwapRouterBase.PathKey({
intermediateCurrency: currency1,
fee: uint24(3000),
hooks: IHooks(address(0)),
hookData: new bytes(0),
poolManager: poolManager,
parameters: params.setTickSpacing(10)
});
ICLSwapRouterBase.V4CLExactOutputParams memory input = ICLSwapRouterBase
.V4CLExactOutputParams({
currencyOut: currency2,
path: path,
recipient: address(this),
amountOut: 1 ether,
amountInMaximum: 1.1 ether
});
uint256 amountIn = router.exactOutput(input, block.timestamp);
Input:
currencyOut
: output tokenpath
: Array ofPathKey[]
which describe the pool to hoprecipient
: address to receive the output tokenamountOut
: desired amount outamountInMaximum
: max amount out. transaction revert if amountIn required is more.deadline
: deadline of this transaction. transaction will revert ifblock.timestamp
is greater thandeadline
Output:
amountIn
: amount of token in from the swap