Uniswap UniswapV3 – Understanding Token Usage Discrepancies When Minting a New Position

uniswapuniswapv3

i am using this code to create and initialize a pool and mint a new position on it.

// 1 ETH (y) = 2000 USDC (x)
pool = IUniswapV3Pool(factory.createPool(address(weth), address(usdc), 500));
pool.initialize(1771595571142957166518320255467520); // current tick : 200311

// mint a new position
INonfungiblePositionManager.MintParams memory params = 
            INonfungiblePositionManager.MintParams(
                address(usdc),
                address(weth),
                500,
                200310,
                200320,
                2000 * 10 ** 6, // Desired amount of token0
                1 * 10 ** 18, // Desired amount of token1
                1900 * 10 ** 6, // Minimum amount of token1
                0.1 * 10 ** 18, // Minimum amount of token0
                recepient,
                block.timestamp + 33600 // Deadline 1 hour from now
            );

in the above code i have initialized a pool between usdc and weth for 500 bip fee (remember usdc has 6 decimals and weth has 18) i then initialize with a sqrtpricex96 that is based upon the price exchange 1 eth = 2000 usdc.

when i use this code to calculate price from sqrtpricex96 i get the correct price

def sqrtp_to_price(p):
  return (p/q96) ** 2

p = sqrtp_to_price(1771595571142957166518320255467520)
q = p * 1e6/1e18
print(q) // 0.0005

when minting a new position, i pass exactly that amount the 2000 usdc which gets used up fully but only o.1 of my 1 weth get used up, why? Is thehre a way to calculate the amounts that are going to get used up before hand as to avoid trial and error in slippage tolerance.

Best Answer

Uniswap V3 positions consist of ticks with equal amount of liquidity in each tick. So if the current tick is 200312 and your are placing position between 200310 and 200320, the position will end up having roughly 80% of one token and 20% of the other token. NFT manager will try to maximize amounts of tokens getting in, but it's normal to have one of the two tokens left over.

To calculate how many tokens a position would take you could use something like this:

(uint256 amt0, uint256 amt1) = _amountsForLiquidity(
    sqrtRatioX96, // take it from slot0
    tickLow, // 200310
    tickHigh, // 200320
    10**18 // just some number here
);

// after you get amt0 and amt1 you could see the proportions between 
// these two tokens in a position with 10**18 liquidity that could 
// theoretically go in. Use this proportion to calculate real amounts 
// based on the funds you have at hand. 

function _amountsForLiquidity(
    uint160 sqrtRatioX96,
    int24 tickLower,
    int24 tickUpper,
    uint128 liquidity
) internal pure returns (uint256 amount0, uint256 amount1) {
    // LiquidityAmounts is a lib from Uniswap V3 periphery
    (amount0, amount1) = LiquidityAmounts.getAmountsForLiquidity(
        sqrtRatioX96,
        TickMath.getSqrtRatioAtTick(tickLower),
        TickMath.getSqrtRatioAtTick(tickUpper),
        liquidity
    );
}
Related Topic