From 28fe307e0f82d4ec48dd56b44d1cf7cd05fb184b Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Tue, 3 Sep 2024 16:06:24 -0400 Subject: [PATCH 1/2] Spearbit 43 and 44 --- src/libraries/TickMath.sol | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/libraries/TickMath.sol b/src/libraries/TickMath.sol index 8c7108b0f..11fd21da6 100644 --- a/src/libraries/TickMath.sol +++ b/src/libraries/TickMath.sol @@ -69,6 +69,9 @@ library TickMath { if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick); + // The tick is decomposed into bits, and for each bit with index i that is set, the product of 1/sqrt(1.0001^(2^i)) + // is calculated. The constants used for this calculation are rounded to the nearest integer + // Equivalent to: // price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; // or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128 @@ -110,11 +113,11 @@ library TickMath { } } - /// @notice Calculates the greatest tick value such that getPriceAtTick(tick) <= price - /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getPriceAtTick may + /// @notice Calculates the greatest tick value such that getSqrtPriceAtTick(tick) <= sqrtPriceX96 + /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getSqrtPriceAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96 - /// @return tick The greatest tick for which the price is less than or equal to the input price + /// @return tick The greatest tick for which the getSqrtPriceAtTick(tick) is less than or equal to the input sqrtPriceX96 function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) { unchecked { // Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice(); @@ -219,9 +222,14 @@ library TickMath { log_2 := or(log_2, shl(50, f)) } - int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number + int256 log_sqrt10001 = log_2 * 255738958999603826347141; // Q22.128 number + // Magic number represents the ceiling of the maximum value of the error when approximating log_sqrt10001(x) int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); + + // Magic number represents the minimum value of the error when approximating log_sqrt10001(x), when + // sqrtPrice is from the range (2^-64, 2^64). This is safe as MIN_SQRT_PRICE is more than 2^-64. If MIN_SQRT_PRICE + // is changed, this may need to be changed too int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; From b4ea3ae3896d9f4036167e45737b1f43f5f32eb5 Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Wed, 4 Sep 2024 17:52:36 -0400 Subject: [PATCH 2/2] clarification --- src/libraries/TickMath.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/TickMath.sol b/src/libraries/TickMath.sol index 11fd21da6..daebab87d 100644 --- a/src/libraries/TickMath.sol +++ b/src/libraries/TickMath.sol @@ -70,7 +70,7 @@ library TickMath { if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick); // The tick is decomposed into bits, and for each bit with index i that is set, the product of 1/sqrt(1.0001^(2^i)) - // is calculated. The constants used for this calculation are rounded to the nearest integer + // is calculated (using Q128.128). The constants used for this calculation are rounded to the nearest integer // Equivalent to: // price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;