# Mint Position (/docs/protocols/v4/guides/managing-liquidity/mint-position)

Mint a new Uniswap v4 liquidity position using PositionManager command encoding.

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](/docs/protocols/v4/guides/managing-liquidity/getting-started)

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

## 1. Import and define IPositionManager
```solidity
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

**If providing ETH liquidity, a third action is required:**

* sweep - to recover excess eth sent to the position manager

```solidity
import {Actions} from "v4-periphery/src/libraries/Actions.sol";

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

// For ETH liquidity positions
bytes memory actions = abi.encodePacked(uint8(Actions.MINT_POSITION), uint8(Actions.SETTLE_PAIR), uint8(Actions.SWEEP));
```

## 3. Encode parameters
```solidity
bytes[] memory params = new bytes[](2); // new bytes[](3) for ETH liquidity positions
```

The `MINT_POSITION` action requires the following parameters:

| Parameter    | Type      | Description                                                    |
| ------------ | --------- | -------------------------------------------------------------- |
| `poolKey`    | *PoolKey* | where the liquidity will be added to                           |
| `tickLower`  | *int24*   | the lower tick boundary of the position                        |
| `tickUpper`  | *int24*   | the upper tick boundary of the position                        |
| `liquidity`  | *uint256* | the amount of liquidity units to mint                          |
| `amount0Max` | *uint128* | the maximum amount of currency0 msg.sender is willing to pay   |
| `amount1Max` | *uint128* | the maximum amount of currency1 msg.sender is willing to pay   |
| `recipient`  | *address* | the address that will receive the liquidity position (ERC-721) |
| `hookData`   | *bytes*   | arbitrary data that will be forwarded to hook functions        |

```solidity
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

```solidity
params[1] = abi.encode(currency0, currency1);
```

The `SWEEP` action requires the following parameters:

* `currency` - *Currency*, token to sweep - most commonly native Ether: `CurrencyLibrary.ADDRESS_ZERO`
* `recipient` - *address*, where to send excess tokens

```solidity
params[2] = abi.encode(currency, recipient);
```

## 4. Submit call
The entrypoint for all liquidity operations is `modifyLiquidities()`

```solidity
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
