简体   繁体   中英

UniswapV3 position minting algorithm can't get correct pool address based on params I've passed in

Uniswap V3 PoolAddress.computeAddress computes different address comparing to the one I get from UniswapV3poolFactory.getPool . And in my code it is ok, I can get pool address from this mapping, but uniswap contracts uses PoolAddress library in order to get pool address.

When I try to mint new position using mint function from NonfungiblePositionManager.sol this function calls addLiquidity from LiquidityManagement.sol and this function has call to the PoolAddress.sol library method computeAddress . And there it throws because after computing pool address it tries to call methods from pool but it can't cause address is wrong.

I've tried to change the order of the tokens that I pass to the mint function but the order is correct, I've also logged all of the data that is related to pool address computation in uniswap contracts using hardhat local chain and it is the same to the one I used for getPool mapping. The only thing that still can cause wrong computations on my opinion is the POOL_INIT_CODE_HASH constant in PoolAddress library, but I haven't changed that. All mentioned methods I'll post below the text along with links to uniswap repos. Compiler version that I've used for all unsiwap contracts is 0.7.6 . If anyone got any idea how to solve this, please, let me know.

v3-core

v3-periphery

NonfungiblePositionManager.sol

LiquidityManagement.sol

PoolAddress.sol

NonfungiblePositionManager.sol

function mint(MintParams calldata params)
    external
    payable
    override
    checkDeadline(params.deadline)
    returns (
      uint256 tokenId,
      uint128 liquidity,
      uint256 amount0,
      uint256 amount1
    )
  {
    IUniswapV3Pool pool;
    

// it throws
---> (liquidity, amount0, amount1, pool) = addLiquidity(
      AddLiquidityParams({
        token0: params.token0,
        token1: params.token1,
        fee: params.fee,
        recipient: address(this),
        tickLower: params.tickLower,
        tickUpper: params.tickUpper,
        amount0Desired: params.amount0Desired,
        amount1Desired: params.amount1Desired,
        amount0Min: params.amount0Min,
        amount1Min: params.amount1Min
      })
    );
    

    _mint(params.recipient, (tokenId = _nextId++));

    bytes32 positionKey = PositionKey.compute(address(this), params.tickLower, params.tickUpper);
    (, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
    
    // idempotent set
    uint80 poolId = cachePoolKey(
      address(pool),
      PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee})
    );
    
    _positions[tokenId] = Position({
      nonce: 0,
      operator: address(0),
      poolId: poolId,
      tickLower: params.tickLower,
      tickUpper: params.tickUpper,
      liquidity: liquidity,
      feeGrowthInside0LastX128: feeGrowthInside0LastX128,
      feeGrowthInside1LastX128: feeGrowthInside1LastX128,
      tokensOwed0: 0,
      tokensOwed1: 0
    });
    
    emit IncreaseLiquidity(tokenId, liquidity, amount0, amount1);
  }
LiquidityManagement.sol

function addLiquidity(AddLiquidityParams memory params)
    internal
    returns (
      uint128 liquidity,
      uint256 amount0,
      uint256 amount1,
      IUniswapV3Pool pool
    )
  {
    PoolAddress.PoolKey memory poolKey = PoolAddress.PoolKey({
      token0: params.token0,
      token1: params.token1,
      fee: params.fee
    });
    

    // here is the computation of pool address
---> pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));

    // all subsequent operations fails 

    // compute the liquidity amount
    {
      (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();
      console.log("liquidity 4");
      uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);
      console.log("liquidity 5");
      uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);
      console.log("liquidity 6");

      liquidity = LiquidityAmounts.getLiquidityForAmounts(
        sqrtPriceX96,
        sqrtRatioAX96,
        sqrtRatioBX96,
        params.amount0Desired,
        params.amount1Desired
      );
      console.log("liquidity 7");
    }

    (amount0, amount1) = pool.mint(
      params.recipient,
      params.tickLower,
      params.tickUpper,
      liquidity,
      abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))
    );
    

    require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, "Price slippage check");
  }
PoolAddress.sol

  bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;


  function computeAddress(address factory, PoolKey memory key) internal view returns (address pool) {
    require(key.token0 < key.token1);
    pool = address(
      // uint160(
      uint256(
        keccak256(
          abi.encodePacked(
            hex"ff",
            factory,
            keccak256(abi.encode(key.token0, key.token1, key.fee)),
            POOL_INIT_CODE_HASH
          )
        )
      )
      // )
    );
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM