Concentrated liquidity
Price ranges determine where liquidity is active and which assets a position holds.
In a CLMM, each position contributes liquidity over a chosen interval. The pool's active liquidity is the sum of positions covering the current price. It is not the sum of token balances in the vaults.
Ticks and price
Ticks discretize prices. Tick indices are signed; token quantities are unsigned. Position endpoints must be ordered and aligned to the pool's tick spacing. The exact tick domain and fixed-point constants belong to the math reference, not a frontend approximation.
The pool tracks a square-root price and active liquidity. For price expressed as token B per token A, an A-to-B swap moves price down; B-to-A moves it up. UI prices must account for mint decimals.
flowchart LR
Start[Current square-root price] --> Step[Compute swap within active interval]
Step --> Bound{Reached initialized tick?}
Bound -->|Yes| Cross[Apply signed liquidity change]
Cross --> Step
Bound -->|No| End[Input consumed or explicit limit]
Crossing a boundary
A correct crossing updates active liquidity and the fee-growth boundary records. Direction matters: crossing the same tick in opposite directions applies opposite liquidity changes. A gap with no active liquidity must have a defined result; it cannot mint free output.
Full range is a position choice
Full range means using the supported outer ticks rounded inward to the pool spacing. Use full_range_ticks(spacing) and initialize only the two endpoint pages. At spacing 64 the endpoints are [-443584, 443584]. See construction and storage. It remains a CLMM position. It does not create a fungible share over every other position or turn the implementation into a separate CPMM engine.
These concepts follow established CLMM mechanics. grapl's own bounds, rounding, and account representation must be verified independently. See the Uniswap concentrated-liquidity explanation and the pinned implementation references.