Nuclear_Man_D

Broken createPosition implementation for uniswapv4

Apr 19th, 2025
718
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 2.72 KB | Cryptocurrency | 0 0
  1.  
  2.     function _createPosition2(PoolKey calldata key, uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity) internal {
  3.  
  4.         // Calculate amounts of each token
  5.         // I can't use LiquidityAmounts.getAmountsForLiquidity because the function does not exist in the v4
  6.         // library.  See below links, there is a discrepency between the source and the documentation:
  7.         //  https://docs.uniswap.org/contracts/v4/reference/core/libraries/liquidity-amounts
  8.         //  https://github.com/Uniswap/v4-periphery/blob/main/src/libraries/LiquidityAmounts.sol
  9.         // In any case, I included my own implementation in my utils contract:
  10.         //  http://etherscan.io/address/0xC97B6F6DC641C0f59c724657B91569aF00C28B7D
  11.         // It's based on the UniswapV3 code so I'm pretty sure it works fine.
  12.         (uint256 amount0, uint256 amount1) = utils.getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity);
  13.  
  14.         // This function reverts if the amounts of the tokens are less than amount0 and amount1 by the end of the call
  15.         // From this, we can be sure that we have enough of the tokens, assuming that amount0 and amount1 are correct
  16.         obtainTokens(Currency.unwrap(key.currency0), Currency.unwrap(key.currency1), amount0, amount1);
  17.  
  18.         // Grant allowance to the position manager
  19.         if (Currency.unwrap(key.currency0) != address(0)) permit2.approve(Currency.unwrap(key.currency0), address(v4PositionManager), uint160(amount0), 0);
  20.         permit2.approve(Currency.unwrap(key.currency1), address(v4PositionManager), uint160(amount1), 0);
  21.  
  22.         // Based on code from:
  23.         // https://docs.uniswap.org/contracts/v4/quickstart/manage-liquidity/mint-position
  24.         // https://docs.uniswap.org/contracts/v4/guides/position-manager
  25.         bytes memory actions = abi.encodePacked(
  26.             uint8(Actions.MINT_POSITION),
  27.             uint8(Actions.SETTLE_PAIR)
  28.         );
  29.         bytes[] memory params = new bytes[](2);
  30.         unchecked {
  31.             params[0] = abi.encode(
  32.                 key,
  33.                 (TickMath.getTickAtSqrtPrice(sqrtRatioAX96) / key.tickSpacing) * key.tickSpacing,
  34.                 (TickMath.getTickAtSqrtPrice(sqrtRatioBX96) / key.tickSpacing) * key.tickSpacing,
  35.                 (liquidity * 1015) >> 10,  // reduces the inserted liquidity a bit, just in case we barely don't have enough
  36.                 amount0,
  37.                 amount1,
  38.                 address(this),
  39.                 abi.encode(address(this))
  40.             );
  41.         }
  42.         params[1] = abi.encode(key.currency0, key.currency1);
  43.  
  44.         unchecked {
  45.             uint256 deadline = block.timestamp + 60;
  46.             uint256 valueToPass = key.currency0.isAddressZero() ? amount0 : 0;
  47.  
  48.             // Our revert happens inside this call, apparently before SETTLE_PAIR is ever reached:
  49.             v4PositionManager.modifyLiquidities{value: valueToPass}(abi.encode(actions, params), deadline);
  50.         }
  51.     }
  52.  
Advertisement