Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Position NFT

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: 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

#TypeDescription
0addressaddress in question

getUserAddress

(address) getUserAddress ()

This function returns user address that owned created this Position NFT

Return Values

#TypeDescription
0addressaddress 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

#TypeDescription
0intliquidity that this position owns
1intlower tick of the position
2intupper tick of the position
3intfee growth of jetton0 in the given range at moment of the creation or latest collect of the NFT position
4intfee 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

#TypeDescription
0boolIs position active (in our case, if positionv3::liquidity != 0)
1intpositionv3::index
2addresspositionv3::pool_address
3addressOwner address (positionv3::user_address)
4cellContent 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.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
user_address Address(267) NFT owner
0 Cell(0) pos0 Position
0 liquidity Uint(128) Amount of the liquidity
0 tickLower Int(24) Lower tick of the NFT
0 tickUpper Int(24) Upper tick of the NFT
0 feeGrowthInside0LastX128 Int(256),x128 Fees collected before the position was opened or updated for jetton0 (in pool terms)
0 feeGrowthInside1LastX128 Int(256),x128 Fees collected before the position was opened or updated for jetton1 (in pool terms)
0 0 Maybe Cell(1) fees newFees
0->0 feeGrowthInside0LastX128 Int(256),x128 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)
0->0 feeGrowthInside1LastX128 Int(256),x128 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)
1 Cell(0) Indexer Fee counters From
1 seqno Uint(64),Indexer Indexer-only. Pool sequence number at mint time
1 nftIndex Uint(64),Indexer Indexer-only. Index of this position NFT in the collection
1 jetton0Amount Coins(124),Indexer Indexer-only. Amount of jetton0 deposited into this position at mint
1 jetton1Amount Coins(124),Indexer Indexer-only. Amount of jetton1 deposited into this position at mint
1 tick Int(24),Indexer Indexer-only. Pool current tick at mint time
1 sqrtPriceX96 Uint(160),PriceX96, Indexer Current price
TL-B Description This is a preliminary tl-b - subject to change **Tlb for POSITIONNFTV3_POSITION_INIT**
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;

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.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
nft_owner Address(267) NFT owner to receive funds
liquidity2Burn Uint(128) Amount of the liquidity to burn, 0 is a valid amount, in this case only collected fees would be returned
tickLower Int(24) Lower tick of the NFT. NFT would check that it is the same as in position
tickUpper Int(24) Upper tick of the NFT. NFT would check that it is the same as in position
0 Cell(0) old_fee_cell Fee counters From
0 feeGrowthInside0LastX128 Int(256),x128 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
0 feeGrowthInside1LastX128 Int(256),x128 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
action Cell(0),Maybe Cell that describes what to do with burn result
TL-B Description This is a preliminary tl-b - subject to change **Tlb for POSITIONNFT_POSITION_BURN**
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;

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.

PathMnemonicTypeDescription
op Uint(32),op
text String(32) Text with command
TL-B Description This is a preliminary tl-b - subject to change **Tlb for BURN_WITH_TEXT**
BURN_WITH_TEXT#0 
    text:Text
= ContractMessages;

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.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
new_owner Address(267) New NFT owner
response_destination Address(267) Address to receive response
custom_payload Cell(0),Maybe Custom information for NFT. Ignored by our implementation
forward_amount Coins(124) Amount of coins to forward for processing
forward_payload Cell(0),Either Payload for processing
TL-B Description This is a preliminary tl-b - subject to change **Tlb for POSITIONNFTV3_NFT_TRANSFER**
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;