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:

  1. Tick from Price:

    • Formula: =LN(Price * 10^(Dec1-Dec0)) / LN(1.0001)
    • Result is typically rounded to integer.
  2. Price from Tick:

    • Formula: =(1.0001^Tick) / 10^(Dec1-Dec0)
  3. 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_range for specific formulas.
USDC_DECIMALS = 6
WETH_DECIMALS = 18
TICK_SPACING_500 = 10
TICK_SPACING_3000 = 60
def test_canonical_price_0_000333_base_token_0():

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
def test_inverted_price_3000_base_token_1():

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!)

def test_both_formats_produce_same_tick():

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.

def test_tick_spacing_10_snapping():

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.

def test_tick_spacing_60_snapping():

Test: Tick is properly snapped to tick_spacing=60.

NUMERICAL EXAMPLE (PC-PT-05)

For 0.3% fee tier, tick_spacing = 60.

def test_zero_price_returns_zero():

Test: Zero price returns tick = 0.

NUMERICAL EXAMPLE (PC-PT-06)

Input: price = 0 Expected: tick = 0 (guard clause)

def test_high_precision_decimal():

Test: Decimal precision is maintained (50 digits).

NUMERICAL EXAMPLE (PC-PT-07)

Using high-precision input to verify Decimal handling.

def test_tick_196200_base_token_0():

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
def test_tick_196200_base_token_1():

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

def test_tick_zero():

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.

def test_round_trip_consistency():

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%

def test_canonical_price_to_tick_positive():

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.

def test_canonical_tick_to_price():

Test canonical tick -> price conversion.

def test_canonical_price_range_to_ticks():

Test canonical price range -> tick bounds.

def test_canonical_ticks_to_price_range():

Test tick bounds -> canonical price range.

@pytest.fixture
def sample_pool_params():

Standard USDC/WETH pool parameters.

def test_current_tick_below_range(sample_pool_params):

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)

def test_current_tick_above_range(sample_pool_params):

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)

def test_current_tick_in_range(sample_pool_params):

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
def test_adjusted_amounts_have_correct_decimals(sample_pool_params):

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

def test_real_pool_sqrt_price():

Test: Using real sqrtPriceX96 from mainnet.

NUMERICAL EXAMPLE (PC-TA-05)

Real USDC/WETH pool sqrtPriceX96 (example): 1771845812700903892492222464458752 (ETH ~ $3500)

def test_standard_sqrt_price():

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

def test_wei_conversion():

Test: Wei/smallest unit conversions are correct.

def test_min_tick_constant():

Verify MIN_TICK matches Solidity.

def test_max_tick_constant():

Verify MAX_TICK matches Solidity.

def test_tick_to_price_at_min_tick():

Test: Price at MIN_TICK is valid and very small.

def test_tick_to_price_at_max_tick():

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