Broken createPosition implementation for uniswapv4
Nuclear_Man_D |
PRO |
04/19/25 10:48:59 PM UTC |
0 ⭐ |
12952 👁️ |
Never ⏰ |
[create, Uniswap, liquidity, uniswapv4]
function _createPosition2(PoolKey calldata key, uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity) internal {
// Calculate amounts of each token
// I can't use LiquidityAmounts.getAmountsForLiquidity because the function does not exist in the v4
// library. See below links, there is a discrepency between the source and the documentation:
// https://docs.uniswap.org/contracts/v4/reference/core/libraries/liquidity-amounts
// https://github.com/Uniswap/v4-periphery/blob/main/src/libraries/LiquidityAmounts.sol
// In any case, I included my own implementation in my utils contract:
// http://etherscan.io/address/0xC97B6F6DC641C0f59c724657B91569aF00C28B7D
// It's based on the UniswapV3 code so I'm pretty sure it works fine.
(uint256 amount0, uint256 amount1) = utils.getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity);
// This function reverts if the amounts of the tokens are less than amount0 and amount1 by the end of the call
// From this, we can be sure that we have enough of the tokens, assuming that amount0 and amount1 are correct
obtainTokens(Currency.unwrap(key.currency0), Currency.unwrap(key.currency1), amount0, amount1);
// Grant allowance to the position manager
if (Currency.unwrap(key.currency0) != address(0)) permit2.approve(Currency.unwrap(key.currency0), address(v4PositionManager), uint160(amount0), 0);
permit2.approve(Currency.unwrap(key.currency1), address(v4PositionManager), uint160(amount1), 0);
// Based on code from:
// https://docs.uniswap.org/contracts/v4/quickstart/manage-liquidity/mint-position
// https://docs.uniswap.org/contracts/v4/guides/position-manager
bytes memory actions = abi.encodePacked(
uint8(Actions.MINT_POSITION),
uint8(Actions.SETTLE_PAIR)
);
bytes[] memory params = new bytes[](2);
unchecked {
params[0] = abi.encode(
key,
(TickMath.getTickAtSqrtPrice(sqrtRatioAX96) / key.tickSpacing) * key.tickSpacing,
(TickMath.getTickAtSqrtPrice(sqrtRatioBX96) / key.tickSpacing) * key.tickSpacing,
(liquidity * 1015) >> 10, // reduces the inserted liquidity a bit, just in case we barely don't have enough
amount0,
amount1,
address(this),
abi.encode(address(this))
);
}
params[1] = abi.encode(key.currency0, key.currency1);
unchecked {
uint256 deadline = block.timestamp + 60;
uint256 valueToPass = key.currency0.isAddressZero() ? amount0 : 0;
// Our revert happens inside this call, apparently before SETTLE_PAIR is ever reached:
v4PositionManager.modifyLiquidities{value: valueToPass}(abi.encode(actions, params), deadline);
}
}
Comments
0 B
|👍
/👎
0 B
|👍
/👎