From 3c2292e8b6cf6b77b067e4bbd14f6f00f9dcc1e1 Mon Sep 17 00:00:00 2001 From: riemann Date: Tue, 26 Mar 2024 12:07:52 +0300 Subject: [PATCH 1/5] feat: add tests for TickMath --- src/test/TickMathTest.sol | 8 ++++ test/TickMath.t.sol | 78 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/src/test/TickMathTest.sol b/src/test/TickMathTest.sol index 44b519e39..132be99aa 100644 --- a/src/test/TickMathTest.sol +++ b/src/test/TickMathTest.sol @@ -39,4 +39,12 @@ contract TickMathTest { function MAX_TICK() external pure returns (int24) { return TickMath.MAX_TICK; } + + function maxUsableTick(int24 tickSpacing) external pure returns (int24) { + return TickMath.maxUsableTick(tickSpacing); + } + + function minUsableTick(int24 tickSpacing) external pure returns (int24) { + return TickMath.minUsableTick(tickSpacing); + } } diff --git a/test/TickMath.t.sol b/test/TickMath.t.sol index 9817918d4..12deba245 100644 --- a/test/TickMath.t.sol +++ b/test/TickMath.t.sol @@ -7,6 +7,9 @@ import {TickMathTest} from "../src/test/TickMathTest.sol"; import {TickMath} from "../src/libraries/TickMath.sol"; import {JavascriptFfi} from "./utils/JavascriptFfi.sol"; +// rm before git add . +import "forge-std/console.sol"; + contract TickMathTestTest is Test, JavascriptFfi { int24 constant MIN_TICK = -887272; int24 constant MAX_TICK = -MIN_TICK; @@ -21,6 +24,11 @@ contract TickMathTestTest is Test, JavascriptFfi { uint160[] getSqrtRatioAtTickFuzzResults; int24[] getTickAtSqrtRatioFuzzResults; + struct FeeTier { + uint256 fee; + int24 tickSpacing; + } + TickMathTest tickMath; function setUp() public { @@ -44,6 +52,76 @@ contract TickMathTestTest is Test, JavascriptFfi { assertEq(maxTick, MAX_TICK); } + function test_maxUsableTick_SpecificFeeTiers() public { + // The size of tick spacing is relative to the fee tier. + // The tick spacing is double the size of the fee tier. + // For example, a tick for 0.30% fee tier pool will be 0.60% in size. + // The 0.01% fee tier has a size of 0.01%. + FeeTier[] memory feeTiers = new FeeTier[](5); + feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee tier + feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee tier + feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee tier + feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee tier + feeTiers[4] = FeeTier({fee: 500, tickSpacing: 1000}); // very high fee tier + + for (uint256 i = 0; i < feeTiers.length; i++) { + FeeTier memory tier = feeTiers[i]; + int24 expectedMaxTick = (MAX_TICK / tier.tickSpacing) * tier.tickSpacing; + assertEq( + tickMath.maxUsableTick(tier.tickSpacing), + expectedMaxTick, + "Max usable tick does not match for fee tier." + ); + } + } + + function test_minUsableTick_SpecificFeeTiers() public { + // The size of tick spacing is relative to the fee tier. + // The tick spacing is double the size of the fee tier. + // For example, a tick for 0.30% fee tier pool will be 0.60% in size. + // The 0.01% fee tier has a size of 0.01%. + FeeTier[] memory feeTiers = new FeeTier[](5); + feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee tier + feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee tier + feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee tier + feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee tier + feeTiers[4] = FeeTier({fee: 500, tickSpacing: 1000}); // very high fee tier + + for (uint256 i = 0; i < feeTiers.length; i++) { + FeeTier memory tier = feeTiers[i]; + int24 expectedMinTick = (MIN_TICK / tier.tickSpacing) * tier.tickSpacing; + assertEq( + tickMath.minUsableTick(tier.tickSpacing), + expectedMinTick, + "Min usable tick does not match for fee tier." + ); + } + } + + function testFuzz_maxUsableTick_SpecificFeeTiers(int24 tickSpacing) public { + vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); + + int24 expectedMaxTick = (MAX_TICK / tickSpacing) * tickSpacing; + assertEq(tickMath.maxUsableTick(tickSpacing), expectedMaxTick, "Max usable tick does not match for fee tier."); + } + + function testFuzz_minUsableTick_SpecificFeeTiers(int24 tickSpacing) public { + vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); + + int24 expectedMinTick = (MIN_TICK / tickSpacing) * tickSpacing; + assertEq(tickMath.minUsableTick(tickSpacing), expectedMinTick, "Max usable tick does not match for fee tier."); + } + + function test_maxUsableTick_revertsForZero() public { + vm.expectRevert(); + tickMath.maxUsableTick(0); + } + + function test_minUsableTick_revertsForZero() public { + vm.expectRevert(); + tickMath.minUsableTick(0); + } + function test_getSqrtRatioAtTick_throwsForTooLow() public { vm.expectRevert(TickMath.InvalidTick.selector); tickMath.getSqrtRatioAtTick(MIN_TICK - 1); From a6f68fb1f876427f0cb437568fe7b523ed3b1cf2 Mon Sep 17 00:00:00 2001 From: riemann Date: Tue, 26 Mar 2024 12:10:26 +0300 Subject: [PATCH 2/5] rm console.log --- test/TickMath.t.sol | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/test/TickMath.t.sol b/test/TickMath.t.sol index 12deba245..fa8712933 100644 --- a/test/TickMath.t.sol +++ b/test/TickMath.t.sol @@ -7,9 +7,6 @@ import {TickMathTest} from "../src/test/TickMathTest.sol"; import {TickMath} from "../src/libraries/TickMath.sol"; import {JavascriptFfi} from "./utils/JavascriptFfi.sol"; -// rm before git add . -import "forge-std/console.sol"; - contract TickMathTestTest is Test, JavascriptFfi { int24 constant MIN_TICK = -887272; int24 constant MAX_TICK = -MIN_TICK; @@ -67,11 +64,7 @@ contract TickMathTestTest is Test, JavascriptFfi { for (uint256 i = 0; i < feeTiers.length; i++) { FeeTier memory tier = feeTiers[i]; int24 expectedMaxTick = (MAX_TICK / tier.tickSpacing) * tier.tickSpacing; - assertEq( - tickMath.maxUsableTick(tier.tickSpacing), - expectedMaxTick, - "Max usable tick does not match for fee tier." - ); + assertEq(tickMath.maxUsableTick(tier.tickSpacing), expectedMaxTick); } } @@ -90,11 +83,7 @@ contract TickMathTestTest is Test, JavascriptFfi { for (uint256 i = 0; i < feeTiers.length; i++) { FeeTier memory tier = feeTiers[i]; int24 expectedMinTick = (MIN_TICK / tier.tickSpacing) * tier.tickSpacing; - assertEq( - tickMath.minUsableTick(tier.tickSpacing), - expectedMinTick, - "Min usable tick does not match for fee tier." - ); + assertEq(tickMath.minUsableTick(tier.tickSpacing), expectedMinTick); } } @@ -102,14 +91,14 @@ contract TickMathTestTest is Test, JavascriptFfi { vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); int24 expectedMaxTick = (MAX_TICK / tickSpacing) * tickSpacing; - assertEq(tickMath.maxUsableTick(tickSpacing), expectedMaxTick, "Max usable tick does not match for fee tier."); + assertEq(tickMath.maxUsableTick(tickSpacing), expectedMaxTick); } function testFuzz_minUsableTick_SpecificFeeTiers(int24 tickSpacing) public { vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); int24 expectedMinTick = (MIN_TICK / tickSpacing) * tickSpacing; - assertEq(tickMath.minUsableTick(tickSpacing), expectedMinTick, "Max usable tick does not match for fee tier."); + assertEq(tickMath.minUsableTick(tickSpacing), expectedMinTick); } function test_maxUsableTick_revertsForZero() public { From 4b281092824e88ffdd277504a15d19d275df2313 Mon Sep 17 00:00:00 2001 From: riemann Date: Tue, 26 Mar 2024 12:20:39 +0300 Subject: [PATCH 3/5] fix: rename fuzzing tests --- test/TickMath.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TickMath.t.sol b/test/TickMath.t.sol index fa8712933..81c16f306 100644 --- a/test/TickMath.t.sol +++ b/test/TickMath.t.sol @@ -87,14 +87,14 @@ contract TickMathTestTest is Test, JavascriptFfi { } } - function testFuzz_maxUsableTick_SpecificFeeTiers(int24 tickSpacing) public { + function testFuzz_maxUsableTick(int24 tickSpacing) public { vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); int24 expectedMaxTick = (MAX_TICK / tickSpacing) * tickSpacing; assertEq(tickMath.maxUsableTick(tickSpacing), expectedMaxTick); } - function testFuzz_minUsableTick_SpecificFeeTiers(int24 tickSpacing) public { + function testFuzz_minUsableTick(int24 tickSpacing) public { vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); int24 expectedMinTick = (MIN_TICK / tickSpacing) * tickSpacing; From e3edabd38834ee035d17effd59a0dab7b461b0a0 Mon Sep 17 00:00:00 2001 From: riemann Date: Wed, 27 Mar 2024 11:50:59 +0300 Subject: [PATCH 4/5] feat: update TickMath tests --- test/libraries/TickMath.t.sol | 36 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/test/libraries/TickMath.t.sol b/test/libraries/TickMath.t.sol index 7cd842bbe..cdfda968f 100644 --- a/test/libraries/TickMath.t.sol +++ b/test/libraries/TickMath.t.sol @@ -22,7 +22,7 @@ contract TickMathTestTest is Test, JavascriptFfi { int24[] getTickAtSqrtRatioFuzzResults; struct FeeTier { - uint256 fee; + uint24 fee; int24 tickSpacing; } @@ -49,17 +49,17 @@ contract TickMathTestTest is Test, JavascriptFfi { assertEq(maxTick, MAX_TICK); } - function test_maxUsableTick_SpecificFeeTiers() public { + function test_maxUsableTick_checkTypicalFeeTiers() public { // The size of tick spacing is relative to the fee tier. // The tick spacing is double the size of the fee tier. // For example, a tick for 0.30% fee tier pool will be 0.60% in size. // The 0.01% fee tier has a size of 0.01%. FeeTier[] memory feeTiers = new FeeTier[](5); - feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee tier - feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee tier - feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee tier - feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee tier - feeTiers[4] = FeeTier({fee: 500, tickSpacing: 1000}); // very high fee tier + feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee + feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee + feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee + feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee + feeTiers[4] = FeeTier({fee: 1000000, tickSpacing: 2000000}); // max fee for (uint256 i = 0; i < feeTiers.length; i++) { FeeTier memory tier = feeTiers[i]; @@ -68,17 +68,17 @@ contract TickMathTestTest is Test, JavascriptFfi { } } - function test_minUsableTick_SpecificFeeTiers() public { + function test_minUsableTick_checkTypicalFeeTiers() public { // The size of tick spacing is relative to the fee tier. // The tick spacing is double the size of the fee tier. // For example, a tick for 0.30% fee tier pool will be 0.60% in size. // The 0.01% fee tier has a size of 0.01%. FeeTier[] memory feeTiers = new FeeTier[](5); - feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee tier - feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee tier - feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee tier - feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee tier - feeTiers[4] = FeeTier({fee: 500, tickSpacing: 1000}); // very high fee tier + feeTiers[0] = FeeTier({fee: 1, tickSpacing: 1}); // 0.01% fee + feeTiers[1] = FeeTier({fee: 5, tickSpacing: 10}); // 0.05% fee + feeTiers[2] = FeeTier({fee: 30, tickSpacing: 60}); // 0.30% fee + feeTiers[3] = FeeTier({fee: 100, tickSpacing: 200}); // 1% fee + feeTiers[4] = FeeTier({fee: 1000000, tickSpacing: 2000000}); // max fee for (uint256 i = 0; i < feeTiers.length; i++) { FeeTier memory tier = feeTiers[i]; @@ -87,15 +87,17 @@ contract TickMathTestTest is Test, JavascriptFfi { } } - function testFuzz_maxUsableTick(int24 tickSpacing) public { - vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); + function test_maxUsableTick_shouldMatchExpectedMaxTickGivenSpacing_fuzz(int24 tickSpacing) public { + tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); + vm.assume(tickSpacing != 0); int24 expectedMaxTick = (MAX_TICK / tickSpacing) * tickSpacing; assertEq(tickMath.maxUsableTick(tickSpacing), expectedMaxTick); } - function testFuzz_minUsableTick(int24 tickSpacing) public { - vm.assume(tickSpacing > 0 && tickSpacing <= MAX_TICK && tickSpacing >= MIN_TICK); + function test_minUsableTick_shouldMatchExpectedMinTickGivenSpacing_fuzz(int24 tickSpacing) public { + tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); + vm.assume(tickSpacing != 0); int24 expectedMinTick = (MIN_TICK / tickSpacing) * tickSpacing; assertEq(tickMath.minUsableTick(tickSpacing), expectedMinTick); From 089503fe6179264353766203a172712258a8f203 Mon Sep 17 00:00:00 2001 From: riemann Date: Wed, 27 Mar 2024 12:04:39 +0300 Subject: [PATCH 5/5] feat: add TickMath fuzz test --- test/libraries/TickMath.t.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/libraries/TickMath.t.sol b/test/libraries/TickMath.t.sol index cdfda968f..b0ff413f5 100644 --- a/test/libraries/TickMath.t.sol +++ b/test/libraries/TickMath.t.sol @@ -103,6 +103,13 @@ contract TickMathTestTest is Test, JavascriptFfi { assertEq(tickMath.minUsableTick(tickSpacing), expectedMinTick); } + function test_maxUsableTick_equalsMinUsableTick_fuzz(int24 tickSpacing) public { + tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); + vm.assume(tickSpacing != 0); + + assertEq(-tickMath.minUsableTick(tickSpacing), tickMath.maxUsableTick(tickSpacing)); + } + function test_maxUsableTick_revertsForZero() public { vm.expectRevert(); tickMath.maxUsableTick(0);