Skip to main content
Each pool stores initialized ticks in a doubly linked list. This avoids asking the swap caller to supply a sequence of tick hints and gives the contract a deterministic next boundary in either direction.

Sentinels

Pool creation writes two sentinel Tick entries:
  • Minimum sentinel at -400001
  • Maximum sentinel at 400001
At pool birth, the minimum sentinel points forward to the maximum sentinel, and the maximum sentinel points back to the minimum sentinel. The pool Slot also stores:
  • next_init_below, the nearest initialized tick at or below the current tick
  • next_init_above, the nearest initialized tick above the current tick

Inserting a boundary

Mint and increase accept tick_lower_hint and tick_upper_hint. A hint is the initialized predecessor of the new boundary. For an uninitialized boundary, finalize verifies:
  • The hinted tick belongs to the pool.
  • It is the minimum sentinel or has positive gross liquidity.
  • It is below the new tick.
  • Its next pointer is above the new tick.
The contract then splices the new tick between the predecessor and successor. If both position boundaries are new, the upper insertion re-reads its predecessor because the lower insertion may have changed the list.

Removing a boundary

Decrease and freeze call the shared liquidity-removal logic. When a boundary’s liquidity_gross becomes zero, the program links its predecessor directly to its successor and removes the tick mapping entry. Slot pointers are advanced if they referred to the removed boundary.

Walking during swaps

A single-hop swap starts from the slot’s nearest pointer and performs five swap iterations. Each iteration reads the next boundary, moves price toward that tick or the user limit, applies fees, crosses when appropriate, and updates the pointers. Each multi-hop leg performs three iterations. Route design must account for this bounded walk. A large input can remain partially unspent when the walk or price limit stops progress.

Exact-limit crossing

The crossing condition treats exact arrival at an initialized tick price as a crossing, including when the price equals sqrt_price_limit. Otherwise, the price could park at a boundary while the previous range’s liquidity remained active. This condition applies together with the current Q128 fee-growth types. See Exact-limit tick crossing for the combined invariant.

Indexer checks

An indexer can audit list integrity by checking reciprocal prev and next links, sorted order, pool identity, positive gross liquidity for non-sentinels, and agreement between slot pointers and the current tick. These checks detect corrupted or stale routing state earlier than a failed swap.