> For the complete documentation index, see [llms.txt](https://docs.tonco.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tonco.io/contracts-v1.6-forthcoming/position_nft.md).

# Position NFT

### position\_nft

* [Description](#description)
* [Data Storage](#data-storage)
* [Interface](#interface)
* [Messages](#messages)

## Description

The **Position NFT** represents a single liquidity position as a standalone, TEP-62/TEP-64 compatible NFT contract. Its address is deterministic — derived from `{pool, index}` — so the pool can always recompute and trust it. The NFT holds the position's liquidity, tick range and fee counters, and works hand in hand with the [Pool](/contracts-v1.6-forthcoming/pool.md): the pool seeds it on mint, and burns flow through it so it can verify ownership and tick consistency. The owner can transfer it, deposit part of it into their Account, or burn it — including via a plain wallet `burn` text comment, a front-end-free escape hatch (see BURN\_WITH\_TEXT).

## Interface

### getPoolAddress

(address) getPoolAddress ()

This function returns pool address that created this Position NFT

#### Return Values

| # | Type    | Description         |
| - | ------- | ------------------- |
| 0 | address | address in question |

### getUserAddress

(address) getUserAddress ()

This function returns user address that owned created this Position NFT

#### Return Values

| # | Type    | Description         |
| - | ------- | ------------------- |
| 0 | address | address in question |

### getPositionInfo

(int, int, int, int, int) getPositionInfo ()

This function returns data stored in Position NFT and is related to the position

#### Return Values

| # | Type | Description                                                                                              |
| - | ---- | -------------------------------------------------------------------------------------------------------- |
| 0 | int  | liquidity that this position owns                                                                        |
| 1 | int  | lower tick of the position                                                                               |
| 2 | int  | upper tick of the position                                                                               |
| 3 | int  | fee growth of jetton0 in the given range at moment of the creation or latest collect of the NFT position |
| 4 | int  | fee growth of jetton1 in the given range at moment of the creation or latest collect of the NFT position |

### get\_nft\_data

(bool, int, address, address, cell) get\_nft\_data ()

This function returns data of this Position NFT that is related to NFT as TEP-62 It also attaches some values to transfer them to pool

#### Return Values

| # | Type    | Description                                                                                                |
| - | ------- | ---------------------------------------------------------------------------------------------------------- |
| 0 | bool    | Is position active (in our case, if positionv3::liquidity != 0)                                            |
| 1 | int     | positionv3::index                                                                                          |
| 2 | address | positionv3::pool\_address                                                                                  |
| 3 | address | Owner address (positionv3::user\_address)                                                                  |
| 4 | cell    | Content of the NFT. The cell with a dict that has position data appended to the cell for the pool to parse |

## Messages

### POSITIONNFTV3\_POSITION\_INIT

Opcode : **0xd5ecca2a**

Initial message that pools sends to the NFT after state\_init\
Access Rights: Accepted only from the pool that owns this NFT (its address is fixed at creation). Sent right after deployment to fill in the position.<br>

<table data-full-width="true"><thead><tr><th width="90">Path</th><th width="200">Mnemonic</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td></td><td>op</td><td>Uint(32),op</td><td></td></tr><tr><td></td><td>query_id</td><td>Uint(64)</td><td>queryid as of the TON documentation</td></tr><tr><td></td><td>user_address</td><td>Address(267)</td><td>NFT owner</td></tr><tr><td></td><td>0</td><td>Cell(0) pos0</td><td>Position</td></tr><tr><td>0</td><td>liquidity</td><td>Uint(128)</td><td>Amount of the liquidity</td></tr><tr><td>0</td><td>tickLower</td><td>Int(24)</td><td>Lower tick of the NFT</td></tr><tr><td>0</td><td>tickUpper</td><td>Int(24)</td><td>Upper tick of the NFT</td></tr><tr><td>0</td><td>feeGrowthInside0LastX128</td><td>Int(256),x128</td><td>Fees collected before the position was opened or updated for jetton0 (in pool terms)</td></tr><tr><td>0</td><td>feeGrowthInside1LastX128</td><td>Int(256),x128</td><td>Fees collected before the position was opened or updated for jetton1 (in pool terms)</td></tr><tr><td>0</td><td>0</td><td>Maybe Cell(1) fees</td><td>newFees</td></tr><tr><td>0->0</td><td>feeGrowthInside0LastX128</td><td>Int(256),x128</td><td>Optional updated fee growth for jetton0 inside the range, per unit of liquidity, 128.128 fixed point (used by the indexer to track fees to collect)</td></tr><tr><td>0->0</td><td>feeGrowthInside1LastX128</td><td>Int(256),x128</td><td>Optional updated fee growth for jetton1 inside the range, per unit of liquidity, 128.128 fixed point (used by the indexer to track fees to collect)</td></tr><tr><td></td><td>1</td><td>Cell(0) Indexer</td><td>Fee counters From</td></tr><tr><td>1</td><td>seqno</td><td>Uint(64),Indexer</td><td>Indexer-only. Pool sequence number at mint time</td></tr><tr><td>1</td><td>nftIndex</td><td>Uint(64),Indexer</td><td>Indexer-only. Index of this position NFT in the collection</td></tr><tr><td>1</td><td>jetton0Amount</td><td>Coins(124),Indexer</td><td>Indexer-only. Amount of jetton0 deposited into this position at mint</td></tr><tr><td>1</td><td>jetton1Amount</td><td>Coins(124),Indexer</td><td>Indexer-only. Amount of jetton1 deposited into this position at mint</td></tr><tr><td>1</td><td>tick</td><td>Int(24),Indexer</td><td>Indexer-only. Pool current tick at mint time</td></tr><tr><td>1</td><td>sqrtPriceX96</td><td>Uint(160),PriceX96, Indexer</td><td>Current price</td></tr></tbody></table>

<details>

<summary>TL-B Description</summary>

This is a preliminary tl-b - subject to change

{% code title="Tlb for POSITIONNFTV3\_POSITION\_INIT" overflow="wrap" lineNumbers="true" %}

```javascript
POSITIONNFTV3_POSITION_INIT#d5ecca2a 
    query_id:uint64
    user_address:MsgAddress
    pos0:^Pos0Type
    Indexer:^IndexerType
= ContractMessages;
_ 
    feeGrowthInside0LastX128:int256
    feeGrowthInside1LastX128:int256
= FeesType;
_ 
    liquidity:uint128
    tickLower:int24
    tickUpper:int24
    feeGrowthInside0LastX128:int256
    feeGrowthInside1LastX128:int256
    fees:(Maybe ^FeesType)
= Pos0Type;
_ 
    seqno:uint64
    nftIndex:uint64
    jetton0Amount:(VarUInteger 16)
    jetton1Amount:(VarUInteger 16)
    tick:int24
    sqrtPriceX96:uint160
= IndexerType;
```

{% endcode %}

</details>

### POSITIONNFT\_POSITION\_BURN

Opcode : **0x46ca335a**

Message from the pool that is part of burn process. This message carries new feeGrowthInside?Last values form the pool\
Access Rights: Accepted only from the pool that owns this NFT. It is the pool's reply within the burn flow, carrying the fee counters needed to settle the position.<br>

<table data-full-width="true"><thead><tr><th width="90">Path</th><th width="200">Mnemonic</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td></td><td>op</td><td>Uint(32),op</td><td></td></tr><tr><td></td><td>query_id</td><td>Uint(64)</td><td>queryid as of the TON documentation</td></tr><tr><td></td><td>nft_owner</td><td>Address(267)</td><td>NFT owner to receive funds</td></tr><tr><td></td><td>liquidity2Burn</td><td>Uint(128)</td><td>Amount of the liquidity to burn, 0 is a valid amount, in this case only collected fees would be returned</td></tr><tr><td></td><td>tickLower</td><td>Int(24)</td><td>Lower tick of the NFT. NFT would check that it is the same as in position</td></tr><tr><td></td><td>tickUpper</td><td>Int(24)</td><td>Upper tick of the NFT. NFT would check that it is the same as in position</td></tr><tr><td></td><td>0</td><td>Cell(0) old_fee_cell</td><td>Fee counters From</td></tr><tr><td>0</td><td>feeGrowthInside0LastX128</td><td>Int(256),x128</td><td>Current fee growth for jetton0 inside the position range supplied by the pool, per unit of liquidity, 128.128 fixed point. The NFT uses the delta versus its stored value to compute fees owed</td></tr><tr><td>0</td><td>feeGrowthInside1LastX128</td><td>Int(256),x128</td><td>Current fee growth for jetton1 inside the position range supplied by the pool, per unit of liquidity, 128.128 fixed point. The NFT uses the delta versus its stored value to compute fees owed</td></tr><tr><td></td><td>action</td><td>Cell(0),Maybe</td><td>Cell that describes what to do with burn result</td></tr></tbody></table>

<details>

<summary>TL-B Description</summary>

This is a preliminary tl-b - subject to change

{% code title="Tlb for POSITIONNFT\_POSITION\_BURN" overflow="wrap" lineNumbers="true" %}

```javascript
POSITIONNFT_POSITION_BURN#46ca335a 
    query_id:uint64
    nft_owner:MsgAddress
    liquidity2Burn:uint128
    tickLower:int24
    tickUpper:int24
    old_fee_cell:^Old_fee_cellType
    action:(Maybe ^Cell)
= ContractMessages;
_ 
    feeGrowthInside0LastX128:int256
    feeGrowthInside1LastX128:int256
= Old_fee_cellType;
```

{% endcode %}

</details>

### BURN\_WITH\_TEXT

Opcode : **0x0**

A plain wallet transfer with the text comment `burn`, sent by the position owner to burn the **whole** position manually. Meant for an ordinary, non-technical user: no front-end, no SDK and no knowledge of message layouts required. From any wallet (Tonkeeper, Tonhub, etc.) the owner just sends a small amount of GRAM to the address of their own position NFT and types `burn` in the comment field. The wallet encodes that comment in the standard TON way — 32 zero bits (op = 0) followed by the UTF-8 bytes of the text, no query\_id — and the NFT recognises it.

The comment must be exactly `burn`: the contract compares the whole comment against the literal `burn`, so any extra text or argument is rejected (WRONG\_COMMAND). There is no `burn <amount>` form — this path always burns the entire position. Accepted only from the current owner of the NFT (otherwise INVALID\_CALLER); the NFT then forwards START\_BURN to the pool for the position's full liquidity.

Why it exists: a deliberate self-custodial escape hatch. The owner can always reclaim their funds directly on-chain with nothing but a wallet — no front-end, SDK or indexer needed — even if the indexer is down or the web front-end is unavailable to them (e.g. geo-blocking). (At the TS level the same body is `beginCell().storeUint(0, 32).storeBuffer(Buffer.from("burn")).endCell()` — see `sendBurnText` in jest/burn.system.spec.ts — but a real user never needs this; it is just the wallet comment under the hood.)

Dangers — mind the gas. The NFT requires a minimum attached value (BURN\_GAS\_AMOUNT, \~0.1 GRAM in release builds) and rejects anything below it with INSUFFICIENT\_GAS. That minimum only covers the first hop, though: a burn fans out into a multi-contract round-trip (NFT → pool → router → jetton wallets). If too little GRAM is attached, an intermediate step can run out of gas and the funds are NOT recovered automatically. Over-fund to be safe (the tests attach \~0.5 GRAM); unspent gas is returned. Always send the comment to the correct NFT address — a typo or a foreign/forged NFT just wastes the gas spent.\
Access Rights: Allowed only for the current NFT owner. Sending the text comment `burn` initiates a full-position burn toward the pool.<br>

<table data-full-width="true"><thead><tr><th width="90">Path</th><th width="200">Mnemonic</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td></td><td>op</td><td>Uint(32),op</td><td></td></tr><tr><td></td><td>text</td><td>String(32)</td><td>Text with command</td></tr></tbody></table>

<details>

<summary>TL-B Description</summary>

This is a preliminary tl-b - subject to change

{% code title="Tlb for BURN\_WITH\_TEXT" overflow="wrap" lineNumbers="true" %}

```javascript
BURN_WITH_TEXT#0 
    text:Text
= ContractMessages;
```

{% endcode %}

</details>

### POSITIONNFTV3\_NFT\_TRANSFER

Opcode : **0x5fcc3d14**

Transfer LP NFT to another user. Please be warned that some UI elements could be unable to track it. However with SDK it still can be burned\
Access Rights: Allowed only for the current NFT owner. Transfers ownership of the position to a new address.<br>

<table data-full-width="true"><thead><tr><th width="90">Path</th><th width="200">Mnemonic</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td></td><td>op</td><td>Uint(32),op</td><td></td></tr><tr><td></td><td>query_id</td><td>Uint(64)</td><td>queryid as of the TON documentation</td></tr><tr><td></td><td>new_owner</td><td>Address(267)</td><td>New NFT owner</td></tr><tr><td></td><td>response_destination</td><td>Address(267)</td><td>Address to receive response</td></tr><tr><td></td><td>custom_payload</td><td>Cell(0),Maybe</td><td>Custom information for NFT. Ignored by our implementation</td></tr><tr><td></td><td>forward_amount</td><td>Coins(124)</td><td>Amount of coins to forward for processing</td></tr><tr><td></td><td>forward_payload</td><td>Cell(0),Either</td><td>Payload for processing</td></tr></tbody></table>

<details>

<summary>TL-B Description</summary>

This is a preliminary tl-b - subject to change

{% code title="Tlb for POSITIONNFTV3\_NFT\_TRANSFER" overflow="wrap" lineNumbers="true" %}

```javascript
POSITIONNFTV3_NFT_TRANSFER#5fcc3d14 
    query_id:uint64
    new_owner:MsgAddress
    response_destination:MsgAddress
    custom_payload:(Maybe ^Cell)
    forward_amount:(VarUInteger 16)
    forward_payload:(Either ^Cell Cell)
= ContractMessages;
```

{% endcode %}

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tonco.io/contracts-v1.6-forthcoming/position_nft.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
