Skip to main content
decrease_liquidity removes some or all liquidity from a position. It does not transfer token value to the holder. The contract converts withdrawn principal and pending fees into public tokens_owed balances, which the holder later withdraws through collect. Decrease and collect are separate operations:

Outcome

The decrease is complete when the transaction is accepted, the public position shows the remaining liquidity, withdrawn principal and fees are reflected in tokens_owed, and the replacement PositionNFT is stored. No payout record is created until a later collect.

Before you start

Read the current position, slot, fee growth, and freeze state. Reserve the current PositionNFT, choose the exact liquidity amount to remove, and calculate raw token minimums using the current price and the position’s fixed range.

Inputs and outputs

The transition accepts:
  • Current PositionNFT record
  • Public liquidity to remove
  • Public token0 minimum
  • Public token1 minimum
It returns the public token ID and a replacement PositionNFT record. The pool, token programs, and range come from the PositionNFT. The public Position mapping must match those values.

Exit controls

The position must not be frozen, and the requested amount cannot exceed its public liquidity. The decrease finalize path does not check pool entry controls. An LP can reduce exposure while pool, global, token, or pair controls stop new entry and trading. A position-specific freeze still blocks the decrease. A frozen live position is handled separately by the administrator’s freeze path. Freeze removes all active liquidity and settles value into tokens_owed, then blocks decrease and collect until unfreeze.

Principal calculation

The contract calculates principal at the current square-root price using the position’s fixed lower and upper ticks. Depending on price:
  • Below range, withdrawn principal is token0.
  • In range, withdrawn principal can include both tokens.
  • Above range, withdrawn principal is token1.
Principal amounts and public minimums use native base units. The contract checks:
A failed minimum check rejects the finalize and its state changes.

Fee settlement order

The position’s pending fee entitlement is settled using its full liquidity before the requested reduction:
The new owed balances are:
The position then stores:
  • Reduced liquidity
  • Current inside-growth checkpoints
  • Updated owed balances
For a partial decrease, all pending fees through the checkpoint settle, including the share earned by liquidity that remains. Later growth applies only to the reduced liquidity. This ordering closes the old liquidity epoch before opening the reduced one.

Tick updates

At the lower boundary:
At the upper boundary:
Outside fee-growth values are preserved while the boundary remains initialized. If liquidity_gross reaches zero, the contract:
  1. Reconnects the boundary’s previous and next neighbors.
  2. Updates cached nearest-tick pointers if necessary.
  3. Removes the boundary from the ticks mapping.
Removing the mapping row prevents a later LP epoch at the same numeric tick from inheriting stale outside-growth state. If lower and upper boundaries interact with the same neighboring ticks, the contract rereads the upper boundary after unlinking the lower one so it does not write stale list links. Read Initialized tick index.

Active-liquidity update

The slot’s active liquidity decreases only if the current tick is inside the range:
An out-of-range decrease changes position and boundary liquidity but does not change current active liquidity. Use the accepted slot state, not a pre-transaction quote, when reconciling this condition. Reaching an initialized tick at an exact user price limit completes the crossing. A swap that stops exactly at a boundary can therefore change whether the position is active before the decrease executes.

Partial and full decrease

Partial decrease

  • Position remains in the mapping.
  • Replacement PositionNFT remains necessary.
  • Remaining liquidity may continue earning fees if active.
  • Settled principal and fees stay in tokens_owed.

Full decrease

  • Position liquidity becomes zero.
  • Boundary ticks may be removed if no other position uses them.
  • All principal and settled fees stay in tokens_owed.
  • The position cannot be burned until both owed balances are collected.
A full decrease leaves principal and settled fees in tokens_owed. The LP must collect those amounts before burning the position.

Rounding and settlement cadence

Principal is rounded down under the amount-for-liquidity formulas. Fee entitlement is also rounded down to an integer native base unit when the checkpoint advances. Each partial decrease can discard a sub-unit fee fraction. A strategy that repeatedly removes small amounts can settle more often than a single large decrease and may leave more dust in the contract. There is no per-position residual field, pool-level residual carry, or generic surplus sweep. Discarding the sub-Q128 remainder prevents fee fractions from moving across liquidity epochs.

Operational sequence

For a managed exit:
  1. Read the latest slot, position, and boundary state.
  2. Compute principal in native base units using the current Q128.128 price.
  3. Set raw minimum amounts for the intended slippage tolerance.
  4. Submit decrease with the latest ownership record.
  5. Save the replacement record.
  6. Verify new public liquidity and owed balances.
  7. Collect the desired native base-unit amounts.
  8. Burn only after liquidity and both owed balances are zero.
See Collecting and burning and LP workflow.