Documentation Index
Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
Use this file to discover all available pages before exploring further.
This page consolidates the derivations behind CLMM. For the on-chain implementation, see
products/clmm/math (which cites this page) and products/clmm/ticks-and-positions (which motivates the tick lattice).Why sqrt-price, not price
Uniswap-v3-family CLMMs represent price as its square root, stored in a fixed-pointQ64.64:
- Linear liquidity math. The amount of token0 or token1 in a price range turns out to be a linear function of
sqrt_price, not ofprice. Storingsqrt_pricelets the swap step evaluate those linear formulas without computing a square root. - Overflow control.
sqrt_price · Lfits inu256for all reasonable parameters;price · Lcan overflow much sooner. - Tick math is uniform. Because ticks are defined as
1.0001^i,sqrt(price) = 1.00005^iis also an exact power-of-1.00005 ladder. Each tick-cross translates to a small multiplication insqrt_price_x64space.
price = (sqrt_price_x64 / 2^64)^2.
Tick lattice
Prices are discretized onto a grid:tick_i is an i32. The live range is [MIN_TICK, MAX_TICK] = [−443636, 443636], giving a price range of roughly [2^−128, 2^128]. Each pool’s tick_spacing is set by its fee tier: smaller spacings for tight pairs (e.g. stablecoin 0.01% tier uses spacing 1), larger spacings for volatile pairs (0.25% tier uses 60, 1% tier uses 120).
Positions must have tick_lower and tick_upper aligned to tick_spacing. A pool’s active ticks (those with liquidity starting or ending there) are the only ticks the swap step cares about.
Liquidity-to-amount
For a position with liquidityL and price range [sqrt_lo, sqrt_hi] (all sqrt_price values):
| Pool state | Amount of token0 | Amount of token1 |
|---|---|---|
Price above range (sqrt_p ≥ sqrt_hi) | 0 | L · (sqrt_hi − sqrt_lo) |
| Price in range | L · (sqrt_hi − sqrt_p) / (sqrt_p · sqrt_hi) | L · (sqrt_p − sqrt_lo) |
Price below range (sqrt_p ≤ sqrt_lo) | L · (sqrt_hi − sqrt_lo) / (sqrt_lo · sqrt_hi) | 0 |
(x_v, y_v) chosen so the pool’s current (sqrt_p, L) is consistent with L = sqrt(x_v · y_v). Integrating from sqrt_p to the range boundary yields the amounts above.
Inverse formulas (used when minting a position for a given amount0 or amount1):
Single-tick swap step
Within a single tick range the pool behaves like a CPMM. Given currentsqrt_p and target sqrt_target:
Exact-input step
GivenΔin_remaining:
0→1 swap lowers sqrt_p (price declines as we sell token0 in). A 1→0 swap raises it. The formulas are symmetric with sqrt_p and sqrt_target swapped.
Exact-output step
Same structure, solving forΔin instead.
Multi-tick swap loop
A swap iterates over ticks until the input is exhausted or the price limit is hit:single_step uses the pool’s current L. L changes only when crossing an initialized tick. Liquidity between ticks is constant, which is what makes the step math closed-form.
liquidity_net at a tick is the signed sum of position liquidities that start at that tick minus those that end there. Crossing upward adds liquidity_net; crossing downward subtracts it.
When the pool has limit orders open at a tick, the cross-tick step also opportunistically consumes part of the swap input to fill those orders (FIFO across cohorts). The matching algorithm and the dynamic-fee surcharge that may apply on top of the base step are documented in products/clmm/math; they don’t change the closed-form single-step formulas above.
Fee-growth accumulators
CLMM tracks fees per unit of active liquidity, per side, globally and per tick:single_step:
fee_growth_global does not move on this step, since no token on that side was paid as input.)
When crossing a tick, the program flips fee_growth_outside:
tick_current. When tick_current is above the tick, outside means “below”. When tick_current is below, outside means “above”. The flip swaps the interpretation.
fee_growth_inside for a position
Given a position [tick_lower, tick_upper] and the current tick_current:
s are:
IncreaseLiquidity, DecreaseLiquidity, CollectFees).
Worked example — crossing one tick
Pool (simplified):sqrt_p_x64 = 2^64 · 1.0 = 2^64(price = 1.0)L = 1_000_000tick_current = 0- Next initialized tick below:
tick = −60,sqrt_price = 1.0001^(−30) ≈ 0.99700,liquidity_net = −400_000(this tick ends a position, so a downward cross removes 400k) - Fee rate: 0.25%
Δin = 10_000 token0, direction = 0→1.
Step 1 — up to sqrt_target = 0.99700 · 2^64:
L = 600_000:
The next initialized tick (say tick = −120) is at sqrt = 0.99402. Recompute amount_in_to_target:
Δin_remaining. Cross again. Continue until Δin_remaining reaches zero.
The full sequence of Δout accumulates to the final swap output.
Initialization and overflow guards
MIN_SQRT_PRICE_X64andMAX_SQRT_PRICE_X64correspond totick = ±443636. Any swap that would pushsqrt_poutside this range reverts.- The user’s
sqrt_price_limitparameter must lie in the same interval; the program checks. - Products of
L · Δsqrtare computed inu256then shifted back tou128to avoid overflow.
Differences vs Uniswap v3
- Oracle. Raydium’s
ObservationStatestores(block_timestamp, tick_cumulative, seconds_per_liquidity_cumulative)ring buffer; slightly different wire format from Uniswap’s but the same TWAP math. - Token-2022. Raydium CLMM supports Token-2022 mints; the transfer-fee variant requires additional pre/post-swap amount adjustments. See
algorithms/token-2022-transfer-fees. - Tick bitmap. Raydium packs the initialized-tick bitmap into
[u64; 16]per pool for fastfind_next_initialized_tick; Uniswap uses a per-word on-chain mapping. The tradeoff is rent vs lookup cost. - Reward slots. Raydium supports 3 per-pool reward streams with separate
reward_growth_global_x64counters; same structure as the fee-growth accumulator.
Pointers
products/clmm/math— the on-chain implementation and worked example with actual CLMM struct fields.products/clmm/ticks-and-positions— tick lattice,liquidity_net/gross, active-range semantics.products/clmm/fees— the fee-growth accumulator in action.
- Uniswap v3 whitepaper (canonical derivation of sqrt-price math).
- Raydium CLMM program source.


