From a37c0c0d8253e2b387c36288cd60136d77bce62d Mon Sep 17 00:00:00 2001 From: Korrrba Date: Mon, 31 Jul 2023 18:06:39 +0200 Subject: [PATCH] test: Tick: Call library directly instead of test contract. The test contract was a middle layer between library and was used by javascript / HardHat tests. Due to the middle layer using Foundry, gas cost usage was calculated incorrectly. Generate correct gas snapshots using direct library calls. Delete unnecessary comments. Functions moved and internalized from TickTest.sol: * ticks() * tickSpacingToMaxLiquidityPerTick() * setTick(), * getFeeGrowthInside() * update() * clear() Ref: #315 --- test/foundry-tests/Tick.t.sol | 188 +++++++++++++++++++++------------- 1 file changed, 116 insertions(+), 72 deletions(-) diff --git a/test/foundry-tests/Tick.t.sol b/test/foundry-tests/Tick.t.sol index 5738ac2eb..dc1b83aa2 100644 --- a/test/foundry-tests/Tick.t.sol +++ b/test/foundry-tests/Tick.t.sol @@ -5,12 +5,13 @@ import "forge-std/console.sol"; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import {GasSnapshot} from "../../lib/forge-gas-snapshot/src/GasSnapshot.sol"; -import {TickTest} from "../../contracts/test/TickTest.sol"; import {Constants} from "./utils/Constants.sol"; import {Pool} from "../../contracts/libraries/Pool.sol"; contract TickTestTest is Test, GasSnapshot { - TickTest tick; + using Pool for Pool.State; + + Pool.State public pool; enum FeeAmount { LOW, @@ -23,8 +24,54 @@ contract TickTestTest is Test, GasSnapshot { int24 constant MIN_TICK = -887272; int24 constant MAX_TICK = 887272; - function setUp() public { - tick = new TickTest(); + function ticks(int24 tick) internal view returns (Pool.TickInfo memory) { + return pool.ticks[tick]; + } + + function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128) { + return Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing); + } + + function setTick(int24 tick, Pool.TickInfo memory info) internal { + pool.ticks[tick] = info; + } + + function getFeeGrowthInside( + int24 tickLower, + int24 tickUpper, + int24 tickCurrent, + uint256 feeGrowthGlobal0X128, + uint256 feeGrowthGlobal1X128 + ) internal returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { + pool.slot0.tick = tickCurrent; + pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128; + pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128; + return pool.getFeeGrowthInside(tickLower, tickUpper); + } + + function update( + int24 tick, + int24 tickCurrent, + int128 liquidityDelta, + uint256 feeGrowthGlobal0X128, + uint256 feeGrowthGlobal1X128, + bool upper + ) internal returns (bool flipped, uint128 liquidityGrossAfter) { + pool.slot0.tick = tickCurrent; + pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128; + pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128; + return pool.updateTick(tick, liquidityDelta, upper); + } + + function clear(int24 tick) internal { + pool.clearTick(tick); + } + + function cross(int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) + internal + returns (int128 liquidityNet) + { + return pool.crossTick(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128); } function getMinTick(int24 tickSpacing) internal pure returns (int256) { @@ -45,11 +92,10 @@ contract TickTestTest is Test, GasSnapshot { ); } - // #tickSpacingToMaxLiquidityPerTick function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForLowFeeTickSpacing() public { int24 tickSpacing = TICK_SPACINGS[uint256(FeeAmount.LOW)]; - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(tickSpacing); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(tickSpacing); assertEq(maxLiquidityPerTick, 1917565579412846627735051215301243); checkCantOverflow(TICK_SPACINGS[uint256(FeeAmount.LOW)], maxLiquidityPerTick); @@ -58,7 +104,7 @@ contract TickTestTest is Test, GasSnapshot { function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMediumFeeTickSpacing() public { int24 tickSpacing = TICK_SPACINGS[uint256(FeeAmount.MEDIUM)]; - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(tickSpacing); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(tickSpacing); assertEq(maxLiquidityPerTick, 11505069308564788430434325881101413); // 113.1 bits checkCantOverflow(TICK_SPACINGS[uint256(FeeAmount.MEDIUM)], maxLiquidityPerTick); @@ -67,28 +113,28 @@ contract TickTestTest is Test, GasSnapshot { function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForHighFeeTickSpacing() public { int24 tickSpacing = TICK_SPACINGS[uint256(FeeAmount.HIGH)]; - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(tickSpacing); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(tickSpacing); assertEq(maxLiquidityPerTick, 38347205785278154309959589375342946); // 114.7 bits checkCantOverflow(TICK_SPACINGS[uint256(FeeAmount.HIGH)], maxLiquidityPerTick); } function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueFor1() public { - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(1); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(1); assertEq(maxLiquidityPerTick, 191757530477355301479181766273477); // 126 bits checkCantOverflow(1, maxLiquidityPerTick); } function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForEntireRange() public { - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(887272); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(887272); assertEq(maxLiquidityPerTick, Constants.MAX_UINT128 / 3); // 126 bits checkCantOverflow(887272, maxLiquidityPerTick); } function test_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueFor2302() public { - uint128 maxLiquidityPerTick = tick.tickSpacingToMaxLiquidityPerTick(2302); + uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(2302); assertEq(maxLiquidityPerTick, 440854192570431170114173285871668350); // 118 bits checkCantOverflow(2302, maxLiquidityPerTick); @@ -96,13 +142,13 @@ contract TickTestTest is Test, GasSnapshot { function test_tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing() public { snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing"); - tick.getGasCostOfTickSpacingToMaxLiquidityPerTick(1); + tickSpacingToMaxLiquidityPerTick(1); snapEnd(); } function test_tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing() public { snapStart("tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing"); - tick.getGasCostOfTickSpacingToMaxLiquidityPerTick(60); + tickSpacingToMaxLiquidityPerTick(60); snapEnd(); } @@ -110,27 +156,26 @@ contract TickTestTest is Test, GasSnapshot { int24 MAX_TICK_SPACING = 32767; snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMaxTickSpacing"); - tick.getGasCostOfTickSpacingToMaxLiquidityPerTick(MAX_TICK_SPACING); + tickSpacingToMaxLiquidityPerTick(MAX_TICK_SPACING); snapEnd(); } - // #getFeeGrowthInside function test_getFeeGrowthInside_returnsAllForTwoUninitializedTicksIfTickIsInside() public { - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 0, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); assertEq(feeGrowthInside0X128, 15); assertEq(feeGrowthInside1X128, 15); } function test_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsAbove() public { - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 4, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 4, 15, 15); assertEq(feeGrowthInside0X128, 0); assertEq(feeGrowthInside1X128, 0); } function test_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsBelow() public { - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, -4, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, -4, 15, 15); assertEq(feeGrowthInside0X128, 0); assertEq(feeGrowthInside1X128, 0); @@ -144,9 +189,9 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(2, info); + setTick(2, info); - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 0, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); assertEq(feeGrowthInside0X128, 13); assertEq(feeGrowthInside1X128, 12); @@ -160,9 +205,9 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(-2, info); + setTick(-2, info); - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 0, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); assertEq(feeGrowthInside0X128, 13); assertEq(feeGrowthInside1X128, 12); @@ -176,16 +221,16 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(-2, info); + setTick(-2, info); info.feeGrowthOutside0X128 = 4; info.feeGrowthOutside1X128 = 1; info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(2, info); + setTick(2, info); - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 0, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); assertEq(feeGrowthInside0X128, 9); assertEq(feeGrowthInside1X128, 11); @@ -199,48 +244,47 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(-2, info); + setTick(-2, info); info.feeGrowthOutside0X128 = 3; info.feeGrowthOutside1X128 = 5; info.liquidityGross = 0; info.liquidityNet = 0; - tick.setTick(2, info); + setTick(2, info); - (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = tick.getFeeGrowthInside(-2, 2, 0, 15, 15); + (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); assertEq(feeGrowthInside0X128, 16); assertEq(feeGrowthInside1X128, 13); } - // #update function test_update_flipsFromZeroToNonzero() public { - (bool flipped, uint128 liquidityGrossAfter) = tick.update(0, 0, 1, 0, 0, false); + (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false); assertEq(flipped, true); assertEq(liquidityGrossAfter, 1); } function test_update_doesNotFlipFromNonzeroToGreaterNonzero() public { - tick.update(0, 0, 1, 0, 0, false); - (bool flipped, uint128 liquidityGrossAfter) = tick.update(0, 0, 1, 0, 0, false); + update(0, 0, 1, 0, 0, false); + (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false); assertEq(flipped, false); assertEq(liquidityGrossAfter, 2); } function test_update_flipsFromNonzeroToZero() public { - tick.update(0, 0, 1, 0, 0, false); - (bool flipped, uint128 liquidityGrossAfter) = tick.update(0, 0, -1, 0, 0, false); + update(0, 0, 1, 0, 0, false); + (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false); assertEq(flipped, true); assertEq(liquidityGrossAfter, 0); } function test_update_doesNotFlipFromNonzeroToLesserZero() public { - tick.update(0, 0, 2, 0, 0, false); - (bool flipped, uint128 liquidityGrossAfter) = tick.update(0, 0, -1, 0, 0, false); + update(0, 0, 2, 0, 0, false); + (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false); assertEq(flipped, false); assertEq(liquidityGrossAfter, 1); @@ -249,28 +293,28 @@ contract TickTestTest is Test, GasSnapshot { function test_update_netsTheLiquidityBasedOnUpperFlag() public { Pool.TickInfo memory tickInfo; - tick.update(0, 0, 2, 0, 0, false); - tick.update(0, 0, 1, 0, 0, true); - tick.update(0, 0, 3, 0, 0, true); - tick.update(0, 0, 1, 0, 0, false); - tickInfo = tick.ticks(0); + update(0, 0, 2, 0, 0, false); + update(0, 0, 1, 0, 0, true); + update(0, 0, 3, 0, 0, true); + update(0, 0, 1, 0, 0, false); + tickInfo = ticks(0); assertEq(tickInfo.liquidityGross, 2 + 1 + 3 + 1); assertEq(tickInfo.liquidityNet, 2 - 1 - 3 + 1); } function test_update_revertsOnOverflowLiquidityGross() public { - tick.update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); + update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); vm.expectRevert(); - tick.update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); + update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); } function test_update_assumesAllGrowthHappensBelowTicksLteCurrentTick() public { Pool.TickInfo memory tickInfo; - tick.update(1, 1, 1, 1, 2, false); - tickInfo = tick.ticks(1); + update(1, 1, 1, 1, 2, false); + tickInfo = ticks(1); assertEq(tickInfo.feeGrowthOutside0X128, 1); assertEq(tickInfo.feeGrowthOutside1X128, 2); @@ -279,9 +323,9 @@ contract TickTestTest is Test, GasSnapshot { function test_update_doesNotSetAnyGrowthFieldsIfTickIsAlreadyInitialized() public { Pool.TickInfo memory tickInfo; - tick.update(1, 1, 1, 1, 2, false); - tick.update(1, 1, 1, 6, 7, false); - tickInfo = tick.ticks(1); + update(1, 1, 1, 1, 2, false); + update(1, 1, 1, 6, 7, false); + tickInfo = ticks(1); assertEq(tickInfo.feeGrowthOutside0X128, 1); assertEq(tickInfo.feeGrowthOutside1X128, 2); @@ -290,8 +334,8 @@ contract TickTestTest is Test, GasSnapshot { function test_update_doesNotSetAnyGrowthFieldsForTicksGtCurrentTick() public { Pool.TickInfo memory tickInfo; - tick.update(2, 1, 1, 1, 2, false); - tickInfo = tick.ticks(2); + update(2, 1, 1, 1, 2, false); + tickInfo = ticks(2); assertEq(tickInfo.feeGrowthOutside0X128, 0); assertEq(tickInfo.feeGrowthOutside1X128, 0); @@ -306,10 +350,10 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = Constants.MAX_UINT128; info.liquidityNet = 0; - tick.setTick(2, info); - tick.update(2, 1, -1, 1, 2, false); + setTick(2, info); + update(2, 1, -1, 1, 2, false); - info = tick.ticks(2); + info = ticks(2); assertEq(info.liquidityGross, Constants.MAX_UINT128 - 1); assertEq(info.liquidityNet, -1); @@ -323,11 +367,11 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = (Constants.MAX_UINT128 / 2) + 1; info.liquidityNet = 0; - tick.setTick(2, info); + setTick(2, info); - tick.update(2, 1, int128(Constants.MAX_UINT128 / 2), 1, 2, false); + update(2, 1, int128(Constants.MAX_UINT128 / 2), 1, 2, false); - info = tick.ticks(2); + info = ticks(2); assertEq(info.liquidityGross, Constants.MAX_UINT128); assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2)); @@ -341,10 +385,10 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 1; info.liquidityNet = int128(Constants.MAX_UINT128 / 2); - tick.setTick(2, info); - tick.update(2, 1, -1, 1, 2, false); + setTick(2, info); + update(2, 1, -1, 1, 2, false); - info = tick.ticks(2); + info = ticks(2); assertEq(info.liquidityGross, 0); assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2 - 1)); @@ -358,11 +402,11 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 0; info.liquidityNet = int128(Constants.MAX_UINT128 / 2 - 1); - tick.setTick(2, info); + setTick(2, info); - tick.update(2, 1, 1, 1, 2, false); + update(2, 1, 1, 1, 2, false); - info = tick.ticks(2); + info = ticks(2); assertEq(info.liquidityGross, 1); assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2)); @@ -377,11 +421,11 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 3; info.liquidityNet = 4; - tick.setTick(2, info); + setTick(2, info); - tick.clear(2); + clear(2); - info = tick.ticks(2); + info = ticks(2); assertEq(info.feeGrowthOutside0X128, 0); assertEq(info.feeGrowthOutside1X128, 0); @@ -398,11 +442,11 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 3; info.liquidityNet = 4; - tick.setTick(2, info); + setTick(2, info); - tick.cross(2, 7, 9); + cross(2, 7, 9); - info = tick.ticks(2); + info = ticks(2); assertEq(info.feeGrowthOutside0X128, 6); assertEq(info.feeGrowthOutside1X128, 7); @@ -416,12 +460,12 @@ contract TickTestTest is Test, GasSnapshot { info.liquidityGross = 3; info.liquidityNet = 4; - tick.setTick(2, info); + setTick(2, info); - tick.cross(2, 7, 9); - tick.cross(2, 7, 9); + cross(2, 7, 9); + cross(2, 7, 9); - info = tick.ticks(2); + info = ticks(2); assertEq(info.feeGrowthOutside0X128, 1); assertEq(info.feeGrowthOutside1X128, 2);