Skip to main content
mint creates a concentrated-liquidity position from token records. It writes public economic state and returns a PositionNFT record. Minting does not import earlier pool fees. The contract initializes the position’s fee checkpoints at the current fee growth inside its chosen range.

Outcome

Minting is complete when the transaction is accepted, the public position row contains the expected range and liquidity, the returned PositionNFT is stored, and both token change records are accounted for.

Prerequisites

Before minting:
  1. Confirm the program deployment and checksum.
  2. Confirm the pool exists and is enabled.
  3. Confirm global, token, and pair pause controls permit entry.
  4. Verify the supplied token IDs match canonical pool token0 and token1.
  5. Read the current slot and tick spacing.
  6. Select aligned lower and upper ticks.
  7. Find current predecessor hints for boundaries that are not initialized.
  8. Select token records with enough unspent value.
  9. Obtain freezelist non-inclusion proofs for signer, position owner, and withdrawal address.
The Q128.128 fee-growth schema is incompatible with the earlier scalar mapping layout, so adopting it requires a fresh deployment. A wallet must not submit records or pool keys to a newly deployed program merely because they came from a contract with the same source name. Program addresses, records, and mapping state are deployment-specific.

Inputs

The transition accepts:
  • A private nonce
  • A token0 record
  • A token1 record
  • A private recipient address
  • A private immutable withdrawal address
  • A public MintPositionRequest
  • Public token0 and token1 program IDs
  • Three pairs of MerkleProof values for signer, recipient, and withdrawal
The request contains:
The range, desired amounts, minimum amounts, pool, and hints are public. The recipient is a private input. The resulting token_id is public. The investigator-owned MintComplianceRecord supports authorized review of the mint. It contains the token ID, token programs, nonce, request, caller, signer, position owner, and immutable withdrawal address. The request’s public fields remain visible.

Range validation

The contract requires:
The active-range convention is:
Read Choosing a range for the inventory and boundary implications.

Native base-unit amounts

Desired and minimum amounts use each token’s native base units. The contract calculates the maximum liquidity supported by the desired amounts at the current Q128.128 square-root price. It then calculates actual base-unit amounts with explicit rounding and checks that:
  • Actual amount does not exceed desired amount.
  • Actual amount meets the corresponding minimum.
  • Any token required by the current price region has a nonzero amount.
The private-to-public token calls move the full desired amounts into AMM custody. Dynamic change records hold only input-record value above those desired transfers. After the contract calculates the actual amounts used for liquidity, it credits each desired - used excess to the new position’s public tokens_owed balance. A newly minted position can therefore begin with a nonzero owed balance.

Boundary initialization

Each boundary has:
  • liquidity_gross
  • Signed liquidity_net
  • Outside fee growth for both tokens
  • Previous and next initialized-tick pointers
For a new tick at or below the current tick, outside fee growth is initialized to current global growth. For a new tick above the current tick, outside growth starts at zero. This makes prior fee history outside the new position’s entitlement. At the lower tick:
At the upper tick:
Both gross values must remain within max_liquidity_per_tick. New boundaries are inserted into the pool’s linked tick index using caller-supplied predecessor hints. Existing boundaries keep their current list links.

Fee checkpoint

After both ticks are updated, the contract derives current fee growth inside the range:
The result is stored as:
  • fee_growth_inside0_last_x_128
  • fee_growth_inside1_last_x_128
This snapshot establishes the position’s first liquidity epoch. The position can earn only growth that occurs after this checkpoint while its liquidity is active. The values are two-limb wrapping Q128.128 accumulators. An indexer must preserve hi and lo as arbitrary-precision integers. Read Q128.128 fee growth.

Pool active liquidity

If the current tick is inside the new range, the slot’s active liquidity increases immediately. If the position is out of range, only its boundary state changes. It will enter the active set when price later crosses the appropriate tick. The slot also tightens its cached nearest initialized-tick pointers if a new boundary is closer to the current tick.

Outputs

A successful mint returns:
  • Public token_id
  • PositionNFT record
  • Token0 change record
  • Token1 change record
  • Investigator-owned MintComplianceRecord
The PositionNFT contains owner, immutable withdrawal address, token ID, token program IDs, pool, and tick range. It does not contain live liquidity or fee balances. Those remain in the public positions mapping. Persist:
  • Original transaction ID
  • Program ID and checksum
  • Pool key and token ID
  • Returned PositionNFT ciphertext
  • Decrypted record metadata
  • Returned change records
  • Public position state after finalization
Reconcile the new position’s tokens_owed0 and tokens_owed1 against the desired and actual used amounts. Do not treat the token change records as a refund of AMM-held excess.

Common rejection causes

  • Wrong token order
  • Pool, token, pair, or global pause
  • Invalid signer, recipient, or withdrawal freezelist proof
  • Lower or upper tick not aligned to spacing
  • Invalid or stale insertion hint
  • Zero calculated liquidity
  • Per-tick liquidity cap exceeded
  • Minimum amounts above actual consumed amounts
  • Reused nonce and request producing an existing token ID
  • Spent or insufficient token record
Do not automatically retry a failed mint with the same stale state. Refresh the slot, boundary mappings, hints, record inventory, and deployment identity first. After minting, continue with LP workflow, Increasing liquidity, or Fee entitlements.