From e3bef1e743822a4a80b6497a61d933fe6a75874d Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Mon, 20 May 2024 17:31:29 -0500 Subject: [PATCH] Optimize `sqrtPriceX96` rounding in `TickMath.getSqrtPriceAtTick` (#665) * Refactor `price` calculation in `TickMath` TickMath's price calculation has been updated for scenarios where tick is greater than zero. This change was made by replacing the earlier calculation with an assembly block to improve efficiency and performance. Additionally, a rounding operation was maintained to ensure conformity with the 160 bit input constraint. * Optimize `sqrtPriceX96` rounding in `TickMath.getSqrtPriceAtTick` In the TickMath.sol file, the square root price calculation has been optimized using assembly for better performance. The new implementation improves computational efficiency by replacing the standard division operation with bit shifting and bitwise operations. * Combine assembly blocks --- .forge-snapshots/TickMathGetSqrtPriceAtTick.snap | 2 +- .forge-snapshots/TickMathGetTickAtSqrtPrice.snap | 2 +- ...dity to already existing position with salt.snap | 2 +- .forge-snapshots/addLiquidity CA fee.snap | 2 +- .forge-snapshots/addLiquidity with empty hook.snap | 2 +- .../addLiquidity with native token.snap | 2 +- ...reate new liquidity to a position with salt.snap | 2 +- .forge-snapshots/initialize.snap | 2 +- .forge-snapshots/poolManager bytecode size.snap | 2 +- .forge-snapshots/removeLiquidity CA fee.snap | 2 +- .../removeLiquidity with empty hook.snap | 2 +- .../removeLiquidity with native token.snap | 2 +- ...ple addLiquidity second addition same range.snap | 2 +- .forge-snapshots/simple addLiquidity.snap | 2 +- ...mple removeLiquidity some liquidity remains.snap | 2 +- .forge-snapshots/simple removeLiquidity.snap | 2 +- .forge-snapshots/simple swap with native.snap | 2 +- .forge-snapshots/simple swap.snap | 2 +- .forge-snapshots/swap CA fee on unspecified.snap | 2 +- .../swap against liquidity with native token.snap | 2 +- .forge-snapshots/swap against liquidity.snap | 2 +- .forge-snapshots/swap burn 6909 for input.snap | 2 +- .../swap burn native 6909 for input.snap | 2 +- .../swap mint native output as 6909.snap | 2 +- .forge-snapshots/swap mint output as 6909.snap | 2 +- .../swap skips hook call if hook is caller.snap | 2 +- .forge-snapshots/swap with dynamic fee.snap | 2 +- .forge-snapshots/swap with hooks.snap | 2 +- .../swap with lp fee and protocol fee.snap | 2 +- .forge-snapshots/swap with return dynamic fee.snap | 2 +- .../update dynamic fee in before swap.snap | 2 +- src/libraries/TickMath.sol | 13 ++++++++----- 32 files changed, 39 insertions(+), 36 deletions(-) diff --git a/.forge-snapshots/TickMathGetSqrtPriceAtTick.snap b/.forge-snapshots/TickMathGetSqrtPriceAtTick.snap index 47c561f7b..3f9b14365 100644 --- a/.forge-snapshots/TickMathGetSqrtPriceAtTick.snap +++ b/.forge-snapshots/TickMathGetSqrtPriceAtTick.snap @@ -1 +1 @@ -87496 \ No newline at end of file +80082 \ No newline at end of file diff --git a/.forge-snapshots/TickMathGetTickAtSqrtPrice.snap b/.forge-snapshots/TickMathGetTickAtSqrtPrice.snap index 90f41c594..6e3ae1235 100644 --- a/.forge-snapshots/TickMathGetTickAtSqrtPrice.snap +++ b/.forge-snapshots/TickMathGetTickAtSqrtPrice.snap @@ -1 +1 @@ -233945 \ No newline at end of file +227576 \ No newline at end of file diff --git a/.forge-snapshots/add liquidity to already existing position with salt.snap b/.forge-snapshots/add liquidity to already existing position with salt.snap index ff76e7f86..243f23c8a 100644 --- a/.forge-snapshots/add liquidity to already existing position with salt.snap +++ b/.forge-snapshots/add liquidity to already existing position with salt.snap @@ -1 +1 @@ -153643 \ No newline at end of file +153494 \ No newline at end of file diff --git a/.forge-snapshots/addLiquidity CA fee.snap b/.forge-snapshots/addLiquidity CA fee.snap index b4678d19b..885c6a535 100644 --- a/.forge-snapshots/addLiquidity CA fee.snap +++ b/.forge-snapshots/addLiquidity CA fee.snap @@ -1 +1 @@ -331309 \ No newline at end of file +331160 \ No newline at end of file diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap index c59df0298..0d0b571fd 100644 --- a/.forge-snapshots/addLiquidity with empty hook.snap +++ b/.forge-snapshots/addLiquidity with empty hook.snap @@ -1 +1 @@ -286302 \ No newline at end of file +286153 \ No newline at end of file diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap index c5bed833e..c5edfa171 100644 --- a/.forge-snapshots/addLiquidity with native token.snap +++ b/.forge-snapshots/addLiquidity with native token.snap @@ -1 +1 @@ -143853 \ No newline at end of file +143704 \ No newline at end of file diff --git a/.forge-snapshots/create new liquidity to a position with salt.snap b/.forge-snapshots/create new liquidity to a position with salt.snap index cbb3de708..d633601b5 100644 --- a/.forge-snapshots/create new liquidity to a position with salt.snap +++ b/.forge-snapshots/create new liquidity to a position with salt.snap @@ -1 +1 @@ -301821 \ No newline at end of file +301672 \ No newline at end of file diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap index 74aa20508..f6e21d211 100644 --- a/.forge-snapshots/initialize.snap +++ b/.forge-snapshots/initialize.snap @@ -1 +1 @@ -61862 \ No newline at end of file +61811 \ No newline at end of file diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap index 81ca44cf1..c6b439c0f 100644 --- a/.forge-snapshots/poolManager bytecode size.snap +++ b/.forge-snapshots/poolManager bytecode size.snap @@ -1 +1 @@ -21709 \ No newline at end of file +21667 \ No newline at end of file diff --git a/.forge-snapshots/removeLiquidity CA fee.snap b/.forge-snapshots/removeLiquidity CA fee.snap index 082d59d10..bd25f2f9d 100644 --- a/.forge-snapshots/removeLiquidity CA fee.snap +++ b/.forge-snapshots/removeLiquidity CA fee.snap @@ -1 +1 @@ -186775 \ No newline at end of file +186626 \ No newline at end of file diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap index e7fddfb22..9aebeeca5 100644 --- a/.forge-snapshots/removeLiquidity with empty hook.snap +++ b/.forge-snapshots/removeLiquidity with empty hook.snap @@ -1 +1 @@ -123143 \ No newline at end of file +122994 \ No newline at end of file diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap index 8b983838d..57ce483d8 100644 --- a/.forge-snapshots/removeLiquidity with native token.snap +++ b/.forge-snapshots/removeLiquidity with native token.snap @@ -1 +1 @@ -119930 \ No newline at end of file +119781 \ No newline at end of file diff --git a/.forge-snapshots/simple addLiquidity second addition same range.snap b/.forge-snapshots/simple addLiquidity second addition same range.snap index ccf9f3450..56be2edd4 100644 --- a/.forge-snapshots/simple addLiquidity second addition same range.snap +++ b/.forge-snapshots/simple addLiquidity second addition same range.snap @@ -1 +1 @@ -104932 \ No newline at end of file +104808 \ No newline at end of file diff --git a/.forge-snapshots/simple addLiquidity.snap b/.forge-snapshots/simple addLiquidity.snap index 8f3accdaa..cb67d6f19 100644 --- a/.forge-snapshots/simple addLiquidity.snap +++ b/.forge-snapshots/simple addLiquidity.snap @@ -1 +1 @@ -167424 \ No newline at end of file +167300 \ No newline at end of file diff --git a/.forge-snapshots/simple removeLiquidity some liquidity remains.snap b/.forge-snapshots/simple removeLiquidity some liquidity remains.snap index fc72404ca..a0071306b 100644 --- a/.forge-snapshots/simple removeLiquidity some liquidity remains.snap +++ b/.forge-snapshots/simple removeLiquidity some liquidity remains.snap @@ -1 +1 @@ -98529 \ No newline at end of file +98405 \ No newline at end of file diff --git a/.forge-snapshots/simple removeLiquidity.snap b/.forge-snapshots/simple removeLiquidity.snap index 0eb1ac8de..f1d44602e 100644 --- a/.forge-snapshots/simple removeLiquidity.snap +++ b/.forge-snapshots/simple removeLiquidity.snap @@ -1 +1 @@ -90569 \ No newline at end of file +90445 \ No newline at end of file diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap index 4fc9f9feb..261cf66ae 100644 --- a/.forge-snapshots/simple swap with native.snap +++ b/.forge-snapshots/simple swap with native.snap @@ -1 +1 @@ -116827 \ No newline at end of file +116663 \ No newline at end of file diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap index 7a20c6b3d..5ee86dce6 100644 --- a/.forge-snapshots/simple swap.snap +++ b/.forge-snapshots/simple swap.snap @@ -1 +1 @@ -131988 \ No newline at end of file +131824 \ No newline at end of file diff --git a/.forge-snapshots/swap CA fee on unspecified.snap b/.forge-snapshots/swap CA fee on unspecified.snap index 27c7f51ac..a75595573 100644 --- a/.forge-snapshots/swap CA fee on unspecified.snap +++ b/.forge-snapshots/swap CA fee on unspecified.snap @@ -1 +1 @@ -183126 \ No newline at end of file +182962 \ No newline at end of file diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap index 8550686dc..e5f8861df 100644 --- a/.forge-snapshots/swap against liquidity with native token.snap +++ b/.forge-snapshots/swap against liquidity with native token.snap @@ -1 +1 @@ -112548 \ No newline at end of file +112435 \ No newline at end of file diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap index 14ee97dfc..d0890ccf3 100644 --- a/.forge-snapshots/swap against liquidity.snap +++ b/.forge-snapshots/swap against liquidity.snap @@ -1 +1 @@ -123891 \ No newline at end of file +123778 \ No newline at end of file diff --git a/.forge-snapshots/swap burn 6909 for input.snap b/.forge-snapshots/swap burn 6909 for input.snap index b19efd36d..d997832ef 100644 --- a/.forge-snapshots/swap burn 6909 for input.snap +++ b/.forge-snapshots/swap burn 6909 for input.snap @@ -1 +1 @@ -135923 \ No newline at end of file +135785 \ No newline at end of file diff --git a/.forge-snapshots/swap burn native 6909 for input.snap b/.forge-snapshots/swap burn native 6909 for input.snap index dc06b6c6a..324ba79d2 100644 --- a/.forge-snapshots/swap burn native 6909 for input.snap +++ b/.forge-snapshots/swap burn native 6909 for input.snap @@ -1 +1 @@ -125140 \ No newline at end of file +125038 \ No newline at end of file diff --git a/.forge-snapshots/swap mint native output as 6909.snap b/.forge-snapshots/swap mint native output as 6909.snap index fa5caa1ba..c290ce5bd 100644 --- a/.forge-snapshots/swap mint native output as 6909.snap +++ b/.forge-snapshots/swap mint native output as 6909.snap @@ -1 +1 @@ -147180 \ No newline at end of file +147042 \ No newline at end of file diff --git a/.forge-snapshots/swap mint output as 6909.snap b/.forge-snapshots/swap mint output as 6909.snap index 1acf3c68f..873d723a3 100644 --- a/.forge-snapshots/swap mint output as 6909.snap +++ b/.forge-snapshots/swap mint output as 6909.snap @@ -1 +1 @@ -163842 \ No newline at end of file +163678 \ No newline at end of file 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 b2d6ca0cd..1f83ba701 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 @@ -222199 \ No newline at end of file +221922 \ No newline at end of file diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap index 96c9f4d55..b6f7b05d8 100644 --- a/.forge-snapshots/swap with dynamic fee.snap +++ b/.forge-snapshots/swap with dynamic fee.snap @@ -1 +1 @@ -148043 \ No newline at end of file +147879 \ No newline at end of file diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap index 897a376b0..939a6cc8a 100644 --- a/.forge-snapshots/swap with hooks.snap +++ b/.forge-snapshots/swap with hooks.snap @@ -1 +1 @@ -123903 \ No newline at end of file +123790 \ No newline at end of file diff --git a/.forge-snapshots/swap with lp fee and protocol fee.snap b/.forge-snapshots/swap with lp fee and protocol fee.snap index 9efd3b6c3..52d7b3932 100644 --- a/.forge-snapshots/swap with lp fee and protocol fee.snap +++ b/.forge-snapshots/swap with lp fee and protocol fee.snap @@ -1 +1 @@ -180223 \ No newline at end of file +180059 \ 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 cb2abe163..cb4e4e791 100644 --- a/.forge-snapshots/swap with return dynamic fee.snap +++ b/.forge-snapshots/swap with return dynamic fee.snap @@ -1 +1 @@ -155902 \ No newline at end of file +155738 \ No newline at end of file diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap index 265212952..b9ffd5fe9 100644 --- a/.forge-snapshots/update dynamic fee in before swap.snap +++ b/.forge-snapshots/update dynamic fee in before swap.snap @@ -1 +1 @@ -158505 \ No newline at end of file +158341 \ No newline at end of file diff --git a/src/libraries/TickMath.sol b/src/libraries/TickMath.sol index 4628870b5..9f8b108ac 100644 --- a/src/libraries/TickMath.sol +++ b/src/libraries/TickMath.sol @@ -71,12 +71,15 @@ library TickMath { if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128; - if (tick > 0) price = type(uint256).max / price; + assembly { + // if (tick > 0) price = type(uint256).max / price; + if sgt(tick, 0) { price := div(not(0), price) } - // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. - // we then downcast because we know the result always fits within 160 bits due to our tick input constraint - // we round up in the division so getTickAtSqrtPrice of the output price is always consistent - sqrtPriceX96 = uint160((price >> 32) + (price & ((1 << 32) - 1) == 0 ? 0 : 1)); + // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. + // we then downcast because we know the result always fits within 160 bits due to our tick input constraint + // we round up in the division so getTickAtSqrtPrice of the output price is always consistent + sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1))) + } } }