From c109924b82e9bca7a3c75461ee2546e84a5a7f72 Mon Sep 17 00:00:00 2001 From: dianakocsis <diana.kocsis@uniswap.org> Date: Fri, 17 Jan 2025 14:48:17 -0500 Subject: [PATCH] add liquidity beforehand --- .../PositionManager.modifyLiquidities.t.sol | 128 ++++++++---------- 1 file changed, 57 insertions(+), 71 deletions(-) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index 148598b41..c2f5b0fcc 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -982,59 +982,18 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF } } - function test_fuzz_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens( - uint256 amount0, - uint256 amount1, - int24 tickLower, - int24 tickUpper - ) public { - MockFOT(address(fotToken)).setFee(10_000); - tickLower = int24( - bound( - tickLower, - fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), - fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) - ) - ); - tickUpper = int24( - bound( - tickUpper, - fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), - fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) - ) - ); - - tickLower = fotKey.tickSpacing * (tickLower / fotKey.tickSpacing); - tickUpper = fotKey.tickSpacing * (tickUpper / fotKey.tickSpacing); - vm.assume(tickUpper > tickLower); - + function test_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens() public { + int24 tickUpper = 60; (uint160 sqrtPriceX96,,,) = manager.getSlot0(fotKey.toId()); - { - uint128 maxLiquidityPerTick = Pool.tickSpacingToMaxLiquidityPerTick(fotKey.tickSpacing); - (uint256 maxAmount0, uint256 maxAmount1) = LiquidityAmounts.getAmountsForLiquidity( - sqrtPriceX96, - TickMath.getSqrtPriceAtTick(tickLower), - TickMath.getSqrtPriceAtTick(tickUpper), - maxLiquidityPerTick - ); - - maxAmount0 = maxAmount0 == 0 ? 1 : maxAmount0 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount0; - maxAmount1 = maxAmount1 == 0 ? 1 : maxAmount1 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount1; - amount0 = bound(amount0, 1, maxAmount0); - amount1 = bound(amount1, 1, maxAmount1); - } + // current tick is 0, tickLower is -60 + int24 tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96) - fotKey.tickSpacing; uint256 tokenId = lpm.nextTokenId(); - BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); - BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); - BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); - BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); - Plan memory planner = Planner.init(); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, amount0, true)); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, amount1, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); planner.add( Actions.MINT_POSITION_FROM_DELTAS, abi.encode( @@ -1050,19 +1009,51 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // take the excess of each currency planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); - // needed to remove variables because of stack too deep - // Read below as: - // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); - // bool positionIsEntirelyInOtherToken = currency0IsFOT - // ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 - // : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96; - // if (positionIsEntirelyInOtherToken) { - if ( - fotKey.currency0 == Currency.wrap(address(fotToken)) - ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 - : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96 - ) { + // alice adds the liquidity in range [-60, 60] + vm.prank(alice); + seedToken(fotToken, alice); + IERC20(Currency.unwrap(fotKey.currency1)).approve(address(permit2), type(uint256).max); + permit2.approve(Currency.unwrap(fotKey.currency1), alice, type(uint160).max, type(uint48).max); + lpm.modifyLiquidities(planner.encode(), _deadline); + vm.stopPrank(); + + // set tick lower to current tick, making the new position that will be added entirely in other token + // tickLower = 0 = current tick + tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96); + + BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); + BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); + BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); + BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); + + // set fee of fotToken to 100% + MockFOT(address(fotToken)).setFee(10_000); + + // assume currency1 is fotToken + if (!(fotKey.currency0 == Currency.wrap(address(fotToken)))) { // MINT FROM DELTAS. + tokenId = lpm.nextTokenId(); + + planner = Planner.init(); + + planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); + planner.add( + Actions.MINT_POSITION_FROM_DELTAS, + abi.encode( + fotKey, + tickLower, + tickUpper, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES + ) + ); + // take the excess of each currency + planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); + + // add liquidity lpm.modifyLiquidities(planner.encode(), _deadline); balance0._after = fotKey.currency0.balanceOf(address(this)); @@ -1073,13 +1064,13 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // Calculate the expected resulting balances used to create liquidity after the fee is applied. Balance memory expected; { - bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); - uint256 expectedFee = (currency0IsFOT ? amount0 : amount1).calculatePortion(10_000); - (expected._0, expected._1) = currency0IsFOT - ? (balance0._before - balance0._after - expectedFee, balance1._before - balance1._after) - : (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); + // expected fee is the same amount that was sent, since fee is now 100% + uint256 expectedFee = 1 ether; + (expected._0, expected._1) = + (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); } assertEq(expected._0, balance0PM._after - balance0PM._before); + // expected._1 is 0 because no fotToken was sent to PM because of 100% fee assertEq(expected._1, balance1PM._after - balance1PM._before); { // the liquidity that was created is a diff of the balance change @@ -1097,12 +1088,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // BURN. planner = Planner.init(); // Note that the slippage does not include the fee from the transfer. - planner.add( - Actions.BURN_POSITION, - abi.encode( - tokenId, expected._0 == 0 ? 0 : expected._0 - 1, expected._1 == 0 ? 0 : expected._1 - 1, ZERO_BYTES - ) - ); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, expected._0 - 1, 0, ZERO_BYTES)); planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); @@ -1113,7 +1099,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // After redeeming the position, the liquidity provider should not have received any of the fot token since the position was entirely in the other token. assertEq(fotKey.currency1.balanceOf(address(this)), balance1._after); - assertGe(fotKey.currency0.balanceOf(address(this)), balance0._after); + assertGt(fotKey.currency0.balanceOf(address(this)), balance0._after); assertEq(lpm.getPositionLiquidity(tokenId), 0); }