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,
salt: bytes32(0),
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 tickUppersalt: Add extra information to the position, for most use cases, set asbytes32(0)is sufficient.amount0Desired | 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.timestampis 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.timestampis 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.timestampis 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.timestampis 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.timestampis 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.exactOutputSingleInput:
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.timestampis 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.timestampis greater thandeadline
Output:
amountIn: amount of token in from the swap