UniswapV3 – Extracting Amounts for Non-Current Tick from Uniswap v3 Pool

polygonuniswapuniswapv3

I want to get the amounts of the tokens for a tick range which is higher or lower than the current tick.
For example I have current tick: -282986 with range [-282990, -282980], I want to get the amounts for the tick range [-282980, -282970] (next higher tick range), but I have no success.

I am using this formula:

if(sqrtPrice <= sqrtPriceLower){

    amount0 = (liquidity * ((sqrtPriceUpper - sqrtPriceLower) / (sqrtPriceLower * sqrtPriceUpper))) / Math.pow(10, 18);

}else if(sqrtPrice >= sqrtPriceUpper){

    amount1 = (liquidity * ( sqrtPriceUpper - sqrtPriceLower) ) / Math.pow(10, 6);

}else{

    amount0 = (liquidity * ((sqrtPriceUpper - sqrtPrice) / (sqrtPrice * sqrtPriceUpper))) / Math.pow(10, 18);
    amount1 = (liquidity * (sqrtPrice - sqrtPriceLower) ) / Math.pow(10, 6);

}

I have read somewhere that for this situations I need to take in calculation the liquidityNet, but I have no idea how to use it, if the information is right.

Someone can help me withe formula for ranges which are out of the current tick?

Best Answer

You can use the @uniswap/v3-core and @uniswap/v3-periphery libraries as shown in the following contract, the uniswap v3 libraries are all open source so feel free to dive into the solidity implementation code.

pragma solidity =0.7.6;

import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
import "@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol";

contract UniswapV3Liquidity {

    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
        sqrtPriceX96 = TickMath.getSqrtRatioAtTick(tick);
    }

    function getAmountsForLiquidity(
        uint160 sqrtRatioX96,
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount0, uint256 amount1) {
        (amount0, amount1) = LiquidityAmounts.getAmountsForLiquidity(
            sqrtRatioX96,
            sqrtRatioAX96,
            sqrtRatioBX96,
            liquidity            
        );
    }

    // This seems to be the function you're looking for
    function getAmountsPerUnitOfLiquidity(
        int24 currentTick,
        int24 lowerTick,
        int24 upperTick
    ) external pure returns (uint256 amount0, uint256 amount1) {
        uint160 currentSqrtPriceX96 = getSqrtRatioAtTick(currentTick);
        uint160 lowerSqrtPriceX96 = getSqrtRatioAtTick(lowerTick);
        uint160 upperSqrtPriceX96 = getSqrtRatioAtTick(upperTick);

        (amount0, amount1) = getAmountsForLiquidity(
            currentSqrtPriceX96,
            lowerSqrtPriceX96,
            upperSqrtPriceX96,
            1
        );
    }
}

Now to get the amount{0&1} per unit of liquidity minted given the current price corresponds exactly with the current tick(this is a close enough approximation in any case i.e. at most 0.01% off) you can call UniswapV3Liquidity.getAmountsPerUnitOfLiquidity(-282986, -282980, -282970) which yields the result:

{
  // since the [lowerTick, upperTick] range is above the currentTick, only token0 is required and not token1 
  "amount0": 697,
  "amount1": 0
}
Related Topic