From 4526a2b30ad402f2f02c8ebffc6a28779c80b571 Mon Sep 17 00:00:00 2001 From: Guillaume Lambert Date: Sun, 26 Nov 2023 07:03:29 -0500 Subject: [PATCH] test: removed SFPM roll tests --- .../core/SemiFungiblePositionManager.t.sol | 468 ------------------ 1 file changed, 468 deletions(-) diff --git a/test/foundry/core/SemiFungiblePositionManager.t.sol b/test/foundry/core/SemiFungiblePositionManager.t.sol index d9bd4de..e4b5b67 100644 --- a/test/foundry/core/SemiFungiblePositionManager.t.sol +++ b/test/foundry/core/SemiFungiblePositionManager.t.sol @@ -2630,474 +2630,6 @@ contract SemiFungiblePositionManagerTest is PositionUtils { TickMath.MAX_TICK ); } - - /*////////////////////////////////////////////////////////////// - ROLLING: + - //////////////////////////////////////////////////////////////*/ - - function test_Success_rollTokenizedPosition_2xOutsideRangeShortCall( - uint256 x, - uint256 widthSeed, - uint256 widthSeed2, - int256 strikeSeed, - int256 strikeSeed2, - uint256 positionSizeSeed - ) public { - _initPool(x); - - (int24 width, int24 strike) = PositionUtils.getOutOfRangeSW( - widthSeed, - strikeSeed, - uint24(tickSpacing), - currentTick - ); - - (int24 width2, int24 strike2) = PositionUtils.getOutOfRangeSW( - widthSeed2, - strikeSeed2, - uint24(tickSpacing), - currentTick - ); - vm.assume(width2 != width || strike2 != strike); - - populatePositionData([width, width2], [strike, strike2], positionSizeSeed); - - /// position size is denominated in the opposite of asset, so we do it in the token that is not WETH - // leg 1 - uint256 tokenId = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike, - width - ); - // leg 2 - tokenId = tokenId.addLeg(1, 1, isWETH, 0, 0, 1, strike2, width2); - - sfpm.mintTokenizedPosition( - tokenId, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - - // fully roll leg 2 to the same as leg 1 - uint256 newTokenId = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike, - width - ); - - newTokenId = newTokenId.addLeg(1, 1, isWETH, 0, 0, 1, strike, width); - - { - ( - int256 totalCollectedBurn, - int256 totalSwappedBurn, - int256 totalCollectedMint, - int256 totalSwappedMint, - int24 newTick - ) = sfpm.rollTokenizedPositions( - tokenId, - newTokenId, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - - (, currentTick, , , , , ) = pool.slot0(); - assertEq(newTick, currentTick); - - assertEq(totalCollectedBurn, 0); - assertEq(totalCollectedMint, 0); - - // both legs are now the same, so we have twice the size of leg 1 - expectedLiq = isWETH == 0 - ? LiquidityAmounts.getLiquidityForAmount0( - sqrtLowers[0], - sqrtUppers[0], - positionSize * 2 - ) - : LiquidityAmounts.getLiquidityForAmount1( - sqrtLowers[0], - sqrtUppers[0], - positionSize * 2 - ); - - $amount0MovedBurn = sqrtUppers[0] < currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount0Delta( - sqrtLowers[0] < currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtLowers[0], - sqrtUppers[0], - int128(expectedLiq) - ); - - $amount1MovedBurn = sqrtLowers[0] > currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount1Delta( - sqrtLowers[0], - sqrtUppers[0] > currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtUppers[0], - int128(expectedLiq) - ); - - assertApproxEqAbs(totalSwappedBurn.rightSlot(), -$amount0Moveds[1], 10); - assertApproxEqAbs(totalSwappedBurn.leftSlot(), -$amount1Moveds[1], 10); - - assertEq(totalSwappedMint.rightSlot(), $amount0Moveds[0]); - assertEq(totalSwappedMint.leftSlot(), $amount1Moveds[0]); - } - - assertEq(sfpm.balanceOf(Alice, tokenId), 0); - assertEq(sfpm.balanceOf(Alice, newTokenId), positionSize); - - // ensure that old liquidity chunk (ticklowers[1]-tickUppers[1]) - // has been rolled to (tickLowers[0]-tickUppers[0]) - { - uint256 accountLiquidities = sfpm.getAccountLiquidity( - address(pool), - Alice, - 0, - tickLowers[0], - tickUppers[0] - ); - assertEq(accountLiquidities.leftSlot(), 0); - assertApproxEqAbs(accountLiquidities.rightSlot(), expectedLiq, 10); - } - { - uint256 accountLiquidities = sfpm.getAccountLiquidity( - address(pool), - Alice, - 0, - tickLowers[1], - tickUppers[1] - ); - assertEq(accountLiquidities.leftSlot(), 0); - assertEq(accountLiquidities.rightSlot(), 0); - } - { - (uint256 realLiq, , , uint256 tokensOwed0, uint256 tokensOwed1) = pool.positions( - keccak256(abi.encodePacked(address(sfpm), tickLowers[0], tickUppers[0])) - ); - assertApproxEqAbs(realLiq, expectedLiq, 10); - assertEq(tokensOwed0, 0); - assertEq(tokensOwed1, 0); - } - - { - (uint256 realLiq, , , uint256 tokensOwed0, uint256 tokensOwed1) = pool.positions( - keccak256(abi.encodePacked(address(sfpm), tickLowers[1], tickUppers[1])) - ); - assertEq(realLiq, 0); - assertEq(tokensOwed0, 0); - assertEq(tokensOwed1, 0); - } - - assertEq(IERC20Partial(token0).balanceOf(address(sfpm)), 0); - assertEq(IERC20Partial(token1).balanceOf(address(sfpm)), 0); - } - - function test_Success_rollTokenizedPosition_OutsideRangeShortCallPoolChange( - uint256 x, - uint256 x2, - uint256 widthSeed, - int256 strikeSeed, - uint256 positionSize - ) public { - _initPool(x); - - (int24 width, int24 strike) = PositionUtils.getOutOfRangeSW( - widthSeed, - strikeSeed, - uint24(tickSpacing), - currentTick - ); - - /// position size is denominated in the opposite of asset, so we do it in the token that is not WETH - uint256 tokenId = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike, - width - ); - - tickLowers.push(int24(strike - (width * tickSpacing) / 2)); - tickUppers.push(int24(strike + (width * tickSpacing) / 2)); - sqrtLowers.push(TickMath.getSqrtRatioAtTick(tickLowers[0])); - sqrtUppers.push(TickMath.getSqrtRatioAtTick(tickUppers[0])); - - positionSize = getContractsForAmountAtTick( - currentTick, - tickLowers[0], - tickUppers[0], - isWETH, - bound(positionSize, 10 ** 15, 10 ** 22) - ); - - expectedLiq = isWETH == 0 - ? LiquidityAmounts.getLiquidityForAmount0(sqrtLowers[0], sqrtUppers[0], positionSize) - : LiquidityAmounts.getLiquidityForAmount1(sqrtLowers[0], sqrtUppers[0], positionSize); - - $amount0Moveds.push( - sqrtUppers[0] < currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount0Delta( - sqrtLowers[0] < currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtLowers[0], - sqrtUppers[0], - int128(expectedLiq) - ) - ); - $amount1Moveds.push( - sqrtLowers[0] > currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount1Delta( - sqrtLowers[0], - sqrtUppers[0] > currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtUppers[0], - int128(expectedLiq) - ) - ); - - sfpm.mintTokenizedPosition( - tokenId, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - - IUniswapV3Pool oldPool = pool; - - // reinit with new pool and roll to it - vm.stopPrank(); - _initPool(x2); - vm.assume(pool != oldPool); - - (int24 width2, int24 strike2) = PositionUtils.getOutOfRangeSW( - widthSeed, - strikeSeed, - uint24(tickSpacing), - currentTick - ); - - tickLowers.push(int24(strike2 - (width2 * tickSpacing) / 2)); - tickUppers.push(int24(strike2 + (width2 * tickSpacing) / 2)); - sqrtLowers.push(TickMath.getSqrtRatioAtTick(tickLowers[1])); - sqrtUppers.push(TickMath.getSqrtRatioAtTick(tickUppers[1])); - - expectedLiq = isWETH == 0 - ? LiquidityAmounts.getLiquidityForAmount0(sqrtLowers[1], sqrtUppers[1], positionSize) - : LiquidityAmounts.getLiquidityForAmount1(sqrtLowers[1], sqrtUppers[1], positionSize); - - $amount0Moveds.push( - sqrtUppers[1] < currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount0Delta( - sqrtLowers[1] < currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtLowers[1], - sqrtUppers[1], - int128(expectedLiq) - ) - ); - - $amount1Moveds.push( - sqrtLowers[1] > currentSqrtPriceX96 - ? int256(0) - : SqrtPriceMath.getAmount1Delta( - sqrtLowers[1], - sqrtUppers[1] > currentSqrtPriceX96 ? currentSqrtPriceX96 : sqrtUppers[1], - int128(expectedLiq) - ) - ); - - { - // ensure roll is sufficiently large - (uint256 amount0, uint256 amount1) = LiquidityAmounts.getAmountsForLiquidity( - currentSqrtPriceX96, - sqrtLowers[1], - sqrtUppers[1], - expectedLiq - ); - uint256 priceX128 = FullMath.mulDiv(currentSqrtPriceX96, currentSqrtPriceX96, 2 ** 64); - // total ETH value must be >= 10 ** 15 - uint256 ETHValue = isWETH == 0 - ? amount0 + FullMath.mulDiv(amount1, 2 ** 128, priceX128) - : Math.mulDiv128(amount0, priceX128) + amount1; - vm.assume(ETHValue >= 10 ** 15); - } - - uint256 newTokenID = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike2, - width2 - ); - - { - ( - totalCollectedBurn, - totalSwappedBurn, - totalCollectedMint, - totalSwappedMint, - newTick - ) = sfpm.rollTokenizedPositions( - tokenId, - newTokenID, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - - assertEq(totalCollectedBurn, 0); - assertEq(totalCollectedMint, 0); - - assertApproxEqAbs(totalSwappedBurn.rightSlot(), -$amount0Moveds[0], 10); - assertApproxEqAbs(totalSwappedBurn.leftSlot(), -$amount1Moveds[0], 10); - - assertEq(totalSwappedMint.rightSlot(), $amount0Moveds[1]); - assertEq(totalSwappedMint.leftSlot(), $amount1Moveds[1]); - } - - assertEq(sfpm.balanceOf(Alice, tokenId), 0); - assertEq(sfpm.balanceOf(Alice, newTokenID), positionSize); - - { - uint256 accountLiquidities = sfpm.getAccountLiquidity( - address(oldPool), - Alice, - 0, - tickLowers[0], - tickUppers[0] - ); - assertEq(accountLiquidities.leftSlot(), 0); - assertEq(accountLiquidities.rightSlot(), 0); - } - { - uint256 accountLiquidities = sfpm.getAccountLiquidity( - address(pool), - Alice, - 0, - tickLowers[1], - tickUppers[1] - ); - assertEq(accountLiquidities.leftSlot(), 0); - assertEq(accountLiquidities.rightSlot(), expectedLiq); - } - { - (uint256 realLiq, , , , ) = oldPool.positions( - keccak256(abi.encodePacked(address(sfpm), tickLowers[0], tickUppers[1])) - ); - - assertEq(realLiq, 0); - } - (uint256 realLiq, , , , ) = pool.positions( - keccak256(abi.encodePacked(address(sfpm), tickLowers[1], tickUppers[1])) - ); - - assertEq(realLiq, expectedLiq); - } - - /*////////////////////////////////////////////////////////////// - ROLLING: - - //////////////////////////////////////////////////////////////*/ - - function test_Fail_rollTokenizedPosition_ReentrancyLock( - uint256 x, - uint256 widthSeed, - uint256 widthSeed2, - int256 strikeSeed, - int256 strikeSeed2, - uint256 positionSizeSeed - ) public { - _initPool(x); - - (int24 width, int24 strike) = PositionUtils.getOutOfRangeSW( - widthSeed, - strikeSeed, - uint24(tickSpacing), - currentTick - ); - - (int24 width2, int24 strike2) = PositionUtils.getOutOfRangeSW( - widthSeed2, - strikeSeed2, - uint24(tickSpacing), - currentTick - ); - vm.assume(width2 != width || strike2 != strike); - - populatePositionData([width, width2], [strike, strike2], positionSizeSeed); - - /// position size is denominated in the opposite of asset, so we do it in the token that is not WETH - // leg 1 - uint256 tokenId = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike, - width - ); - // leg 2 - tokenId = tokenId.addLeg(1, 1, isWETH, 0, 0, 1, strike2, width2); - - sfpm.mintTokenizedPosition( - tokenId, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - - // fully roll leg 2 to the same as leg 1 - uint256 newTokenId = uint256(0).addUniv3pool(poolId).addLeg( - 0, - 1, - isWETH, - 0, - 0, - 0, - strike, - width - ); - newTokenId = newTokenId.addLeg(1, 1, isWETH, 0, 0, 1, strike, width); - - // replace the Uniswap pool with a mock that responds correctly to queries but calls back on - // any other operations - vm.etch(address(pool), address(new ReenterRoll()).code); - - ReenterRoll(address(pool)).construct( - ReenterRoll.Slot0(currentSqrtPriceX96, currentTick, 0, 0, 0, 0, true), - address(token0), - address(token1), - fee, - tickSpacing - ); - - vm.expectRevert(Errors.ReentrantCall.selector); - - sfpm.rollTokenizedPositions( - tokenId, - newTokenId, - uint128(positionSize), - TickMath.MIN_TICK, - TickMath.MAX_TICK - ); - } - /*////////////////////////////////////////////////////////////// TRANSFER HOOK LOGIC: + //////////////////////////////////////////////////////////////*/