> ## Documentation Index
> Fetch the complete documentation index at: https://shield.fi/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Collecting and burning

> Fee and principal collection, confidential payout records, and final position removal.

Collect and burn perform different jobs.

* `collect` transfers requested owed amounts into token records and advances fee checkpoints.
* `burn` consumes an empty ownership record and removes the public position row.

Neither operation removes active liquidity. Liquidity must be reduced first.

## Outcome

Collection is complete when the transaction is accepted, requested owed amounts are transferred into token records, the replacement `PositionNFT` is stored, and the wallet has discovered both payout records. Burning is complete only after liquidity and owed amounts are zero and the public position row is removed.

## Before you start

Read the public position and current inside fee growth, verify the position is not frozen, reserve the current `PositionNFT`, choose base-unit collection amounts within the settled and pending entitlement, and obtain non-inclusion proofs for the NFT owner and immutable withdrawal address.

## What can be collected

A position can have value from:

* Pending LP fees not yet reflected in `tokens_owed`
* Previously settled LP fees
* Principal credited by decrease or freeze

The public `tokens_owed0` and `tokens_owed1` fields include only amounts already settled. A collect transaction also calculates pending fees from current inside growth before checking the requested amounts.

## Collect inputs and outputs

`collect` accepts:

* Current `PositionNFT` record
* Public base-unit token0 amount requested
* Public base-unit token1 amount requested
* Public token0 and token1 program IDs
* Two owner and two withdrawal `MerkleProof` values

It returns:

* Replacement `PositionNFT` record
* Token0 payout record
* Token1 payout record

The token IDs must match the pool. Payout always goes to the immutable `withdrawal` address in the NFT. That address cannot be the AMM, router, or zero address.

Collection amounts and position accounting are public. The withdrawal address and payout token records are confidential under Aleo's record model, but the investigator-owned mint record contains the withdrawal address.

Read [Public data](../confidentiality/public-data) for the broader observability boundary.

## Amount validation

Collection requests use native token base units. The contract checks each request directly against total owed after pending fee settlement.

## Pending-fee settlement

For each token:

```text theme={"languages":{"custom":["/languages/leo.tmLanguage.json"]}}
pending =
    floor(
        wrapping_sub(inside_now, inside_last)
        * position_liquidity
        / 2^128
    )

total_owed = stored_tokens_owed + pending
remaining_owed = total_owed - amount_requested
```

The contract stores current inside growth as the new checkpoint even if part of `total_owed` remains uncollected. The uncollected integer amount is preserved in `tokens_owed`.

The fractional remainder below one native base unit is discarded when the checkpoint advances. Collect changes fee checkpoints and owed balances.

Read [Fee entitlements](./fee-entitlements) and [Q128.128 fee growth](../math/q128-fee-growth).

## Choosing requested amounts

A caller may request less than the available amount. This is useful when:

* Keeping part of the balance in the AMM's owed accounting
* Matching a custody or treasury instruction
* Avoiding an overestimate caused by stale off-chain state
* Collecting one token without collecting the other

To request the full amount, calculate pending fees from a consistent slot, tick, and position snapshot. The integer result is already in native base units. A swap accepted before collect can only increase eligible growth for an active position, but tick movement can change the inside-growth derivation. Use modular arithmetic and current boundaries.

A conservative request below the calculated total can succeed while leaving the remainder owed. An overestimate is rejected.

## Settlement dust

Each step's LP fee is recorded with 128 fractional bits and no cross-epoch residual. This prevents a later LP set from receiving an earlier set's fractional fee.

Two floors still matter:

1. Step growth is `floor(lp_fee * 2^128 / active_liquidity)`.
2. Position settlement is `floor(delta_growth * position_liquidity / 2^128)`.

The first leaves less than one native token base unit unallocated across the active set for that step. The second leaves less than one base unit for the position at settlement. Because collect advances the checkpoint, repeated small collections can leave more settlement dust than a less frequent schedule.

The contract has no generic sweep for this surplus. Protocol collection is limited to recorded `protocol_fees0` and `protocol_fees1`.

See [Rounding, overflow, and invariants](../math/rounding-overflow-and-invariants).

## Collect under controls

Collect does not apply the pool entry-pause hierarchy. Disabling a pool or pausing trading does not by itself trap an LP's settled value.

A position freeze is different. Frozen positions cannot collect. If a live position is frozen, the freeze path first removes its liquidity and settles principal and fees into `tokens_owed`. Unfreeze makes that value collectable but does not restore liquidity.

## Burn prerequisites

`burn` succeeds only when:

```text theme={"languages":{"custom":["/languages/leo.tmLanguage.json"]}}
position exists
position is not frozen
position.liquidity == 0
position.tokens_owed0 == 0
position.tokens_owed1 == 0
```

Burn consumes the `PositionNFT` and removes the public `positions[token_id]` entry. It returns no replacement ownership record.

The transition does not inspect pending fee growth. With zero position liquidity, later fee growth creates no additional position entitlement. Any fees earned before liquidity reached zero were settled by the decrease or freeze operation that removed the liquidity.

## Complete closeout

Use this sequence:

1. Decrease all remaining liquidity.
2. Wait for acceptance and save the replacement `PositionNFT`.
3. Read public `tokens_owed` balances.
4. Include any pending fee estimate if liquidity was not actually zero.
5. Collect token0 and token1 in native base units.
6. Save the replacement ownership record from collect.
7. Verify liquidity and both owed balances are zero.
8. Burn using the latest record.
9. Mark the token ID closed in the custody and accounting systems.

Do not submit burn with the pre-collect record. It has been spent.

## Closeout records

An institutional closeout record should retain:

* Deployment ID and program checksum
* Position token ID and pool key
* Decrease transaction and credited principal
* Fee calculation inputs and rounding policy
* Public requested collection amounts
* Payout record custody references
* Final zero position state
* Burn transaction removing the mapping row

The chain demonstrates the state transitions. Legal ownership, valuation policy, and accounting classification remain operator responsibilities.
