From 20d585515486e83856f4ec5582502b3c616d3b10 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 15 Oct 2024 12:52:03 -0400 Subject: [PATCH 1/4] add swap to price tests --- ...wap skips hook call if hook is caller.snap | 2 +- .../swap with return dynamic fee.snap | 2 +- test/PoolManager.t.sol | 41 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/.forge-snapshots/swap skips hook call if hook is caller.snap b/.forge-snapshots/swap skips hook call if hook is caller.snap index f1e126934..a98a52ade 100644 --- a/.forge-snapshots/swap skips hook call if hook is caller.snap +++ b/.forge-snapshots/swap skips hook call if hook is caller.snap @@ -1 +1 @@ -206403 \ No newline at end of file +206415 \ No newline at end of file diff --git a/.forge-snapshots/swap with return dynamic fee.snap b/.forge-snapshots/swap with return dynamic fee.snap index bcbae20f7..09bc9151b 100644 --- a/.forge-snapshots/swap with return dynamic fee.snap +++ b/.forge-snapshots/swap with return dynamic fee.snap @@ -1 +1 @@ -145661 \ No newline at end of file +145673 \ No newline at end of file diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol index be71725a1..bb1d785b9 100644 --- a/test/PoolManager.t.sol +++ b/test/PoolManager.t.sol @@ -808,6 +808,47 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee); } + function test_swap_toLiquidity_fromMinPrice() public { + PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); + manager.initialize(_key, TickMath.MIN_SQRT_PRICE); + + IPoolManager.ModifyLiquidityParams memory params = + IPoolManager.ModifyLiquidityParams({tickLower: -10, tickUpper: 10, liquidityDelta: 100e18, salt: 0}); + modifyLiquidityRouter.modifyLiquidity(_key, params, ZERO_BYTES); + + // zeroForOne=false to swap higher + IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(false, 1, TickMath.MAX_SQRT_PRICE - 1); + PoolSwapTest.TestSettings memory testSettings = + PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); + + (uint160 sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); + + swapRouter.swap(_key, swapParams, testSettings, ZERO_BYTES); + + (sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); + + // The swap pushes the price to the start of liquidity. + assertEq(TickMath.getTickAtSqrtPrice(sqrtPriceX96), -10); + } + + function test_swap_toPrice_fromMaxPrice() public { + PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); + manager.initialize(_key, TickMath.MAX_SQRT_PRICE - 1); + + // zeroForOne=true to swap lower + IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(true, 1, SQRT_PRICE_1_4); + PoolSwapTest.TestSettings memory testSettings = + PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); + + (uint160 sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); + swapRouter.swap(_key, swapParams, testSettings, ZERO_BYTES); + + (sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); + + // The swap pushes the price to the sqrtPriceLimit. + assertEq(TickMath.getTickAtSqrtPrice(SQRT_PRICE_1_4), TickMath.getTickAtSqrtPrice(sqrtPriceX96)); + } + function test_donate_failsIfNotInitialized() public { vm.expectRevert(Pool.PoolNotInitialized.selector); donateRouter.donate(uninitializedKey, 100, 100, ZERO_BYTES); From 35e27463cb9acdf1df9a53c557976d416822c0c9 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 15 Oct 2024 14:19:50 -0400 Subject: [PATCH 2/4] gas --- .forge-snapshots/swap skips hook call if hook is caller.snap | 2 +- .forge-snapshots/swap with return dynamic fee.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.forge-snapshots/swap skips hook call if hook is caller.snap b/.forge-snapshots/swap skips hook call if hook is caller.snap index a98a52ade..f1e126934 100644 --- a/.forge-snapshots/swap skips hook call if hook is caller.snap +++ b/.forge-snapshots/swap skips hook call if hook is caller.snap @@ -1 +1 @@ -206415 \ No newline at end of file +206403 \ No newline at end of file diff --git a/.forge-snapshots/swap with return dynamic fee.snap b/.forge-snapshots/swap with return dynamic fee.snap index 09bc9151b..bcbae20f7 100644 --- a/.forge-snapshots/swap with return dynamic fee.snap +++ b/.forge-snapshots/swap with return dynamic fee.snap @@ -1 +1 @@ -145673 \ No newline at end of file +145661 \ No newline at end of file From 7d19a7ed39a8a3e3bb82a61e938aa7e508a924ea Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Wed, 16 Oct 2024 22:52:21 -0400 Subject: [PATCH 3/4] fuzz test --- test/PoolManager.t.sol | 58 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol index bb1d785b9..22b3fabd8 100644 --- a/test/PoolManager.t.sol +++ b/test/PoolManager.t.sol @@ -34,6 +34,8 @@ import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol"; import {StateLibrary} from "../src/libraries/StateLibrary.sol"; import {Actions} from "../src/test/ActionsRouter.sol"; +import "forge-std/console2.sol"; + contract PoolManagerTest is Test, Deployers, GasSnapshot { using Hooks for IHooks; using LPFeeLibrary for uint24; @@ -808,7 +810,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee); } - function test_swap_toLiquidity_fromMinPrice() public { + function test_swap_toLiquidity_fromMinPrice_withLiquidity() public { PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); manager.initialize(_key, TickMath.MIN_SQRT_PRICE); @@ -831,7 +833,59 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { assertEq(TickMath.getTickAtSqrtPrice(sqrtPriceX96), -10); } - function test_swap_toPrice_fromMaxPrice() public { + function test_fuzz_swap_toLiquidity(uint160 sqrtPriceX96) public { + PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); + sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); + vm.assume(sqrtPriceX96 != 0); + manager.initialize(_key, sqrtPriceX96); + + int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); + + bool zeroForOne; + uint160 sqrtPriceX96Limit; + int24 tickBoundary; + if (tick <= -10) { + // zeroForOne=false to swap higher + zeroForOne = false; + sqrtPriceX96Limit = TickMath.MAX_SQRT_PRICE - 1; + tickBoundary = -10; + } else if (tick > 10) { + // zeroForOne=true to swap lower + zeroForOne = true; + sqrtPriceX96Limit = TickMath.MIN_SQRT_PRICE + 1; + tickBoundary = 9; + } else { + // the price is between the position, so let's just swap down + zeroForOne = true; + sqrtPriceX96Limit = TickMath.MIN_SQRT_PRICE + 1; + // the tick will just stay the same, we're only swapping 1 wei + tickBoundary = TickMath.getTickAtSqrtPrice(sqrtPriceX96); + } + + // deeeeeep liquidity so that swapping 1 wei doesn't change the price too much if the price is within the tick range + IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({ + tickLower: -10, + tickUpper: 10, + liquidityDelta: 100000000000e18, + salt: 0 + }); + + modifyLiquidityRouter.modifyLiquidity(_key, params, ZERO_BYTES); + + IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(zeroForOne, 1, sqrtPriceX96Limit); + PoolSwapTest.TestSettings memory testSettings = + PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); + + swapRouter.swap(_key, swapParams, testSettings, ZERO_BYTES); + + int24 _tick; + (sqrtPriceX96, _tick,,) = manager.getSlot0(_key.toId()); + + // The swap pushes the price to one of the tick boundaries. + assertEq(TickMath.getTickAtSqrtPrice(sqrtPriceX96), tickBoundary); + } + + function test_swap_toPrice_fromMaxPrice_withoutLiquidity() public { PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); manager.initialize(_key, TickMath.MAX_SQRT_PRICE - 1); From 64f235af5cc44b95c44d00b32b6c7f8ade3808fd Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Wed, 16 Oct 2024 23:22:33 -0400 Subject: [PATCH 4/4] use price, rename --- test/PoolManager.t.sol | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol index 22b3fabd8..40d76d074 100644 --- a/test/PoolManager.t.sol +++ b/test/PoolManager.t.sol @@ -34,8 +34,6 @@ import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol"; import {StateLibrary} from "../src/libraries/StateLibrary.sol"; import {Actions} from "../src/test/ActionsRouter.sol"; -import "forge-std/console2.sol"; - contract PoolManagerTest is Test, Deployers, GasSnapshot { using Hooks for IHooks; using LPFeeLibrary for uint24; @@ -810,7 +808,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee); } - function test_swap_toLiquidity_fromMinPrice_withLiquidity() public { + function test_swap_toLiquidity_fromMinPrice() public { PoolKey memory _key = PoolKey(currency0, currency1, 500, 10, IHooks(address(0))); manager.initialize(_key, TickMath.MIN_SQRT_PRICE); @@ -819,7 +817,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { modifyLiquidityRouter.modifyLiquidity(_key, params, ZERO_BYTES); // zeroForOne=false to swap higher - IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(false, 1, TickMath.MAX_SQRT_PRICE - 1); + IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(false, -1, TickMath.MAX_SQRT_PRICE - 1); PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); @@ -830,7 +828,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { (sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); // The swap pushes the price to the start of liquidity. - assertEq(TickMath.getTickAtSqrtPrice(sqrtPriceX96), -10); + assertEq(sqrtPriceX96, TickMath.getSqrtPriceAtTick(-10)); } function test_fuzz_swap_toLiquidity(uint160 sqrtPriceX96) public { @@ -890,7 +888,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { manager.initialize(_key, TickMath.MAX_SQRT_PRICE - 1); // zeroForOne=true to swap lower - IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(true, 1, SQRT_PRICE_1_4); + IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(true, -1, SQRT_PRICE_1_4); PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); @@ -900,7 +898,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { (sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); // The swap pushes the price to the sqrtPriceLimit. - assertEq(TickMath.getTickAtSqrtPrice(SQRT_PRICE_1_4), TickMath.getTickAtSqrtPrice(sqrtPriceX96)); + assertEq(SQRT_PRICE_1_4, sqrtPriceX96); } function test_donate_failsIfNotInitialized() public {