2/5
## Code Walkthrough: Collect Function To collect fees or to remove tokens after decreasing liquidity, we'll need to call the function `collect`. This function takes a single input, a struct called `CollectParams`. This struct is defined inside the interface `INonfungiblePositionManager`. The inputs are as follows: * `tokenID` - The ID of the NFT. * `recipient` - The address that will be receiving the tokens. * `amount0Max` and `amount1Max` - The maximum amount of tokens to transfer. The function first checks that the input `amount0Max` is greater than 0 or that `amount1Max` is greater than 0. ```javascript require(params.amount0Max > 0 || params.amount1Max > 0); ``` Then, it sets the address for the recipient. If the recipient is not set, then the recipient will be set to this contract. ```javascript address recipient = params.recipient == address(0) ? address(this) : params.recipient; ``` Otherwise, it will use the recipient specified by the input. Next, we'll get the position that is stored inside of the contract. ```javascript Position storage position = _positions[params.tokenId]; ``` Then the `poolKey` is retrieved and finally, the `uniswapV3Pool` contract. ```javascript PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId]; IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey)); ``` The variables `tokensOwed0` and `tokensOwed1` are cached. ```javascript uint128 tokensOwed0; uint128 tokensOwed1; ``` These values are stored in `position.tokensOwed0` and `position.tokensOwed1`. If this position has any liquidity, then it calls the function `burn` on the `uniswapV3Pool` contract. This is done to update the `feeGrowthInside0LastX128` and `feeGrowthInside1LastX128` that is stored inside the pool contract. ```javascript if (position.liquidity > 0) { pool.burn(position.tickLower, position.tickUpper, 0); (, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, ) = pool.positions(PositionKey.compute(address(this), position.tickLower, position.tickUpper)); } ``` Then, it calculates the amount of the fees that were collected for this position, and adds them to the variables `tokensOwed0` and `tokensOwed1`. ```javascript tokensOwed0 += uint128( FullMath.mulDiv( feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128, position.liquidity, FixedPoint128.Q128 ) ); tokensOwed1 += uint128( FullMath.mulDiv( feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128, position.liquidity, FixedPoint128.Q128 ) ); position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128; position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128; ``` Since the fees that can be claimed are now up to date, the code will update `feeGrowthInside0LastX128` and `feeGrowthInside1LastX128` to their latest values. Next it will calculate the amount of tokens that can be transferred out. If the amount that was specified by the input is greater than the actual amount of tokens that are owed, then the amount of tokens to transfer is the amount of tokens that is owed. Otherwise, the amount that was specified by the input will be transferred over. In other words, the amount to be transferred is the minimum of the input `amount0Max` and the amount of tokens that are owed. This is done for both `token0` and `token1`. To actually transfer the tokens, it will call the function `collect` on the contract `uniswapV3Pool`. ```javascript (amount0, amount1) = pool.collect( recipient, position.tickLower, position.tickUpper, amount0Collect, amount1Collect ); ``` After the tokens are transferred, we update the position that is stored in the contract. The tokens that are owed are stored in the variables `tokensOwed0` and `tokensOwed1`. When the function collect was called, `amount0Collect` and `amount1Collect` was transferred out. The current amount of tokens that are owed are the difference between `tokensOwed0` - `amount0Collect` and `tokensOwed1` - `amount1Collect`. ```javascript position.tokensOwed0 = (tokensOwed0 - amount0Collect); position.tokensOwed1 = (tokensOwed1 - amount1Collect); ``` The new values are stored inside `position.tokensOwed0` and `position.tokensOwed1`. And that ends the code walkthrough for the function `collect`.
To collect fees or to remove tokens after decreasing liquidity, we'll need to call the function collect
. This function takes a single input, a struct called CollectParams
. This struct is defined inside the interface INonfungiblePositionManager
. The inputs are as follows:
tokenID
- The ID of the NFT.
recipient
- The address that will be receiving the tokens.
amount0Max
and amount1Max
- The maximum amount of tokens to transfer.
The function first checks that the input amount0Max
is greater than 0 or that amount1Max
is greater than 0.
Then, it sets the address for the recipient. If the recipient is not set, then the recipient will be set to this contract.
Otherwise, it will use the recipient specified by the input. Next, we'll get the position that is stored inside of the contract.
Then the poolKey
is retrieved and finally, the uniswapV3Pool
contract.
The variables tokensOwed0
and tokensOwed1
are cached.
These values are stored in position.tokensOwed0
and position.tokensOwed1
. If this position has any liquidity, then it calls the function burn
on the uniswapV3Pool
contract. This is done to update the feeGrowthInside0LastX128
and feeGrowthInside1LastX128
that is stored inside the pool contract.
Then, it calculates the amount of the fees that were collected for this position, and adds them to the variables tokensOwed0
and tokensOwed1
.
Since the fees that can be claimed are now up to date, the code will update feeGrowthInside0LastX128
and feeGrowthInside1LastX128
to their latest values. Next it will calculate the amount of tokens that can be transferred out.
If the amount that was specified by the input is greater than the actual amount of tokens that are owed, then the amount of tokens to transfer is the amount of tokens that is owed. Otherwise, the amount that was specified by the input will be transferred over.
In other words, the amount to be transferred is the minimum of the input amount0Max
and the amount of tokens that are owed. This is done for both token0
and token1
.
To actually transfer the tokens, it will call the function collect
on the contract uniswapV3Pool
.
After the tokens are transferred, we update the position that is stored in the contract. The tokens that are owed are stored in the variables tokensOwed0
and tokensOwed1
. When the function collect was called, amount0Collect
and amount1Collect
was transferred out. The current amount of tokens that are owed are the difference between tokensOwed0
- amount0Collect
and tokensOwed1
- amount1Collect
.
The new values are stored inside position.tokensOwed0
and position.tokensOwed1
. And that ends the code walkthrough for the function collect
.
A detailed walkthrough of the Solidity `collect` function for Non-Fungible Position Manager. The function collects fees owed to a specific position, updates the position's fee growth, and transfers the fees to the specified recipient. It is designed to handle the collection of fees that are owed to a specific position in a liquidity pool.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Concentrated liquidity and derive its equations
Uniswap V3 math
How to calculate the spot price of tokens
Single and multi position swapping
Factory contract architecture
How to calculate liquidity requirements
Uniswap V3 fee algorithm
Flash loans
TWAP price oracle
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Blockchain Financial Analyst
$100,000 - $150,000 (avg. salary)
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Last updated on June 12, 2025
Duration: 3min
Duration: 35min
Duration: 25min
Duration: 22min
Duration: 1h 43min
Duration: 11min
Duration: 1h 03min
Duration: 12min
Duration: 51min
Duration: 41min
Duration: 10min
Duration: 7min
Course Overview
About the course
Concentrated liquidity and derive its equations
Uniswap V3 math
How to calculate the spot price of tokens
Single and multi position swapping
Factory contract architecture
How to calculate liquidity requirements
Uniswap V3 fee algorithm
Flash loans
TWAP price oracle
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Blockchain Financial Analyst
$100,000 - $150,000 (avg. salary)
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Last updated on June 12, 2025