core.test_position
Tests for Position Calculator Module.
This module tests the Decimal-precision functions for converting between prices and ticks in Uniswap V3, matching the Solidity TickMath.sol behavior.
CRITICAL: Decimal Adjustment Order (d1 - d0)
The Uniswap V3 tick formula is:
tick = log_{1.0001}(canonical_price * 10^(d1 - d0))
Where:
- canonical_price = token1/token0 (Uniswap's native format)
- d0 = token0 decimals
- d1 = token1 decimals
IMPORTANT: The exponent is (d1 - d0), NOT (d0 - d1)!
EXCEL VERIFICATION GUIDE
For a mathematician to verify Uniswap V3 math in Excel:
Tick from Price:
- Formula:
=LN(Price * 10^(Dec1-Dec0)) / LN(1.0001) - Result is typically rounded to integer.
- Formula:
Price from Tick:
- Formula:
=(1.0001^Tick) / 10^(Dec1-Dec0)
- Formula:
Liquidity Amounts (simplified):
- If
P <= Pa(Price below range): Only Token0 needed. - If
P >= Pb(Price above range): Only Token1 needed. - If
Pa < P < Pb(In range): Mix of both. - See
test_current_tick_in_rangefor specific formulas.
- If
Test: Canonical price 0.000333 WETH/USDC with base_token_id=0.
NUMERICAL EXAMPLE (PC-PT-01)
Input: price = 0.000333 (WETH per USDC, canonical format) base_token_id = 0 (Canonical) decimals = (6, 18)
Tick Calculation: adjusted = 0.000333 * 10^(18-6) = 0.000333 * 10^12 = 3.33e8 tick = ln(3.33e8) / ln(1.0001) = +196,206
Expected: tick ~ +196,200 (snapped to tick_spacing=10)
EXCEL REPRODUCTION
1. Inputs (Cells A1:B3)
| Cell | Parameter | Value |
|---|---|---|
| B1 | Price | 0.000333 |
| B2 | Dec0 | 6 |
| B3 | Dec1 | 18 |
2. Calculation (Cells B4:B5)
| Cell | Name | Formula | Expectation |
|---|---|---|---|
| B4 | Adj | =B1 * 10^(B3-B2) |
333000000 |
| B5 | Tick | =ROUND(LN(B4)/LN(1.0001), 0) |
~196206 |
Test: Inverted price 3000 USDC/WETH with base_token_id=1.
NUMERICAL EXAMPLE (PC-PT-02)
Input: price = 3000 (USDC per WETH, inverted format) base_token_id = 1 (Inverted) decimals = (6, 18)
Conversion: canonical_price = 1/3000 = 0.000333 WETH per USDC
Tick Calculation: adjusted = 0.000333 * 10^12 = 3.33e8 tick = ln(3.33e8) / ln(1.0001) ~ +196,206
Expected: tick ~ +196,200 (POSITIVE, same as canonical input!)
Test: Both inverted and canonical inputs produce same tick.
NUMERICAL EXAMPLE (PC-PT-03)
Inverted: 3000 USDC/WETH (base_token_id=1) Canonical: 1/3000 = 0.000333 WETH/USDC (base_token_id=0)
Both should produce the same canonical tick.
Test: Tick is properly snapped to tick_spacing=10.
NUMERICAL EXAMPLE (PC-PT-04)
For any price, the resulting tick should be divisible by tick_spacing.
Test: Tick is properly snapped to tick_spacing=60.
NUMERICAL EXAMPLE (PC-PT-05)
For 0.3% fee tier, tick_spacing = 60.
Test: Zero price returns tick = 0.
NUMERICAL EXAMPLE (PC-PT-06)
Input: price = 0 Expected: tick = 0 (guard clause)
Test: Decimal precision is maintained (50 digits).
NUMERICAL EXAMPLE (PC-PT-07)
Using high-precision input to verify Decimal handling.
Test: Tick 196200 with base_token_id=0 returns Canonical price.
NUMERICAL EXAMPLE (PC-TP-01)
Input: tick = 196200 base_token_id = 0 (Canonical) decimals = (6, 18)
Calculation: raw = 1.0001^196200 ~ 3.33e8 canonical = 3.33e8 / 10^12 = 0.000333 WETH/USDC
Expected: price ~ 0.000333 WETH per USDC
EXCEL REPRODUCTION
1. Inputs (Cells A1:B3)
| Cell | Parameter | Value |
|---|---|---|
| B1 | Tick | 196200 |
| B2 | Dec0 | 6 |
| B3 | Dec1 | 18 |
2. Calculation (Cell B4)
| Cell | Name | Formula | Expectation |
|---|---|---|---|
| B4 | Price | =(1.0001^B1)/10^(B3-B2) |
~0.000333 |
Test: Tick 196200 with base_token_id=1 returns Inverted price.
NUMERICAL EXAMPLE (PC-TP-02)
Input: tick = 196200 base_token_id = 1 (Inverted)
Expected: price ~ 3000 USDC per WETH
Test: Tick 0 returns price = 1.0 (decimal adjusted).
NUMERICAL EXAMPLE (PC-TP-03)
Input: tick = 0
Calculation: raw = 1.0001^0 = 1.0 canonical = 1.0 / 10^12 = 1e-12 (very small) inverted = 1e12 (very large)
This represents the theoretical neutral point.
Test: price -> tick -> price round-trip maintains precision.
NUMERICAL EXAMPLE (PC-TP-04)
Original: 3000 USDC/WETH tick = calculate_price_to_tick(3000) recovered = calculate_tick_to_price(tick)
Error should be < 0.01%
Test: Canonical price 0.0005 produces positive tick.
NUMERICAL EXAMPLE
canonical_price = 0.0005 WETH per USDC (ETH at $2000) adjusted = 0.0005 * 10^12 = 5e8 tick = ln(5e8) / ln(1.0001) ~ +200,314
Tick is POSITIVE because ETH is expensive.
Test canonical tick -> price conversion.
Test canonical price range -> tick bounds.
Test tick bounds -> canonical price range.
Standard USDC/WETH pool parameters.
Test: Current tick below range produces 100% token0.
NUMERICAL EXAMPLE (PC-TA-01)
Position range: ticks [195000, 200000] Current tick: 190000 (BELOW range)
Expected: amount0 > 0 amount1 = 0 (all Token0)
Test: Current tick above range produces 100% token1.
NUMERICAL EXAMPLE (PC-TA-02)
Position range: ticks [195000, 200000] Current tick: 205000 (ABOVE range)
Expected: amount0 = 0 amount1 > 0 (all Token1)
Test: Current tick in range produces both tokens.
NUMERICAL EXAMPLE (PC-TA-03)
Position range: ticks [195000, 200000] Current tick: 197000 (IN range)
Expected: amount0 > 0 amount1 > 0 (mix of both)
EXCEL REPRODUCTION
1. Inputs (Cells A1:B5)
| Cell | Parameter | Value |
|---|---|---|
| B1 | Liquidity | 1e18 |
| B2 | TickLower | 195000 |
| B3 | TickUpper | 200000 |
| B4 | TickCurr | 197000 |
2. Sqrt Prices (Cells B6:B8)
| Cell | Name | Formula | Description |
|---|---|---|---|
| B6 | SqrtPl | =1.0001^(B2/2) |
Lower |
| B7 | SqrtPu | =1.0001^(B3/2) |
Upper |
| B8 | SqrtP | =1.0001^(B4/2) |
Current |
3. Token Amounts (Cells B9:B10)
| Cell | Name | Formula | Expectation |
|---|---|---|---|
| B9 | Token0 | =B1 * (B7-B8) / (B8*B7) |
> 0 |
| B10 | Token1 | =B1 * (B8-B6) |
> 0 |
Test: Adjusted amounts are divided by 10^decimals.
NUMERICAL EXAMPLE (PC-TA-04)
token0_adjusted = token0_raw / 10^6 token1_adjusted = token1_raw / 10^18
Test: Using real sqrtPriceX96 from mainnet.
NUMERICAL EXAMPLE (PC-TA-05)
Real USDC/WETH pool sqrtPriceX96 (example): 1771845812700903892492222464458752 (ETH ~ $3500)
Test: Convert standard sqrtPriceX96 to prices.
NUMERICAL EXAMPLE
sqrtPriceX96 for ETH at $3000 in USDC/WETH pool: sqrt(0.000333 * 10^12) * 2^96 ~ 1.44e33
Test: Wei/smallest unit conversions are correct.
Verify MIN_TICK matches Solidity.
Verify MAX_TICK matches Solidity.
Test: Price at MIN_TICK is valid and very small.
Test: Price at MAX_TICK is valid and very large.
For USDC(6)/WETH(18) pool with decimal adjustment 10^12: canonical_price = 1.0001^887272 / 10^12 ~ 3.4e26