Skip to main content

Ticks and Ranges

V3 uses a tick system to discretize the continuous price space. Each tick represents a specific price point, and liquidity positions are defined by a range of ticks.

Ticks

A tick i maps to a price via: p(i)=1.0001ip(i) = 1.0001^i Each tick represents a 0.01% (1 basis point) price change from the adjacent tick. Ticks are integers ranging from -887272 to 887272.
TickPrice
01.0
11.0001
1001.01005
100002.71828
-100000.36788

Tick Spacing

Not every tick is usable — positions must align to tick spacing boundaries determined by the pool’s fee tier:
Fee TierTick SpacingPrice Granularity
0.01%1Every 0.01%
0.05%10Every 0.10%
0.3%60Every 0.60%
1%200Every 2.02%
When creating a position, tickLower and tickUpper must be multiples of the pool’s tick spacing.

sqrtPriceX96

On-chain, prices are stored as sqrtPriceX96 — the square root of the price multiplied by 2^96: sqrtPriceX96=p×296\text{sqrtPriceX96} = \sqrt{p} \times 2^{96} This encoding enables efficient fixed-point arithmetic without floating-point operations. To convert back to a human-readable price: p=(sqrtPriceX96296)2p = \left(\frac{\text{sqrtPriceX96}}{2^{96}}\right)^2

Price Ranges

A liquidity position is defined by [tickLower, tickUpper]:

Converting Between Prices and Ticks

Price to tick: i=log1.0001(p)i = \lfloor \log_{1.0001}(p) \rfloor Then round to the nearest usable tick (multiple of tick spacing). Tick to price: p=1.0001ip = 1.0001^i

Token0 and Token1

V3 defines prices as token1 per token0 (price = token1/token0). The token with the lower address is always token0. For a KAS/USDC pool where KAS is token0:
  • price = 0.05 means 1 KAS = 0.05 USDC
  • tick ≈ -29959

Nearest Usable Tick

When specifying a price range, the exact tick might not align with the pool’s tick spacing. Use the nearest usable tick:
nearestUsableTick = round(tick / tickSpacing) × tickSpacing
The API and SDK handle this conversion automatically.