Skip to main content
Helpful?

Adding & Removing Liquidity

Introduction

This guide will cover how to modify a liquidity position by adding or removing liquidity on the Uniswap V3 protocol. It is based on the modifying a position code example, found in the Uniswap code examples repository. To run this example, check out the examples's README and follow the setup instructions.

info

If you need a briefer on the SDK and to learn more about how these guides connect to the examples repository, please visit our background page!

In the Uniswap V3 protocol, liquidity positions are represented using non-fungible tokens. In this guide we will use the NonfungiblePositionManager class to help us mint a liquidity position and then modify the provided liquidity for the USDC - DAI pair. The inputs to our guide are the two tokens that we are pooling for, the amount of each token we are pooling for, the Pool fee and the fraction by which to add and remove from our position.

The guide will cover:

  1. Adding liquidity to our position
  2. Removing liquidity from our position

At the end of the guide, given the inputs above, we should be able to add or remove liquidity from a minted position with the press of a button and see the change reflected in our position and the balance of our tokens.

For this guide, the following Uniswap packages are used:

The core code of this guide can be found in addLiquidity() and removeLiquidity()

note

This guide assumes you are familiar with our Minting a Position guide. A minted position is required to add or remove liquidity from, so the buttons will be disabled until a position is minted.

Also note that we do not need to give approval to the NonfungiblePositionManager to transfer our tokens as we will have already done that when minting our position.

Adding liquidity to our position

Assuming we have already minted a position, our first step is to construct the modified position using our original position to calculate the amount by which we want to increase our current position:

Creating the Position
loading...

The function receives two arguments, which are the CurrencyAmounts that are used to construct the Position instance. In this example, both of the arguments follow the same logic: we multiply the parameterized tokenAmount by the parameterized fractionToAdd since the new liquidity position will be added on top of the already minted liquidity position.

We then need to construct an options object of type AddLiquidityOptions similar to how we did in the minting case. In this case, we will use IncreaseOptions:

Constructing the options object
loading...

Compared to minting, we have we have omitted the recipient parameter and instead passed in the tokenId of the position we previously minted.

The newly created position along with the options object are then passed to the NonfungiblePositionManager's addCallParameters:

Passing the position and options object to addCallParameters
loading...

The return values of addCallParameters are the calldata and value of the transaction we need to submit to increase our position's liquidity. We can now build and execute the transaction:

Building and submitting the transaction
loading...

After pressing the button, note how the balance of USDC and DAI drops and our position's liquidity increases.

Removing liquidity from our position

The removeLiquidity function is the mirror action of adding liquidity and will be somewhat similar as a result, requiring a position to already be minted.

To start, we create a position identical to the one we minted:

Creating an identical position as minting
loading...

We then need to construct an options object of type RemoveLiquidityOptions:

Constructing the options object
loading...

Just as with adding liquidity, we have we have omitted the recipient parameter and instead passed in the tokenId of the position we previously minted.

We have also provide two additional parameters:

  • liquidityPercentage determines how much liquidity is removed from our initial position (as a Percentage), and transfers the removed liquidity back to our address. We set this percentage from our guide configuration ranging from 0 (0%) to 1 (100%).
  • collectOptions gives us the option to collect the fees, if any, that we have accrued for this position. In this example, we won't collect any fees, so we provide zero values. If you'd like to see how to collect fees without modifying your position, check out our collecting fees guide!
Constructing the collect options object
loading...

The position object along with the options object is passed to the NonfungiblePositionManager's removeCallParameters, similar to how we did in the adding liquidity case:

Getting the calldata and value for the transaction
loading...

The return values removeCallParameters are the calldata and value that are needed to construct the transaction to remove liquidity from our position. We can build the transaction and send it for execution:

Building and submitting the transaction
loading...

After pressing the button, note how the balance of USDC and DAI increases and our position's liquidity drops.

Next Steps

Now that you can mint and modify a position, check out how to collect fees from the position!

Helpful?