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

Router

Description

The Router is the system's central dispatcher and the custodian of all LP jetton wallets. Users reach the protocol by transferring jettons to the router with a payload (see router payloads); the router parses it and routes the funds to the right Pool for a swap or for funding a mint. It also deploys new pools (from the Pool Factory or the admin), pays funds back out through its own jetton wallets (PAY_TO), and supports a multihop shortcut. The router cannot cryptographically verify that a transfer notification came from a real jetton wallet, so it derives the target pool from the sender — a fake sender simply maps to a pool that does not exist. Critical parameters (admin, proxyTON wallet, flags, router/pool code) change only through a two-phase timelock; the admin is expected to be a multisig.

Interface

getRouterState

(address, address, address, address?, int, int, int) getRouterState ()

returns the router state and configuration

Return Values

#TypeDescription
0addressrouter admin address
1addresspool admin address (passed to pools on creation; has privileged pool rights)
2addresspool factory address (allowed to request pool creation)
3address?proxy TON wallet address (critial to multihop shortcut)
4introuter flags
5introuter seqno (monotonic counter for indexing)
6introuter version (e.g. 16000 = v1.6.000)

getPoolAddress

(address) getPoolAddress (jettonWallet0: address, jettonWallet1: address)

returns pool address for two given jetton_wallets belonging to the router

Parameters

#TypeNameDescription
0addressjettonWallet0Address of the jetton 0 wallet belonging to router
1addressjettonWallet1Address of the jetton 1 wallet belonging to router

Return Values

#TypeDescription
0addresspool address

getChildContracts

(cell, cell, cell, cell) getChildContracts ()

returns code of the child contracts deprecated

Return Values

#TypeDescription
0cellcode of the pool contract
1cellcode of the account contract
2cellcode of the nft position contract
3cellcode of the pool prototype contract

get_pending_timelocks

( int, int, address?, int, address?, int, int, int, cell?, int, cell?,) get_pending_timelocks ()

returns active router timelocks to monitor system state. Timestamp 0xFFFFFFFFFFFFFFFF means - never/timelock not active

Return Values

#TypeDescription
0intTimelock delay
1intTimestamp when new Admin Address can be committed
2address?New Admin Address
3intTimestamp when new Proxy Ton Address can be committed
4address?New Proxy Ton Address
5intTimestamp when new flags can be committed
6intNew Flags
7intTimestamp when new code can be committed
8cell?Cell with new code
9intTimestamp when new pool code can be committed
10cell?Cell with new pool code

Messages

JETTON_TRANSFER_NOTIFICATION

Opcode : 0x7362d09c

Process router funding, payload determines if it is mint or swap
Access Rights: Sent by a jetton wallet when a user transfers tokens to the router. The router cannot verify that the notification truly comes from a real jetton wallet, so it does not authorize the sender directly: the target pool is derived from the sender, and if the sender is not a genuine wallet the derived pool simply does not exist. Funds that fail validation are returned to the user.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
jetton_amount Coins(124) Amount of coins sent to the router
from_user Address(267) User that originated the transfer
forward_payload Cell(0),Either, Payload Payload for processing
TL-B Description This is a preliminary tl-b - subject to change **Tlb for JETTON_TRANSFER_NOTIFICATION**
JETTON_TRANSFER_NOTIFICATION#7362d09c 
    query_id:uint64
    jetton_amount:(VarUInteger 16)
    from_user:MsgAddress
    forward_payload:(Either ^Cell Cell)
= ContractMessages;

ROUTER_CREATE_POOL

Opcode : 0x2e3034ef

Operation that deploys and inits new Pool contract for two given jettons identified by their wallets. New pool would reorder the jettons to match the invariant slice_hash(jetton0_address) > slice_hash(jetton1_address).
Access Rights: Allowed for the Pool Factory and the Router Admin (Superadmin). On a repeated CREATE_POOL for an existing pool the router forwards an initialization message, which lets the admin change tick spacing, NFT metadata, the initial price (while no positions exist), the Pool Admin and Controller, and the lock state; a request coming through the Pool Factory cannot assign the ALM Vault or Arbiter roles.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
jetton_wallet0 Address(267) Address of the jetton0 wallet. Used to compute pool address
jetton_wallet1 Address(267) Address of the jetton1 wallet. Used to compute pool address
tick_spacing Uint(24) Tick spacing to be used in the pool
initial_priceX96 Uint(160),PriceX96 Initial price for the pool
pool_active Uint(1) Should pool be created as active
protocol_fee Uint(16),Fee Protocol fee in FEE_DENOMINATOR parts. If value is more than 10000 value would be default
lp_fee_base Uint(16),Fee Liquidity provider base fee in FEE_DENOMINATOR. If value is more than 10000 value would be default
lp_fee_current Uint(16),Fee Current value of the pool fee, in case of dynamic adjustment. If value is more than 10000 value would be default
0 Cell(0) roles_cell Cell With Role
0 has_controller Uint(1),Bool Flag that shows if this message have a new controller address
0 controller_addr Address(267) Address that is allowed to change the fee. Can always be updated by admin.
0 has_creator Uint(1),Bool Flag that shows if this message have a new creator address
0 creator_addr Address(267) Address that is allowed to change the fee. Can always be updated by admin. If has_controller is false could be 00b
0 0 Cell(0) privilege_roles_cell Cell With Privilege Roles
0->0 has_arbiter Uint(1),Bool Flag that shows if this message have a new Arbiter address
0->0 arbiter_addr Address(267) Address that is allowed to make privileged swaps
0->0 has_alm Uint(1),Bool Flag that shows if this message have a new ALM address
0->0 alm_addr Address(267) Address that is used to identify ALM contract
0 1 Cell(0) roles_add Cell With Additional Roles
0->1 has_oracle Uint(1),Bool Flag that shows if this message have a new oracle address
0->1 oracle_addr Address(267) Address that is allowed to change the fee. Can always be updated by admin. Could be 00b
1 Cell(0) metadata_cell Cell With Metainfo
1 nftv3_content Cell(0),Metadata Metadata for the NFT Collection
1 nftv3item_content Cell(0),Metadata Metadata for the NFT Item
2 Cell(0) minter_cell Cell With Minters
2 jetton0_minter Address(267) Address of the jetton0 minter, used by indexer and frontend
2 jetton1_minter Address(267) Address of the jetton1 minter, used by indexer and frontend
TL-B Description This is a preliminary tl-b - subject to change **Tlb for ROUTER_CREATE_POOL**
ROUTER_CREATE_POOL#2e3034ef 
    query_id:uint64
    jetton_wallet0:MsgAddress
    jetton_wallet1:MsgAddress
    tick_spacing:uint24
    initial_priceX96:uint160
    pool_active:uint1
    protocol_fee:uint16
    lp_fee_base:uint16
    lp_fee_current:uint16
    roles_cell:^Roles_cellType
    metadata_cell:^Metadata_cellType
    minter_cell:^Minter_cellType
= ContractMessages;
_ 
    has_arbiter:uint1
    arbiter_addr:MsgAddress
    has_alm:uint1
    alm_addr:MsgAddress
= Privilege_roles_cellType;
_ 
    has_oracle:uint1
    oracle_addr:MsgAddress
= Roles_addType;
_ 
    has_controller:uint1
    controller_addr:MsgAddress
    has_creator:uint1
    creator_addr:MsgAddress
    privilege_roles_cell:^Privilege_roles_cellType   // optional ref (present only if a ref is left)
    roles_add:^Roles_addType   // optional ref (present only if a ref is left)
= Roles_cellType;
_ 
    nftv3_content:^Cell
    nftv3item_content:^Cell
= Metadata_cellType;
_ 
    jetton0_minter:MsgAddress
    jetton1_minter:MsgAddress
= Minter_cellType;

ROUTER_PAY_TO

Opcode : 0xa1daa96d

This message is the message that is sent to Router by the pool, an it would be accepted only from the pool:

Possible error codes

OperationError CoreValueMeaning
SWAPRESULT_SWAP_OK200Swap went fine
SWAPRESULT_SWAP_OUTPUT_TOO_SMALL230minAmount was not reached, swap reverted
SWAPRESULT_SWAP_INTERNAL_ERROR231Internal error, generally this should not happen
SWAPRESULT_SWAP_POOL_LOCKED232Attempt to swap in the locked pool
SWAPRESULT_SWAP_POOL_EMPTY233Attempt to swap in the empty pool
MINTRESULT_MINT_OK202Mint went fine
MINTRESULT_NO_LIQUIDITY226Minting Zero liquidity was asked (not always unintended)
MINTRESULT_TICK_IMPOSSIBLE_LOW220One of the ticks is too low
MINTRESULT_TICK_IMPOSSIBLE_HIGH221One of the ticks is too high
MINTRESULT_WRONG_TICK_SPACING222One of ticks is not divisible by tick_spacing
MINTRESULT_TOO_MANY_TICKS223Pool is full
MINTRESULT_TOO_MUCH_LIQUIDITY224Too much liquidity in one tick
MINTRESULT_NOT_ENOUGH_COINS225Not enough coins to mint
BURNRESULT_BURN_OK201Burn went fine

Access Rights: Accepted by the router only from a pool: the sender must match the pool the router itself derives, so no other contract can trigger a payout. The router then sends the funds out through its own jetton wallet. As an exception, when the router's emergency mode is enabled the Router Admin may invoke PAY_TO directly.
PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
reciever0 Address(267) Address of the first receiver of the funds
reciever1 Address(267) Address of the second receiver of the funds
exit_code0 Uint(8),ErrorCode Most significant byte. Reforge: result of the first processed order
exit_code1 Uint(8),ErrorCode Reforge: result of the second processed order
exit_code2 Uint(8),ErrorCode Reforge: result of the third processed order
exit_code3 Uint(8),ErrorCode Least significant byte. Swap/burn/collect result is here; reforge: fourth order
seqno Uint(64),Indexer Internal pool sequence number
0 Maybe Cell(1) coinsinfo_cell Cell with info about the coins
0 jetton0_address Address(267) Jetton to be sent to receiver0 identified by the wallet that belongs to router
0 jetton1_address Address(267) Jetton to be sent to receiver1 identified by the wallet that belongs to router
0 amount0 Coins(124) Amount of coins to be payed to receiver0
0 amount1 Coins(124) Amount of coins to be payed to receiver1
0 0 Cell(0) payload_cell Information about the payload
0->0 payload_amount0 Coins(124) Amount of GRAM to forward to receiver0 together with payload_0
0->0 payload_0 Cell(1),Maybe, Payload Forward payload delivered to receiver0 with the jetton transfer
0->0 payload_amount1 Coins(124) Amount of GRAM to forward to receiver1 together with payload_1
0->0 payload_1 Cell(1),Maybe, Payload Forward payload delivered to receiver1 with the jetton transfer
0->0 excess_address Address(267) Address to receive the excess gas
1 Maybe Cell(1) indexer_swap_info_cell Indexer-only. Post-swap pool state (null for non-swap)
1 liquidity Uint(128),Indexer Post-swap concentrated liquidity at current tick
1 price_sqrt Uint(160),Indexer,PriceX96 Post-swap square root of the price stored as fixed point 64.96
1 tick Int(24),Indexer Post-swap current tick
1 feeGrowthGlobal0X128 Int(256),Indexer Current range fee per unit of the liquidity for jetton0
1 feeGrowthGlobal1X128 Int(256),Indexer Current range fee per unit of the liquidity for jetton1
2 Maybe Cell(1) positions_cell Cell with positions (null for swap/collect)
2 0 Maybe Cell(1) burn0 Cell with burn number 0
2->0 index[0] Uint(64) Index of the burned position NFT
2->0 subindex[0] Uint(4) Subindex
2->0 liquidity[0] Uint(128) Position liquidity before this burn
2->0 tickLower[0] Int(24) lower bound of the range in which to mint
2->0 tickUpper[0] Int(24) upper bound of the range in which to mint
2->0 feeGrowthInside0LastX128[0] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->0 feeGrowthInside1LastX128[0] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2,0 0 Maybe Cell(1) new_fee_cell Fee counters to collect to (Used by indexer)
2->0->0 feeGrowthInside0CurrentX128[0] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->0->0 feeGrowthInside1CurrentX128[0] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2->0 liquidity2Burn[0] Uint(128) Amount of liquidity that was burned from this position
2 1 Maybe Cell(1) burn1 Cell with burn number 1
2->1 index[1] Uint(64) Index of the burned position NFT
2->1 subindex[1] Uint(4) Subindex
2->1 liquidity[1] Uint(128) Position liquidity before this burn
2->1 tickLower[1] Int(24) lower bound of the range in which to mint
2->1 tickUpper[1] Int(24) upper bound of the range in which to mint
2->1 feeGrowthInside0LastX128[1] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->1 feeGrowthInside1LastX128[1] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2,1 0 Maybe Cell(1) new_fee_cell Fee counters to collect to (Used by indexer)
2->1->0 feeGrowthInside0CurrentX128[1] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->1->0 feeGrowthInside1CurrentX128[1] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2->1 liquidity2Burn[1] Uint(128) Amount of liquidity that was burned from this position
2 2 Maybe Cell(1) burn2 Cell with burn number 2
2->2 index[2] Uint(64) Index of the burned position NFT
2->2 subindex[2] Uint(4) Subindex
2->2 liquidity[2] Uint(128) Position liquidity before this burn
2->2 tickLower[2] Int(24) lower bound of the range in which to mint
2->2 tickUpper[2] Int(24) upper bound of the range in which to mint
2->2 feeGrowthInside0LastX128[2] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->2 feeGrowthInside1LastX128[2] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2,2 0 Maybe Cell(1) new_fee_cell Fee counters to collect to (Used by indexer)
2->2->0 feeGrowthInside0CurrentX128[2] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->2->0 feeGrowthInside1CurrentX128[2] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2->2 liquidity2Burn[2] Uint(128) Amount of liquidity that was burned from this position
2 3 Maybe Cell(1) burn3 Cell with burn number 3
2->3 index[3] Uint(64) Index of the burned position NFT
2->3 subindex[3] Uint(4) Subindex
2->3 liquidity[3] Uint(128) Position liquidity before this burn
2->3 tickLower[3] Int(24) lower bound of the range in which to mint
2->3 tickUpper[3] Int(24) upper bound of the range in which to mint
2->3 feeGrowthInside0LastX128[3] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->3 feeGrowthInside1LastX128[3] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2,3 0 Maybe Cell(1) new_fee_cell Fee counters to collect to (Used by indexer)
2->3->0 feeGrowthInside0CurrentX128[3] Int(256),x128 Fee counter inside position range for jetton0, per unit of liquidity, in 128.128 fixed point
2->3->0 feeGrowthInside1CurrentX128[3] Int(256),x128 Fee counter inside position range for jetton1, per unit of liquidity, in 128.128 fixed point
2->3 liquidity2Burn[3] Uint(128) Amount of liquidity that was burned from this position
TL-B Description This is a preliminary tl-b - subject to change **Tlb for ROUTER_PAY_TO**
ROUTER_PAY_TO#a1daa96d 
    query_id:uint64
    reciever0:MsgAddress
    reciever1:MsgAddress
    exit_code0:uint8
    exit_code1:uint8
    exit_code2:uint8
    exit_code3:uint8
    seqno:uint64
    coinsinfo_cell:(Maybe ^Coinsinfo_cellType)
    indexer_swap_info_cell:(Maybe ^Indexer_swap_info_cellType)
    positions_cell:(Maybe ^Positions_cellType)
= ContractMessages;
_ 
    payload_amount0:(VarUInteger 16)
    payload_0:(Maybe ^Cell)
    payload_amount1:(VarUInteger 16)
    payload_1:(Maybe ^Cell)
    excess_address:MsgAddress
= Payload_cellType;
_ 
    jetton0_address:MsgAddress
    jetton1_address:MsgAddress
    amount0:(VarUInteger 16)
    amount1:(VarUInteger 16)
    payload_cell:^Payload_cellType   // optional ref (present only if a ref is left)
= Coinsinfo_cellType;
_ 
    liquidity:uint128
    price_sqrt:uint160
    tick:int24
    feeGrowthGlobal0X128:int256
    feeGrowthGlobal1X128:int256
= Indexer_swap_info_cellType;
_ 
    feeGrowthInside0CurrentX128_0:int256
    feeGrowthInside1CurrentX128_0:int256
= New_fee_cellType;
_ 
    index_0:uint64
    subindex_0:uint4
    liquidity_0:uint128
    tickLower_0:int24
    tickUpper_0:int24
    feeGrowthInside0LastX128_0:int256
    feeGrowthInside1LastX128_0:int256
    new_fee_cell:(Maybe ^New_fee_cellType)
    liquidity2Burn_0:uint128
= Burn0Type;
_ 
    feeGrowthInside0CurrentX128_1:int256
    feeGrowthInside1CurrentX128_1:int256
= New_fee_cellType1;
_ 
    index_1:uint64
    subindex_1:uint4
    liquidity_1:uint128
    tickLower_1:int24
    tickUpper_1:int24
    feeGrowthInside0LastX128_1:int256
    feeGrowthInside1LastX128_1:int256
    new_fee_cell:(Maybe ^New_fee_cellType1)
    liquidity2Burn_1:uint128
= Burn1Type;
_ 
    feeGrowthInside0CurrentX128_2:int256
    feeGrowthInside1CurrentX128_2:int256
= New_fee_cellType2;
_ 
    index_2:uint64
    subindex_2:uint4
    liquidity_2:uint128
    tickLower_2:int24
    tickUpper_2:int24
    feeGrowthInside0LastX128_2:int256
    feeGrowthInside1LastX128_2:int256
    new_fee_cell:(Maybe ^New_fee_cellType2)
    liquidity2Burn_2:uint128
= Burn2Type;
_ 
    feeGrowthInside0CurrentX128_3:int256
    feeGrowthInside1CurrentX128_3:int256
= New_fee_cellType3;
_ 
    index_3:uint64
    subindex_3:uint4
    liquidity_3:uint128
    tickLower_3:int24
    tickUpper_3:int24
    feeGrowthInside0LastX128_3:int256
    feeGrowthInside1LastX128_3:int256
    new_fee_cell:(Maybe ^New_fee_cellType3)
    liquidity2Burn_3:uint128
= Burn3Type;
_ 
    burn0:(Maybe ^Burn0Type)
    burn1:(Maybe ^Burn1Type)
    burn2:(Maybe ^Burn2Type)
    burn3:(Maybe ^Burn3Type)
= Positions_cellType;

ROUTERV3_RESET_GAS

Opcode : 0x42a0fb43

This operation allows router owners the gas if too much accumulated on the contract
Access Rights: Allowed only for the Router Admin. Withdraws excess TON that accumulated on the router, leaving enough to keep it funded.

PathMnemonicTypeDescription
op Uint(32),op
query_id Uint(64) queryid as of the TON documentation
TL-B Description This is a preliminary tl-b - subject to change **Tlb for ROUTERV3_RESET_GAS**
ROUTERV3_RESET_GAS#42a0fb43 
    query_id:uint64
= ContractMessages;