Skip to main content
Helpful?

Mint Position

Similar to Uniswap v3, liquidity positions are minted as ERC-721 tokens and depend on a periphery contract. v4's PositionManager contract will facilitate liquidity management

Context

Please note that PositionManager is a command-based contract, where integrators will be encoding commands and their corresponding parameters.

Setup

See the setup guide

Guide

Below is a step-by-step guide for minting a v4 liquidity position, in solidity

1. Import and define IPositionManager

import {IPositionManager} from "v4-periphery/src/interfaces/IPositionManager.sol";

// inside a contract, test, or foundry script:
IPositionManager posm = IPositionManager(<address>);

2. Encode Actions

To mint a position, two actions are required:

  • mint operation - the creation of the liquidity position
  • settle pair - the two tokens to be paid by msg.sender
import {Actions} from "v4-periphery/src/libraries/Actions.sol";

bytes memory actions = abi.encodePacked(Actions.MINT_POSITION, Actions.SETTLE_PAIR);

3. Encode Parameters

bytes[] memory params = new bytes[](2);

The MINT_POSITION action requires the following parameters:

ParameterTypeDescription
poolKeyPoolKeywhere the liquidity will be added to
tickLowerint24the lower tick boundary of the position
tickUpperint24the upper tick boundary of the position
liquidityuint256the amount of liquidity units to mint
amount0Maxuint128the maximum amount of currency0 msg.sender is willing to pay
amount1Maxuint128the maximum amount of currency1 msg.sender is willing to pay
recipientaddressthe address that will receive the liquidity position (ERC-721)
hookDatabytesarbitrary data that will be forwarded to hook functions
Currency currency0 = Currency.wrap(<tokenAddress1>); // tokenAddress1 = 0 for native ETH
Currency currency1 = Currency.wrap(<tokenAddress2>);
PoolKey poolKey = PoolKey(currency0, currency1, 3000, 60, IHooks(hook));

params[0] = abi.encode(poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, recipient, hookData);

The SETTLE_PAIR action requires the following parameters:

  • currency0 - Currency, one of the tokens to be paid by msg.sender
  • currency1 - Currency, the other token to be paid by msg.sender
params[1] = abi.encode(currency0, currency1);

4. Submit Call

The entrypoint for all liquidity operations is modifyLiquidities()

uint256 deadline = block.timestamp + 60;

uint256 valueToPass = currency0.isAddressZero() ? amount0Max : 0;

posm.modifyLiquidities{value: valueToPass}(
abi.encode(actions, params),
deadline
);

Additional notes:

  • To obtain balance changes, callers should read token balances before and after the .modifyLiquidities() call
Helpful?