CLMM
Raydium's original AMM is an elegant first design: deposit two tokens in equal value, the pool prices swaps via x * y = k, you earn fees proportional to your share. The problem the Concentrated Liquidity Market Maker (CLMM) set out to solve is that the standard AMM wastes most of the capital LPs deposit. This lecture covers what concentrated liquidity is, how Raydium CLMM represents it with ticks, why a position below the current price needs only one token rather than two, and what else CLMM changed. The mental model takes some unpacking but the payoff is understanding how every modern DEX with concentrated liquidity thinks about LP capital.What's wrong with the standard AMM
A constant-product pool prices trades along the hyperbola x * y = k. The curve covers every possible price from zero to infinity. As price moves up or down, reserves shift along the curve. The math is simple and the system works.
The trouble is that LPs end up providing depth at prices that will never trade. If the current SOL price is $200 and you deposit $10,000 into a standard SOL/USDC pool, a tiny fraction of your $10,000 is providing liquidity at prices near $200 (where trades actually happen). The rest of your capital is reserved for hypothetical trades at $1, at $5,000, at $100,000. Trades there will never happen, but your dollars are pinned to those price points anyway. They sit idle, earning no fees.
Empirically, in a standard SOL/USDC pool, an LP's capital that's "active" within any reasonable trading band is often less than 5% of their deposit. The other 95% is dead weight. They earn fees proportional to their share of total liquidity, but most of that liquidity isn't doing anything useful.
CLMM's idea: concentrated liquidity
CLMM lets an LP say: "I think SOL will trade between $180 and $220. Concentrate all my capital in that range." The LP picks a lower price Pl and an upper price Pu. Their capital provides depth only in [Pl, Pu]. If trades happen inside that range, they earn fees. If price moves outside their range, their position earns nothing until either the price comes back or the LP repositions.
The same $10,000 deposit in CLMM with a range of [$180, $220] provides depth comparable to roughly $100,000+ of standard-AMM liquidity, since none of the capital is wasted at unreachable prices. The exact multiplier depends on how narrow the range is. Narrower range means more concentration, which means more fees per dollar when active, but a higher risk that price leaves the range and the position earns nothing.
CLMM isn't strictly better than the standard AMM. It's a tradeoff: capital efficiency in exchange for active management. An LP who picks a tight range gets great returns when price stays inside, but loses fee income whenever price exits. The standard AMM's passive LPs earn less per dollar but never go "out of range." Which is better depends on the LP's willingness to monitor and adjust.
Ticks: discrete price levels
Now the implementation question. CLMM lets you pick a range [Pl, Pu]. But CLMM doesn't allow arbitrary prices for the boundaries. Ranges must start and end at specific discrete price levels called ticks.
A tick is just a price level on a predefined grid. The formula is:
undefinedprice(tick) = 1.0001 ^ tickEach tick is 0.0001 of a price multiplier from the next, which is 0.01% (one basis point). Tick 0 corresponds to price 1.0. Tick 1 corresponds to price 1.0001. Tick -1 to price 0.9999. And so on.
For a SOL/USDC pool with SOL around $200, the corresponding tick is around 52,983. The integer is large because the price ratio is far from 1, but the math handles it cleanly. Frontends and SDKs convert between tick numbers and human-readable prices for you. You almost never compute ticks by hand.
The number 1.0001 was chosen because it makes the per-tick step equal to a clean basis point. The whole tick range CLMM supports runs from roughly -443,636 to +443,636, which corresponds to a price range from about 1e-19 to 1e19. More than enough to cover every conceivable asset pair.
A few practical things to internalize about ticks:
Tick boundaries are integer-valued. You can't say "my range starts at price $217.23." You say "my range starts at tick 53,820," which the SDK will round to from your input price.
The same range can be expressed by different tick pairs depending on token order. CLMM pools have a notion of token0 and token1, decided by the sort order of the token mint addresses. Price is conventionally token1 per token0. If you swap the order, ticks flip sign.
Tick spacing controls granularity. A pool with tick spacing 60 only allows positions whose endpoints are multiples of 60. So instead of using every possible tick from 52,980 to 52,989, you'd be picking from a coarser ladder.
Fee tiers
The standard AMM has one fee, typically 0.25% on Raydium. CLMM has multiple, each with its own pool and tick spacing:
- 0.01% for pairs that should trade at almost identical prices, like two stablecoins. Tick spacing 1 (most granular).
- 0.05% for correlated assets that move closely together, like SOL and a liquid staking derivative such as jitoSOL or mSOL. Tick spacing 10.
- 0.25% for typical volatile pairs like SOL/USDC. Tick spacing 60.
- 1.00% for exotic pairs with high volatility. Tick spacing 200.
Each fee tier is a separate pool. So when you talk about "the SOL/USDC pool" on Raydium CLMM, you actually have to specify which one of several pools you mean. Liquidity is split across these tiers, which is a real downside: thin markets fragment further. Aggregators like Jupiter route trades through whichever pool gives the best execution.
LPs choose a fee tier based on the volatility they expect. Higher volatility means higher fee income but also more risk of price moving out of range. The coarser tick spacing for higher fee tiers reflects that fine-grained ranges are less useful for assets that move a lot.
Three position types: where single-sided liquidity comes from
Now to the part where CLMM starts to feel different from the standard AMM.
In the standard AMM, you always deposit both tokens, in the ratio set by the current pool price. There's no other option. In CLMM, the ratio depends on where your chosen range sits relative to the current price. Sometimes you deposit both tokens. Sometimes only one. And it's not up to you which case applies. The range you pick forces the composition.
Why this works: think in trade flows
The single-sided deposit rule seems strange at first. To make sense of it, watch what the pool actually does when price moves.
When price rises, someone is buying SOL. They send USDC into the pool, the pool sends SOL out. The pool gains USDC and loses SOL. From the pool's perspective, it just "sold SOL for USDC."
When price falls, someone is selling SOL. They send SOL into the pool, the pool sends USDC out. The pool gains SOL and loses USDC. From the pool's perspective, it just "bought SOL with USDC."
So a pool acts as a market maker that's always taking the other side of trades. To sell SOL (when price rises) it needs SOL inventory. To buy SOL (when price falls) it needs USDC inventory.
Now apply this to a CLMM position with range [Pl, Pu]:
Range entirely above current price (current price < Pl). For price to ever reach this range, it has to rise from where it is to Pl, then potentially keep rising up to Pu. The entire trip through the range is a rising-price trip. The pool is selling SOL the whole way. Your position needs SOL on hand to participate, so you deposit only SOL. As price rises through your range, your SOL gradually gets sold off in exchange for USDC. By the time price reaches Pu, all your SOL is gone, replaced by USDC at the highest prices in your range.
Range entirely below current price (current price > Pu). For price to enter this range, it has to fall from where it is to Pu, then potentially keep falling to Pl. The entire trip is a falling-price trip. The pool is buying SOL the whole way. Your position needs USDC ready to spend, so you deposit only USDC. As price falls through your range, your USDC gradually gets converted to SOL at the falling prices. By the time price reaches Pl, all your USDC is gone, replaced by SOL at the lowest prices in your range.
Range straddling current (Pl < current < Pu). The price can move either direction from the current spot. The pool might need SOL inventory (for upward moves) or USDC inventory (for downward moves). Your position needs both, in a ratio that depends on where current sits within the range.
The rule of thumb to remember: at the lower boundary Pl, a position holds 100% of token X (SOL in this example). At the upper boundary Pu, it holds 100% of token Y (USDC). In between, the position is a mix. Where the current price sits relative to these boundaries dictates the deposit composition.
Range orders: limit orders in disguise
The single-sided behavior turns CLMM into something the previous AMMs couldn't be: a venue for limit orders.
Suppose SOL is at $200 and you want to sell at $250. In the standard AMM, you'd have to actively monitor the price and execute a swap when it hits your target. In CLMM, you create a tight position with range [$250, $250.50]. The position is entirely above current price, so you deposit only SOL. If price never reaches $250, the position sits idle. If price moves through $250 to $250.50, your SOL gets swapped for USDC inside the range, and by the time price exits at the top, your position holds 100% USDC at an average price near $250.
You've effectively placed a sell order that fills around $250. Same logic in reverse for limit buys with a tight range below current.
The fill price isn't exactly the target. There's some spread between Pl and Pu, so the actual execution price is an average within the range. Tighter ranges mean closer-to-exact fills but smaller fee earnings while filling. This is the difference between a true limit order and a CLMM range order: the CLMM version still earns fees during the fill, in exchange for some slippage.
Several Solana limit-order frontends are built on this idea, mounting their UI on top of CLMM positions.
NFT positions
Standard AMM LP positions are SPL Tokens. Every LP in a standard pool has the same kind of claim, just for different amounts, so fungibility works. You can send your LP tokens to anyone, stake them in another protocol, swap them, anything an SPL Token can do.
CLMM positions can't be fungible SPL Tokens because they're not interchangeable. Two LPs in the same pool with different ranges have completely different exposures. If Alice has range [$180, $220] and Bob has range [$200, $300], their positions aren't comparable. You can't have a fungible "SOL/USDC CLMM LP token" because there's no single representative position.
CLMM uses NFTs instead. Each position is a non-fungible token whose metadata records the pool, the range (tickLower, tickUpper), the liquidity amount, and accumulated fees. The Raydium CLMM program is the standard entry point: LPs mint position NFTs through it, manage liquidity through it, collect fees through it. The position NFT is transferable like any other NFT, so you can sell your position on a secondary market or use it as collateral.
This is one of the things that makes building on CLMM more complex than the standard AMM. Every LP integration has to handle individual positions rather than treating LP shares as fungible balances.
A better TWAP
Standard AMM oracles use a single cumulative price counter, sampled at whatever times consumers care about. CLMM ships a more refined version.
Each CLMM pool keeps an observations array, a circular buffer of past (timestamp, tick cumulative) entries. Pools default to a small number of slots but can be extended to cover longer windows. The slots get filled on every state-changing interaction (swap, mint, burn). A consumer reading a TWAP for the last 30 minutes asks the pool to find observations bracketing the start and end of the window, and computes the average from those two readings.
The advantages over the standard AMM's design:
- Consumers don't need to take their own observation. The pool's observations are already there, indexed by time.
- Multiple consumers reading the same window share the cost.
- Pools with extended observation arrays cover hours or days of history.
CLMM also uses the geometric mean of tick (the log of price) rather than the arithmetic mean of raw price. This matters when prices can swing in large ratios. The geometric mean of $100 and $400 is $200. The arithmetic mean is $250. The geometric version is symmetric around the true price, which is more useful for risk-bearing applications.
When CLMM vs the standard AMM
CLMM strengths:
- Capital efficiency for LPs willing to manage positions
- Limit-order-like behavior via range orders
- Lower slippage for traders, since concentrated liquidity makes pools effectively deeper near current prices
- Stronger oracle for downstream protocols
CLMM weaknesses:
- LPs have to manage active positions, or accept that price will eventually move out of range
- Multiple fee tiers fragment liquidity across pools
- Tick math, NFT positions, and per-position fee accounting make the codebase and integrations more complex
- Less suitable for pairs where price has no natural "center" the LP can target
The standard AMM design is still a reasonable choice for some applications: assets with extreme volatility where any chosen range becomes irrelevant quickly, passive LPs who can't or won't monitor positions, simple integrations where fungible LP tokens make the rest of the program design cleaner. Raydium's standard AMM isn't deprecated. It coexists with CLMM because the tradeoffs go different ways for different use cases.