[\[1\]](#references)] and its usage in TON.
### A.2.1. Curve25519 [#a21-curve25519]
*Curve25519* is defined as the Montgomery curve
$$
y^2=x^3+Ax^2+x\quad\text{over }\mathbb{F}_p\text{, where }p=2^{255}-19\text{ and }A=486662. \quad (31)
$$
The order of this curve is $8\ell$, where $\ell$ is a prime number, and $c=8$ is the cofactor. The cyclic subgroup of order $\ell$ is generated by a point $G$ with $x_G=9$ (this determines $G$ up to the sign of $y_G$, which is unimportant). The order of the quadratic twist $2y^2=x^3+Ax^2+x$ of Curve25519 is $4\ell'$ for another prime number $\ell'$.[42](#fn42)
### A.2.2. Parameters of Curve25519 [#a22-parameters-of-curve25519]
The parameters of Curve25519 are as follows:
* Base field: Prime finite field $\mathbb{F}_p$ for $p=2^{255}-19$.
* Equation: $y^2=x^3+Ax^2+x$ for $A=486662$.
* Base point $G$: Characterized by $x_G=9$ (nine is the smallest positive integer $x$-coordinate of a generator of the subgroup of large prime order of $E(\mathbb{F}_p)$).
* Order of $E(\mathbb{F}_p)$:
$$
|E(\mathbb{F}_p)|=p-t+1=8\ell,\quad\text{where} \quad (32)
$$
$$
\ell=2^{252}+27742317777372353535851937790883648493\quad\text{is prime.} \quad (33)
$$
* Order of $\tilde E(\mathbb{F}_p)$, where $\tilde E$ is the quadratic twist of $E$:
$$
|\tilde E(\mathbb{F}_p)|=p+t+1=2p+2-8\ell=4\ell',\quad\text{where} \quad (34)
$$
$$
\ell'=2^{253}-55484635554744707071703875581767296995\quad\text{is prime.} \quad (35)
$$
### A.2.3. Private and public keys for standard Curve25519 cryptography [#a23-private-and-public-keys-for-standard-curve25519-cryptography]
A private key for Curve25519 cryptography is usually defined as a *secret exponent* $a$, while the corresponding public key is $x_A$, the $x$-coordinate of point $A:=[a]G$. This is usually sufficient for performing ECDH (elliptic curve Diffie--Hellman key exchange) and asymmetric elliptic curve cryptography, as follows:
If a party wants to send a message $M$ to another party, which has public key $x_A$ (and private key $a$), the following computations are performed. A one-time random secret exponent $b$ is generated, and $x_B:=x_{[b]G}$ and $x_{[b]A}$ are computed using a Montgomery ladder. After that, the message $M$ is encrypted by a symmetric cypher such as AES using the 256-bit "shared secret" $S:=x_{[b]A}$ as a key, and 256-bit integer ("one-time public key") $x_B$ is prepended to the encrypted message. Once the party with public key $x_A$ receives this message, it can compute $x_{[a]B}$ starting from $x_B$ (transmitted with the encrypted message) and the private key $a$. Since $x_{[a]B}=x_{[ab]G}=x_{[b]A}=S$, the receiving party recovers the shared secret $S$ and is able to decrypt the remainder of the message.
### A.2.4. Public and private keys for TON Curve25519 cryptography [#a24-public-and-private-keys-for-ton-curve25519-cryptography]
TON uses another form for public and private keys of Curve25519 cryptography, borrowed from Ed25519 cryptography.
A private key for TON Curve25519 cryptography is just a random 256-bit string $k$. It is used by computing $\text{Sha512}(k)$, taking the first 256 bits of the result, interpreting them as a little-endian 256-bit integer $a$, clearing bits $0$, $1$, $2$, and $255$ of $a$, and setting bit $254$ so as to obtain a value $2^{254}\leq a<2^{255}$, divisible by eight. The value $a$ thus obtained is the *secret exponent* corresponding to $k$; meanwhile, the remaining 256 bits of $\text{Sha512}(k)$ constitute the *secret salt* $k''$.
The public key corresponding to $k$—or to the secret exponent $a$—is just the $x$-coordinate $x_A$ of the point $A:=[a]G$. Once $a$ and $x_A$ are computed, they are used in exactly the [same way](#a-2-3-private-and-public-keys-for-standard-curve25519-cryptography). In particular, if $x_A$ needs to be serialized, it is serialized into 32 octets as an unsigned little-endian 256-bit integer.
### A.2.5. Curve25519 is used in the TON Network [#a25-curve25519-is-used-in-the-ton-network]
Notice that the asymmetric [Curve25519 cryptography](#a-2-4-public-and-private-keys-for-ton-curve25519-cryptography) is extensively used by the TON Network, especially the ADNL (Abstract Datagram Network Layer) protocol. However, TON Blockchain needs elliptic curve cryptography mostly for signatures. For this purpose, Ed25519 signatures described in the next section are used.
***
## A.3 Ed25519 cryptography [#a3--ed25519-cryptography]
Ed25519 cryptography is extensively used for fast cryptographic signatures by both the TON Blockchain and the TON Network. This section describes the variant of Ed25519 cryptography used by TON. An important difference from the standard approaches (as defined by D. Bernstein et al. in [\[2\]](#references) ) is that TON provides automatic conversion of private and public Ed25519 keys into Curve25519 keys, so that the same keys could be used both for encrypting/decrypting and for signing messages.
### A.3.1. Twisted Edwards curves [#a31-twisted-edwards-curves]
A *twisted Edwards curve* $E_{a,d}$ with parameters $a\neq 0$ and $d\neq0,a$ over a field $k$ is given by equation
$$
E_{a,d}:\, ax^2+y^2=1+dx^2y^2\quad\text{over }k \quad (36)
$$
If $a=1$, this equation defines an (untwisted) Edwards curve. Point $O(0,1)$ is usually chosen as the marked point of $E_{a,d}$.
### A.3.2. Twisted Edwards curves are birationally equivalent to Montgomery curves [#a32-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves]
A twisted Edwards curve $E_{a,d}$ is birationally equivalent to a Montgomery elliptic curve
$$
M_A:\, v^2=u^3+Au^2+u \quad (37)
$$
where $A=2(a+d)/(a-d)$ and $d/a=(A-2)/(A+2)$. The birational equivalence $\phi:E_{a,d}\dashrightarrow M_A$ and its inverse $\phi^{-1}$ are given by
$$
\phi:(x,y)\mapsto\Biggl(\frac{1+y}{1-y},\frac{c(1+y)}{x(1-y)}\Biggr) \quad (38)
$$
and
$$
\phi^{-1}:(u,v)\mapsto\Biggl(\frac{cu}{v},\frac{u-1}{u+1}\Biggr) \quad (39)
$$
where
$$
c=\sqrt{\frac{A+2}{a}} \quad (40)
$$
Notice that $\phi$ transforms the marked point $O(0,1)$ of $E_{a,d}$ into the marked point of $M_A$ (i.e., its point at infinity).
### A.3.3. Addition of points on a twisted Edwards curve [#a33-addition-of-points-on-a-twisted-edwards-curve]
Since $E_{a,d}$ is birationally equivalent to an elliptic curve $M_A$, the addition of points on $M_A$ can be transferred to $E_{a,d}$ by setting
$$
P+Q:=\phi^{-1}\bigl(\phi(P)+\phi(Q)\bigr)\quad\text{for any }P, Q\in E_{a,d}(k). \quad (41)
$$
Notice that the marked point $O(0,1)$ is the neutral element with respect to this addition, and that $-(x_P,y_P)=(-x_P,y_P)$.
### A.3.4. Formulas for adding points on a twisted Edwards curve [#a34-formulas-for-adding-points-on-a-twisted-edwards-curve]
The coordinates $x_{P+Q}$ and $y_{P+Q}$ admit simple expressions as rational functions of $x_P$, $y_P$, $x_Q$, $y_Q$:
$$
x_{P+Q}=\frac{x_Py_Q+x_Qy_P}{1+dx_Px_Qy_Py_Q} \quad (42)
$$
$$
y_{P+Q}=\frac{y_Py_Q-ax_Px_Q}{1-dx_Px_Qy_Py_Q} \quad (43)
$$
These expressions can be efficiently computed, especially if $a=-1$. This is the reason twisted Edwards curves are important for fast elliptic curve cryptography.
### A.3.5. Ed25519 twisted Edwards curve [#a35-ed25519-twisted-edwards-curve]
Ed25519 is the twisted Edwards curve $E_{-1,d}$ over $\mathbb{F}_p$, where $p=2^{255}-19$ is the same prime number as that used for Curve25519, and $d=-(A-2)/(A+2)=-121665/121666$, where $A=486662$ is the same as in the equation ([31](#a-2-1-curve25519)):
$$
-x^2+y^2=1-\frac{121665}{121666}x^2y^2\quad\text{for }x, y\in\mathbb{F}_p, p=2^{255}-19. \quad (44)
$$
In this way, Ed25519-curve $E_{-1,d}$ is birationally equivalent to Curve25519 ([31](#a-2-1-curve25519)), and one can use $E_{-1,d}$ and formulas ([42](#a-3-4-formulas-for-adding-points-on-a-twisted-edwards-curve))–([43](#a-3-4-formulas-for-adding-points-on-a-twisted-edwards-curve)) for point addition on either Ed25519 or Curve25519, using ([38](#a-3-2-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves)) and ([39](#a-3-2-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves)) to convert points on Ed25519 into corresponding points on Curve25519, and vice versa.
### A.3.6. Generator of Ed25519 [#a36-generator-of-ed25519]
The generator of Ed25519 is the point $G'$ with $y(G')=4/5$ and $0\leq x(G')**1** As of August 2018, this document does not include a detailed description of serialized invalidity proofs, because they are likely to change significantly during the development of the validator software. Only the general design principles for consistency conditions and serialized invalidity proofs are discussed. [Back ↑](#ref-fn1)
**2** This is not included in the present version of this document, but will be provided in a separate appendix to a future revision. [Back ↑](#ref-fn2)
**3** Completely identical cells are often identified in memory and in disk storage; this is the reason why trees of cells are transparently transformed into DAGs of cells. From this perspective, a DAG is just a storage optimization of the underlying tree of cells, irrelevant for most considerations. [Back ↑](#ref-fn3)
**4** \[[4](#ref-4), 3.3.3–4], where an example is given and explained, pending a more complete reference. [Back ↑](#ref-fn4)
**5** If there are no transactions related to an account, the corresponding virtual block is empty and is omitted in the shardchain block. [Back ↑](#ref-fn5)
**6** Recall that TON Blockchain supports *dynamic* sharding, so the shard configuration may change from block to block because of shard merge and split events. Therefore, we cannot simply say that each shardchain corresponds to a fixed set of accountchains. [Back ↑](#ref-fn6)
**7** This condition applies if there is exactly one immediate antecessor (i.e., if a shardchain merge event did not occur immediately before the block in question); otherwise, this condition becomes more convoluted. [Back ↑](#ref-fn7)
**8** This example is a bit simplified since it does not take into account the presence of transit messages in InMsgDescr, which are not processed by any explicit transaction. [Back ↑](#ref-fn8)
**9** It is interesting to note that this part of the work can be done almost automatically. [Back ↑](#ref-fn9)
**10** In order to express this condition correctly in the presence of dynamic sharding, one should fix some account $\xi$, and consider the latest blocks $S$ and $S'$ of the shardchains containing $\xi$ in the shard configurations of both $B$ and $B'$, since the shards containing $\xi$ might be different in $B$ and $B'$. [Back ↑](#ref-fn10)
**11** Value-bearing messages with the `bounce` flag set will not be accepted by an uninitialized account, but will be "bounced" back. [Back ↑](#ref-fn11)
**12** "Messages to nowhere" may have some special fields in their body indicating their destination outside the TON Blockchain—for instance, an account in some other blockchain, or an IP address and port—which may be interpreted by the third-party software appropriately. Such fields are ignored by the TON Blockchain. [Back ↑](#ref-fn12)
**13** The problem of bypassing possible validator censorship—which could happen, for instance, if all validators conspire not to include external messages sent to accounts belonging to some set of blacklisted accounts—is dealt with separately elsewhere. The main idea is that the validators may be forced to promise to include a message with a known hash in a future block, without knowing anything about the identity of the sender or the receiver; they will have to keep this promise afterwards when the message itself with pre-agreed hash is presented. [Back ↑](#ref-fn13)
**14** However, the internal routing process described in [Internal routing](#2-1-11-internal-routing) is applied immediately after that, which may further modify the transit address. [Back ↑](#ref-fn14)
**15** When the addresses involved are of different lengths (e.g., because they belong to different workchains), one should consider only the first 96 bits of the addresses in the above formula. [Back ↑](#ref-fn15)
**16** Instead of Hamming optimality, we might have considered the equivalent property of Kademlia optimality, written for the Kademlia (or weighted $L_1$) distance as given by $\|\xi-\eta\|_K:=\sum_i2^{-i}|\xi_i-\eta_i|$ instead of the Hamming distance. [Back ↑](#ref-fn16)
**17** Notice that the next-hop and internal-routing computations are still applied to such messages, since the current shardchain may be split before the message is processed. In this case, the new sub-shardchain containing the destination address will inherit the message. [Back ↑](#ref-fn17)
**18** We may define the (virtual) output queue of an account(chain) as the subset of the OutMsgQueue of the shard currently containing that account that consists of messages with transit addresses equal to the address of the account. [Back ↑](#ref-fn18)
**19** In particular, if the hash of a recent block of a neighboring shardchain is not yet reflected in the latest masterchain block, its modifications to OutMsgQueue must not be taken into account. [Back ↑](#ref-fn19)
**20** This statement is not as trivial as it seems at first, because some of the shardchains involved may split or merge during the routing. A correct proof may be obtained by adopting the ISP perspective to HR as explained in [Hypercube Routing and the ISP](#2-1-14-hypercube-routing-and-the-isp) and observing that $m'$ will always be behind $m$, either in terms of the intermediate accountchain reached or, if they happen to be in the same accountchain, in terms of logical creation time. [Back ↑](#ref-fn20)
**21** One must not only look up the key $\text{Hash}(m)$ in the InMsgDescr of these blocks, but also check the intermediate addresses in the envelope of the corresponding entry, if found. [Back ↑](#ref-fn21)
**22** A description of an older version of TL may be found at [https://core.telegram.org/mtproto/TL](https://core.telegram.org/mtproto/TL). Alternatively, an informal introduction to TL-B schemes may be found in [\[4\]](#references) . [Back ↑](#ref-fn22)
**23** Address rewriting is a feature used to implement "anycast addresses" employed by the so-called large or global smart contracts (see [\[3\]](#references) ), which can have instances in several shardchains. When address rewriting is enabled, a message may be routed to and processed by a smart contract with an address coinciding with the destination address up to the first $d$ bits, where $d\leq 32$ is the "splitting depth" of the smart contract indicated in the `anycast.depth` field ([Support for anycast addresses](#2-1-6-support-for-anycast-addresses)). Otherwise, the addresses must match exactly. [Back ↑](#ref-fn23)
**24** More precisely, the information from the `init` field of an inbound message is used either when the receiving account is uninitialized or frozen with the hash of StateInit equal to the one expected by the account, or when the receiving account is active, and its code or data is an external hash reference matching the hash of the code or data received in the StateInit of the message. [Back ↑](#ref-fn24)
**25** Strictly speaking, InMsgDescr is the type of this structure; we deliberately use the same notation to describe the only instance of this type in a block. [Back ↑](#ref-fn25)
**26** Recall that a shardchain is considered a neighbor of itself. [Back ↑](#ref-fn26)
**27** This situation is rare and occurs only after shardchain merge events. Normally the messages imported from the OutMsgQueue of the same shardchain have destinations inside this shardchain, and are processed accordingly instead of being re-queued. [Back ↑](#ref-fn27)
**28** For simplicity, we sometimes treat the masterchain as just another workchain with $\mathit{workchain\_id}=-1$. [Back ↑](#ref-fn28)
**29** In fact, up to the first $d$ bits are replaced in such a way that each shard contains at most one instance of the large smart contract, and that shards $(w,s)$ with prefix $s$ of length $|s|\leq d$ contain exactly one instance. [Back ↑](#ref-fn29)
**30** This scheme uses anonymous constructors and anonymous fields, both represented by an underscore `_`. [Back ↑](#ref-fn30)
**31** In particular, if a user mistakenly sends some funds to a non-existent address in a bounceable message, the funds will not be wasted, but rather will be returned (bounced) back. Therefore, a user wallet application should set the bounce flag in all generated messages by default unless explicitly instructed otherwise. However, non-bounceable messages are indispensable in some situations ([Using non-bounceable messages](#1-7-6-using-non-bounceable-messages)). [Back ↑](#ref-fn31)
**32** A reference implementation of a TVM emulator running in a stripped-down version of TVM may be committed into the masterchain to be used when a disagreement between the validators on a specific run of TVM arises. In this way, flawed implementations of TVM may be detected. The reference implementation then serves as an authoritative source on the operational semantics of TVM. ([\[2\]](#references) B.2) [Back ↑](#ref-fn32)
**33** Notice that this record does not represent a change in the state of the account, because the transaction may still be aborted during the action phase. In that case, the new persistent data indirectly referenced by vm\_final\_state\_hash will be discarded. [Back ↑](#ref-fn33)
**34** The most common way of creating shared libraries for TVM is to publish a reference to the root cell of the library in the masterchain. [Back ↑](#ref-fn34)
**35** The persistent data of the smart contract need not be loaded in its entirety for this to occur. Instead the root is loaded, and TVM may load other cells by their references from the root only when they are accessed, thus providing a form of virtual memory. [Back ↑](#ref-fn35)
**36** Both the global gas limit and the gas price are configurable parameters determined by the current state of the masterchain. [Back ↑](#ref-fn36)
**37** In principle, an experimental version of TON Blockchain might choose to keep only the hashes of the initial and final states of the shardchain. The Merkle update increases the block size, but it is handy for full nodes that want to keep and update their copy of the shardchain state. Otherwise, the full nodes would have to repeat all the computations contained in a block to compute the updated state of the shardchain by themselves. [Back ↑](#ref-fn37)
**38** Notice that these "absent cells" are different from the library reference and external reference cells, which are kinds of exotic cells ([\[4\]](#references) , 3.1.7). Absent cells, by contrast, are introduced only for the purpose of serializing incomplete bags of cells, and can never be processed by TVM. [Back ↑](#ref-fn38)
**39** Notice that exotic cells (with $s=1$) always have $b\geq8$, with the cell type encoded in the first eight data bits ([\[4\]](#references) , 3.1.7). [Back ↑](#ref-fn39)
**40** If the bag of cells is not complete, some of these cell references may refer to cells $c'$ absent from the bag of cells. In that case, special "absent cells" with $r=7$ are included into the bag of cells and are assigned some indices $j$. These indices are then used to represent references to absent cells. [Back ↑](#ref-fn40)
**41** Arithmetic modulo $p$ for a modulus $p$ near a power of two can be implemented very efficiently. On the other hand, residues modulo $2^{255}-19$ can be represented by 255-bit integers. This is the reason this particular value of $p$ has been chosen by D. Bernstein. [Back ↑](#ref-fn41)
**42** Actually, D. Bernstein chose $A=486662$ because it is the smallest positive integer $A\equiv 2\pmod 4$ such that both the corresponding Montgomery curve ([31](#a-2-1-curve25519)) over $\mathbb{F}_p$ for $p=2^{255}-19$ and the quadratic twist of this curve have small cofactors. Such an arrangement avoids the necessity to check whether an $x$-coordinate $x_P\in\mathbb{F}_p$ of a point $P$ defines a point $(x_P,y_P)\in\mathbb{F}_p^2$ lying on the Montgomery curve itself or on its quadratic twist. [Back ↑](#ref-fn42)
# The Open Network (/blockchain-basics/whitepapers/ton)
**Authors**: Nikolai Durov, TON Core
**Date**: July 26, 2021
: [Original whitepaper, PDF](/resources/pdfs/ton.pdf)
## Abstract [#abstract]
The aim of this text is to provide a first description of the Telegram Open Network (TON) and related blockchain, peer-to-peer, distributed storage and service hosting technologies. To reduce the size of this document to reasonable proportions, we focus mainly on the unique and defining features of the TON platform that are important for it to achieve its stated goals.
***
## Introduction [#introduction]
The *Telegram Open Network (TON)* is a fast, secure and scalable blockchain and network project, capable of handling millions of transactions per second if necessary, and both user-friendly and service provider-friendly. We aim for it to be able to host all reasonable applications currently proposed and conceived. One might think about TON as a huge distributed supercomputer, or rather a huge "superserver", intended to host and provide a variety of services.
This text is not intended to be the ultimate reference with respect to all implementation details. Some particulars are likely to change during the development and testing phases.
***
## 1 Brief Description of TON Components [#1--brief-description-of-ton-components]
The *Telegram Open Network (TON)* is a combination of the following components:
* A flexible multi-blockchain platform (*TON Blockchain*; cf. [Chapter 2](#2-ton-blockchain)), capable of processing millions of transactions per second, with Turing-complete smart contracts, upgradable formal blockchain specifications, multi-cryptocurrency value transfer, support for micropayment channels and off-chain payment networks. *TON Blockchain* presents some new and unique features, such as the "self-healing" vertical blockchain mechanism (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)) and Instant Hypercube Routing (cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-“fast-path”-for-messages)), which enable it to be fast, reliable, scalable and self-consistent at the same time.
* A peer-to-peer network (*TON P2P Network*, or just *TON Network*; cf. [Chapter 3](#3-ton-networking)), used for accessing the TON Blockchain, sending transaction candidates, and receiving updates about only those parts of the blockchain a client is interested in (e.g., those related to the client's accounts and smart contracts), but also able to support arbitrary distributed services, blockchain-related or not.
* A distributed file storage technology (*TON Storage*; cf. [4.1.8](#4-1-8-example%3A-keeping-files-off-chain%3B-ton-storage)), accessible through *TON Network*, used by the TON Blockchain to store archive copies of blocks and status data (snapshots), but also available for storing arbitrary files for users or other services running on the platform, with torrent-like access technology.
* A network proxy/anonymizer layer (*TON Proxy*; cf. [4.1.11](#4-1-11-example%3A-ton-proxy-is-a-fog-service) and [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), similar to the $I^2P$ (Invisible Internet Project), used to hide the identity and IP addresses of *TON Network* nodes if necessary (e.g., nodes committing transactions from accounts with large amounts of cryptocurrency, or high-stake blockchain validator nodes who wish to hide their exact IP address and geographical location as a measure against DDoS attacks).
* A Kademlia-like distributed hash table (*TON DHT*; cf. [3.2](#3-2-ton-dht%3A-kademlia-like-distributed-hash-table)), used as a "torrent tracker" for *TON Storage* (cf. [3.2.10](#3-2-10-distributed-“torrent-trackers”-and-“network-interest-groups”-in-ton-dht)), as an "input tunnel locator" for *TON Proxy* (cf. [3.2.14](#3-2-14-locating-abstract-addresses)), and as a service locator for *TON Services* (cf. [3.2.12](#3-2-12-locating-services)).
* A platform for arbitrary services (*TON Services*; cf. [Chapter 4](#4-ton-services-and-applications)), residing in and available through *TON Network* and *TON Proxy*, with formalized interfaces (cf. [4.3.14](#4-3-14-public-interfaces-of-a-smart-contract)) enabling browser-like or smartphone application interaction. These formal interfaces and persistent service entry points can be published in the TON Blockchain (cf. [4.3.17](#4-3-17-locating-user-interfaces-via-ton-dns)); actual nodes providing service at any given moment can be looked up through the *TON DHT* starting from information published in the TON Blockchain (cf. [3.2.12](#3-2-12-locating-services)). Services may create smart contracts in the TON Blockchain to offer some guarantees to their clients (cf. [4.1.7](#4-1-7-mixed-services%3A-partly-off-chain%2C-partly-on-chain)).
* *TON DNS* (cf. [4.3.1](#4-3-1-ton-dns%3A-a-mostly-on-chain-hierarchical-domain-name-service)), a service for assigning human-readable names to accounts, smart contracts, services and network nodes.
* *TON Payments* (cf. [Chapter 5](#5-ton-payments)), a platform for micropayments, micropayment channels and a micropayment channel network. It can be used for fast off-chain value transfers, and for paying for services powered by *TON Services*.
* TON will allow easy integration with third-party messaging and social networking applications, thus making blockchain technologies and distributed services finally available and accessible to ordinary users (cf. [4.3.24](#4-3-24-ton-www)), rather than just to a handful of early cryptocurrency adopters. We will provide an example of such an integration in another of our projects, the Telegram Messenger (cf. [4.3.19](#4-3-19-a-light-wallet-and-ton-entity-explorer-can-be-built-into-telegram-messenger-clients)).
While the TON Blockchain is the core of the TON project, and the other components might be considered as playing a supportive role for the blockchain, they turn out to have useful and interesting functionality by themselves. Combined, they allow the platform to host more versatile applications than it would be possible by just using the TON Blockchain (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain%3F) and [4.1](#4-1-ton-service-implementation-strategies)).
***
## 2 TON Blockchain [#2--ton-blockchain]
We start with a description of the Telegram Open Network (TON) Blockchain, the core component of the project. Our approach here is "top-down": we give a general description of the whole first, and then provide more detail on each component.
For simplicity, we speak here about *the* TON Blockchain, even though in principle several instances of this blockchain protocol may be running independently (for example, as a result of hard forks). We consider only one of them.
### 2.1 TON Blockchain as a Collection of 2-Blockchains [#21--ton-blockchain-as-a-collection-of-2-blockchains]
The TON Blockchain is actually a *collection* of blockchains (even a collection of *blockchains of blockchains*, or *2-blockchains*—this point will be clarified later in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), because no single blockchain project is capable of achieving our goal of processing millions of transactions per second, as opposed to the now-standard dozens of transactions per second.
#### 2.1.1. List of blockchain types [#211-list-of-blockchain-types]
The blockchains in this collection are:
* The unique *master blockchain*, or *masterchain* for short, containing general information about the protocol and the current values of its parameters, the set of validators and their stakes, the set of currently active workchains and their "shards", and, most importantly, the set of hashes of the most recent blocks of all workchains and shardchains.
* Several (up to $2^{32}$) *working blockchains*, or *workchains* for short, which are actually the "workhorses", containing the value-transfer and smart-contract transactions. Different workchains may have different "rules", meaning different formats of account addresses, different formats of transactions, different virtual machines (VMs) for smart contracts, different basic cryptocurrencies and so on. However, they all must satisfy certain basic interoperability criteria to make interaction between different workchains possible and relatively simple. In this respect, the TON Blockchain is *heterogeneous* (cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)), similarly to the EOS (cf. [2.9.7](#2-9-7-eos)) and PolkaDot (cf. [2.9.8](#2-9-8-polkadot)) projects.
* Each workchain is in turn subdivided into up to $2^{60}$ *shard blockchains*, or *shardchains* for short, having the same rules and block format as the workchain itself, but responsible only for a subset of accounts, depending on several first (most significant) bits of the account address. In other words, a form of sharding is built into the system (cf. [2.8.12](#2-8-12-sharding-support)). Because all these shardchains share a common block format and rules, the TON Blockchain is *homogeneous* in this respect (cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)), similarly to what has been discussed in one of Ethereum scaling proposals.[1](#fn1)
* Each block in a shardchain (and in the masterchain) is actually not just a block, but a small blockchain. Normally, this "block blockchain" or "vertical blockchain" consists of exactly one block, and then we might think this is just the corresponding block of the shardchain (also called "horizontal blockchain" in this situation). However, if it becomes necessary to fix incorrect shardchain blocks, a new block is committed into the "vertical blockchain", containing either the replacement for the invalid "horizontal blockchain" block, or a "block difference", containing only a description of those parts of the previous version of this block that need to be changed. This is a TON-specific mechanism to replace detected invalid blocks without making a true fork of all shardchains involved; it will be explained in more detail in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks). For now, we just remark that each shardchain (and the masterchain) is not a conventional blockchain, but a *blockchain of blockchains*, or *2D-blockchain*, or just a *2-blockchain*.
#### 2.1.2. Infinite Sharding Paradigm [#212-infinite-sharding-paradigm]
Almost all blockchain sharding proposals are "top-down": one first imagines a single blockchain, and then discusses how to split it into several interacting shardchains to improve performance and achieve scalability.
The TON approach to sharding is "bottom-up", explained as follows.
Imagine that sharding has been taken to its extreme, so that exactly one account or smart contract remains in each shardchain. Then we have a huge number of "account-chains", each describing the state and state transitions of only one account, and sending value-bearing messages to each other to transfer value and information.
Of course, it is impractical to have hundreds of millions of blockchains, with updates (i.e., new blocks) usually appearing quite rarely in each of them. In order to implement them more efficiently, we group these "account-chains" into "shardchains", so that each block of the shardchain is essentially a collection of blocks of account-chains that have been assigned to this shard. Thus the "account-chains" have only a purely virtual or logical existence inside the "shardchains".
We call this perspective the *Infinite Sharding Paradigm*. It explains many of the design decisions for the TON Blockchain.
#### 2.1.3. Messages. Instant Hypercube Routing [#213-messages-instant-hypercube-routing]
The Infinite Sharding Paradigm instructs us to regard each account (or smart contract) as if it were in its own shardchain by itself. Then the only way one account might affect the state of another is by sending a *message* to it (this is a special instance of the so-called Actor model, with accounts as Actors; cf. [2.4.2](#2-4-2-accounts-as-processes-or-actors-actor-model)). Therefore, a system of messages between accounts (and shardchains, because the source and destination accounts are, generally speaking, located in different shardchains) is of paramount importance to a scalable system such as the TON Blockchain. In fact, a novel feature of the TON Blockchain, called *Instant Hypercube Routing* (cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-fast-path-for-messages)), enables it to deliver and process a message created in a block of one shardchain into the very next block of the destination shardchain, *regardless of the total number of shardchains in the system.*
#### 2.1.4. Quantity of masterchains, workchains and shardchains [#214-quantity-of-masterchains-workchains-and-shardchains]
A TON Blockchain contains exactly one masterchain. However, the system can potentially accommodate up to $2^{32}$ workchains, each subdivided into up to $2^{60}$ shardchains.
#### 2.1.5. Workchains can be virtual blockchains, not true blockchains [#215-workchains-can-be-virtual-blockchains-not-true-blockchains]
Because a workchain is usually subdivided into shardchains, the existence of the workchain is "virtual", meaning that it is not a true blockchain in the sense of the general definition provided in [2.2.1](#2-2-1-general-blockchain-definition) below, but just a collection of shardchains. When only one shardchain corresponds to a workchain, this unique shardchain may be identified with the workchain, which in this case becomes a "true" blockchain, at least for some time, thus gaining a superficial similarity to customary single-blockchain design. However, the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)) tells us that this similarity is indeed superficial: it is just a coincidence that the potentially huge number of "account-chains" can temporarily be grouped into one blockchain.
#### 2.1.6. Identification of workchains [#216-identification-of-workchains]
Each workchain is identified by its *number* or *workchain identifier* ($\mathit{workchain\_id}:\mathit{uint}_{32}$), which is simply an unsigned 32-bit integer. Workchains are created by special transactions in the masterchain, defining the (previously unused) workchain identifier and the formal description of the workchain, sufficient at least for the interaction of this workchain with other workchains and for superficial verification of this workchain's blocks.
#### 2.1.7. Creation and activation of new workchains [#217-creation-and-activation-of-new-workchains]
The creation of a new workchain may be initiated by essentially any member of the community, ready to pay the (high) masterchain transaction fees required to publish the formal specification of a new workchain. However, in order for the new workchain to become active, a two-thirds consensus of validators is required, because they will need to upgrade their software to process blocks of the new workchain, and signal their readiness to work with the new workchain by special masterchain transactions. The party interested in the activation of the new workchain might provide some incentive for the validators to support the new workchain by means of some rewards distributed by a smart contract.
#### 2.1.8. Identification of shardchains [#218-identification-of-shardchains]
Each shardchain is identified by a couple $(w,s)=(\mathit{workchain\_id}, \mathit{shard\_prefix})$, where $\mathit{workchain\_id}:\text{uint}_{32}$ identifies the corresponding workchain, and $\mathit{shard\_prefix}:\mathbf{2}^{0\ldots 60}$ is a bit string of length at most 60, defining the subset of accounts for which this shardchain is responsible. Namely, all accounts with $\mathit{account\_id}$ starting with $\mathit{shard\_prefix}$ (i.e., having $\mathit{shard\_prefix}$ as most significant bits) will be assigned to this shardchain.
#### 2.1.9. Identification of account-chains [#219-identification-of-account-chains]
Recall that account-chains have only a virtual existence (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)). However, they have a natural identifier—namely, $(\mathit{workchain\_id},\mathit{account\_id})$—because any account-chain contains information about the state and updates of exactly one account (either a simple account or smart contract—the distinction is unimportant here).
#### 2.1.10. Dynamic splitting and merging of shardchains; cf 2.7. [#2110-dynamic-splitting-and-merging-of-shardchains-cf-27]
A less sophisticated system might use *static sharding*—for example, by using the top eight bits of the $\mathit{account\_id}$ to select one of 256 pre-defined shards.
An important feature of the TON Blockchain is that it implements *dynamic sharding*, meaning that the number of shards is not fixed. Instead, shard $(w,s)$ can be automatically subdivided into shards $(w,s.0)$ and $(w,s.1)$ if some formal conditions are met (essentially, if the transaction load on the original shard is high enough for a prolonged period of time). Conversely, if the load stays too low for some period of time, the shards $(w,s.0)$ and $(w,s.1)$ can be automatically merged back into shard $(w,s)$.
Initially, only one shard $(w,\emptyset)$ is created for workchain $w$. Later, it is subdivided into more shards, if and when this becomes necessary (cf. [2.7.6](#2-7-6-determining-the-necessity-of-split-operations) and [2.7.8](#2-7-8-determining-the-necessity-of-merge-operations)).
#### 2.1.11. Basic workchain or Workchain Zero [#2111-basic-workchain-or-workchain-zero]
While up to $2^{32}$ workchains can be defined with their specific rules and transactions, we initially define only one, with $\mathit{workchain\_id}=0$. This workchain, called Workchain Zero or the basic workchain, is the one used to work with *TON smart contracts* and transfer *TON coins*, also known as *Grams* (cf. [Appendix A](#appendix-the-ton-coin-or-the-gram)). Most applications are likely to require only Workchain Zero. Shardchains of the basic workchain will be called *basic shardchains*.
#### 2.1.12. Block generation intervals [#2112-block-generation-intervals]
We expect a new block to be generated in each shardchain and the masterchain approximately once every five seconds. This will lead to reasonably small transaction confirmation times. New blocks of all shardchains are generated approximately simultaneously; a new block of the masterchain is generated approximately one second later, because it must contain the hashes of the latest blocks of all shardchains.
#### 2.1.13. Using the masterchain to make workchains and shardchains tightly coupled [#2113-using-the-masterchain-to-make-workchains-and-shardchains-tightly-coupled]
Once the hash of a block of a shardchain is incorporated into a block of the masterchain, that shardchain block and all its ancestors are considered "canonical", meaning that they can be referenced from the subsequent blocks of all shardchains as something fixed and immutable. In fact, each new shardchain block contains a hash of the most recent masterchain block, and all shardchain blocks referenced from that masterchain block are considered immutable by the new block.
Essentially, this means that a transaction or a message committed in a shardchain block may be safely used in the very next blocks of the other shardchains, without needing to wait for, say, twenty confirmations (i.e., twenty blocks generated after the original block in the same blockchain) before forwarding a message or taking other actions based on a previous transaction, as is common in most proposed "loosely-coupled" systems (cf. [2.8.14](#2-8-14-interaction-between-blockchains%3A-loosely-coupled-and-tightly-coupled-systems)), such as EOS. This ability to use transactions and messages in other shardchains a mere five seconds after being committed is one of the reasons we believe our "tightly-coupled" system, the first of its kind, will be able to deliver unprecedented performance (cf. [2.8.12](#2-8-12-sharding-support) and [2.8.14](#2-8-14-interaction-between-blockchains%3A-loosely-coupled-and-tightly-coupled-systems)).
#### 2.1.14. Masterchain block hash as a global state [#2114-masterchain-block-hash-as-a-global-state]
According to [2.1.13](#2-1-13-using-the-masterchain-to-make-workchains-and-shardchains-tightly-coupled), the hash of the last masterchain block completely determines the overall state of the system from the perspective of an external observer. One does not need to monitor the state of all shardchains separately.
#### 2.1.15. Generation of new blocks by validators; cf 2.6 [#2115-generation-of-new-blocks-by-validators-cf-26]
The TON Blockchain uses a Proof-of-Stake (PoS) approach for generating new blocks in the shardchains and the masterchain. This means that there is a set of, say, up to a few hundred *validators*—special nodes that have deposited *stakes* (large amounts of TON coins) by a special masterchain transaction to be eligible for new block generation and validation.
Then a smaller subset of validators is assigned to each shard $(w,s)$ in a deterministic pseudorandom way, changing approximately every 1024 blocks. This subset of validators suggests and reaches consensus on what the next shardchain block would be, by collecting suitable proposed transactions from the clients into new valid block candidates. For each block, there is a pseudorandomly chosen order on the validators to determine whose block candidate has the highest priority to be committed at each turn.
Validators and other nodes check the validity of the proposed block candidates; if a validator signs an invalid block candidate, it may be automatically punished by losing part or all of its stake, or by being suspended from the set of validators for some time. After that, the validators should reach consensus on the choice of the next block, essentially by an efficient variant of the BFT (Byzantine Fault Tolerant; cf. [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft)) consensus protocol, similar to PBFT \[[4](#ref-4)] or Honey Badger BFT \[[11](#ref-11)]. If consensus is reached, a new block is created, and validators divide between themselves the transaction fees for the transactions included, plus some newly-created ("minted") coins.
Each validator can be elected to participate in several validator subsets; in this case, it is expected to run all validation and consensus algorithms in parallel.
After all new shardchain blocks are generated or a timeout is passed, a new masterchain block is generated, including the hashes of the latest blocks of all shardchains. This is done by BFT consensus of *all* validators.[2](#fn2)
More detail on the TON PoS approach and its economical model is provided in section [2.6](#2-6-creating-and-validating-new-blocks).
#### 2.1.16. Forks of the masterchain [#2116-forks-of-the-masterchain]
A complication that arises from our tightly-coupled approach is that switching to a different fork in the masterchain will almost necessarily require switching to another fork in at least some of the shardchains. On the other hand, as long as there are no forks in the masterchain, no forks in the shardchain are even possible, because no blocks in the alternative forks of the shardchains can become "canonical" by having their hashes incorporated into a masterchain block.
The general rule is that *if masterchain block $B'$ is a predecessor of $B$, $B'$ includes hash $\text{Hash}(B'_{w,s})$ of $(w,s)$-shardchain block $B'_{w,s}$, and $B$ includes hash $\text{Hash}(B_{w,s})$, then $B'_{w,s}$ **must** be a predecessor of $B_{w,s}$; otherwise, the masterchain block $B$ is invalid.*
We expect masterchain forks to be rare, next to non-existent, because in the BFT paradigm adopted by the TON Blockchain they can happen only in the case of incorrect behavior by a majority of validators (cf. [2.6.1](#2-6-1-validators) and [2.6.15](#2-6-15-generation-of-new-masterchain-blocks)), which would imply significant stake losses by the offenders. Therefore, no true forks in the shardchains should be expected. Instead, if an invalid shardchain block is detected, it will be corrected by means of the "vertical blockchain" mechanism of the 2-blockchain (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), which can achieve this goal without forking the "horizontal blockchain" (i.e., the shardchain). The same mechanism can be used to fix non-fatal mistakes in the masterchain blocks as well.
#### 2.1.17. Correcting invalid shardchain blocks [#2117-correcting-invalid-shardchain-blocks]
Normally, only valid shardchain blocks will be committed, because validators assigned to the shardchain must reach a two-thirds Byzantine consensus before a new block can be committed. However, the system must allow for detection of previously committed invalid blocks and their correction.
Of course, once an invalid shardchain block is found—either by a validator (not necessarily assigned to this shardchain) or by a "fisherman" (any node of the system that made a certain deposit to be able to raise questions about block validity; cf. [2.6.4](#2-6-4-fishermen%3A-obtaining-money-by-pointing-out-others%E2%80%99-mistakes))—the invalidity claim and its proof are committed into the masterchain, and the validators that have signed the invalid block are punished by losing part of their stake and/or being temporarily suspended from the set of validators (the latter measure is important for the case of an attacker stealing the private signing keys of an otherwise benign validator).
However, this is not sufficient, because the overall state of the system (TON Blockchain) turns out to be invalid because of the invalid shardchain block previously committed. This invalid block must be replaced by a newer valid version.
Most systems would achieve this by "rolling back" to the last block before the invalid one in this shardchain and the last blocks unaffected by messages propagated from the invalid block in each of the other shardchains, and creating a new fork from these blocks. This approach has the disadvantage that a large number of otherwise correct and committed transactions are suddenly rolled back, and it is unclear whether they will be included later at all.
The TON Blockchain solves this problem by making each "block" of each shardchain and of the masterchain ("horizontal blockchains") a small blockchain ("vertical blockchain") by itself, containing different versions of this "block", or their "differences". Normally, the vertical blockchain consists of exactly one block, and the shardchain looks like a classical blockchain. However, once the invalidity of a block is confirmed and committed into a masterchain block, the "vertical blockchain" of the invalid block is allowed to grow by a new block in the vertical direction, replacing or editing the invalid block. The new block is generated by the current validator subset for the shardchain in question.
The rules for a new "vertical" block to be valid are quite strict. In particular, if a virtual "account-chain block" (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)) contained in the invalid block is valid by itself, it must be left unchanged by the new vertical block.
Once a new "vertical" block is committed on top of the invalid block, its hash is published in a new masterchain block (or rather in a new "vertical" block, lying above the original masterchain block where the hash of the invalid shardchain block was originally published), and the changes are propagated further to any shardchain blocks referring to the previous version of this block (e.g., those having received messages from the incorrect block). This is fixed by committing new "vertical" blocks in vertical blockchains for all blocks previously referring to the "incorrect" block; new vertical blocks will refer to the most recent (corrected) versions instead. Again, strict rules forbid changing account-chains that are not really affected (i.e., that receive the same messages as in the previous version). In this way, fixing an incorrect block generates "ripples" that are ultimately propagated towards the most recent blocks of all affected shardchains; these changes are reflected in new "vertical" masterchain blocks as well.
Once the "history rewriting" ripples reach the most recent blocks, the new shardchain blocks are generated in one version only, being successors of the newest block versions only. This means that they will contain references to the correct (most recent) vertical blocks from the very beginning.
The masterchain state implicitly defines a map transforming the hash of the first block of each "vertical" blockchain into the hash of its latest version. This enables a client to identify and locate any vertical blockchain by the hash of its very first (and usually the only) block.
#### 2.1.18. TON coins and multi-currency workchains [#2118-ton-coins-and-multi-currency-workchains]
The TON Blockchain supports up to $2^{32}$ different "cryptocurrencies", "coins", or "tokens", distinguished by a 32-bit $\mathit{currency\_id}$. New cryptocurrencies can be added by special transactions in the masterchain. Each workchain has a basic cryptocurrency, and can have several additional cryptocurrencies.
There is one special cryptocurrency with $\mathit{currency\_id}=0$, namely, the *TON coin*, also known as the *Gram* (cf. [Appendix A](#appendix-the-ton-coin-or-the-gram)). It is the basic cryptocurrency of Workchain Zero. It is also used for transaction fees and validator stakes.
In principle, other workchains may collect transaction fees in other tokens. In this case, some smart contract for automated conversion of these transaction fees into Grams should be provided.
#### 2.1.19. Messaging and value transfer [#2119-messaging-and-value-transfer]
Shardchains belonging to the same or different workchains may send *messages* to each other. While the exact form of the messages allowed depends on the receiving workchain and receiving account (smart contract), there are some common fields making inter-workchain messaging possible. In particular, each message may have some *value* attached, in the form of a certain amount of Grams (TON coins) and/or other registered cryptocurrencies, provided they are declared as acceptable cryptocurrencies by the receiving workchain.
The simplest form of such messaging is a value transfer from one (usually not a smart-contract) account to another.
#### 2.1.20. TON Virtual Machine [#2120-ton-virtual-machine]
The *TON Virtual Machine*, also abbreviated as *TON VM* or *TVM*, is the virtual machine used to execute smart-contract code in the masterchain and in the basic workchain. Other workchains may use other virtual machines alongside or instead of the TVM.
Here we list some of its features. They are discussed further in [2.3.12](#2-3-12-peculiarities-of-ton-vm), [2.3.14](#2-3-14-tvm-cells) and elsewhere:
• TVM represents all data as a collection of *(TVM) cells* (cf. [2.3.14](#2-3-14-tvm-cells)). Each cell contains up to 128 data bytes and up to 4 references to other cells. As a consequence of the "everything is a bag of cells" philosophy (cf. [2.5.14](#2-5-14-everything-is-a-bag-of-cells-philosophy)), this enables TVM to work with all data related to the TON Blockchain, including blocks and blockchain global state if necessary.
• TVM can work with values of arbitrary algebraic data types (cf. [2.3.12](#2-3-12-peculiarities-of-ton-vm)), represented as trees or directed acyclic graphs of TVM cells. However, it is agnostic towards the existence of algebraic data types; it just works with cells.
• TVM has built-in support for hashmaps (cf. [2.3.7](#2-3-7-denition-of-hashmap-type-as-a-patricia-tree)).
• TVM is a stack machine. Its stack keeps either 64-bit integers or cell references.
• 64-bit, 128-bit and 256-bit arithmetic is supported. All $n$-bit arithmetic operations come in three flavors: for unsigned integers, for signed integers and for integers modulo $2^n$ (no automatic overflow checks in the latter case).
• TVM has unsigned and signed integer conversion from $n$-bit to $m$-bit, for all $0 \leq m, n \leq 256$, with overflow checks.
• All arithmetic operations perform overflow checks by default, greatly simplifying the development of smart contracts.
• TVM has "multiply-then-shift" and "shift-then-divide" arithmetic operations with intermediate values computed in a larger integer type; this simplifies implementing fixed-point arithmetic.
• TVM offers support for bit strings and byte strings.
• Support for 256-bit Elliptic Curve Cryptography (ECC) for some predefined curves, including Curve25519, is present.
• Support for Weil pairings on some elliptic curves, useful for fast implementation of zk-SNARKs, is also present.
• Support for popular hash functions, including SHA-256, is present.
• TVM can work with Merkle proofs (cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels)).
• TVM offers support for "large" or "global" smart contracts. Such smart contracts must be aware of sharding (cf. [2.3.18](#2-3-18-local-and-global-smart-contracts%3B-smart-contract-instances) and [2.3.16](#2-3-16-support-for-sharding-in-ton-vm-data-structures)). Usual (local) smart contracts can be sharding-agnostic.
• TVM supports closures.
• A "spineless tagless G-machine" [\[13\]](#ref-13) can be easily implemented inside TVM.
Several high-level languages can be designed for TVM, in addition to the "TVM assembly". All these languages will have static types and will support algebraic data types. We envision the following possibilities:
* A Java-like imperative language, with each smart contract resembling a separate class.
* A lazy functional language (think of Haskell).
* An eager functional language (think of ML).
#### 2.1.21. Configurable parameters [#2121-configurable-parameters]
An important feature of the TON Blockchain is that many of its parameters are *configurable*. This means that they are part of the masterchain state, and can be changed by certain special proposal/vote/result transactions in the masterchain, without any need for hard forks. Changing such parameters will require collecting two-thirds of validator votes and more than half of the votes of all other participants who would care to take part in the voting process in favor of the proposal.
***
### 2.2 Generalities on Blockchains [#22--generalities-on-blockchains]
#### 2.2.1. General blockchain definition [#221-general-blockchain-definition]
In general, any *(true) blockchain* is a sequence of *blocks*, each block $B$ containing a reference $\text{Blk-Prev}(B)$ to the previous block (usually by including the hash of the previous block into the header of the current block), and a list of *transactions*. Each transaction describes some transformation of the *global blockchain state*; the transactions listed in a block are applied sequentially to compute the new state starting from the old state, which is the resulting state after the evaluation of the previous block.
#### 2.2.2. Relevance for the TON Blockchain [#222-relevance-for-the-ton-blockchain]
Recall that the *TON Blockchain* is not a true blockchain, but a collection of 2-blockchains (i.e., of blockchains of blockchains; cf. [2.1.1](#2-1-1-list-of-blockchain-types)), so the above is not directly applicable to it. However, we start with these generalities on true blockchains to use them as building blocks for our more sophisticated constructions.
#### 2.2.3. Blockchain instance and blockchain type [#223-blockchain-instance-and-blockchain-type]
One often uses the word *blockchain* to denote both a general *blockchain type* and its specific *blockchain instances*, defined as sequences of blocks satisfying certain conditions. For example, [2.2.1](#2-2-1-general-blockchain-definition) refers to blockchain instances.
In this way, a blockchain type is usually a "subtype" of the type $\text{Block}^*$ of lists (i.e., finite sequences) of blocks, consisting of those sequences of blocks that satisfy certain compatibility and validity conditions:
$$
\text{Blockchain} \subset \text{Block}^* \tag{1}
$$
A better way to define $\text{Blockchain}$ would be to say that $\text{Blockchain}$ is a *dependent couple type*, consisting of couples $(\mathbb{B}, v)$, with first component $\mathbb{B} : \text{Block}^*$ being of type $\text{Block}^*$ (i.e., a list of blocks), and the second component $v : \text{isValidBc}(\mathbb{B})$ being a proof or a witness of the validity of $\mathbb{B}$. In this way,
$$
\text{Blockchain} \equiv \Sigma_{(\mathbb{B} : \text{Block}^*)} \text{isValidBc}(\mathbb{B}) \tag{2}
$$
We use here the notation for dependent sums of types borrowed from \[[16](#ref-16)].
#### 2.2.4. Dependent type theory, Coq and TL [#224-dependent-type-theory-coq-and-tl]
Note that we are using (Martin-Löf) dependent type theory here, similar to that used in the Coq[3](#fn3) proof assistant. A simplified version of dependent type theory is also used in *TL (Type Language)*,[4](#fn4) which will be used in the formal specification of the TON Blockchain to describe the serialization of all data structures and the layouts of blocks, transactions, and the like.
In fact, dependent type theory gives a useful formalization of what a proof is, and such formal proofs (or their serializations) might become handy when one needs to provide proof of invalidity for some block, for example.
#### 2.2.5. TL, or the Type Language [#225-tl-or-the-type-language]
Since TL (Type Language) will be used in the formal specifications of TON blocks, transactions, and network datagrams, it warrants a brief discussion.
TL is a language suitable for description of dependent algebraic *types*, which are allowed to have numeric (natural) and type parameters. Each type is described by means of several *constructors*. Each constructor has a (human-readable) identifier and a *name,* which is a bit string (32-bit integer by default). Apart from that, the definition of a constructor contains a list of fields along with their types.
A collection of constructor and type definitions is called a *TL-scheme*. It is usually kept in one or several files with the suffix `.tl`.
An important feature of TL-schemes is that they determine an unambiguous way of serializing and deserializing values (or objects) of algebraic types defined. Namely, when a value needs to be serialized into a stream of bytes, first the name of the constructor used for this value is serialized. Recursively computed serializations of each field follow.
The description of a previous version of TL, suitable for serializing arbitrary objects into sequences of 32-bit integers, is available at [https://core.telegram.org/mtproto/TL](https://core.telegram.org/mtproto/TL). A new version of TL, called *TL-B*, is being developed for the purpose of describing the serialization of objects used by the TON Project. This new version can serialize objects into streams of bytes and even bits (not just 32-bit integers), and offers support for serialization into a tree of TVM cells (cf. [2.3.14](#2-3-14-tvm-cells)). A description of TL-B will be a part of the formal specification of the TON Blockchain.
#### 2.2.6. Blocks and transactions as state transformation operators [#226-blocks-and-transactions-as-state-transformation-operators]
Normally, any blockchain (type) *Blockchain* has an associated global state (type) *State*, and a transaction (type) *Transaction*. The semantics of a blockchain are to a large extent determined by the transaction application function:
$$
\mathit{ev\_trans}':\mathit{Transaction}\times\mathit{State}\to\mathit{State}^? \tag{3}
$$
Here $X^?$ denotes $\text{Maybe}$ $X$, the result of applying the $\text{Maybe}$ monad to type $X$. This is similar to our use of $X^*$ for $\text{List}$ $X$. Essentially, a value of type $X^?$ is either a value of type $X$ or a special value $\bot$ indicating the absence of an actual value (think about a null pointer). In our case, we use $\mathit{State}^?$ instead of $\mathit{State}$ as the result type because a transaction may be invalid if invoked from certain original states (think about attempting to withdraw from an account more money than it is actually there).
We might prefer a curried version of $\mathit{ev\_trans}'$:
$$
\mathit{ev\_trans}:\mathit{Transaction}\to\mathit{State}\to\mathit{State}^? \tag{4}
$$
Because a block is essentially a list of transactions, the block evaluation function
$$
\mathit{ev\_block}:\mathit{Block}\to\mathit{State}\to\mathit{State}^? \tag{5}
$$
can be derived from $\mathit{ev\_trans}$. It takes a block $B$:*Block* and the previous blockchain state $s$:*State* (which might include the hash of the previous block) and computes the next blockchain state $s'=\mathit{ev\_block}(B)(s)$:*State*, which is either a true state or a special value $\bot$ indicating that the next state cannot be computed (i.e., that the block is invalid if evaluated from the starting state given—for example, the block includes a transaction trying to debit an empty account.)
#### 2.2.7. Block sequence numbers [#227-block-sequence-numbers]
Each block $B$ in the blockchain can be referred to by its *sequence number* $\text{Blk-Seqno}(B)$, starting from zero for the very first block, and incremented by one whenever passing to the next block. More formally,
$$
\text{Blk-Seqno}(B) = \text{Blk-Seqno}\bigl(\text{Blk-Prev}(B)\bigr) + 1 \tag{6}
$$
Notice that the sequence number does not identify a block uniquely in the presence of *forks*.
#### 2.2.8. Block hashes [#228-block-hashes]
Another way of referring to a block $B$ is by its hash $\text{Blk-Hash}(B)$, which is actually the hash of the *header* of block $B$ (however, the header of the block usually contains hashes that depend on all content of block $B$). Assuming that there are no collisions for the hash function used (or at least that they are very improbable), a block is uniquely identified by its hash.
#### 2.2.9. Hash assumption [#229-hash-assumption]
During formal analysis of blockchain algorithms, we assume that there are no collisions for the $k$-bit hash function $\text{Hash} : \text{Bytes}^* \to \mathbf{2}^k$ used:
$$
\text{Hash}(s) = \text{Hash}(s') \Rightarrow s = s' \quad \text{for any } s, s' \in \text{Bytes}^* \tag{7}
$$
Here $\text{Bytes} = \{0\ldots255\} = \mathbf{2}^8$ is the type of bytes, or the set of all byte values, and $\text{Bytes}^*$ is the type or set of arbitrary (finite) lists of bytes; while $\mathbf{2} = \{0,1\}$ is the bit type, and $\mathbf{2}^k$ is the set (or actually the type) of all $k$-bit sequences (i.e., of $k$-bit numbers).
Of course, ([7](#2-2-9-hash-assumption)) is impossible mathematically, because a map from an infinite set to a finite set cannot be injective. A more rigorous assumption would be
$$
\forall s, s': s \neq s', P\bigl(\text{Hash}(s) = \text{Hash}(s')\bigr) = 2^{-k} \tag{8}
$$
However, this is not so convenient for the proofs. If ([8](#2-2-9-hash-assumption)) is used at most $N$ times in a proof with $2^{-k}N < \epsilon$ for some small $\epsilon$ (say, $\epsilon = 10^{-18}$), we can reason as if ([7](#2-2-9-hash-assumption)) were true, provided we accept a failure probability $\epsilon$ (i.e., the final conclusions will be true with probability at least $1 - \epsilon$).
Final remark: in order to make the probability statement of ([8](#2-2-9-hash-assumption)) really rigorous, one must introduce a probability distribution on the set $\text{Bytes}^*$ of all byte sequences. A way of doing this is by assuming all byte sequences of the same length $l$ equiprobable, and setting the probability of observing a sequence of length $l$ equal to $p^l - p^{l+1}$ for some $p \to 1^-$. Then ([8](#2-2-9-hash-assumption)) should be understood as a limit of conditional probability $P\bigl(\text{Hash}(s) = \text{Hash}(s') | s \neq s'\bigr)$ when $p$ tends to one from below.
#### 2.2.10. Hash used for the TON Blockchain [#2210-hash-used-for-the-ton-blockchain]
We are using the 256-bit SHA-256 hash for the TON Blockchain for the time being. If it turns out to be weaker than expected, it can be replaced by another hash function in the future. The choice of the hash function is a configurable parameter of the protocol, so it can be changed without hard forks as explained in [2.1.21](#2-1-21-configurable-parameters).
***
### 2.3 Blockchain State, Accounts and Hashmaps [#23---blockchain-state-accounts-and-hashmaps]
We have noted above that any blockchain defines a certain global state, and each block and each transaction defines a transformation of this global state. Here we describe the global state used by TON blockchains.
#### 2.3.1. Account IDs [#231-account-ids]
The basic account IDs used by TON blockchains—or at least by its masterchain and Workchain Zero—are 256-bit integers, assumed to be public keys for 256-bit Elliptic Curve Cryptography (ECC) for a specific elliptic curve. In this way,
$$
\mathit{account\_id}:\mathit{Account}=\mathit{uint}_{256}=\mathbf{2}^{256} \tag{9}
$$
Here $\mathit{Account}$ is the account *type*, while $\mathit{account\_id}:\mathit{Account}$ is a specific variable of type $\mathit{Account}$.
Other workchains can use other account ID formats, 256-bit or otherwise. For example, one can use Bitcoin-style account IDs, equal to SHA-256 of an ECC public key.
However, the bit length $l$ of an account ID must be fixed during the creation of the workchain (in the masterchain), and it must be at least 64, because the first 64 bits of $\mathit{account\_id}$ are used for sharding and message routing.
#### 2.3.2. Main component: *Hashmaps* [#232-main-component-hashmaps]
The principal component of the TON blockchain state is a *hashmap*. In some cases we consider (partially defined) "maps" $h:\mathbf{2}^n\dashrightarrow \mathbf{2}^m$. More generally, we might be interested in hashmaps $h:\mathbf{2}^n\dashrightarrow X$ for a composite type $X$. However, the source (or index) type is almost always $\mathbf{2}^n$.
Sometimes, we have a "default value" $\mathit{empty}:X$, and the hashmap $h:\mathbf{2}^n\to X$ is "initialized" by its "default value" $i\mapsto\mathit{empty}$.
#### 2.3.3. Example: TON account balances [#233-example-ton-account-balances]
An important example is given by TON account balances. It is a hashmap
$$
\mathit{balance} : \mathit{Account} \to \mathit{uint}_{128} \tag{10}
$$
mapping $\mathit{Account} = \mathbf{2}^{256}$ into a Gram (TON coin) balance of type $\mathit{uint}_{128} = \mathbf{2}^{128}$. This hashmap has a default value of zero, meaning that initially (before the first block is processed) the balance of all accounts is zero.
#### 2.3.4. Example: smart-contract persistent storage [#234-example-smart-contract-persistent-storage]
Another example is given by smart-contract persistent storage, which can be (very approximately) represented as a hashmap
$$
\mathit{storage} : \mathbf{2}^{256} \dashrightarrow \mathbf{2}^{256} \tag{11}
$$
This hashmap also has a default value of zero, meaning that uninitialized cells of persistent storage are assumed to be zero.
#### 2.3.5. Example: persistent storage of all smart contracts [#235-example-persistent-storage-of-all-smart-contracts]
Because we have more than one smart contract, distinguished by $\mathit{account\_id}$, each having its separate persistent storage, we must actually have a hashmap
$$
\mathit{Storage}:\mathit{Account}\dashrightarrow(\mathbf{2}^{256}\dashrightarrow \mathbf{2}^{256}) \tag{12}
$$
mapping $\mathit{account\_id}$ of a smart contract into its persistent storage.
#### 2.3.6. Hashmap type [#236-hashmap-type]
The hashmap is not just an abstract (partially defined) function $\mathbf{2}^n\dashrightarrow X$; it has a specific representation. Therefore, we suppose that we have a special hashmap type
$$
\mathit{Hashmap}(n,X):\mathit{Type} \tag{13}
$$
corresponding to a data structure encoding a (partial) map $\mathbf{2}^n\dashrightarrow X$. We can also write
$$
\mathit{Hashmap}(n:\mathit{nat})(X:\mathit{Type}):\mathit{Type} \tag{14}
$$
or
$$
\mathit{Hashmap}:\mathit{nat}\to\mathit{Type}\to\mathit{Type} \tag{15}
$$
We can always transform $h:\mathit{Hashmap}(n,X)$ into a map $\mathit{hget}(h):\mathbf{2}^n\to X^?$. Henceforth, we usually write $h[i]$ instead of $\mathit{hget}(h)(i)$:
$$
h[i]:\equiv\mathit{hget}(h)(i):X^?\quad\text{for any }i:\mathbf{2}^n,\ h:\mathit{Hashmap}(n,X) \tag{16}
$$
#### 2.3.7. Definition of hashmap type as a Patricia tree [#237-definition-of-hashmap-type-as-a-patricia-tree]
Logically, one might define $\mathit{Hashmap}(n,X)$ as an (incomplete) binary tree of depth $n$ with edge labels $0$ and $1$ and with values of type $X$ in the leaves. Another way to describe the same structure would be as a *(bitwise) trie* for binary strings of length equal to $n$.
In practice, we prefer to use a compact representation of this trie, by compressing each vertex having only one child with its parent. The resulting representation is known as a *Patricia tree* or a *binary radix tree*. Each intermediate vertex now has exactly two children, labeled by two non-empty binary strings, beginning with zero for the left child and with one for the right child.
In other words, there are two types of (non-root) nodes in a Patricia tree:
* $\text{Leaf}(x)$, containing value $x$ of type $X$.
* $\text{Node}(l,s_l,r,s_r)$, where $l$ is the (reference to the) left child or subtree, $s_l$ is the bitstring labeling the edge connecting this vertex to its left child (always beginning with 0), $r$ is the right subtree, and $s_r$ is the bitstring labeling the edge to the right child (always beginning with 1).
A third type of node, to be used only once at the root of the Patricia tree, is also necessary:
* $\text{Root}(n,s_0,t)$, where $n$ is the common length of index bitstrings of $\mathit{Hashmap}(n,X)$, $s_0$ is the common prefix of all index bitstrings, and $t$ is a reference to a $\text{Leaf}$ or a $\text{Node}$.
If we want to allow the Patricia tree to be empty, a fourth type of (root) node would be used:
* $\text{EmptyRoot}(n)$, where $n$ is the common length of all index bitstrings.
We define the height of a Patricia tree by
$$
\texttt{Height}(\texttt{Leaf}(x))=0 \tag{17}
$$
$$
\texttt{Height}\bigl(\texttt{Node}(l,s_l,r,s_r)\bigr) = \texttt{Height}(l)+\texttt{Len}(s_l) = \texttt{Height}(r)+\texttt{Len}(s_r) \qquad (18)
$$
$$
\texttt{Height}\bigl(\texttt{Root}(n,s_0,t)\bigr)=\texttt{Len}(s_0)+\texttt{Height}(t)=n \tag{19}
$$
The last two expressions in each of the last two formulas must be equal. We use Patricia trees of height $n$ to represent values of type $\mathit{Hashmap}(n,X)$.
If there are $N$ leaves in the tree (i.e., our hashmap contains $N$ values), then there are exactly $N-1$ intermediate vertices. Inserting a new value always involves splitting an existing edge by inserting a new vertex in the middle and adding a new leaf as the other child of this new vertex. Deleting a value from a hashmap does the opposite: a leaf and its parent are deleted, and the parent's parent and its other child become directly linked.
#### 2.3.8. Merkle-Patricia trees [#238-merkle-patricia-trees]
When working with blockchains, we want to be able to compare Patricia trees (i.e., hash maps) and their subtrees, by reducing them to a single hash value. The classical way of achieving this is given by the Merkle tree. Essentially, we want to describe a way of hashing objects $h$ of type $\mathit{Hashmap}(n,X)$ with the aid of a hash function $\text{Hash}$ defined for binary strings, provided we know how to compute hashes $\text{Hash}(x)$ of objects $x:X$ (e.g., by applying the hash function $\text{Hash}$ to a binary serialization of object $x$).
One might define $\text{Hash}(h)$ recursively as follows:
$$
\text{Hash}\bigl(\text{Leaf}(x)\bigr):=\text{Hash}(x) \tag{20}
$$
$$
\texttt{Hash}\bigl(\texttt{Node}(l,s_l,r,s_r)\bigr):=\texttt{Hash}\bigl(\texttt{Hash}(l).\texttt{Hash}(r).\texttt{Code}(s_l).\texttt{Code}(s_r)\bigr) \qquad (21)
$$
$$
\texttt{Hash}\bigl(\texttt{Root}(n,s_0,t)\bigr):=\texttt{Hash}\bigl(\texttt{Code}(n).\texttt{Code}(s_0).\texttt{Hash}(t)\bigr) \tag{22}
$$
Here $s.t$ denotes the concatenation of (bit) strings $s$ and $t$, and $\text{Code}(s)$ is a prefix code for all bit strings $s$. For example, one might encode 0 by 10, 1 by 11, and the end of the string by 0.[5](#fn5)
We will see later (cf. [2.3.12](#2-3-12-peculiarities-of-ton-vm) and [2.3.14](#2-3-14-tvm-cells)) that this is a (slightly tweaked) version of recursively defined hashes for values of arbitrary (dependent) algebraic types.
#### 2.3.9. Recomputing Merkle tree hashes [#239-recomputing-merkle-tree-hashes]
This way of recursively defining $\text{Hash}(h)$, called a *Merkle tree hash*, has the advantage that, if one explicitly stores $\text{Hash}(h')$ along with each node $h'$ (resulting in a structure called a *Merkle tree*, or, in our case, a *Merkle–Patricia tree*), one needs to recompute only at most $n$ hashes when an element is added to, deleted from or changed in the hashmap.
In this way, if one represents the global blockchain state by a suitable Merkle tree hash, it is easy to recompute this state hash after each transaction.
#### 2.3.10. Merkle proofs [#2310-merkle-proofs]
Under the assumption ([7](#2-2-9-hash-assumption)) of "injectivity" of the chosen hash function $\texttt{Hash}$, one can construct a proof that, for a given value $z$ of $\texttt{Hash}(h)$, $h:\mathit{Hashmap}(n,X)$, one has $\mathit{hget}(h)(i)=x$ for some $i:\mathbf{2}^n$ and $x:X$. Such a proof will consist of the path in the Merkle–Patricia tree from the leaf corresponding to $i$ to the root, augmented by the hashes of all siblings of all nodes occurring on this path.
In this way, a light node[6](#fn6) knowing only the value of $\text{Hash}(h)$ for some hashmap $h$ (e.g., smart-contract persistent storage or global blockchain state) might request from a full node[7](#fn7) not only the value $x=h[i]=\mathit{hget}(h)(i)$, but such a value along with a Merkle proof starting from the already known value $\text{Hash}(h)$. Then, under assumption ([7](#2-2-9-hash-assumption)), the light node can check for itself that $x$ is indeed the correct value of $h[i]$.
In some cases, the client may want to obtain the value $y=\text{Hash}(x)=\text{Hash}(h[i])$ instead—for example, if $x$ itself is very large (e.g., a hashmap itself). Then a Merkle proof for $(i,y)$ can be provided instead. If $x$ is a hashmap as well, then a second Merkle proof starting from $y=\text{Hash}(x)$ may be obtained from a full node, to provide a value $x[j]=h[i][j]$ or just its hash.
#### 2.3.11. Importance of Merkle proofs for a multi-chain system such as TON [#2311-importance-of-merkle-proofs-for-a-multi-chain-system-such-as-ton]
Notice that a node normally cannot be a full node for all shardchains existing in the TON environment. It usually is a full node only for some shardchains—for instance, those containing its own account, a smart contract it is interested in, or those that this node has been assigned to be a validator of. For other shardchains, it must be a light node—otherwise the storage, computing and network bandwidth requirements would be prohibitive. This means that such a node cannot directly check assertions about the state of other shardchains; it must rely on Merkle proofs obtained from full nodes for those shardchains, which is as safe as checking by itself unless ([7](#2-2-9-hash-assumption)) fails (i.e., a hash collision is found)
#### 2.3.12. Peculiarities of TON VM [#2312-peculiarities-of-ton-vm]
The TON VM or TVM (TON Virtual Machine), used to run smart contracts in the masterchain and Workchain Zero, is considerably different from customary designs inspired by the EVM (Ethereum Virtual Machine): it works not just with 256-bit integers, but actually with (almost) arbitrary records, structures, or sum-product types, making it more suitable to execute code written in high-level (especially functional) languages. Essentially, TVM uses tagged data types, not unlike those used in implementations of Prolog or Erlang.
One might imagine first that the state of a TVM smart contract is not just a hashmap $\mathbf{2}^{256}\to \mathbf{2}^{256}$, or $\mathit{Hashmap}(256,\mathbf{2}^{256})$, but (as a first step) $\mathit{Hashmap}(256,X)$, where $X$ is a type with several constructors, enabling it to store, apart from 256-bit integers, other data structures, including other hashmaps $\mathit{Hashmap}(256,X)$ in particular. This would mean that a cell of TVM (persistent or temporary) storage—or a variable or an element of an array in a TVM smart-contract code—may contain not only an integer, but a whole new hashmap. Of course, this would mean that a cell contains not just 256 bits, but also, say, an 8-bit tag, describing how these 256 bits should be interpreted.
In fact, values do not need to be precisely 256-bit. The value format used by TVM consists of a sequence of raw bytes and references to other structures, mixed in arbitrary order, with some descriptor bytes inserted in suitable locations to be able to distinguish pointers from raw data (e.g., strings or integers); cf. [2.3.14](#2-3-14-tvm-cells).
This raw value format may be used to implement arbitrary sum-product algebraic types. In this case, the value would contain a raw byte first, describing the constructor being used (from the perspective of a high-level language), and then other fields or constructor arguments, consisting of raw bytes and references to other structures depending on the constructor chosen (cf. [2.2.5](#2-2-5-tl%2C-or-the-type-language)). However, TVM does not know anything about the correspondence between constructors and their arguments; the mixture of bytes and references is explicitly described by certain descriptor bytes.[8](#fn8)
The Merkle tree hashing is extended to arbitrary such structures: to compute the hash of such a structure, all references are recursively replaced by hashes of objects referred to, and then the hash of the resulting byte string (descriptor bytes included) is computed.
In this way, the Merkle tree hashing for hashmaps, described in [2.3.8](#2-3-8-merkle-patricia-trees), is just a special case of hashing for arbitrary (dependent) algebraic data types, applied to type $Hashmap(n, X)$ with two constructors.[9](#fn9)
#### 2.3.13. Persistent storage of TON smart contracts [#2313-persistent-storage-of-ton-smart-contracts]
Persistent storage of a TON smart contract essentially consists of its "global variables", preserved between calls to the smart contract. As such, it is just a "product", "tuple", or "record" type, consisting of fields of the correct types, corresponding to one global variable each. If there are too many global variables, they cannot fit into one TON cell because of the global restriction on TON cell size. In such a case, they are split into several records and organized into a tree, essentially becoming a "product of products" or "product of products of products" type instead of just a product type.
#### 2.3.14. TVM Cells [#2314-tvm-cells]
Ultimately, the TON VM keeps all data in a collection of *(TVM) cells*. Each cell contains two descriptor bytes first, indicating how many bytes of raw data are present in this cell (up to 128) and how many references to other cells are present (up to four). Then these raw data bytes and references follow. Each cell is referenced exactly once, so we might have included in each cell a reference to its "parent" (the only cell referencing this one). However, this reference need not be explicit.
In this way, the persistent data storage cells of a TON smart contract are organized into a tree,[10](#fn10) with a reference to the root of this tree kept in the smart-contract description. If necessary, a Merkle tree hash of this entire persistent storage is recursively computed, starting from the leaves and then simply replacing all references in a cell with the recursively computed hashes of the referenced cells, and subsequently computing the hash of the byte string thus obtained.
#### 2.3.15. Generalized Merkle proofs for values of arbitrary algebraic types [#2315-generalized-merkle-proofs-for-values-of-arbitrary-algebraic-types]
Because the TON VM represents a value of arbitrary algebraic type by means of a tree consisting of (TVM) cells, and each cell has a well-defined (recursively computed) Merkle hash, depending in fact on the whole subtree rooted in this cell, we can provide "generalized Merkle proofs" for (parts of) values of arbitrary algebraic types, intended to prove that a certain subtree of a tree with a known Merkle hash takes a specific value or a value with a specific hash. This generalizes the approach of [2.3.10](#2-3-10-merkle-proofs), where only Merkle proofs for $x[i]=y$ have been considered.
#### 2.3.16. Support for sharding in TON VM data structures [#2316-support-for-sharding-in-ton-vm-data-structures]
We have just outlined how the TON VM, without being overly complicated, supports arbitrary (dependent) algebraic data types in high-level smart-contract languages. However, sharding of large (or global) smart contracts requires special support on the level of TON VM. To this end, a special version of the hashmap type has been added to the system, amounting to a "map" $\mathit{Account}\dashrightarrow X$. This "map" might seem equivalent to $\mathit{Hashmap}(m,X)$, where $\mathit{Account}=\mathbf{2}^m$. However, when a shard is split in two, or two shards are merged, such hashmaps are automatically split in two, or merged back, so as to keep only those keys that belong to the corresponding shard.
#### 2.3.17. Payment for persistent storage [#2317-payment-for-persistent-storage]
A noteworthy feature of the TON Blockchain is the payment exacted from smart contracts for storing their persistent data (i.e., for enlarging the total state of the blockchain). It works as follows:
Each block declares two rates, nominated in the principal currency of the blockchain (usually the Gram): the price for keeping one cell in the persistent storage, and the price for keeping one raw byte in some cell of the persistent storage. Statistics on the total numbers of cells and bytes used by each account are stored as part of its state, so by multiplying these numbers by the two rates declared in the block header, we can compute the payment to be deducted from the account balance for keeping its data between the previous block and the current one.
However, payment for persistent storage usage is not exacted for every account and smart contract in each block; instead, the sequence number of the block where this payment was last exacted is stored in the account data, and when any action is done with the account (e.g., a value transfer or a message is received and processed by a smart contract), the storage usage payment for all blocks since the previous such payment is deducted from the account balance before performing any further actions. If the account's balance would become negative after this, the account is destroyed.
A workchain may declare some number of raw data bytes per account to be "free" (i.e., not participating in the persistent storage payments) in order to make "simple" accounts, which keep only their balance in one or two cryptocurrencies, exempt from these constant payments.
Notice that, if nobody sends any messages to an account, its persistent storage payments are not collected, and it can exist indefinitely. However, anybody can send, for instance, an empty message to destroy such an account. A small incentive, collected from part of the original balance of the account to be destroyed, can be given to the sender of such a message. We expect, however, that the validators would destroy such insolvent accounts for free, simply to decrease the global blockchain state size and to avoid keeping large amounts of data without compensation.
Payments collected for keeping persistent data are distributed among the validators of the shardchain or the masterchain (proportionally to their stakes in the latter case).
#### 2.3.18. Local and global smart contracts; smart-contract instances [#2318-local-and-global-smart-contracts-smart-contract-instances]
A smart contract normally resides just in one shard, selected according to the smart contract's $account\_id$, similarly to an "ordinary" account. This is usually sufficient for most applications. However, some "high-load" smart contracts may want to have an "instance" in each shardchain of some workchain. To achieve this, they must propagate their creating transaction into all shardchains, for instance, by committing this transaction into the "root" shardchain $(w,\emptyset)$[11](#fn11) of the workchain $w$ and paying a large commission.[12](#fn12)
This action effectively creates instances of the smart contract in each shard, with separate balances. Originally, the balance transferred in the creating transaction is distributed simply by giving the instance in shard $(w,s)$ the $2^{-|s|}$ part of the total balance. When a shard splits into two child shards, balances of all instances of global smart contracts are split in half; when two shards merge, balances are added together.
In some cases, splitting/merging instances of global smart contracts may involve (delayed) execution of special methods of these smart contracts. By default, the balances are split and merged as described above, and some special "account-indexed" hashmaps are also automatically split and merged (cf. [2.3.16](#2-3-16-support-for-sharding-in-ton-vm-data-structures)).
#### 2.3.19. Limiting splitting of smart contracts [#2319-limiting-splitting-of-smart-contracts]
A global smart contract may limit its splitting depth $d$ upon its creation, in order to make persistent storage expenses more predictable. This means that, if shardchain $(w,s)$ with $|s|\geq d$ splits in two, only one of two new shardchains inherits an instance of the smart contract. This shardchain is chosen deterministically: each global smart contract has some "$account\_id$", which is essentially the hash of its creating transaction, and its instances have the same $account\_id$ with the first $\leq d$ bits replaced by suitable values needed to fall into the correct shard. This $account\_id$ selects which shard will inherit the smart-contract instance after splitting.
#### 2.3.20. Account/Smart-contract state [#2320-accountsmart-contract-state]
We can summarize all of the above to conclude that an account or smart-contract state consists of the following:
* A balance in the principal currency of the blockchain
* A balance in other currencies of the blockchain
* Smart-contract code (or its hash)
* Smart-contract persistent data (or its Merkle hash)
* Statistics on the number of persistent storage cells and raw bytes used
* The last time (actually, the masterchain block number) when payment for smart-contract persistent storage was collected
* The public key needed to transfer currency and send messages from this account (optional; by default equal to $account\_id$ itself). In some cases, more sophisticated signature checking code may be located here, similar to what is done for Bitcoin transaction outputs; then the $account\_id$ will be equal to the hash of this code.
We also need to keep somewhere, either in the account state or in some other account-indexed hashmap, the following data:
* The output message queue of the account (cf. [2.4.17](#2-4-17-output-queues))
* The collection of (hashes of) recently delivered messages (cf. [2.4.23](#2-4-23-preventing-double-delivery-of-messages))
Not all of these are really required for every account; for example, smart-contract code is needed only for smart contracts, but not for "simple" accounts. Furthermore, while any account must have a non-zero balance in the principal currency (e.g., Grams for the masterchain and shardchains of the basic workchain), it may have balances of zero in other currencies. In order to avoid keeping unused data, a sum-product type (depending on the workchain) is defined (during the workchain's creation), which uses different tag bytes (e.g., TL constructors; cf. [2.2.5](#2-2-5-tl-or-the-type-language)) to distinguish between different "constructors" used. Ultimately, the account state is itself kept as a collection of cells of the TVM persistent storage.
***
### 2.4 Messages Between Shardchains [#24--messages-between-shardchains]
An important component of the TON Blockchain is the *messaging system* between blockchains. These blockchains may be shardchains of the same workchain, or of different workchains.
#### 2.4.1. Messages, accounts and transactions: a bird's eye view of the system [#241-messages-accounts-and-transactions-a-birds-eye-view-of-the-system]
*Messages* are sent from one account to another. Each *transaction* consists of an account receiving one message, changing its state according to certain rules, and generating several (maybe one or zero) new messages to other accounts. Each message is generated and received (delivered) exactly once.
This means that messages play a fundamental role in the system, comparable to that of accounts (smart contracts). From the perspective of the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), each account resides in its separate "account-chain", and the only way it can affect the state of some other account is by sending a message.
#### 2.4.2. Accounts as processes or actors; Actor model [#242-accounts-as-processes-or-actors-actor-model]
One might think about accounts (and smart contracts) as "processes", or "actors", that are able to process incoming messages, change their internal state and generate some outbound messages as a result. This is closely related to the so-called *Actor model*, used in languages such as Erlang (however, actors in Erlang are usually called "processes"). Since new actors (i.e., smart contracts) are also allowed to be created by existing actors as a result of processing an inbound message, the correspondence with the Actor model is essentially complete.
#### 2.4.3. Message recipient [#243-message-recipient]
Any message has its *recipient*, characterized by the *target workchain identifier $w$* (assumed by default to be the same as that of the originating shardchain), and the *recipient account $account\_id$*. The exact format (i.e., number of bits) of $account\_id$ depends on $w$; however, the shard is always determined by its first (most significant) 64 bits.
#### 2.4.4. Message sender [#244-message-sender]
In most cases, a message has a *sender*, characterized again by a $(w',\mathit{account\_id}')$ pair. If present, it is located after the message recipient and message value. Sometimes, the sender is unimportant or it is somebody outside the blockchain (i.e., not a smart contract), in which case this field is absent.
Notice that the Actor model does not require the messages to have an implicit sender. Instead, messages may contain a reference to the Actor to which an answer to the request should be sent; usually it coincides with the sender. However, it is useful to have an explicit unforgeable sender field in a message in a cryptocurrency (Byzantine) environment.
#### 2.4.5. Message value [#245-message-value]
Another important characteristic of a message is its attached *value*, in one or several cryptocurrencies supported both by the source and by the target workchain. The value of the message is indicated at its very beginning immediately after the message recipient; it is essentially a list of $(currency\_id, value)$ pairs.
Notice that "simple" value transfers between "simple" accounts are just empty (no-op) messages with some value attached to them. On the other hand, a slightly more complicated message body might contain a simple text or binary comment (e.g., about the purpose of the payment).
#### 2.4.6. External messages, or "messages from nowhere" [#246-external-messages-or-messages-from-nowhere]
Some messages arrive into the system "from nowhere"—that is, they are not generated by an account (smart contract or not) residing in the blockchain. The most typical example arises when a user wants to transfer some funds from an account controlled by her to some other account. In this case, the user sends a "message from nowhere" to her own account, requesting it to generate a message to the receiving account, carrying the specified value. If this message is correctly signed, her account receives it and generates the required outbound messages.
In fact, one might consider a "simple" account as a special case of a smart contract with predefined code. This smart contract receives only one type of message. Such an inbound message must contain a list of outbound messages to be generated as a result of delivering (processing) the inbound message, along with a signature. The smart contract checks the signature, and, if it is correct, generates the required messages.
Of course, there is a difference between "messages from nowhere" and normal messages, because the "messages from nowhere" cannot bear value, so they cannot pay for their "gas" (i.e., their processing) themselves. Instead, they are tentatively executed with a small gas limit before even being suggested for inclusion in a new shardchain block; if the execution fails (the signature is incorrect), the "message from nowhere" is deemed incorrect and is discarded. If the execution does not fail within the small gas limit, the message may be included in a new shardchain block and processed completely, with the payment for the gas (processing capacity) consumed exacted from the receiver's account. "Messages from nowhere" can also define some transaction fee which is deducted from the receiver's account on top of the gas payment for redistribution to the validators.
In this sense, "messages from nowhere" or "external messages" take the role of transaction candidates used in other blockchain systems (e.g., Bitcoin and Ethereum).
#### 2.4.7. Log messages, or "messages to nowhere" [#247-log-messages-or-messages-to-nowhere]
Similarly, sometimes a special message can be generated and routed to a specific shardchain not to be delivered to its recipient, but to be logged in order to be easily observable by anybody receiving updates about the shard in question. These logged messages may be output in a user's console, or trigger an execution of some script on an off-chain server. In this sense, they represent the external "output" of the "blockchain supercomputer", just as the "messages from nowhere" represent the external "input" of the "blockchain supercomputer".
#### 2.4.8. Interaction with off-chain services and external blockchains [#248-interaction-with-off-chain-services-and-external-blockchains]
These external input and output messages can be used for interacting with off-chain services and other (external) blockchains, such as Bitcoin or Ethereum. One might create tokens or cryptocurrencies inside the TON Blockchain pegged to Bitcoins, Ethers or any ERC-20 tokens defined in the Ethereum blockchain, and use "messages from nowhere" and "messages to nowhere", generated and processed by scripts residing on some third-party off-chain servers, to implement the necessary interaction between the TON Blockchain and these external blockchains.
#### 2.4.9. Message body [#249-message-body]
The *message body* is simply a sequence of bytes, the meaning of which is determined only by the receiving workchain and/or smart contract. For blockchains using TON VM, this could be the serialization of any TVM cell, generated automatically via the `Send()` operation. Such a serialization is obtained simply by recursively replacing all references in a TON VM cell with the cells referred to. Ultimately, a string of raw bytes appears, which is usually prepended by a 4-byte "message type" or "message constructor", used to select the correct method of the receiving smart contract.
Another option would be to use TL-serialized objects (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) as message bodies. This might be especially useful for communication between different workchains, one or both of which are not necessarily using the TON VM.
#### 2.4.10. Gas limit and other workchain/VM-specific parameters [#2410-gas-limit-and-other-workchainvm-specific-parameters]
Sometimes a message needs to carry information about the gas limit, the gas price, transaction fees and similar values that depend on the receiving workchain and are relevant only for the receiving workchain, but not necessarily for the originating workchain. Such parameters are included in or before the message body, sometimes (depending on the workchain) with special 4-byte prefixes indicating their presence (which can be defined by a TL-scheme; cf. [2.2.5](#2-2-5-tl-or-the-type-language)).
#### 2.4.11. Creating messages: smart contracts and transactions [#2411-creating-messages-smart-contracts-and-transactions]
There are two sources of new messages. Most messages are created during smart-contract execution (via the `Send()` operation in TON VM), when some smart contract is invoked to process an incoming message. Alternatively, messages may come from the outside as "external messages" or "messages from nowhere" (cf. [2.4.6](#2-4-6-external-messages-or-messages-from-nowhere)).[13](#fn13)
#### 2.4.12. Delivering messages [#2412-delivering-messages]
When a message reaches the shardchain containing its destination account,[14](#fn14) it is "delivered" to its destination account. What happens next depends on the workchain; from an outside perspective, it is important that such a message can never be forwarded further from this shardchain.
For shardchains of the basic workchain, delivery consists in adding the message value (minus any gas payments) to the balance of the receiving account, and possibly in invoking a message-dependent method of the receiving smart contract afterwards, if the receiving account is a smart contract. In fact, a smart contract has only one entry point for processing all incoming messages, and it must distinguish between different types of messages by looking at their first few bytes (e.g., the first four bytes containing a TL constructor; cf. [2.2.5](#2-2-5-tl-or-the-type-language)).
#### 2.4.13. Delivery of a message is a transaction [#2413-delivery-of-a-message-is-a-transaction]
Because the delivery of a message changes the state of an account or smart contract, it is a special *transaction* in the receiving shardchain, and is explicitly registered as such. Essentially, *all* TON Blockchain transactions consist in the delivery of one inbound message to its receiving account (smart contract), neglecting some minor technical details.
#### 2.4.14. Messages between instances of the same smart contract [#2414-messages-between-instances-of-the-same-smart-contract]
Recall that a smart contract may be *local* (i.e., residing in one shardchain as any ordinary account does) or *global* (i.e., having instances in all shards, or at least in all shards up to some known depth $d$; cf. [2.3.18](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)). Instances of a global smart contract may exchange special messages to transfer information and value between each other if required. In this case, the (unforgeable) sender $account\_id$ becomes important (cf. [2.4.4](#2-4-4-message-sender)).
#### 2.4.15. Messages to any instance of a smart contract; wildcard addresses [#2415-messages-to-any-instance-of-a-smart-contract-wildcard-addresses]
Sometimes a message (e.g., a client request) needs be delivered to any instance of a global smart contract, usually the closest one (if there is one residing in the same shardchain as the sender, it is the obvious candidate). One way of doing this is by using a "wildcard recipient address", with the first $d$ bits of the destination $account\_id$ allowed to take arbitrary values. In practice, one will usually set these $d$ bits to the same values as in the sender's $account\_id$.
#### 2.4.16. Input queue is absent [#2416-input-queue-is-absent]
All messages received by a blockchain (usually a shardchain; sometimes the masterchain)—or, essentially, by an "account-chain" residing inside some shardchain—are immediately delivered (i.e., processed by the receiving account). Therefore, there is no "input queue" as such. Instead, if not all messages destined for a specific shardchain can be processed because of limitations on the total size of blocks and gas usage, some messages are simply left to accumulate in the output queues of the originating shardchains.
#### 2.4.17. Output queues [#2417-output-queues]
From the perspective of the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), each account-chain (i.e., each account) has its own output queue, consisting of all messages it has generated, but not yet delivered to their recipients. Of course, account-chains have only a virtual existence; they are grouped into shardchains, and a shardchain has an output "queue", consisting of the union of the output queues of all accounts belonging to the shardchain.
This shardchain output "queue" imposes only partial order on its member messages. Namely, a message generated in a preceding block must be delivered before any message generated in a subsequent block, and any messages generated by the same account and having the same destination must be delivered in the order of their generation.
#### 2.4.18. Reliable and fast inter-chain messaging [#2418-reliable-and-fast-inter-chain-messaging]
It is of paramount importance for a scalable multi-blockchain project such as TON to be able to forward and deliver messages between different shardchains (cf. [2.1.3](#2-1-3-messages-instant-hypercube-routing)), even if there are millions of them in the system. The messages should be delivered *reliably* (i.e., messages should not be lost or delivered more than once) and *quickly*. The TON Blockchain achieves this goal by using a combination of two "message routing" mechanisms.
#### 2.4.19. Hypercube routing: "slow path" for messages with assured delivery [#2419-hypercube-routing-slow-path-for-messages-with-assured-delivery]
The TON Blockchain uses "hypercube routing" as a slow, but safe and reliable way of delivering messages from one shardchain to another, using several intermediate shardchains for transit if necessary. Otherwise, the validators of any given shardchain would need to keep track of the state of (the output queues of) all other shardchains, which would require prohibitive amounts of computing power and network bandwidth as the total quantity of shardchains grows, thus limiting the scalability of the system. Therefore, it is not possible to deliver messages directly from any shard to every other. Instead, each shard is "connected" only to shards differing in exactly one hexadecimal digit of their $(w,s)$ shard identifiers (cf. [2.1.8](#2-1-8-identification-of-shardchains)). In this way, all shardchains constitute a "hypercube" graph, and messages travel along the edges of this hypercube.
If a message is sent to a shard different from the current one, one of the hexadecimal digits (chosen deterministically) of the current shard identifier is replaced by the corresponding digit of the target shard, and the resulting identifier is used as the proximate target to forward the message to.[15](#fn15)
The main advantage of hypercube routing is that the block validity conditions imply that validators creating blocks of a shardchain must collect and process messages from the output queues of "neighboring" shardchains, on pain of losing their stakes. In this way, any message can be expected to reach its final destination sooner or later; a message cannot be lost in transit or delivered twice.
Notice that hypercube routing introduces some additional delays and expenses, because of the necessity to forward messages through several intermediate shardchains. However, the number of these intermediate shardchains grows very slowly, as the logarithm $\log N$ (more precisely, $\lceil\log_{16}N\rceil-1$) of the total number of shardchains $N$. For example, if $N\approx250$, there will be at most one intermediate hop; and for $N\approx4000$ shardchains, at most two. With four intermediate hops, we can support up to one million shardchains. We think this is a very small price to pay for the essentially unlimited scalability of the system. In fact, it is not necessary to pay even this price:
#### 2.4.20. Instant Hypercube Routing: "fast path" for messages [#2420-instant-hypercube-routing-fast-path-for-messages]
A novel feature of the TON Blockchain is that it introduces a "fast path" for forwarding messages from one shardchain to any other, allowing in most cases to bypass the "slow" hypercube routing of [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery) altogether and deliver the message into the very next block of the final destination shardchain.
The idea is as follows. During the "slow" hypercube routing, the message travels (in the network) along the edges of the hypercube, but it is delayed (for approximately five seconds) at each intermediate vertex to be committed into the corresponding shardchain before continuing its voyage.
To avoid unnecessary delays, one might instead relay the message along with a suitable Merkle proof along the edges of the hypercube, without waiting to commit it into the intermediate shardchains. In fact, the network message should be forwarded from the validators of the "task group" (cf. [2.6.8](#2-6-8-election-of-validator-task-groups)) of the original shard to the designated block producer (cf. [2.6.9](#2-6-9-rotating-priority-order-on-each-task-group)) of the "task group" of the destination shard; this might be done directly without going along the edges of the hypercube. When this message with the Merkle proof reaches the validators (more precisely, the collators; cf. [2.6.5](#2-6-5-collators-obtaining-money-by-suggesting-new-blocks-to-validators)) of the destination shardchain, they can commit it into a new block immediately, without waiting for the message to complete its travel along the "slow path". Then a confirmation of delivery along with a suitable Merkle proof is sent back along the hypercube edges, and it may be used to stop the travel of the message along the "slow path", by committing a special transaction.
Note that this "instant delivery" mechanism does not replace the "slow" but failproof mechanism described in [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery). The "slow path" is still needed because the validators cannot be punished for losing or simply deciding not to commit the "fast path" messages into new blocks of their blockchains.[16](#fn16)
Therefore, both message forwarding methods are run in parallel, and the "slow" mechanism is aborted only if a proof of success of the "fast" mechanism is committed into an intermediate shardchain.[17](#fn17)
#### 2.4.21. Collecting input messages from output queues of neighboring shardchains [#2421-collecting-input-messages-from-output-queues-of-neighboring-shardchains]
When a new block for a shardchain is proposed, some of the output messages of the neighboring (in the sense of the routing hypercube of [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)) shardchains are included in the new block as "input" messages and immediately delivered (i.e., processed). There are certain rules as to the order in which these neighbors' output messages must be processed. Essentially, an "older" message (coming from a shardchain block referring to an older masterchain block) must be delivered before any "newer" message; and for messages coming from the same neighboring shardchain, the partial order of the output queue described in [2.4.17](#2-4-17-output-queues) must be observed.
#### 2.4.22. Deleting messages from output queues [#2422-deleting-messages-from-output-queues]
Once an output queue message is observed as having been delivered by a neighboring shardchain, it is explicitly deleted from the output queue by a special transaction.
#### 2.4.23. Preventing double delivery of messages [#2423-preventing-double-delivery-of-messages]
To prevent double delivery of messages taken from the output queues of the neighboring shardchains, each shardchain (more precisely, each account-chain inside it) keeps the collection of recently delivered messages (or just their hashes) as part of its state. When a delivered message is observed to be deleted from the output queue by its originating neighboring shardchain (cf. [2.4.22](#2-4-22-deleting-messages-from-output-queues)), it is deleted from the collection of recently delivered messages as well.
#### 2.4.24. Forwarding messages intended for other shardchains [#2424-forwarding-messages-intended-for-other-shardchains]
Hypercube routing (cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)) means that sometimes outbound messages are delivered not to the shardchain containing the intended recipient, but to a neighboring shardchain lying on the hypercube path to the destination. In this case, "delivery" consists in moving the inbound message to the outbound queue. This is reflected explicitly in the block as a special *forwarding transaction*, containing the message itself. Essentially, this looks as if the message had been received by somebody inside the shardchain, and one identical message had been generated as result.
#### 2.4.25. Payment for forwarding and keeping a message [#2425-payment-for-forwarding-and-keeping-a-message]
The forwarding transaction actually spends some gas (depending on the size of the message being forwarded), so a gas payment is deducted from the value of the message being forwarded on behalf of the validators of this shardchain. This forwarding payment is normally considerably smaller than the gas payment exacted when the message is finally delivered to its recipient, even if the message has been forwarded several times because of hypercube routing. Furthermore, as long as a message is kept in the output queue of some shardchain, it is part of the shardchain's global state, so a payment for keeping global data for a long time may be also collected by special transactions.
#### 2.4.26. Messages to and from the masterchain [#2426-messages-to-and-from-the-masterchain]
Messages can be sent directly from any shardchain to the masterchain, and vice versa. However, gas prices for sending messages to and for processing messages in the masterchain are quite high, so this ability will be used only when truly necessary—for example, by the validators to deposit their stakes. In some cases, a minimal deposit (attached value) for messages sent to the masterchain may be defined, which is returned only if the message is deemed "valid" by the receiving party.
Messages cannot be automatically routed through the masterchain. A message with $\mathit{workchain\_id}\neq-1$ ($-1$ being the special $\mathit{workchain\_id}$ indicating the masterchain) cannot be delivered to the masterchain.
In principle, one can create a message-forwarding smart contract inside the masterchain, but the price of using it would be prohibitive.
#### 2.4.27. Messages between accounts in the same shardchain [#2427-messages-between-accounts-in-the-same-shardchain]
In some cases, a message is generated by an account belonging to some shardchain, destined to another account in the same shardchain. For example, this happens in a new workchain which has not yet split into several shardchains because the load is manageable.
Such messages might be accumulated in the output queue of the shardchain and then processed as incoming messages in subsequent blocks (any shard is considered a neighbor of itself for this purpose). However, in most cases it is possible to deliver these messages within the originating block itself.
In order to achieve this, a partial order is imposed on all transactions included in a shardchain block, and the transactions (each consisting in the delivery of a message to some account) are processed respecting this partial order. In particular, a transaction is allowed to process some output message of a preceding transaction with respect to this partial order.
In this case, the message body is not copied twice. Instead, the originating and the processing transactions refer to a shared copy of the message.
### 2.5 Global Shardchain State. "Bag of Cells" Philosophy [#25--global-shardchain-state-bag-of-cells-philosophy]
Now we are ready to describe the global state of a TON blockchain, or at least of a shardchain of the basic workchain.
We start with a "high-level" or "logical" description, which consists in saying that the global state is a value of algebraic type $\mathit{ShardchainState}$.
#### 2.5.1. Shardchain state as a collection of account-chain states [#251-shardchain-state-as-a-collection-of-account-chain-states]
According to the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), any shardchain is just a (temporary) collection of virtual "account-chains", containing exactly one account each. This means that, essentially, the global shardchain state must be a hashmap
$$
\mathit{ShardchainState}:=(\mathit{Account}\dashrightarrow\mathit{AccountState}) \tag{23}
$$
where all $\mathit{account\_id}$ appearing as indices of this hashmap must begin with prefix $s$, if we are discussing the state of shard $(w,s)$ (cf. [2.1.8](#2-1-8-identification-of-shardchains)).
In practice, we might want to split $\mathit{AccountState}$ into several parts (e.g., keep the account output message queue separate to simplify its examination by the neighboring shardchains), and have several hashmaps $(\mathit{Account}\dashrightarrow\mathit{AccountStatePart}_i)$ inside the $\mathit{ShardchainState}$. We might also add a small number of "global" or "integral" parameters to the $\mathit{ShardchainState}$, (e.g., the total balance of all accounts belonging to this shard, or the total number of messages in all output queues).
However, equation ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) is a good first approximation of what the shardchain global state looks like, at least from a "logical" ("high-level") perspective. The formal description of algebraic types $\mathit{AccountState}$ and $\mathit{ShardchainState}$ can be done with the aid of a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)), to be provided elsewhere.
#### 2.5.2. Splitting and merging shardchain states [#252-splitting-and-merging-shardchain-states]
Notice that the Infinite Sharding Paradigm description of the shardchain state above shows how this state ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) should be processed when shards are split or merged. In fact, these state transformations turn out to be very simple operations with hashmaps.
#### 2.5.3. Account-chain state [#253-account-chain-state]
The (virtual) account-chain state is just the state of one account, described by type $\mathit{AccountState}$. Usually it has all or some of the fields listed in [2.3.20](#2-3-20-account-smart-contract-state), depending on the specific constructor used.
#### 2.5.4. Global workchain state [#254-global-workchain-state]
Similarly to ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) the shardchain state equation, we may define the global *workchain* state by the same formula, but with $\mathit{account\_id}$'s allowed to take any values, not just those belonging to one shard. Remarks similar to those made in [2.5.1](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states) apply in this case as well: we might want to split this hashmap into several hashmaps, and we might want to add some "integral" parameters such as the total balance.
Essentially, the global workchain state *must* be given by the same type $\mathit{ShardchainState}$ as the shardchain state, because it is the shardchain state we would obtain if all existing shardchains of this workchain suddenly merged into one.
#### 2.5.5. Low-level perspective: "bag of cells" [#255-low-level-perspective-bag-of-cells]
There is a "low-level" description of the account-chain or shardchain state as well, complementary to the "high-level" description given above. This description is quite important, because it turns out to be pretty universal, providing a common basis for representing, storing, serializing and transferring by network almost all data used by the TON Blockchain (blocks, shardchain states, smart-contract storage, Merkle proofs, etc.). At the same time, such a universal "low-level" description, once understood and implemented, allows us to concentrate our attention on the "high-level" considerations only.
Recall that the TVM represents values of arbitrary algebraic types (including, for instance, $\mathit{ShardchainState}$ of the shardchain state equation) by means of a tree of *TVM cells*, or *cells* for short (cf. [2.3.14](#2-3-14-tvm-cells) and [2.2.5](#2-2-5-tl-or-the-type-language)).
Any such cell consists of two *descriptor bytes*, defining certain flags and values $0\leq b\leq 128$, the quantity of raw bytes, and $0\leq c\leq 4$, the quantity of references to other cells. Then $b$ raw bytes and $c$ cell references follow.[18](#fn18)
The exact format of cell references depends on the implementation and on whether the cell is located in RAM, on disk, in a network packet, in a block, and so on. A useful abstract model consists in imagining that all cells are kept in content-addressable memory, with the address of a cell equal to its (SHA-256) hash. Recall that the (Merkle) hash of a cell is computed exactly by replacing the references to its child cells by their (recursively computed) hashes and hashing the resulting byte string.
In this way, if we use cell hashes to reference cells (e.g., inside descriptions of other cells), the system simplifies somewhat, and the hash of a cell starts to coincide with the hash of the byte string representing it.
Now we see that *any object representable by TVM, the global shardchain state included, can be represented as a "bag of cells"*—i.e., *a collection of cells along with a "root" reference to one of them* (e.g., by hash). Notice that duplicate cells are removed from this description (the "bag of cells" is a set of cells, not a multiset of cells), so the abstract tree representation might actually become a directed acyclic graph (dag) representation.
One might even keep this state on disk in a $B$- or $B+$-tree, containing all cells in question (maybe with some additional data, such as subtree height or reference counter), indexed by cell hash. However, a naive implementation of this idea would result in the state of one smart contract being scattered among distant parts of the disk file, something we would rather avoid.[19](#fn19)
Now we are going to explain in some detail how almost all objects used by the TON Blockchain can be represented as "bags of cells", thus demonstrating the universality of this approach.
#### 2.5.6. Shardchain block as a "bag of cells" [#256-shardchain-block-as-a-bag-of-cells]
A shardchain block itself can be also described by an algebraic type, and stored as a "bag of cells". Then a naive binary representation of the block may be obtained simply by concatenating the byte strings representing each of the cells in the "bag of cells", in arbitrary order. This representation might be improved and optimized, for instance, by providing a list of offsets of all cells at the beginning of the block, and replacing hash references to other cells with 32-bit indices in this list whenever possible. However, one should imagine that a block is essentially a "bag of cells", and all other technical details are just minor optimization and implementation issues.
#### 2.5.7. Update to an object as a "bag of cells" [#257-update-to-an-object-as-a-bag-of-cells]
Imagine that we have an old version of some object represented as a "bag of cells", and that we want to represent a new version of the same object, supposedly not too different from the previous one. One might simply represent the new state as another "bag of cells" with its own root, *and remove from it all cells occurring in the old version*. The remaining "bag of cells" is essentially an *update* to the object. Everybody who has the old version of this object and the update can compute the new version, simply by uniting the two bags of cells, and removing the old root (decreasing its reference counter and de-allocating the cell if the reference counter becomes zero).
#### 2.5.8. Updates to the state of an account [#258-updates-to-the-state-of-an-account]
In particular, updates to the state of an account, or to the global state of a shardchain, or to any hashmap can be represented using the idea described in [2.5.7](#2-5-7-update-to-an-object-as-a-bag-of-cells). This means that when we receive a new shardchain block (which is a "bag of cells"), we interpret this "bag of cells" not just by itself, but by uniting it first with the "bag of cells" representing the previous state of the shardchain. In this sense each block may "contain" the whole state of the blockchain.
#### 2.5.9. Updates to a block [#259-updates-to-a-block]
Recall that a block itself is a "bag of cells", so, if it becomes necessary to edit a block, one can similarly define a "block update" as a "bag of cells", interpreted in the presence of the "bag of cells" which is the previous version of this block. This is roughly the idea behind the "vertical blocks" discussed in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks).
#### 2.5.10. Merkle proof as a "bag of cells" [#2510-merkle-proof-as-a-bag-of-cells]
Notice that a (generalized) Merkle proof—for example, one asserting that $x[i]=y$ starting from a known value of $\texttt{Hash}(x)=h$ (cf. [2.3.10](#2-3-10-merkle-proofs) and [2.3.15](#2-3-15-generalized-merkle-proofs-for-values-of-arbitrary-algebraic-types))—may also be represented as a "bag of cells". Namely, one simply needs to provide a subset of cells corresponding to a path from the root of $x:\mathit{Hashmap}(n,X)$ to its desired leaf with index $i:\mathbf{2}^n$ and value $y:X$. References to children of these cells not lying on this path will be left "unresolved" in this proof, represented by cell hashes. One can also provide a simultaneous Merkle proof of, say, $x[i]=y$ and $x[i']=y'$, by including in the "bag of cells" the cells lying on the union of the two paths from the root of $x$ to leaves corresponding to indices $i$ and $i'$.
#### 2.5.11. Merkle proofs as query responses from full nodes [#2511-merkle-proofs-as-query-responses-from-full-nodes]
In essence, a full node with a complete copy of a shardchain (or account-chain) state can provide a Merkle proof when requested by a light node (e.g., a network node running a light version of the TON Blockchain client), enabling the receiver to perform some simple queries without external help, using only the cells provided in this Merkle proof. The light node can send its queries in a serialized format to the full node, and receive the correct answers with Merkle proofs—or just the Merkle proofs, because the requester should be able to compute the answers using only the cells included in the Merkle proof. This Merkle proof would consist simply of a "bag of cells", containing only those cells belonging to the shardchain's state that have been accessed by the full node while executing the light node's query. This approach can be used in particular for executing "get queries" of smart contracts (cf. [4.3.12](#4-3-12-tentative-execution-of-get-methods-of-smart-contracts)).
#### 2.5.12. Augmented update, or state update with Merkle proof of validity [#2512-augmented-update-or-state-update-with-merkle-proof-of-validity]
Recall (cf. [2.5.7](#2-5-7-update-to-an-object-as-a-bag-of-cells)) that we can describe the changes in an object state from an old value $x:X$ to a new value $x':X$ by means of an "update", which is simply a "bag of cells", containing those cells that lie in the subtree representing new value $x'$, but not in the subtree representing old value $x$, because the receiver is assumed to have a copy of the old value $x$ and all its cells.
However, if the receiver does not have a full copy of $x$, but knows only its (Merkle) hash $h=\text{Hash}(x)$, it will not be able to check the validity of the update (i.e., that all "dangling" cell references in the update do refer to cells present in the tree of $x$). One would like to have "verifiable" updates, augmented by Merkle proofs of existence of all referred cells in the old state. Then anybody knowing only $h=\text{Hash}(x)$ would be able to check the validity of the update and compute the new $h'=\text{Hash}(x')$ by itself.
Because our Merkle proofs are "bags of cells" themselves (cf. [2.5.10](#2-5-10-merkle-proof-as-a-bag-of-cells)), one can construct such an *augmented update* as a "bag of cells", containing the old root of $x$, some of its descendants along with paths from the root of $x$ to them, and the new root of $x'$ and all its descendants that are not part of $x$.
#### 2.5.13. Account state updates in a shardchain block [#2513-account-state-updates-in-a-shardchain-block]
In particular, account state updates in a shardchain block should be augmented as discussed in [2.5.12](#2-5-12-augmented-update-or-state-update-with-merkle-proof-of-validity). Otherwise, somebody might commit a block containing an invalid state update, referring to a cell absent in the old state; proving the invalidity of such a block would be problematic (how is the challenger to prove that a cell is *not* part of the previous state?).
Now, if all state updates included in a block are augmented, their validity is easily checked, and their invalidity is also easily shown as a violation of the recursive defining property of (generalized) Merkle hashes.
#### 2.5.14. "Everything is a bag of cells" philosophy [#2514-everything-is-a-bag-of-cells-philosophy]
Previous considerations show that everything we need to store or transfer, either in the TON Blockchain or in the network, is representable as a "bag of cells". This is an important part of the TON Blockchain design philosophy. Once the "bag of cells" approach is explained and some "low-level" serializations of "bags of cells" are defined, one can simply define everything (block format, shardchain and account state, etc.) on the high level of abstract (dependent) algebraic data types.
The unifying effect of the "everything is a bag of cells" philosophy considerably simplifies the implementation of seemingly unrelated services; cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels) for an example involving payment channels.
#### 2.5.15. Block "headers" for TON blockchains [#2515-block-headers-for-ton-blockchains]
Usually, a block in a blockchain begins with a small header, containing the hash of the previous block, its creation time, the Merkle hash of the tree of all transactions contained in the block, and so on. Then the block hash is defined to be the hash of this small block header. Because the block header ultimately depends on all data included in the block, one cannot alter the block without changing its hash.
In the "bag of cells" approach used by the blocks of TON blockchains, there is no designated block header. Instead, the block hash is defined as the (Merkle) hash of the root cell of the block. Therefore, the top (root) cell of the block might be considered a small "header" of this block.
However, the root cell might not contain all the data usually expected from such a header. Essentially, one wants the header to contain some of the fields defined in the *Block* datatype. Normally, these fields will be contained in several cells, including the root. These are the cells that together constitute a "Merkle proof" for the values of the fields in question. One might insist that a block contain these "header cells" in the very beginning, before any other cells. Then one would need to download only the first several bytes of a block serialization in order to obtain all of the "header cells", and to learn all of the expected fields.
***
### 2.6 Creating and Validating New Blocks [#26---creating-and-validating-new-blocks]
The TON Blockchain ultimately consists of shardchain and masterchain blocks. These blocks must be created, validated and propagated through the network to all parties concerned, in order for the system to function smoothly and correctly.
#### 2.6.1. Validators [#261-validators]
New blocks are created and validated by special designated nodes, called *validators*. Essentially, any node wishing to become a validator may become one, provided it can deposit a sufficiently large stake (in TON coins, i.e., Grams; cf. [Appendix A](#appendix-a-the-ton-coin-or-the-gram)) into the masterchain. Validators obtain some "rewards" for good work, namely, the transaction, storage and gas fees from all transactions (messages) committed into newly generated blocks, and some newly minted coins, reflecting the "gratitude" of the whole community to the validators for keeping the TON Blockchain working. This income is distributed among all participating validators proportionally to their stakes.
However, being a validator is a high responsibility. If a validator signs an invalid block, it can be punished by losing part or all of its stake, and by being temporarily or permanently excluded from the set of validators. If a validator does not participate in creating a block, it does not receive its share of the reward associated with that block. If a validator abstains from creating new blocks for a long time, it may lose part of its stake and be suspended or permanently excluded from the set of validators.
All this means that the validator does not get its money "for nothing". Indeed, it must keep track of the states of all or some shardchains (each validator is responsible for validating and creating new blocks in a certain subset of shardchains), perform all computations requested by smart contracts in these shardchains, receive updates about other shardchains and so on. This activity requires considerable disk space, computing power and network bandwidth.
#### 2.6.2. Validators instead of miners [#262-validators-instead-of-miners]
Recall that the TON Blockchain uses the Proof-of-Stake approach, instead of the Proof-of-Work approach adopted by Bitcoin, the current version of Ethereum, and most other cryptocurrencies. This means that one cannot "mine" a new block by presenting some proof-of-work (computing a lot of otherwise useless hashes) and obtain some new coins as a result. Instead, one must become a validator and spend one's computing resources to store and process TON Blockchain requests and data. In short, *one must be a validator to mine new coins.* In this respect, *validators are the new miners.*
However, there are some other ways to earn coins apart from being a validator.
#### 2.6.3. Nominators and "mining pools" [#263-nominators-and-mining-pools]
To become a validator, one would normally need to buy and install several high-performance servers and acquire a good Internet connection for them. This is not so expensive as the ASIC equipment currently required to mine Bitcoins. However, one definitely cannot mine new TON coins on a home computer, let alone a smartphone.
In the Bitcoin, Ethereum and other Proof-of-Work cryptocurrency mining communities there is a notion of *mining pools*, where a lot of nodes, having insufficient computing power to mine new blocks by themselves, combine their efforts and share the reward afterwards.
A corresponding notion in the Proof-of-Stake world is that of a *nominator*. Essentially, this is a node lending its money to help a validator increase its stake; the validator then distributes the corresponding share of its reward (or some previously agreed fraction of it—say, 50%) to the nominator.
In this way, a nominator can also take part in the "mining" and obtain some reward proportional to the amount of money it is willing to deposit for this purpose. It receives only a fraction of the corresponding share of the validator's reward, because it provides only the "capital", but does not need to buy computing power, storage and network bandwidth.
However, if the validator loses its stake because of invalid behavior, the nominator loses its share of the stake as well. In this sense the nominator *shares the risk*. It must choose its nominated validator wisely, otherwise it can lose money. In this sense, nominators make a weighted decision and "vote" for certain validators with their funds.
On the other hand, this nominating or lending system enables one to become a validator without investing a large amount of money into Grams (TON coins) first. In other words, it prevents those keeping large amounts of Grams from monopolizing the supply of validators.
#### 2.6.4. Fishermen: obtaining money by pointing out others' mistakes [#264-fishermen-obtaining-money-by-pointing-out-others-mistakes]
Another way to obtain some rewards without being a validator is by becoming a *fisherman*. Essentially, any node can become a fisherman by making a small deposit in the masterchain. Then it can use special masterchain transactions to publish (Merkle) invalidity proofs of some (usually shardchain) blocks previously signed and published by validators. If other validators agree with this invalidity proof, the offending validators are punished (by losing part of their stake), and the fisherman obtains some reward (a fraction of coins confiscated from the offending validators). Afterwards, the invalid (shardchain) block must be corrected as outlined in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks). Correcting invalid masterchain blocks may involve creating "vertical" blocks on top of previously committed masterchain blocks (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)); there is no need to create a fork of the masterchain.
Normally, a fisherman would need to become a full node for at least some shardchains, and spend some computing resources by running the code of at least some smart contracts. While a fisherman does not need to have as much computing power as a validator, we think that a natural candidate to become a fisherman is a would-be validator that is ready to process new blocks, but has not yet been elected as a validator (e.g., because of a failure to deposit a sufficiently large stake).
#### 2.6.5. Collators: obtaining money by suggesting new blocks to validators [#265-collators-obtaining-money-by-suggesting-new-blocks-to-validators]
Yet another way to obtain some rewards without being a validator is by becoming a *collator*. This is a node that prepares and suggests to a validator new shardchain block candidates, complemented (collated) with data taken from the state of this shardchain and from other (usually neighboring) shardchains, along with suitable Merkle proofs. (This is necessary, for example, when some messages need to be forwarded from neighboring shardchains.) Then a validator can easily check the proposed block candidate for validity, without having to download the complete state of this or other shardchains.
Because a validator needs to submit new (collated) block candidates to obtain some ("mining") rewards, it makes sense to pay some part of the reward to a collator willing to provide suitable block candidates. In this way, a validator may free itself from the necessity of watching the state of the neighboring shardchains, by outsourcing it to a collator.
However, we expect that during the system's initial deployment phase there will be no separate designated collators, because all validators will be able to act as collators for themselves.
#### 2.6.6. Collators or validators: obtaining money for including user transactions [#266-collators-or-validators-obtaining-money-for-including-user-transactions]
Users can open micropayment channels to some collators or validators and pay small amounts of coins in exchange for the inclusion of their transactions in the shardchain.
#### 2.6.7. Global validator set election [#267-global-validator-set-election]
The "global" set of validators is elected once each month (actually, every $2^{19}$ masterchain blocks). This set is determined and universally known one month in advance.
In order to become a validator, a node must transfer some TON coins (Grams) into the masterchain, and then send them to a special smart contract as its suggested stake $s$. Another parameter, sent along with the stake, is $l\geq 1$, the maximum validating load this node is willing to accept relative to the minimal possible. There is also a global upper bound (another configurable parameter) $L$ on $l$, equal to, say, 10.
Then the global set of validators is elected by this smart contract, simply by selecting up to $T$ candidates with maximal suggested stakes and publishing their identities. Originally, the total number of validators is $T=100$; we expect it to grow to 1000 as the load increases. It is a configurable parameter (cf. [2.1.21](#2-1-21-configurable-parameters)).
The actual stake of each validator is computed as follows: If the top $T$ proposed stakes are $s_1\geq s_2\geq\cdots\geq s_T$, the actual stake of $i$-th validator is set to $s'_i:=\min(s_i,l_i\cdot s_T)$. In this way, $s'_i/s'_T\leq l_i$, so the $i$-th validator does not obtain more than $l_i\leq L$ times the load of the weakest validator (because the load is ultimately proportional to the stake).
Then elected validators may withdraw the unused part of their stake, $s_i-s'_i$. Unsuccessful validator candidates may withdraw all of their proposed stake.
Each validator publishes its *public signing key*, not necessarily equal to the public key of the account the stake came from.[20](#fn20)
The stakes of the validators are frozen until the end of the period for which they have been elected, and one month more, in case new disputes arise (i.e., an invalid block signed by one of these validators is found). After that, the stake is returned, along with the validator's share of coins minted and fees from transactions processed during this time.
#### 2.6.8. Election of validator "task groups" [#268-election-of-validator-task-groups]
The whole global set of validators (where each validator is considered present with multiplicity equal to its stake—otherwise a validator might be tempted to assume several identities and split its stake among them) is used only to validate new masterchain blocks. The shardchain blocks are validated only by specially selected subsets of validators, taken from the global set of validators chosen as described in [2.6.7](#2-6-7-global-validator-set-election).
These validator "subsets" or "task groups", defined for every shard, are rotated each hour (actually, every $2^{10}$ masterchain blocks), and they are known one hour in advance, so that every validator knows which shards it will need to validate, and can prepare for that (e.g., by downloading missing shardchain data).
The algorithm used to select validator task groups for each shard $(w,s)$ is deterministic pseudorandom. It uses pseudorandom numbers embedded by validators into each masterchain block (generated by a consensus using threshold signatures) to create a random seed, and then computes for example $\text{Hash}(\text{CODE}(w).\text{CODE}(s).\mathit{validator\_id}.\mathit{rand\_seed})$ for each validator. Then validators are sorted by the value of this hash, and the first several are selected, so as to have at least $20/T$ of the total validator stakes and consist of at least 5 validators.
This selection could be done by a special smart contract. In that case, the selection algorithm would easily be upgradable without hard forks by the voting mechanism mentioned in [2.1.21](#2-1-21-configurable-parameters). All other "constants" mentioned so far (such as $2^{19}$, $2^{10}$, $T$, 20, and 5) are also configurable parameters.
#### 2.6.9. Rotating priority order on each task group [#269-rotating-priority-order-on-each-task-group]
There is a certain "priority" order imposed on the members of a shard task group, depending on the hash of the previous masterchain block and (shardchain) block sequence number. This order is determined by generating and sorting some hashes as described above.
When a new shardchain block needs to be generated, the shard task group validator selected to create this block is normally the first one with respect to this rotating "priority" order. If it fails to create the block, the second or third validator may do it. Essentially, all of them may suggest their block candidates, but the candidate suggested by the validator having the highest priority should win as the result of Byzantine Fault Tolerant (BFT) consensus protocol.
#### 2.6.10. Propagation of shardchain block candidates [#2610-propagation-of-shardchain-block-candidates]
Because shardchain task group membership is known one hour in advance, their members can use that time to build a dedicated "shard validators multicast overlay network", using the general mechanisms of the TON Network (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). When a new shardchain block needs to be generated—normally one or two seconds after the most recent masterchain block has been propagated—everybody knows who has the highest priority to generate the next block (cf. [2.6.9](#2-6-9-rotating-priority-order-on-each-task-group)). This validator will create a new collated block candidate, either by itself or with the aid of a collator (cf. [2.6.5](#2-6-5-collators-obtaining-money-by-suggesting-new-blocks-to-validators)). The validator must check (validate) this block candidate (especially if it has been prepared by some collator) and sign it with its (validator) private key. Then the block candidate is propagated to the remainder of the task group using the prearranged multicast overlay network (the task group creates its own private overlay network as explained in [3.3](#3-3-overlay-networks-and-multicasting-messages), and then uses a version of the streaming multicast protocol described in [3.3.15](#3-3-15-streaming-broadcast-protocol) to propagate block candidates).
A truly BFT way of doing this would be to use a Byzantine multicast protocol, such as the one used in Honey Badger BFT [\[11\]](#ref-11): encode the block candidate by an $(N,2N/3)$-erasure code, send $1/N$ of the resulting data directly to each member of the group, and expect them to multicast directly their part of the data to all other members of the group.
However, a faster and more straightforward way of doing this (cf. also [3.3.15](#3-3-15-streaming-broadcast-protocol)) is to split the block candidate into a sequence of signed one-kilobyte blocks ("chunks"), augment their sequence by a Reed–Solomon or a fountain code (such as the RaptorQ code [\[9\]](#ref-9) [\[14\]](#ref-14)), and start transmitting chunks to the neighbors in the "multicast mesh" (i.e., the overlay network), expecting them to propagate these chunks further. Once a validator obtains enough chunks to reconstruct the block candidate from them, it signs a confirmation receipt and propagates it through its neighbors to the whole of the group. Then its neighbors stop sending new chunks to it, but may continue to send the (original) signatures of these chunks, believing that this node can generate the subsequent chunks by applying the Reed–Solomon or fountain code by itself (having all data necessary), combine them with signatures, and propagate to its neighbors that are not yet ready.
If the "multicast mesh" (overlay network) remains connected after removing all "bad" nodes (recall that up to one-third of nodes are allowed to be bad in a Byzantine way, i.e., behave in arbitrary malicious fashion), this algorithm will propagate the block candidate as quickly as possible.
Not only the designated high-priority block creator may multicast its block candidate to the whole of the group. The second and third validator by priority may start multicasting their block candidates, either immediately or after failing to receive a block candidate from the top priority validator. However, normally only the block candidate with maximal priority will be signed by all (actually, by at least two-thirds of the task group) validators and committed as a new shardchain block.
#### 2.6.11. Validation of block candidates [#2611-validation-of-block-candidates]
Once a block candidate is received by a validator and the signature of its originating validator is checked, the receiving validator checks the validity of this block candidate, by performing all transactions in it and checking that their result coincides with the one claimed. All messages imported from other blockchains must be supported by suitable Merkle proofs in the collated data, otherwise the block candidate is deemed invalid (and, if a proof of this is committed to the masterchain, the validators having already signed this block candidate may be punished). On the other hand, if the block candidate is found to be valid, the receiving validator signs it and propagates its signature to other validators in the group, either through the "mesh multicast network", or by direct network messages.
We would like to emphasize that *a validator does not need access to the states of this or neighboring shardchains in order to check the validity of a (collated) block candidate*.[21](#fn21) This allows the validation to proceed very quickly (without disk accesses), and lightens the computational and storage burden on the validators (especially if they are willing to accept the services of outside collators for creating block candidates).
#### 2.6.12. Election of the next block candidate [#2612-election-of-the-next-block-candidate]
Once a block candidate collects at least two-thirds (by stake) of the validity signatures of validators in the task group, it is eligible to be committed as the next shardchain block. A BFT protocol is run to achieve consensus on the block candidate chosen (there may be more than one proposed), with all "good" validators preferring the block candidate with the highest priority for this round. As a result of running this protocol, the block is augmented by signatures of at least two-thirds of the validators (by stake). These signatures testify not only to the validity of the block in question, but also to its being elected by the BFT protocol. After that, the block (without collated data) is combined with these signatures, serialized in a deterministic way, and propagated through the network to all parties concerned.
#### 2.6.13. Validators must keep the blocks they have signed [#2613-validators-must-keep-the-blocks-they-have-signed]
During their membership in the task group and for at least one hour (or rather $2^{10}$ blocks) afterward, the validators are expected to keep the blocks they have signed and committed. The failure to provide a signed block to other validators may be punished.
#### 2.6.14. Propagating the headers and signatures of new shardchain blocks to all validators [#2614-propagating-the-headers-and-signatures-of-new-shardchain-blocks-to-all-validators]
Validators propagate the headers and signatures of newly-generated shardchain blocks to the *global* set of validators, using a multicast mesh network similar to the one created for each task group.
#### 2.6.15. Generation of new masterchain blocks [#2615-generation-of-new-masterchain-blocks]
After all (or almost all) new shardchain blocks have been generated, a new masterchain block may be generated. The procedure is essentially the same as for shardchain blocks (cf. [2.6.12](#2-6-12-election-of-the-next-block-candidate)), with the difference that *all* validators (or at least two-thirds of them) must participate in this process. Because the headers and signatures of new shardchain blocks are propagated to all validators, hashes of the newest blocks in each shardchain can and must be included in the new masterchain block. Once these hashes are committed into the masterchain block, outside observers and other shardchains may consider the new shardchain blocks committed and immutable (cf. [2.1.13](#2-1-13-using-the-masterchain-to-make-workchains-and-shardchains-tightly-coupled)).
#### 2.6.16. Validators must keep the state of masterchain [#2616-validators-must-keep-the-state-of-masterchain]
A noteworthy difference between the masterchain and the shardchains is that all validators are expected to keep track of the masterchain state, without relying on collated data. This is important because the knowledge of validator task groups is derived from the masterchain state.
#### 2.6.17. Shardchain blocks are generated and propagated in parallel [#2617-shardchain-blocks-are-generated-and-propagated-in-parallel]
Normally, each validator is a member of several shardchain task groups; their quantity (hence the load on the validator) is approximately proportional to the validator's stake. This means that the validator runs several instances of new shardchain block generation protocol in parallel.
#### 2.6.18. Mitigation of block retention attacks [#2618-mitigation-of-block-retention-attacks]
Because the total set of validators inserts a new shardchain block's hash into the masterchain after having seen only its header and signatures, there is a small probability that the validators that have generated this block will conspire and try to avoid publishing the new block in its entirety. This would result in the inability of validators of neighboring shardchains to create new blocks, because they must know at least the output message queue of the new block, once its hash has been committed into the masterchain.
In order to mitigate this, the new block must collect signatures from some other validators (e.g., two-thirds of the union of task groups of neighboring shardchains) testifying that these validators do have copies of this block and are willing to send them to any other validators if required. Only after these signatures are presented may the new block's hash be included in the masterchain.
#### 2.6.19. Masterchain blocks are generated later than shardchain blocks [#2619-masterchain-blocks-are-generated-later-than-shardchain-blocks]
Masterchain blocks are generated approximately once every five seconds, as are shardchain blocks. However, while the generation of new blocks in all shardchains runs essentially at the same time (normally triggered by the release of a new masterchain block), the generation of new masterchain blocks is deliberately delayed, to allow the inclusion of hashes of newly-generated shardchain blocks in the masterchain.
#### 2.6.20. Slow validators may receive lower rewards [#2620-slow-validators-may-receive-lower-rewards]
If a validator is "slow", it may fail to validate new block candidates, and two-thirds of the signatures required to commit the new block may be gathered without its participation. In this case, it will receive a lower share of the reward associated with this block.
This provides an incentive for the validators to optimize their hardware, software, and network connection in order to process user transactions as fast as possible.
However, if a validator fails to sign a block before it is committed, its signature may be included in one of the next blocks, and then a part of the reward (exponentially decreasing depending on how many blocks have been generated since—e.g., $0.9^k$ if the validator is $k$ blocks late) will be still given to this validator.
#### 2.6.21. "Depth" of validator signatures [#2621-depth-of-validator-signatures]
Normally, when a validator signs a block, the signature testifies only to the *relative validity* of a block: this block is valid provided all previous blocks in this and other shardchains are valid. The validator cannot be punished for taking for granted invalid data committed into previous blocks.
However, the validator signature of a block has an integer parameter called "depth". If it is non-zero, it means that the validator asserts the (relative) validity of the specified number of previous blocks as well. This is a way for "slow" or "temporarily offline" validators to catch up and sign some of the blocks that have been committed without their signatures. Then some part of the block reward will still be given to them (cf. [2.6.20](#2-6-20-slow-validators-may-receive-lower-rewards)).
#### 2.6.22. Validators are responsible for *relative* validity of signed shardchain blocks; absolute validity follows [#2622-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks-absolute-validity-follows]
We would like to emphasize once again that a validator's signature on a shardchain block $B$ testifies to only the *relative* validity of that block (or maybe of $d$ previous blocks as well, if the signature has "depth" $d$, cf. [2.6.21](#2-6-21-depth-of-validator-signatures); but this does not affect the following discussion much). In other words, the validator asserts that the next state $s'$ of the shardchain is obtained from the previous state $s$ by applying the block evaluation function $\mathit{ev\_block}$ described in [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators):
$$
s' = \mathit{ev\_block}(B)(s) \tag{24}
$$
In this way, the validator that signed block $B$ cannot be punished if the original state $s$ turns out to be "incorrect" (e.g., because of the invalidity of one of the previous blocks). A fisherman (cf. [2.6.4](#2-6-4-fishermen-obtaining-money-by-pointing-out-others-mistakes)) should complain only if it finds a block that is *relatively* invalid. The PoS system as a whole endeavors to make every block *relatively* valid, not *recursively (or absolutely)* valid. Notice, however, that *if all blocks in a blockchain are relatively valid, then all of them and the blockchain as a whole are absolutely valid*; this statement is easily shown using mathematical induction on the length of the blockchain. In this way, easily verifiable assertions of *relative* validity of blocks together demonstrate the much stronger *absolute validity* of the whole blockchain.
Note that by signing a block $B$ the validator asserts that the block is valid given the original state $s$ (i.e., that the result of ([24](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks%3B-absolute-validity-follows)) is not the value $\bot$ indicating that the next state cannot be computed). In this way, the validator must perform minimal formal checks of the cells of the original state that are accessed during the evaluation of the ([24](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks%3B-absolute-validity-follows)).
For example, imagine that the cell expected to contain the original balance of an account accessed from a transaction committed into a block turns out to have zero raw bytes instead of the expected 8 or 16. Then the original balance simply cannot be retrieved from the cell, and an "unhandled exception" happens while trying to process the block. In this case, the validator should not sign such a block on pain of being punished.
#### 2.6.23. Signing masterchain blocks [#2623-signing-masterchain-blocks]
The situation with the masterchain blocks is somewhat different: by signing a masterchain block, the validator asserts not only its relative validity, but also the relative validity of all preceding blocks up to the very first block when this validator assumed its responsibility (but not further back).
#### 2.6.24. The total number of validators [#2624-the-total-number-of-validators]
The upper limit $T$ for the total number of validators to be elected (cf. [2.6.7](#2-6-7-global-validator-set-election)) cannot become, in the system described so far, more than, say, several hundred or a thousand, because all validators are expected to participate in a BFT consensus protocol to create each new masterchain block, and it is not clear whether such protocols can scale to thousands of participants. Even more importantly, masterchain blocks must collect the signatures of at least two-thirds of all the validators (by stake), and these signatures must be included in the new block (otherwise all other nodes in the system would have no reason to trust the new block without validating it by themselves). If more than, say, one thousand validator signatures would have to be included in each masterchain block, this would imply more data in each masterchain block, to be stored by all full nodes and propagated through the network, and more processing power spent to check these signatures (in a PoS system, full nodes do not need to validate blocks by themselves, but they need to check the validators' signatures instead).
While limiting $T$ to a thousand validators seems more than sufficient for the first phase of the deployment of the TON Blockchain, a provision must be made for future growth, when the total number of shardchains becomes so large that several hundred validators will not suffice to process all of them. To this end, we introduce an additional configurable parameter $T'\leq T$ (originally equal to $T$), and only the top $T'$ elected validators (by stake) are expected to create and sign new masterchain blocks.
#### 2.6.25. Decentralization of the system [#2625-decentralization-of-the-system]
One might suspect that a Proof-of-Stake system such as the TON Blockchain, relying on $T\approx1000$ validators to create all shardchain and masterchain blocks, is bound to become "too centralized", as opposed to conventional Proof-of-Work blockchains like Bitcoin or Ethereum, where everybody (in principle) might mine a new block, without an explicit upper limit on the total number of miners.
However, popular Proof-of-Work blockchains, such as Bitcoin and Ethereum, currently require vast amounts of computing power (high "hash rates") to mine new blocks with non-negligible probability of success. Thus, the mining of new blocks tends to be concentrated in the hands of several large players, who invest huge amounts money into datacenters filled with custom-designed hardware optimized for mining; and in the hands of several large mining pools, which concentrate and coordinate the efforts of larger groups of people who are not able to provide a sufficient "hash rate" by themselves.
Therefore, as of 2017, more than 75% of new Ethereum or Bitcoin blocks are produced by less than ten miners. In fact, the two largest Ethereum mining pools produce together more than half of all new blocks! Clearly, such a system is much more centralized than one relying on $T\approx1000$ nodes to produce new blocks.
One might also note that the investment required to become a TON Blockchain validator—i.e., to buy the hardware (say, several high-performance servers) and the stake (which can be easily collected through a pool of nominators if necessary; cf. [2.6.3](#2-6-3-nominators-and-mining-pools))—is much lower than that required to become a successful stand-alone Bitcoin or Ethereum miner. In fact, the parameter $L$ of [2.6.7](#2-6-7-global-validator-set-election) will force nominators not to join the largest "mining pool" (i.e., the validator that has amassed the largest stake), but rather to look for smaller validators currently accepting funds from nominators, or even to create new validators, because this would allow a higher proportion $s'_i/s_i$ of the validator's—and by extension also the nominator's—stake to be used, hence yielding larger rewards from mining. In this way, the TON Proof-of-Stake system actually *encourages* decentralization (creating and using more validators) and *punishes* centralization.
#### 2.6.26. Relative reliability of a block [#2626-relative-reliability-of-a-block]
The *(relative) reliability* of a block is simply the total stake of all validators that have signed this block. In other words, this is the amount of money certain actors would lose if this block turns out to be invalid. If one is concerned with transactions transferring value lower than the reliability of the block, one can consider them to be safe enough. In this sense, the relative reliability is a measure of trust an outside observer can have in a particular block.
Note that we speak of the *relative* reliability of a block, because it is a guarantee that the block is valid *provided the previous block and all other shardchains' blocks referred to are valid* (cf. [2.6.22](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks-absolute-validity-follows)).
The relative reliability of a block can grow after it is committed—for example, when belated validators' signatures are added (cf. [2.6.21](#2-6-21-depth-of-validator-signatures)). On the other hand, if one of these validators loses part or all of its stake because of its misbehavior related to some other blocks, the relative reliability of a block may *decrease*.
#### 2.6.27. "Strengthening" the blockchain [#2627-strengthening-the-blockchain]
It is important to provide incentives for validators to increase the relative reliability of blocks as much as possible. One way of doing this is by allocating a small reward to validators for adding signatures to blocks of other shardchains. Even "would-be" validators, who have deposited a stake insufficient to get into the top $T$ validators by stake and to be included in the global set of validators (cf. [2.6.7](#2-6-7-global-validator-set-election)), might participate in this activity (if they agree to keep their stake frozen instead of withdrawing it after having lost the election). Such would-be validators might double as fishermen (cf. [2.6.4](#2-6-4-fishermen-obtaining-money-by-pointing-out-others-mistakes)): if they have to check the validity of certain blocks anyway, they might as well opt to report invalid blocks and collect the associated rewards.
#### 2.6.28. Recursive reliability of a block [#2628-recursive-reliability-of-a-block]
One can also define the *recursive reliability* of a block to be the minimum of its relative reliability and the recursive reliabilities of all blocks it refers to (i.e., the masterchain block, the previous shardchain block, and some blocks of neighboring shardchains). In other words, if the block turns out to be invalid, either because it is invalid by itself or because one of the blocks it depends on is invalid, then at least this amount of money would be lost by someone. If one is truly unsure whether to trust a specific transaction in a block, one should compute the *recursive* reliability of this block, not just the *relative* one.
It does not make sense to go too far back when computing recursive reliability, because, if we look too far back, we will see blocks signed by validators whose stakes have already been unfrozen and withdrawn. In any case, we do not allow the validators to automatically reconsider blocks that are that old (i.e., created more than two months ago, if current values of configurable parameters are used), and create forks starting from them or correct them with the aid of "vertical blockchains" (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), even if they turn out to be invalid. We assume that a period of two months provides ample opportunities for detecting and reporting any invalid blocks, so that if a block is not challenged during this period, it is unlikely to be challenged at all.
#### 2.6.29. Consequence of Proof-of-Stake for light nodes [#2629-consequence-of-proof-of-stake-for-light-nodes]
An important consequence of the Proof-of-Stake approach used by the TON Blockchain is that a light node (running light client software) for the TON Blockchain does not need to download the "headers" of all shardchain or even masterchain blocks in order to be able to check by itself the validity of Merkle proofs provided to it by full nodes as answers to its queries.
Indeed, because the most recent shardchain block hashes are included in the masterchain blocks, a full node can easily provide a Merkle proof that a given shardchain block is valid starting from a known hash of a masterchain block. Next, the light node needs to know only the very first block of the masterchain (where the very first set of validators is announced), which (or at least the hash of which) might be built-in into the client software, and only one masterchain block approximately every month afterwards, where newly-elected validator sets are announced, because this block will have been signed by the previous set of validators. Starting from that, it can obtain the several most recent masterchain blocks, or at least their headers and validator signatures, and use them as a base for checking Merkle proofs provided by full nodes.
***
### 2.7 Splitting and Merging Shardchains [#27---splitting-and-merging-shardchains]
One of the most characteristic and unique features of the TON Blockchain is its ability to automatically split a shardchain in two when the load becomes too high, and merge them back if the load subsides (cf. [2.1.10](#2-1-10-dynamic-splitting-and-merging-of-shardchains)). We must discuss it in some detail because of its uniqueness and its importance to the scalability of the whole project.
#### 2.7.1. Shard configuration [#271-shard-configuration]
Recall that, at any given moment of time, each workchain $w$ is split into one or several shardchains $(w,s)$ (cf. [2.1.8](#2-1-8-identification-of-shardchains)). These shardchains may be represented by leaves of a binary tree, with root $(w,\emptyset)$, and each non-leaf node $(w,s)$ having children $(w,s.0)$ and $(w,s.1)$. In this way, every account belonging to workchain $w$ is assigned to exactly one shard, and everybody who knows the current shardchain configuration can determine the shard $(w,s)$ containing account $\mathit{account\_id}$: it is the only shard with binary string $s$ being a prefix of $\mathit{account\_id}$.
The shard configuration—i.e., this *shard binary tree*, or the collection of all active $(w,s)$ for a given $w$ (corresponding to the leaves of the shard binary tree)—is part of the masterchain state and is available to everybody who keeps track of the masterchain.[22](#fn22)
#### 2.7.2. Most recent shard configuration and state [#272-most-recent-shard-configuration-and-state]
Recall that hashes of the most recent shardchain blocks are included in each masterchain block. These hashes are organized in a shard binary tree (actually, a collection of trees, one for each workchain). In this way, each masterchain block contains the most recent shard configuration.
#### 2.7.3. Announcing and performing changes in the shard configuration [#273-announcing-and-performing-changes-in-the-shard-configuration]
The shard configuration may be changed in two ways: either a shard $(w,s)$ can be *split* into two shards $(w,s.0)$ and $(w,s.1)$, or two "sibling" shards $(w,s.0)$ and $(w,s.1)$ can be *merged* into one shard $(w,s)$.
These split/merge operations are announced several (e.g., $2^6$; this is a configurable parameter) blocks in advance, first in the "headers" of the corresponding shardchain blocks, and then in the masterchain block that refers to these shardchain blocks. This advance announcement is needed for all parties concerned to prepare for the planned change (e.g., build an overlay multicast network to distribute new blocks of the newly-created shardchains, as discussed in [3.3](#3-3-overlay-networks-and-multicasting-messages)). Then the change is committed, first into the (header of the) shardchain block (in case of a split; for a merge, blocks of both shardchains should commit the change), and then propagated to the masterchain block. In this way, the masterchain block defines not only the most recent shard configuration *before* its creation, but also the next immediate shard configuration.
#### 2.7.4. Validator task groups for new shardchains [#274-validator-task-groups-for-new-shardchains]
Recall that each shard, i.e., each shardchain, normally is assigned a subset of validators (a validator task group) dedicated to creating and validating new blocks in the corresponding shardchain (cf. [2.6.8](#2-6-8-election-of-validator-task-groups)). These task groups are elected for some period of time (approximately one hour) and are known some time in advance (also approximately one hour), and are immutable during this period.[23](#fn23)
However, the actual shard configuration may change during this period because of split/merge operations. One must assign task groups to newly created shards. This is done as follows:
Notice that any active shard $(w,s)$ will either be a descendant of some uniquely determined original shard $(w,s')$, meaning that $s'$ is a prefix of $s$, or it will be the root of a subtree of original shards $(w,s')$, where $s$ will be a prefix of every $s'$. In the first case, we simply take the task group of the original shard $(w,s')$ to double as the task group of the new shard $(w,s)$. In the latter case, the task group of the new shard $(w,s)$ will be the union of task groups of all original shards $(w,s')$ that are descendants of $(w,s)$ in the shard tree.
In this way, every active shard $(w,s)$ gets assigned a well-defined subset of validators (task group). When a shard is split, both children inherit the whole of the task group from the original shard. When two shards are merged, their task groups are also merged.
Anyone who keeps track of the masterchain state can compute validator task groups for each of the active shards.
#### 2.7.5. Limit on split/merge operations during the period of responsibility of original task groups [#275-limit-on-splitmerge-operations-during-the-period-of-responsibility-of-original-task-groups]
Ultimately, the new shard configuration will be taken into account, and new dedicated validator subsets (task groups) will automatically be assigned to each shard. Before that happens, one must impose a certain limit on split/merge operations; otherwise, an original task group may end up validating $2^k$ shardchains for a large $k$ at the same time, if the original shard quickly splits into $2^k$ new shards.
This is achieved by imposing limits on how far the active shard configuration may be removed from the original shard configuration (the one used to select validator task groups currently in charge). For example, one might require that the distance in the shard tree from an active shard $(w,s)$ to an original shard $(w,s')$ must not exceed 3, if $s'$ is a predecessor of $s$ (i.e., $s'$ is a prefix of binary string $s$), and must not exceed 2, if $s'$ is a successor of $s$ (i.e., $s$ is a prefix of $s'$). Otherwise, the split or merge operation is not permitted.
Roughly speaking, one is imposing a limit on the number of times a shard can be split (e.g., three) or merged (e.g., two) during the period of responsibility of a given collection of validator task groups. Apart from that, after a shard has been created by merging or splitting, it cannot be reconfigured for some period of time (some number of blocks).
#### 2.7.6. Determining the necessity of split operations [#276-determining-the-necessity-of-split-operations]
The split operation for a shardchain is triggered by certain formal conditions (e.g., if for 64 consecutive blocks the shardchain blocks are at least 90% full). These conditions are monitored by the shardchain task group. If they are met, first a "split preparation" flag is included in the header of a new shardchain block (and propagated to the masterchain block referring to this shardchain block). Then, several blocks afterwards, the "split commit" flag is included in the header of the shardchain block (and propagated to the next masterchain block).
#### 2.7.7. Performing split operations [#277-performing-split-operations]
After the "split commit" flag is included in a block $B$ of shardchain $(w,s)$, there cannot be a subsequent block $B'$ in that shardchain. Instead, two blocks $B'_0$ and $B'_1$ of shardchains $(w,s.0)$ and $(w,s.1)$, respectively, will be created, both referring to block $B$ as their previous block (and both of them will indicate by a flag in the header that the shard has been just split). The next masterchain block will contain hashes of blocks $B'_0$ and $B'_1$ of the new shardchains; it is not allowed to contain the hash of a new block $B'$ of shardchain $(w,s)$, because a "split commit" event has already been committed into the previous masterchain block.
Notice that both new shardchains will be validated by the same validator task group as the old one, so they will automatically have a copy of their state. The state splitting operation itself is quite simple from the perspective of the Infinite Sharding Paradigm (cf. [2.5.2](#2-5-2-splitting-and-merging-shardchain-states)).
#### 2.7.8. Determining the necessity of merge operations [#278-determining-the-necessity-of-merge-operations]
The necessity of shard merge operations is also detected by certain formal conditions (e.g., if for 64 consecutive blocks the sum of the sizes of the two blocks of sibling shardchains does not exceed 60% of maximal block size). These formal conditions should also take into account the total gas spent by these blocks and compare it to the current block gas limit, otherwise the blocks may happen to be small because there are some computation-intensive transactions that prevent the inclusion of more transactions.
These conditions are monitored by validator task groups of both sibling shards $(w,s.0)$ and $(w,s.1)$. Notice that siblings are necessarily neighbors with respect to hypercube routing (cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)), so validators from the task group of any shard will be monitoring the sibling shard to some extent anyways.
When these conditions are met, either one of the validator subgroups can suggest to the other that they merge by sending a special message. Then they combine into a provisional "merged task group", with combined membership, capable of running BFT consensus algorithms and of propagating block updates and block candidates if necessary.
If they reach consensus on the necessity and readiness of merging, "merge prepare" flags are committed into the headers of some blocks of each shardchain, along with the signatures of at least two-thirds of the validators of the sibling's task group (and are propagated to the next masterchain blocks, so that everybody can get ready for the imminent reconfiguration). However, they continue to create separate shardchain blocks for some predefined number of blocks.
#### 2.7.9. Performing merge operations [#279-performing-merge-operations]
After that, when the validators from the union of the two original task groups are ready to become validators for the merged shardchain (this might involve a state transfer from the sibling shardchain and a state merge operation), they commit a "merge commit" flag in the headers of blocks of their shardchain (this event is propagated to the next masterchain blocks), and stop creating new blocks in separate shardchains (once the merge commit flag appears, creating blocks in separate shardchains is forbidden). Instead, a merged shardchain block is created (by the union of the two original task groups), referring to both of its "preceding blocks" in its "header". This is reflected in the next masterchain block, which will contain the hash of the newly created block of the merged shardchain. After that, the merged task group continues creating blocks in the merged shardchain.
***
### 2.8 Classification of Blockchain Projects [#28--classification-of-blockchain-projects]
We will conclude our brief discussion of the TON Blockchain by comparing it with existing and proposed blockchain projects. Before doing this, however, we must introduce a sufficiently general classification of blockchain projects. The comparison of particular blockchain projects, based on this classification, is postponed until [2.9](#2-9-comparison-to-other-blockchain-projects).
#### 2.8.1. Classification of blockchain projects [#281-classification-of-blockchain-projects]
As a first step, we suggest some classification criteria for blockchains (i.e., for blockchain projects). Any such classification is somewhat incomplete and superficial, because it must ignore some of the most specific and unique features of the projects under consideration. However, we feel that this is a necessary first step in providing at least a very rough and approximate map of the blockchain projects territory.
The list of criteria we consider is the following:
* Single-blockchain vs. multi-blockchain architecture (cf. [2.8.2](#2-8-2-single-blockchain-vs-multi-blockchain-projects))
* Consensus algorithm: Proof-of-Stake vs. Proof-of-Work (cf. [2.8.3](#2-8-3-creating-and-validating-blocks-proof-of-work-vs-proof-of-stake))
* For Proof-of-Stake systems, the exact block generation, validation and consensus algorithm used (the two principal options are DPOS vs. BFT; cf. [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft))
* Support for "arbitrary" (Turing-complete) smart contracts (cf. [2.8.6](#2-8-6-support-for-turing-complete-code-in-transactions))
Multi-blockchain systems have additional classification criteria (cf. [2.8.7](#2-8-7-classification-of-multichain-systems)):
* Type and rules of member blockchains: homogeneous, heterogeneous (cf. [2.8.8](#2-8-8-blockchain-types-homogeneous-and-heterogeneous-systems)), mixed (cf. [2.8.9](#2-8-9-mixed-heterogeneous-homogeneous-systems)). Confederations (cf. [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations)).
* Absence or presence of a *masterchain*, internal or external (cf. [2.8.11](#2-8-11-presence-of-a-masterchain-external-or-internal))
* Native support for sharding (cf. [2.8.12](#2-8-12-sharding-support)). Static or dynamic sharding (cf. [2.8.13](#2-8-13-dynamic-and-static-sharding)).
* Interaction between member blockchains: loosely-coupled and tightly-coupled systems (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems))
#### 2.8.2. Single-blockchain vs. multi-blockchain projects [#282-single-blockchain-vs-multi-blockchain-projects]
The first classification criterion is the quantity of blockchains in the system. The oldest and simplest projects consist of a *single blockchain* ("singlechain projects" for short); more sophisticated projects use (or, rather, plan to use) *multiple blockchains* ("multichain projects").
Singlechain projects are generally simpler and better tested; they have withstood the test of time. Their main drawback is low performance, or at least transaction throughput, which is on the level of ten (Bitcoin) to less than one hundred[24](#fn24) (Ethereum) transactions per second for general-purpose systems. Some specialized systems (such as Bitshares) are capable of processing tens of thousands of specialized transactions per second, at the expense of requiring the blockchain state to fit into memory, and limiting the processing to a predefined special set of transactions, which are then executed by highly-optimized code written in languages like C++ (no VMs here).
Multichain projects promise the scalability everybody craves. They may support larger total states and more transactions per second, at the expense of making the project much more complex, and its implementation more challenging. As a result, there are few multichain projects already running, but most proposed projects are multichain. We believe that the future belongs to multichain projects.
#### 2.8.3. Creating and validating blocks: Proof-of-Work vs. Proof-of-Stake [#283-creating-and-validating-blocks-proof-of-work-vs-proof-of-stake]
Another important distinction is the algorithm and protocol used to create and propagate new blocks, check their validity, and select one of several forks if they appear.
The two most common paradigms are *Proof-of-Work (PoW)* and *Proof-of-Stake (PoS)*. The Proof-of-Work approach usually allows any node to create ("mine") a new block (and obtain some reward associated with mining a block) if it is lucky enough to solve an otherwise useless computational problem (usually involving the computation of a large amount of hashes) before other competitors manage to do this. In the case of forks (for example, if two nodes publish two otherwise valid but different blocks to follow the previous one) the longest fork wins. In this way, the guarantee of immutability of the blockchain is based on the amount of *work* (computational resources) spent to generate the blockchain: anybody who would like to create a fork of this blockchain would need to re-do this work to create alternative versions of the already committed blocks. For this, one would need to control more than 50% of the total computing power spent creating new blocks, otherwise the alternative fork will have exponentially low chances of becoming the longest.
The Proof-of-Stake approach is based on large *stakes* (nominated in cryptocurrency) made by some special nodes (*validators*) to assert that they have checked (*validated*) some blocks and have found them correct. Validators sign blocks, and receive some small rewards for this; however, if a validator is ever caught signing an incorrect block, and a proof of this is presented, part or all of its stake is forfeit. In this way, the guarantee of validity and immutability of the blockchain is given by the total volume of stakes put by validators on the validity of the blockchain.
The Proof-of-Stake approach is more natural in the respect that it incentivizes the validators (which replace PoW miners) to perform useful computation (needed to check or create new blocks, in particular, by performing all transactions listed in a block) instead of computing otherwise useless hashes. In this way, validators would purchase hardware that is better adapted to processing user transactions, in order to receive rewards associated with these transactions, which seems quite a useful investment from the perspective of the system as a whole.
However, Proof-of-Stake systems are somewhat more challenging to implement, because one must provide for many rare but possible conditions. For example, some malicious validators might conspire to disrupt the system to extract some profit (e.g., by altering their own cryptocurrency balances). This leads to some non-trivial game-theoretic problems.
In short, Proof-of-Stake is more natural and more promising, especially for multichain projects (because Proof-of-Work would require prohibitive amounts of computational resources if there are many blockchains), but must be more carefully thought out and implemented. Most currently running blockchain projects, especially the oldest ones (such as Bitcoin and at least the original Ethereum), use Proof-of-Work.
#### 2.8.4. Variants of Proof-of-Stake. DPOS vs. BFT [#284-variants-of-proof-of-stake-dpos-vs-bft]
While Proof-of-Work algorithms are very similar to each other and differ mostly in the hash functions that must be computed for mining new blocks, there are more possibilities for Proof-of-Stake algorithms. They merit a sub-classification of their own.
Essentially, one must answer the following questions about a Proof-of-Stake algorithm:
* Who can produce ("mine") a new block—any full node, or only a member of a (relatively) small subset of validators? (Most PoS systems require new blocks to be generated and signed by one of several designated validators.)
* Do validators guarantee the validity of the blocks by their signatures, or are all full nodes expected to validate all blocks by themselves? (Scalable PoS systems must rely on validator signatures instead of requiring all nodes to validate all blocks of all blockchains.)
* Is there a designated producer for the next blockchain block, known in advance, such that nobody else can produce that block instead?
* Is a newly-created block originally signed by only one validator (its producer), or must it collect a majority of validator signatures from the very beginning?
While there seem to be $2^4$ possible classes of PoS algorithms depending on the answers to these questions, the distinction in practice boils down to two major approaches to PoS. In fact, most modern PoS algorithms, designed to be used in scalable multi-chain systems, answer the first two questions in the same fashion: only validators can produce new blocks, and they guarantee block validity without requiring all full nodes to check the validity of all blocks by themselves.
As to the two last questions, their answers turn out to be highly correlated, leaving essentially only two basic options:
* *Delegated Proof-of-Stake (DPOS)*: There is a universally known designated producer for every block; no one else can produce that block; the new block is originally signed only by its producing validator.
* *Byzantine Fault Tolerant (BFT)* PoS algorithms: There is a known subset of validators, any of which can suggest a new block; the choice of the actual next block among several suggested candidates, which must be validated and signed by a majority of validators before being released to the other nodes, is achieved by a version of Byzantine Fault Tolerant consensus protocol.
#### 2.8.5. Comparison of DPOS and BFT PoS [#285-comparison-of-dpos-and-bft-pos]
The BFT approach has the advantage that a newly-produced block has *from the very beginning* the signatures of a majority of validators testifying to its validity. Another advantage is that, if a majority of validators executes the BFT consensus protocol correctly, no forks can appear at all. On the other hand, BFT algorithms tend to be quite convoluted and require more time for the subset of validators to reach consensus. Therefore, blocks cannot be generated too often. This is why we expect the TON Blockchain (which is a BFT project from the perspective of this classification) to produce a block only once every five seconds. In practice, this interval might be decreased to 2–3 seconds (though we do not promise this), but not further, if validators are spread across the globe.
The DPOS algorithm has the advantage of being quite simple and straightforward. It can generate new blocks quite often—say, once every two seconds, or maybe even once every second,[25](#fn25) because of its reliance on designated block producers known in advance.
However, DPOS requires all nodes—or at least all validators—to validate all blocks received, because a validator producing and signing a new block confirms not only the *relative* validity of this block, but also the validity of the previous block it refers to, and all the blocks further back in the chain (maybe up to the beginning of the period of responsibility of the current subset of validators). There is a predetermined order on the current subset of validators, so that for each block there is a designated producer (i.e., validator expected to generate that block); these designated producers are rotated in a round-robin fashion. In this way, a block is at first signed only by its producing validator; then, when the next block is mined, and its producer chooses to refer to this block and not to one of its predecessors (otherwise its block would lie in a shorter chain, which might lose the "longest fork" competition in the future), the signature of the next block is essentially an additional signature on the previous block as well. In this way, a new block gradually collects the signatures of more validators—say, twenty signatures in the time needed to generate the next twenty blocks. A full node will either need to wait for these twenty signatures, or validate the block by itself, starting from a sufficiently confirmed block (say, twenty blocks back), which might be not so easy.
The obvious disadvantage of the DPOS algorithm is that a new block (and transactions committed into it) achieves the same level of trust ("recursive reliability" as discussed in [2.6.28](#2-6-28-recursive-reliability-of-a-block)) only after twenty more blocks are mined, compared to the BFT algorithms, which deliver this level of trust (say, twenty signatures) immediately. Another disadvantage is that DPOS uses the "longest fork wins" approach for switching to other forks; this makes forks quite probable if at least some producers fail to produce subsequent blocks after the one we are interested in (or we fail to observe these blocks because of a network partition or a sophisticated attack).
We believe that the BFT approach, while more sophisticated to implement and requiring longer time intervals between blocks than DPOS, is better adapted to "tightly-coupled" (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)) multichain systems, because other blockchains can start acting almost immediately after seeing a committed transaction (e.g., generating a message intended for them) in a new block, without waiting for twenty confirmations of validity (i.e., the next twenty blocks), or waiting for the next six blocks to be sure that no forks appear and verifying the new block by themselves (verifying blocks of other blockchains may become prohibitive in a scalable multi-chain system). Thus they can achieve scalability while preserving high reliability and availability (cf. [2.8.12](#2-8-12-sharding-support)).
On the other hand, DPOS might be a good choice for a "loosely-coupled" multi-chain system, where fast interaction between blockchains is not required—e.g., if each blockchain ("workchain") represents a separate distributed exchange, and inter-blockchain interaction is limited to rare transfers of tokens from one workchain into another (or, rather, trading one altcoin residing in one workchain for another at a rate approaching $1:1$). This is what is actually done in the BitShares project, which uses DPOS quite successfully.
To summarize, while DPOS can *generate* new blocks and *include transactions* into them *faster* (with smaller intervals between blocks), these transactions reach the level of trust required to use them in other blockchains and off-chain applications as "committed" and "immutable" *much more slowly* than in the BFT systems—say, in thirty seconds[26](#fn26) instead of five. Faster transaction *inclusion* does not mean faster transaction *commitment*. This could become a huge problem if fast inter-blockchain interaction is required. In that case, one must abandon DPOS and opt for BFT PoS instead.
#### 2.8.6. Support for Turing-complete code in transactions, i.e., essentially arbitrary smart contracts [#286-support-for-turing-complete-code-in-transactions-ie-essentially-arbitrary-smart-contracts]
Blockchain projects normally collect some *transactions* in their blocks, which alter the blockchain state in a way deemed useful (e.g., transfer some amount of cryptocurrency from one account to another). Some blockchain projects might allow only some specific predefined types of transactions (such as value transfers from one account to another, provided correct signatures are presented). Others might support some limited form of scripting in the transactions. Finally, some blockchains support the execution of arbitrarily complex code in transactions, enabling the system (at least in principle) to support arbitrary applications, provided the performance of the system permits. This is usually associated with "Turing-complete virtual machines and scripting languages" (meaning that any program that can be written in any other computing language may be re-written to be performed inside the blockchain), and "smart contracts" (which are programs residing in the blockchain).
Of course, support for arbitrary smart contracts makes the system truly flexible. On the other hand, this flexibility comes at a cost: the code of these smart contracts must be executed on some virtual machine, and this must be done every time for each transaction in the block when somebody wants to create or validate a block. This slows down the performance of the system compared to the case of a predefined and immutable set of types of simple transactions, which can be optimized by implementing their processing in a language such as C++ (instead of some virtual machine).
Ultimately, support for Turing-complete smart contracts seems to be desirable in any general-purpose blockchain project; otherwise, the designers of the blockchain project must decide in advance which applications their blockchain will be used for. In fact, the lack of support for smart contracts in the Bitcoin blockchain was the principal reason why a new blockchain project, Ethereum, had to be created.
In a (heterogeneous; cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)) multi-chain system, one might have "the best of both worlds" by supporting Turing-complete smart contracts in some blockchains (i.e., workchains), and a small predefined set of highly-optimized transactions in others.
#### 2.8.7. Classification of multichain systems [#287-classification-of-multichain-systems]
So far, the classification was valid both for single-chain and multi-chain systems. However, multi-chain systems admit several more classification criteria, reflecting the relationship between the different blockchains in the system. We now discuss these criteria.
#### 2.8.8. Blockchain types: homogeneous and heterogeneous systems [#288-blockchain-types-homogeneous-and-heterogeneous-systems]
In a multi-chain system, all blockchains may be essentially of the same type and have the same rules (i.e., use the same format of transactions, the same virtual machine for executing smart-contract code, share the same cryptocurrency, and so on), and this similarity is explicitly exploited, but with different data in each blockchain. In this case, we say that the system is *homogeneous*. Otherwise, different blockchains (which will usually be called *workchains* in this case) can have different "rules". Then we say that the system is *heterogeneous*.
#### 2.8.9. Mixed heterogeneous-homogeneous systems [#289-mixed-heterogeneous-homogeneous-systems]
Sometimes we have a mixed system, where there are several sets of types or rules for blockchains, but many blockchains with the same rules are present, and this fact is explicitly exploited. Then it is a mixed *heterogeneous-homogeneous system*. To our knowledge, the TON Blockchain is the only example of such a system.
#### 2.8.10. Heterogeneous systems with several workchains having the same rules, or *confederations* [#2810-heterogeneous-systems-with-several-workchains-having-the-same-rules-or-confederations]
In some cases, several blockchains (workchains) with the same rules can be present in a heterogeneous system, but the interaction between them is the same as between blockchains with different rules (i.e., their similarity is not exploited explicitly). Even if they appear to use "the same" cryptocurrency, they in fact use different "altcoins" (independent incarnations of the cryptocurrency). Sometimes one can even have certain mechanisms to convert these altcoins at a rate near to $1:1$. However, this does not make the system homogeneous in our view; it remains heterogeneous. We say that such a heterogeneous collection of workchains with the same rules is a *confederation*.
While making a heterogeneous system that allows one to create several workchains with the same rules (i.e., a confederation) may seem a cheap way of building a scalable system, this approach has a lot of drawbacks, too. Essentially, if someone hosts a large project in many workchains with the same rules, she does not obtain a large project, but rather a lot of small instances of this project. This is like having a chat application (or a game) that allows having at most 50 members in any chat (or game) room, but "scales" by creating new rooms to accommodate more users when necessary. As a result, a lot of users can participate in the chats or in the game, but can we say that such a system is truly scalable?
#### 2.8.11. Presence of a masterchain, external or internal [#2811-presence-of-a-masterchain-external-or-internal]
Sometimes, a multi-chain project has a distinguished "masterchain" (sometimes called "control blockchain"), which is used, for example, to store the overall configuration of the system (the set of all active blockchains, or rather workchains), the current set of validators (for a Proof-of-Stake system), and so on. Sometimes other blockchains are "bound" to the masterchain, for example by committing the hashes of their latest blocks into it (this is something the TON Blockchain does, too).
In some cases, the masterchain is *external*, meaning that it is not a part of the project, but some other pre-existing blockchain, originally completely unrelated to its use by the new project and agnostic of it. For example, one can try to use the Ethereum blockchain as a masterchain for an external project, and publish special smart contracts into the Ethereum blockchain for this purpose (e.g., for electing and punishing validators).
#### 2.8.12. Sharding support [#2812-sharding-support]
Some blockchain projects (or systems) have native support for *sharding*, meaning that several (necessarily homogeneous; cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)) blockchains are thought of as *shards* of a single (from a high-level perspective) virtual blockchain. For example, one can create 256 shard blockchains ("shardchains") with the same rules, and keep the state of an account in exactly one shard selected depending on the first byte of its $\mathit{account\_id}$.
Sharding is a natural approach to scaling blockchain systems, because, if it is properly implemented, users and smart contracts in the system need not be aware of the existence of sharding at all. In fact, one often wants to add sharding to an existing single-chain project (such as Ethereum) when the load becomes too high.
An alternative approach to scaling would be to use a "confederation" of heterogeneous workchains as described in [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations), allowing each user to keep her account in one or several workchains of her choice, and transfer funds from her account in one workchain to another workchain when necessary, essentially performing a $1:1$ altcoin exchange operation. The drawbacks of this approach have already been discussed in [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations).
However, sharding is not so easy to implement in a fast and reliable fashion, because it implies a lot of messages between different shardchains. For example, if accounts are evenly distributed between $N$ shards, and the only transactions are simple fund transfers from one account to another, then only a small fraction ($1/N$) of all transactions will be performed within a single blockchain; almost all ($1-1/N$) transactions will involve two blockchains, requiring inter-blockchain communication. If we want these transactions to be fast, we need a fast system for transferring messages between shardchains. In other words, the blockchain project needs to be "tightly-coupled" in the sense described in [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems).
#### 2.8.13. Dynamic and static sharding [#2813-dynamic-and-static-sharding]
Sharding might be *dynamic* (if additional shards are automatically created when necessary) or *static* (when there is a predefined number of shards, which is changeable only through a hard fork at best). Most sharding proposals are static; the TON Blockchain uses dynamic sharding (cf. [2.7](#2-7-splitting-and-merging-shardchains)).
#### 2.8.14. Interaction between blockchains: loosely-coupled and tightly-coupled systems [#2814-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems]
Multi-blockchain projects can be classified according to the supported level of interaction between the constituent blockchains.
The least level of support is the absence of any interaction between different blockchains whatsoever. We do not consider this case here, because we would rather say that these blockchains are not parts of one blockchain system, but just separate instances of the same blockchain protocol.
The next level of support is the absence of any specific support for messaging between blockchains, making interaction possible in principle, but awkward. We call such systems "loosely-coupled"; in them one must send messages and transfer value between blockchains as if they had been blockchains belonging to completely separate blockchain projects (e.g., Bitcoin and Ethereum; imagine two parties want to exchange some Bitcoins, kept in the Bitcoin blockchain, into Ethers, kept in the Ethereum blockchain). In other words, one must include the outbound message (or its generating transaction) in a block of the source blockchain. Then she (or some other party) must wait for enough confirmations (e.g., a given number of subsequent blocks) to consider the originating transaction to be "committed" and "immutable", so as to be able to perform external actions based on its existence. Only then may a transaction relaying the message into the target blockchain (perhaps along with a reference and a Merkle proof of existence for the originating transaction) be committed.
If one does not wait long enough before transferring the message, or if a fork happens anyway for some other reason, the joined state of the two blockchains turns out to be inconsistent: a message is delivered into the second blockchain that has never been generated in (the ultimately chosen fork of) the first blockchain.
Sometimes partial support for messaging is added, by standardizing the format of messages and the location of input and output message queues in the blocks of all workchains (this is especially useful in heterogeneous systems). While this facilitates messaging to a certain extent, it is conceptually not too different from the previous case, so such systems are still "loosely-coupled".
By contrast, "tightly-coupled" systems include special mechanisms to provide fast messaging between all blockchains. The desired behavior is to be able to deliver a message into another workchain immediately after it has been generated in a block of the originating blockchain. On the other hand, "tightly-coupled" systems are also expected to maintain overall consistency in the case of forks. While these two requirements appear to be contradictory at first glance, we believe that the mechanisms used by the TON Blockchain (the inclusion of shardchain block hashes into masterchain blocks; the use of "vertical" blockchains for fixing invalid blocks, cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks); hypercube routing, cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery); Instant Hypercube Routing, cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-“fast-path”-for-messages)) enable it to be a "tightly-coupled" system, perhaps the only one so far.
Of course, building a "loosely-coupled" system is much simpler; however, fast and efficient sharding (cf. [2.8.12](#2-8-12-sharding-support)) requires the system to be "tightly-coupled".
#### 2.8.15. Simplified classification. Generations of blockchain projects [#2815-simplified-classification-generations-of-blockchain-projects]
The classification we have suggested so far splits all blockchain projects into a large number of classes. However, the classification criteria we use happen to be quite correlated in practice. This enables us to suggest a simplified "generational" approach to the classification of blockchain projects, as a very rough approximation of reality, with some examples. Projects that have not been implemented and deployed yet are shown in *italics*; the most important characteristics of a generation are shown in **bold**.
* First generation: Single-chain, **PoW**, no support for smart contracts. Examples: Bitcoin (2009) and a lot of otherwise uninteresting imitators (Litecoin, Monero, ...).
* Second generation: Single-chain, PoW, **smart-contract support**. Example: Ethereum (2013; deployed in 2015), at least in its original form.
* Third generation: Single-chain, **PoS**, smart-contract support. Example: *future Ethereum* (2018 or later).
* Alternative third (3') generation: **Multi-chain**, PoS, no support for smart contracts, loosely-coupled. Example: Bitshares (2013–2014; uses DPOS).
* Fourth generation: **Multi-chain, PoS, smart-contract support**, loosely-coupled. Examples: *EOS* (2017; uses DPOS), *PolkaDot* (2016; uses BFT).
* Fifth generation: Multi-chain, PoS with BFT, smart-contract support, **tightly-coupled, with sharding**. Examples: *TON* (2017).
While not all blockchain projects fall precisely into one of these categories, most of them do.
#### 2.8.16. Complications of changing the "genome" of a blockchain project [#2816-complications-of-changing-the-genome-of-a-blockchain-project]
The above classification defines the "genome" of a blockchain project. This genome is quite "rigid": it is almost impossible to change it once the project is deployed and is used by a lot of people. One would need a series of hard forks (which would require the approval of the majority of the community), and even then the changes would need to be very conservative in order to preserve backward compatibility (e.g., changing the semantics of the virtual machine might break existing smart contracts). An alternative would be to create new "sidechains" with their different rules, and bind them somehow to the blockchain (or the blockchains) of the original project. One might use the blockchain of the existing single-blockchain project as an external masterchain for an essentially new and separate project.[27](#fn27)
Our conclusion is that the genome of a project is very hard to change once it has been deployed. Even starting with PoW and planning to replace it with PoS in the future is quite complicated.[28](#fn28) Adding shards to a project originally designed without support for them seems almost impossible.[29](#fn29) In fact, adding support for smart contracts into a project (namely, Bitcoin) originally designed without support for such features has been deemed impossible (or at least undesirable by the majority of the Bitcoin community) and eventually led to the creation of a new blockchain project, Ethereum.
#### 2.8.17. Genome of the TON Blockchain [#2817-genome-of-the-ton-blockchain]
Therefore, if one wants to build a scalable blockchain system, one must choose its genome carefully from the very beginning. If the system is meant to support some additional specific functionality in the future not known at the time of its deployment, it should support "heterogeneous" workchains (having potentially different rules) from the start. For the system to be truly scalable, it must support sharding from the very beginning; sharding makes sense only if the system is "tightly-coupled" (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)), so this in turn implies the existence of a masterchain, a fast system of inter-blockchain messaging, usage of BFT PoS, and so on.
When one takes into account all these implications, most of the design choices made for the TON Blockchain project appear natural, and almost the only ones possible.
***
### 2.9 Comparison to Other Blockchain Projects [#29--comparison-to-other-blockchain-projects]
We conclude our brief discussion of the TON Blockchain and its most important and unique features by trying to find a place for it on a map containing existing and proposed blockchain projects. We use the classification criteria described in [2.8](#2-8-classification-of-blockchain-projects) to discuss different blockchain projects in a uniform way and construct such a "map of blockchain projects". We represent this map as [Table 1](#table-1), and then briefly discuss a few projects separately to point out their peculiarities that may not fit into the general scheme.
| Project | Year | G. | Cons. | Sm. | Ch. | R. | Sh. | Int. |
| --------- | ------------ | -- | ------- | --- | --- | --- | ---- | ---- |
| Bitcoin | 2009 | 1 | PoW | no | 1 | | | |
| Ethereum | 2013, 2015 | 2 | PoW | yes | 1 | | | |
| NXT | 2014 | 2+ | PoS | no | 1 | | | |
| Tezos | 2017, ? | 2+ | PoS | yes | 1 | | | |
| Casper | 2015, (2017) | 3 | PoW/PoS | yes | 1 | | | |
| BitShares | 2013, 2014 | 3' | DPoS | no | m | ht. | no | L |
| EOS | 2016, (2018) | 4 | DPoS | yes | m | ht. | no | L |
| PolkaDot | 2016, (2019) | 4 | PoS BFT | yes | m | ht. | no | L |
| Cosmos | 2017, ? | 4 | PoS BFT | yes | m | ht. | no | L |
| TON | 2017, (2018) | 5 | PoS BFT | yes | m | mix | dyn. | T |
**Table 1:** A summary of some notable blockchain projects. The columns are: *Project* — project name; *Year* — year announced and year deployed; *G.* — generation (cf. [2.8.15](#2-8-15-simplified-classification-generations-of-blockchain-projects)); *Cons.* — consensus algorithm (cf. [2.8.3](#2-8-3-creating-and-validating-blocks-proof-of-work-vs-proof-of-stake) and [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft)); *Sm.* — support for arbitrary code (smart contracts; cf. [2.8.6](#2-8-6-support-for-turing-complete-code-in-transactions%2C-i-e-%2C-essentially-arbitrary-smart-contracts)); *Ch.* — single/multiple blockchain system (cf. [2.8.2](#2-8-2-single-blockchain-vs-multi-blockchain-projects)); *R.* — heterogeneous/homogeneous multichain systems (cf. [2.8.8](#2-8-8-blockchain-types-homogeneous-and-heterogeneous-systems)); *Sh.* — sharding support (cf. [2.8.12](#2-8-12-sharding-support)); *Int.* — interaction between blockchains, (L)oose or (T)ight (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)).
#### 2.9.1. Bitcoin [\[12\]](#ref-12); [https://bitcoin.org/](https://bitcoin.org/) [#291-bitcoin-12-httpsbitcoinorg]
*Bitcoin* (2009) is the first and the most famous blockchain project. It is a typical *first-generation* blockchain project: it is single-chain, it uses Proof-of-Work with a "longest-fork-wins" fork selection algorithm, and it does not have a Turing-complete scripting language (however, simple scripts without loops are supported). The Bitcoin blockchain has no notion of an account; it uses the UTXO (Unspent Transaction Output) model instead.
#### 2.9.2. Ethereum [\[2\]](#ref-2); [https://ethereum.org/](https://ethereum.org/) [#292-ethereum-2-httpsethereumorg]
*Ethereum* (2015) is the first blockchain with support for Turing-complete smart contracts. As such, it is a typical *second-generation* project, and the most popular among them. It uses Proof-of-Work on a single blockchain, but has smart contracts and accounts.
#### 2.9.3. NXT; [https://nxtplatform.org/](https://nxtplatform.org/) [#293-nxt-httpsnxtplatformorg]
*NXT* (2014) is the first PoS-based blockchain and currency. It is still single-chain, and has no smart contract support.
#### 2.9.4. Tezos; [https://www.tezos.com/](https://www.tezos.com/) [#294-tezos-httpswwwtezoscom]
*Tezos* (2018 or later) is a proposed PoS-based single-blockchain project. We mention it here because of its unique feature: its block interpretation function $\mathit{ev\_block}$ (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) is not fixed, but is determined by an OCaml module, which can be upgraded by committing a new version into the blockchain (and collecting some votes for the proposed change). In this way, one will be able to create custom single-chain projects by first deploying a "vanilla" Tezos blockchain, and then gradually changing the block interpretation function in the desired direction, without any need for hard forks.
This idea, while intriguing, has the obvious drawback that it forbids any optimized implementations in other languages like C++, so a Tezos-based blockchain is destined to have lower performance. We think that a similar result might have been obtained by publishing a formal *specification* of the proposed block interpretation function $\mathit{ev\_trans}$, without fixing a particular *implementation*.
#### 2.9.5. Casper[30](#fn30) [#295-casper30]
*Casper* is an upcoming PoS algorithm for Ethereum; its gradual deployment in 2017 (or 2018), if successful, will change Ethereum into a single-chain PoS or mixed PoW+PoS system with smart contract support, transforming Ethereum into a *third-generation* project.
#### 2.9.6. BitShares [\[8\]](#ref-8); [https://bitshares.org](https://bitshares.org) [#296-bitshares-8-httpsbitsharesorg]
*BitShares* (2014) is a platform for distributed blockchain-based exchanges. It is a heterogeneous multi-blockchain DPoS system without smart contracts; it achieves its high performance by allowing only a small set of predefined specialized transaction types, which can be efficiently implemented in C++, assuming the blockchain state fits into memory. It is also the first blockchain project to use Delegated Proof-of-Stake (DPoS), demonstrating its viability at least for some specialized purposes.
#### 2.9.7. EOS [\[5\]](#ref-5); [https://eos.io](https://eos.io) [#297-eos-5-httpseosio]
*EOS* (2018 or later) is a proposed heterogeneous multi-blockchain DPoS system *with* smart contract support and with some minimal support for messaging (still loosely-coupled in the sense described in [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)). It is an attempt by the same team that has previously successfully created the BitShares and SteemIt projects, demonstrating the strong points of the DPoS consensus algorithm. Scalability will be achieved by creating specialized workchains for projects that need it (e.g., a distributed exchange might use a workchain supporting a special set of optimized transactions, similarly to what BitShares did) and by creating multiple workchains with the same rules (*confederations* in the sense described in [2.8.10](#2-8-11-heterogeneous-systems-with-several-workchains-having-the-same-rules-or-confederations)). The drawbacks and limitations of this approach to scalability have been discussed in *loc. cit.* Cf. also [2.8.5](#2-8-5-comparison-of-dpos-and-bft-pos), [2.8.12](#2-8-13-sharding-support), and [2.8.14](#2-8-15-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems) for a more detailed discussion of DPoS, sharding, interaction between workchains and their implications for the scalability of a blockchain system.
At the same time, even if one will not be able to "create a Facebook inside a blockchain" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)), EOS or otherwise, we think that EOS might become a convenient platform for some highly-specialized weakly interacting distributed applications, similar to BitShares (decentralized exchange) and SteemIt (decentralized blog platform).
#### 2.9.8. PolkaDot [\[17\]](#ref-17); [https://polkadot.io/](https://polkadot.io/) [#298-polkadot-17-httpspolkadotio]
*PolkaDot* (2019 or later) is one of the best thought-out and most detailed proposed multichain Proof-of-Stake projects; its development is led by one of the Ethereum co-founders. This project is one of the closest projects to the TON Blockchain on our map. (In fact, we are indebted for our terminology for "fishermen" and "nominators" to the PolkaDot project.)
PolkaDot is a heterogeneous loosely-coupled multichain Proof-of-Stake project, with Byzantine Fault Tolerant (BFT) consensus for generation of new blocks and a masterchain (which might be external—e.g., the Ethereum blockchain). It also uses hypercube routing, somewhat like (the slow version of) TON's as described in [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery).
Its unique feature is its ability to create not only *public*, but also *private* blockchains. These private blockchains would also be able to interact with other public blockchains, PolkaDot or otherwise.
As such, PolkaDot might become a platform for large-scale *private* blockchains, which might be used, for example, by bank consortiums to quickly transfer funds to each other, or for any other uses a large corporation might have for private blockchain technology.
However, PolkaDot has no sharding support and is not tightly-coupled. This somewhat hampers its scalability, which is similar to that of EOS. (Perhaps a bit better, because PolkaDot uses BFT PoS instead of DPoS.)
#### 2.9.9. Universa; [https://universa.io](https://universa.io) [#299-universa-httpsuniversaio]
The only reason we mention this unusual blockchain project here is because it is the only project so far to make in passing an explicit reference to something similar to our Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)). Its other peculiarity is that it bypasses all complications related to Byzantine Fault Tolerance by promising that only trusted and licensed partners of the project will be admitted as validators, hence they will never commit invalid blocks. This is an interesting decision; however, it essentially makes a blockchain project deliberately *centralized*, something blockchain projects usually want to avoid (why does one need a blockchain at all to work in a trusted centralized environment?).
#### 2.9.10. Plasma; [https://plasma.io](https://plasma.io) [#2910-plasma-httpsplasmaio]
*Plasma* (2019?) is an unconventional blockchain project from another co-founder of Ethereum. It is supposed to mitigate some limitations of Ethereum without introducing sharding. In essence, it is a separate project from Ethereum, introducing a hierarchy of (heterogeneous) workchains, bound to the Ethereum blockchain (to be used as an external masterchain) at the top level. Funds can be transferred from any blockchain up in the hierarchy (starting from the Ethereum blockchain as the root), along with a description of a job to be done. Then the necessary computations are done in the child workchain (possibly requiring forwarding of parts of the original job further down the tree), their results are passed up, and a reward is collected. The problem of achieving consistency and validating these workchains is circumvented by a (payment channel-inspired) mechanism allowing users to unilaterally withdraw their funds from a misbehaving workchain to its parent workchain (albeit slowly), and re-allocate their funds and their jobs to another workchain.
In this way, Plasma might become a platform for distributed computations bound to the Ethereum blockchain, something like a "mathematical co-processor". However, this does not seem like a way to achieve true general-purpose scalability.
#### 2.9.11. Specialized blockchain projects [#2911-specialized-blockchain-projects]
There are also some specialized blockchain projects, such as FileCoin (a system that incentivizes users to offer their disk space for storing the files of other users who are willing to pay for it), Golem (a blockchain-based platform for renting and lending computing power for specialized applications such as 3D-rendering) or SONM (another similar computing power-lending project). Such projects do not introduce anything conceptually new on the level of blockchain organization; rather, they are particular blockchain applications, which could be implemented by smart contracts running in a general-purpose blockchain, provided it can deliver the required performance. As such, projects of this kind are likely to use one of the existing or planned blockchain projects as their base, such as EOS, PolkaDot or TON. If a project needs "true" scalability (based on sharding), it would better use TON; if it is content to work in a "confederated" context by defining a family of workchains of its own, explicitly optimized for its purpose, it might opt for EOS or PolkaDot.
#### 2.9.12. The TON Blockchain [#2912-the-ton-blockchain]
The TON (Telegram Open Network) Blockchain (planned 2018) is the project we are describing in this document. It is designed to be the first fifth-generation blockchain project—that is, a BFT PoS-multichain project, mixed homogeneous/heterogeneous, with support for (shardable) custom workchains, with native sharding support, and tightly-coupled (in particular, capable of forwarding messages between shards almost instantly while preserving a consistent state of all shardchains). As such, it will be a truly scalable general-purpose blockchain project, capable of accommodating essentially any applications that can be implemented in a blockchain at all. When augmented by the other components of the TON Project (cf. [1](#1-brief-description-of-ton-components)), its possibilities expand even further.
#### 2.9.13. Is it possible to "upload Facebook into a blockchain"? [#2913-is-it-possible-to-upload-facebook-into-a-blockchain]
Sometimes people claim that it will be possible to implement a social network on the scale of Facebook as a distributed application residing in a blockchain. Usually a favorite blockchain project is cited as a possible "host" for such an application.
We cannot say that this is a technical impossibility. Of course, one needs a tightly-coupled blockchain project with true sharding (i.e., TON) in order for such a large application not to work too slowly (e.g., deliver messages and updates from users residing in one shardchain to their friends residing in another shardchain with reasonable delays). However, we think that this is not needed and will never be done, because the price would be prohibitive.
Let us consider "uploading Facebook into a blockchain" as a thought experiment; any other project of similar scale might serve as an example as well. Once Facebook is uploaded into a blockchain, all operations currently done by Facebook's servers will be serialized as transactions in certain blockchains (e.g., TON's shardchains), and will be performed by all validators of these blockchains. Each operation will have to be performed, say, at least twenty times, if we expect every block to collect at least twenty validator signatures (immediately or eventually, as in DPOS systems). Similarly, all data kept by Facebook's servers on their disks will be kept on the disks of all validators for the corresponding shardchain (i.e., in at least twenty copies).
Because the validators are essentially the same servers (or perhaps clusters of servers, but this does not affect the validity of this argument) as those currently used by Facebook, we see that the total hardware expenses associated with running Facebook in a blockchain are at least twenty times higher than if it were implemented in the conventional way.
In fact, the expenses would be much higher still, because the blockchain's virtual machine is slower than the "bare CPU" running optimized compiled code, and its storage is not optimized for Facebook-specific problems. One might partially mitigate this problem by crafting a specific workchain with some special transactions adapted for Facebook; this is the approach of BitShares and EOS to achieving high performance, available in the TON Blockchain as well. However, the general blockchain design would still impose some additional restrictions by itself, such as the necessity to register all operations as transactions in a block, to organize these transactions in a Merkle tree, to compute and check their Merkle hashes, to propagate this block further, and so on.
Therefore, a conservative estimate is that one would need 100 times more servers of the same performance as those used by Facebook now in order to validate a blockchain project hosting a social network of that scale. Somebody will have to pay for these servers, either the company owning the distributed application (imagine seeing 700 ads on each Facebook page instead of 7) or its users. Either way, this does not seem economically viable.
We believe that *it is not true that everything should be uploaded into the blockchain*. For example, it is not necessary to keep user photographs in the blockchain; registering the hashes of these photographs in the blockchain and keeping the photographs in a distributed off-chain storage (such as FileCoin or TON Storage) would be a better idea. This is the reason why TON is not just a blockchain project, but a collection of several components (TON P2P Network, TON Storage, TON Services) centered around the TON Blockchain as outlined in Chapters [1](#1-brief-description-of-ton-components) and [4](#4-ton-services-and-applications).
***
## 3. TON Networking [#3-ton-networking]
Any blockchain project requires not only a specification of block format and blockchain validation rules, but also a network protocol used to propagate new blocks, send and collect transaction candidates and so on. In other words, a specialized peer-to-peer network must be set up by every blockchain project. This network must be peer-to-peer, because blockchain projects are normally expected to be decentralized, so one cannot rely on a centralized group of servers and use conventional client-server architecture, as, for instance, classical online banking applications do. Even light clients (e.g., light cryptocurrency wallet smartphone applications), which must connect to full nodes in a client-server–like fashion, are actually free to connect to another full node if their previous peer goes down, provided the protocol used to connect to full nodes is standardized enough.
While the networking demands of single-blockchain projects, such as Bitcoin or Ethereum, can be met quite easily (one essentially needs to construct a "random" peer-to-peer overlay network, and propagate all new blocks and transaction candidates by a gossip protocol), multi-blockchain projects, such as the TON Blockchain, are much more demanding (e.g., one must be able to subscribe to updates of only some shardchains, not necessarily all of them). Therefore, the networking part of the TON Blockchain and the TON Project as a whole merits at least a brief discussion.
On the other hand, once the more sophisticated network protocols needed to support the TON Blockchain are in place, it turns out that they can easily be used for purposes not necessarily related to the immediate demands of the TON Blockchain, thus providing more possibilities and flexibility for creating new services in the TON ecosystem.
### 3.1 Abstract Datagram Network Layer [#31--abstract-datagram-network-layer]
The cornerstone in building the TON networking protocols is the *(TON) Abstract (Datagram) Network Layer*. It enables all nodes to assume certain "network identities", represented by 256-bit "abstract network addresses", and communicate (send datagrams to each other, as a first step) using only these 256-bit network addresses to identify the sender and the receiver. In particular, one does not need to worry about IPv4 or IPv6 addresses, UDP port numbers, and the like; they are hidden by the Abstract Network Layer.
#### 3.1.1. Abstract network addresses [#311-abstract-network-addresses]
An *abstract network address*, or an *abstract address*, or just *address* for short, is a 256-bit integer, essentially equal to a 256-bit ECC public key. This public key can be generated arbitrarily, thus creating as many different network identities as the node likes. However, one must know the corresponding *private* key in order to receive (and decrypt) messages intended for such an address.
In fact, the address is *not* the public key itself; instead, it is a 256-bit hash ($\text{Hash}=\text{Sha256}$) of a serialized TL-object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) that can describe several types of public keys and addresses depending on its constructor (first four bytes). In the simplest case, this serialized TL-object consists just of a 4-byte magic number and a 256-bit elliptic curve cryptography (ECC) public key; in this case, the address will equal the hash of this 36-byte structure. One might use, however, 2048-bit RSA keys, or any other scheme of public-key cryptography instead.
When a node learns another node's abstract address, it must also receive its "preimage" (i.e., the serialized TL-object, the hash of which equals that abstract address) or else it will not be able to encrypt and send datagrams to that address.
#### 3.1.2. Lower-level networks. UDP implementation [#312-lower-level-networks-udp-implementation]
From the perspective of almost all TON Networking components, the only thing that exists is a network (the Abstract Datagram Networking Layer) able to (unreliably) send datagrams from one abstract address to another. In principle, the Abstract Datagram Networking Layer (ADNL) can be implemented over different existing network technologies. However, we are going to implement it over UDP in IPv4/IPv6 networks (such as the Internet or intranets), with an optional TCP fallback if UDP is not available.
#### 3.1.3. Simplest case of ADNL over UDP [#313-simplest-case-of-adnl-over-udp]
The simplest case of sending a datagram from a sender's abstract address to any other abstract address (with known preimage) can be implemented as follows.
Suppose that the sender somehow knows the IP-address and the UDP port of the receiver who owns the destination abstract address, and that both the receiver and the sender use abstract addresses derived from 256-bit ECC public keys.
In this case, the sender simply augments the datagram to be sent by its ECC signature (done with its private key) and its source address (or the preimage of the source address, if the receiver is not known to know that preimage yet). The result is encrypted with the recipient's public key, embedded into a UDP datagram and sent to the known IP and port of the recipient. Because the first 256 bits of the UDP datagram contain the recipient's abstract address, the recipient can identify which private key should be used to decrypt the remainder of the datagram. Only after that is the sender's identity revealed.
#### 3.1.4. Less secure way, with the sender's address in plaintext [#314-less-secure-way-with-the-senders-address-in-plaintext]
Sometimes a less secure scheme is sufficient, when the recipient's and the sender's addresses are kept in plaintext in the UDP datagram; the sender's private key and the recipient's public key are combined together using ECDH (Elliptic Curve Diffie–Hellman) to generate a 256-bit shared secret, which is used afterwards, along with a random 256-bit nonce also included in the unencrypted part, to derive AES keys used for encryption. The integrity may be provided, for instance, by concatenating the hash of the original plaintext data to the plaintext before encryption.
This approach has the advantage that, if more than one datagram is expected to be exchanged between the two addresses, the shared secret can be computed only once and then cached; then slower elliptic curve operations will no longer be required for encrypting or decrypting the next datagrams.
#### 3.1.5. Channels and channel identifiers [#315-channels-and-channel-identifiers]
In the simplest case, the first 256 bits of a UDP datagram carrying an embedded TON ADNL datagram will be equal to the recipient's address. However, in general they constitute a *channel identifier*. There are different types of channels. Some of them are point-to-point; they are created by two parties who wish to exchange a lot of data in the future and generate a shared secret by exchanging several packets encrypted as described in [3.1.3](#3-1-3-simplest-case-of-adnl-over-udp) or [3.1.4](#3-1-4-less-secure-way-with-the-senders-address-in-plaintext), by running classical or elliptic curve Diffie–Hellman (if extra security is required), or simply by one party generating a random shared secret and sending it to the other party.
After that, a channel identifier is derived from the shared secret combined with some additional data (such as the sender's and recipient's addresses), for instance by hashing, and that identifier is used as the first 256 bits of UDP datagrams carrying data encrypted with the aid of that shared secret.
#### 3.1.6. Channel as a tunnel identifier [#316-channel-as-a-tunnel-identifier]
In general, a "channel", or "channel identifier" simply selects a way of processing an inbound UDP datagram, known to the receiver. If the channel is the receiver's abstract address, the processing is done as outlined in [3.1.3](#3-1-3-simplest-case-of-adnl-over-udp) or [3.1.4](#3-1-4-less-secure-way-with-the-senders-address-in-plaintext); if the channel is an established point-to-point channel discussed in [3.1.5](#3-1-5-channels-and-channel-identifiers), the processing consists in decrypting the datagram with the aid of the shared secret as explained in *loc. cit.*, and so on.
In particular, a channel identifier can actually select a "tunnel", when the immediate recipient simply forwards the received message to somebody else—the actual recipient or another proxy. Some encryption or decryption steps (reminiscent of "onion routing" [\[6\]](#ref-6) or even "garlic routing"[31](#fn31) ) might be done along the way, and another channel identifier might be used for re-encrypted forwarded packets (for example, a peer-to-peer channel could be employed to forward the packet to the next recipient on the path).
In this way, some support for "tunneling" and "proxying"—somewhat similar to that provided by the TOR or $I^2P$ projects—can be added on the level of the TON Abstract Datagram Network Layer, without affecting the functionality of all higher-level TON network protocols, which would be agnostic of such an addition. This opportunity is exploited by the *TON Proxy* service (cf. [4.1.11](#4-1-11-example%3A-ton-proxy-is-a-fog-service)).
#### 3.1.7. Zero channel and the bootstrap problem [#317-zero-channel-and-the-bootstrap-problem]
Normally, a TON ADNL node will have some "neighbor table", containing information about other known nodes, such as their abstract addresses and their preimages (i.e., public keys) and their IP addresses and UDP ports. Then it will gradually extend this table by using information learned from these known nodes as answers to special queries, and sometimes prune obsolete records.
However, when a TON ADNL node just starts up, it may happen that it does not know any other node, and can learn only the IP address and UDP port of a node, but not its abstract address. This happens, for example, if a light client is not able to access any of the previously cached nodes and any nodes hardcoded into the software, and must ask the user to enter an IP address or a DNS domain of a node, to be resolved through DNS.
In this case, the node will send packets to a special "zero channel" of the node in question. This does not require knowledge of the recipient's public key (but the message should still contain the sender's identity and signature), so the message is transferred without encryption. It should be normally used only to obtain an identity (maybe a one-time identity created especially for this purpose) of the receiver, and then to start communicating in a safer way.
Once at least one node is known, it is easy to populate the "neighbor table" and "routing table" by more entries, learning them from answers to special queries sent to the already known nodes.
Not all nodes are required to process datagrams sent to the zero channel, but those used to bootstrap light clients should support this feature.
#### 3.1.8. TCP-like stream protocol over ADNL [#318-tcp-like-stream-protocol-over-adnl]
The ADNL, being an unreliable (small-size) datagram protocol based on 256-bit abstract addresses, can be used as a base for more sophisticated network protocols. One can build, for example, a TCP-like stream protocol, using ADNL as an abstract replacement for IP. However, most components of the TON Project do not need such a stream protocol.
#### 3.1.9. RLDP, or Reliable Large Datagram Protocol over ADNL [#319-rldp-or-reliable-large-datagram-protocol-over-adnl]
A reliable arbitrary-size datagram protocol built upon the ADNL, called RLDP, is used instead of a TCP-like protocol. This reliable datagram protocol can be employed, for instance, to send RPC queries to remote hosts and receive answers from them (cf. [4.1.5](#4-1-5-pure-network-services-ton-sites-and-ton-services)).
### 3.2 TON DHT: Kademlia-like Distributed Hash Table [#32---ton-dht-kademlia-like-distributed-hash-table]
The *TON Distributed Hash Table (DHT)* plays a crucial role in the networking part of the TON Project, being used to locate other nodes in the network. For example, a client wanting to commit a transaction into a shardchain might want to find a validator or a collator of that shardchain, or at least some node that might relay the client's transaction to a collator. This can be done by looking up a special key in the TON DHT. Another important application of the TON DHT is that it can be used to quickly populate a new node's neighbor table (cf. [3.1.7](#3-1-7-zero-channel-and-the-bootstrap-problem)), simply by looking up a random key, or the new node's address. If a node uses proxying and tunneling for its inbound datagrams, it publishes the tunnel identifier and its entry point (e.g., IP address and UDP port) in the TON DHT; then all nodes wishing to send datagrams to that node will obtain this contact information from the DHT first.
The TON DHT is a member of the family of *Kademlia-like distributed hash tables* [\[10\]](#ref-10).
#### 3.2.1. Keys of the TON DHT [#321-keys-of-the-ton-dht]
The *keys* of the TON DHT are simply 256-bit integers. In most cases, they are computed as SHA-256 of a TL-serialized object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)), called *preimage* of the key, or *key description*. In some cases, the abstract addresses of the TON Network nodes (cf. [3.1.1](#3-1-1-abstract-network-addresses)) can also be used as keys of the TON DHT, because they are also 256-bit, and they are also hashes of TL-serialized objects. For example, if a node is not afraid of publishing its IP address, it can be found by anybody who knows its abstract address by simply looking up that address as a key in the DHT.
#### 3.2.2. Values of the DHT [#322-values-of-the-dht]
The *values* assigned to these 256-bit keys are essentially arbitrary byte strings of limited length. The interpretation of such byte strings is determined by the preimage of the corresponding key; it is usually known both by the node that looks up the key, and by the node that stores the key.
#### 3.2.3. Nodes of the DHT. Semi-permanent network identities [#323-nodes-of-the-dht-semi-permanent-network-identities]
The key-value mapping of the TON DHT is kept on the *nodes* of the DHT—essentially, all members of the TON Network. To this end, any node of the TON Network (perhaps with the exception of some very light nodes), apart from any number of ephemeral and permanent abstract addresses described in [3.1.1](#3-1-1-abstract-network-addresses), has at least one "semi-permanent address", which identifies it as a member of the TON DHT. This *semi-permanent* or *DHT address* should not to be changed too often, otherwise other nodes would be unable to locate the keys they are looking for. If a node does not want to reveal its "true" identity, it generates a separate abstract address to be used only for the purpose of participating in the DHT. However, this abstract address must be public, because it will be associated with the node's IP address and port.
#### 3.2.4. Kademlia distance [#324-kademlia-distance]
Now we have both 256-bit keys and 256-bit (semi-permanent) node addresses. We introduce the so-called *XOR distance* or *Kademlia distance $d_K$* on the set of 256-bit sequences, given by
$$
\mathit{d_K}(x,y) := (x \oplus y) \quad \text{interpreted as an unsigned 256-bit integer} \quad (25)
$$
Here $x \oplus y$ denotes the bitwise eXclusive OR (XOR) of two bit sequences of the same length.
The Kademlia distance introduces a metric on the set $\mathbf{2}^{256}$ of all 256-bit sequences. In particular, we have $d_K(x,y) = 0$ if and only if $x = y$, $d_K(x,y) = d_K(y,x)$, and $d_K(x,z) \leq d_K(x,y) + d_K(y,z)$. Another important property is that *there is only one point at any given distance from $x$*: $d_K(x,y) = d_K(x,y')$ implies $y = y'$.
#### 3.2.5. Kademlia-like DHTs and the TON DHT [#325-kademlia-like-dhts-and-the-ton-dht]
We say that a distributed hash table (DHT) with 256-bit keys and 256-bit node addresses is a *Kademlia-like DHT* if it is expected to keep the value of key $K$ on $s$ Kademlia-nearest nodes to $K$ (i.e., the $s$ nodes with smallest Kademlia distance from their addresses to $K$.)
Here $s$ is a small parameter, say, $s=7$, needed to improve reliability of the DHT (if we would keep the key only on one node, the nearest one to $K$, the value of that key would be lost if that only node goes offline).
The TON DHT is a Kademlia-like DHT, according to this definition. It is implemented over the ADNL protocol described in [3.1](#3-1-abstract-datagram-network-layer).
#### 3.2.6. Kademlia routing table [#326-kademlia-routing-table]
Any node participating in a Kademlia-like DHT usually maintains a *Kademlia routing table*. In the case of TON DHT, it consists of $n=256$ buckets, numbered from $0$ to $n-1$. The $i$-th bucket will contain information about some known nodes (a fixed number $t$ of "best" nodes, and maybe some extra candidates) that lie at a Kademlia distance from $2^i$ to $2^{i+1}-1$ from the node's address $a$.[32](#fn32) This information includes their (semi-permanent) addresses, IP addresses and UDP ports, and some availability information such as the time and the delay of the last ping.
When a Kademlia node learns about any other Kademlia node as a result of some query, it includes it into a suitable bucket of its routing table, first as a candidate. Then, if some of the "best" nodes in that bucket fail (e.g., do not respond to ping queries for a long time), they can be replaced by some of the candidates. In this way the Kademlia routing table stays populated.
New nodes from the Kademlia routing table are also included in the ADNL neighbor table described in [3.1.7](#3-1-7-zero-channel-and-the-bootstrap-problem). If a "best" node from a bucket of the Kademlia routing table is used often, a channel in the sense described in [3.1.5](#3-1-5-channels-and-channel-identifiers) can be established to facilitate the encryption of datagrams.
A special feature of the TON DHT is that it tries to select nodes with the smallest round-trip delays as the "best" nodes for the buckets of the Kademlia routing table.
#### 3.2.7. Kademlia network queries [#327-kademlia-network-queries]
A Kademlia node usually supports the following network queries:
* $\text{Ping}$ — Checks node availability.
* $\text{Store}(\text{key},\text{value})$ — Asks the node to keep *value* as a value for key *key*. For TON DHT, the $\text{Store}$ queries are slightly more complicated (cf. [3.2.9](#3-2-9-storing-values-in-ton-dht)).
* $\text{Find\_Node}(\text{key},l)$ — Asks the node to return $l$ Kademlia-nearest known nodes (from its Kademlia routing table) to *key*.
* $\text{Find\_Value}(\text{key},l)$ — The same as above, but if the node knows the value corresponding to key *key*, it just returns that value.
When any node wants to look up the value of a key $K$, it first creates a set $S$ of $s'$ nodes (for some small value of $s'$, say, $s'=5$), nearest to $K$ with respect to the Kademlia distance among all known nodes (i.e., they are taken from the Kademlia routing table). Then a $\text{Find\_Value}$ query is sent to each of them, and nodes mentioned in their answers are included in $S$. Then the $s'$ nodes from $S$, nearest to $K$, are also sent a $\text{Find\_Value}$ query if this hasn't been done before, and the process continues until the value is found or the set $S$ stops growing. This is a sort of "beam search" of the node nearest to $K$ with respect to Kademlia distance.
If the value of some key $K$ is to be set, the same procedure is run for $s'\geq s$, with $\text{Find\_Node}$ queries instead of $\text{Find\_Value}$, to find $s$ nearest nodes to $K$. Afterwards, $\text{Store}$ queries are sent to all of them.
There are some less important details in the implementation of a Kademlia-like DHT (for example, any node should look up $s$ nearest nodes to itself, say, once every hour, and re-publish all stored keys to them by means of $\text{Store}$ queries). We will ignore them for the time being.
#### 3.2.8. Booting a Kademlia node [#328-booting-a-kademlia-node]
When a Kademlia node goes online, it first populates its Kademlia routing table by looking up its own address. During this process, it identifies the $s$ nearest nodes to itself. It can download from them all $(key,value)$ pairs known to them to populate its part of the DHT.
#### 3.2.9. Storing values in TON DHT [#329-storing-values-in-ton-dht]
Storing values in TON DHT is slightly different from a general Kademlia-like DHT. When someone wishes to store a value, she must provide not only the key $K$ itself to the $\text{Store}$ query, but also its *preimage*—i.e., a TL-serialized string (with one of several predefined TL-constructors at the beginning) containing a "description" of the key. This key description is later kept by the node, along with the key and the value.
The key description describes the "type" of the object being stored, its "owner", and its "update rules" in case of future updates. The owner is usually identified by a public key included in the key description. If it is included, normally only updates signed by the corresponding private key will be accepted. The "type" of the stored object is normally just a byte string. However, in some cases it can be more sophisticated—for example, an input tunnel description (cf. [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), or a collection of node addresses.
The "update rules" can also be different. In some cases, they simply permit replacing the old value with the new value, provided the new value is signed by the owner (the signature must be kept as part of the value, to be checked later by any other nodes after they obtain the value of this key). In other cases, the old value somehow affects the new value. For example, it can contain a sequence number, and the old value is overwritten only if the new sequence number is larger (to prevent replay attacks).
#### 3.2.10. Distributed "torrent trackers" and "network interest groups" in TON DHT [#3210-distributed-torrent-trackers-and-network-interest-groups-in-ton-dht]
Yet another interesting case is when the value contains a list of nodes—perhaps with their IP addresses and ports, or just with their abstract addresses—and the "update rule" consists in including the requester in this list, provided she can confirm her identity.
This mechanism might be used to create a distributed "torrent tracker", where all nodes interested in a certain "torrent" (i.e., a certain file) can find other nodes that are interested in the same torrent, or already have a copy.
*TON Storage* (cf. [4.1.8](#4-1-8-example%3A-keeping-files-off-chain%3B-ton-storage)) uses this technology to find the nodes that have a copy of a required file (e.g., a snapshot of the state of a shardchain, or an old block). However, its more important use is to create "overlay multicast subnetworks" and "network interest groups" (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). The idea is that only some nodes are interested in the updates of a specific shardchain. If the number of shardchains becomes very large, finding even one node interested in the same shard may become complicated. This "distributed torrent tracker" provides a convenient way to find some of these nodes. Another option would be to request them from a validator, but this would not be a scalable approach, and validators might choose not to respond to such queries coming from arbitrary unknown nodes.
#### 3.2.11. Fall-back keys [#3211-fall-back-keys]
Most of the "key types" described so far have an extra 32-bit integer field in their TL description, normally equal to zero. However, if the key obtained by hashing that description cannot be retrieved from or updated in the TON DHT, the value in this field is increased, and a new attempt is made. In this way, one cannot "capture" and "censor" a key (i.e., perform a key retention attack) by creating a lot of abstract addresses lying near the key under attack and controlling the corresponding DHT nodes.
#### 3.2.12. Locating services [#3212-locating-services]
Some services, located in the TON Network and available through the (higher-level protocols built upon the) TON ADNL described in [3.1](#3-1-abstract-datagram-network-layer), may want to publish their abstract addresses somewhere, so that their clients would know where to find them.
However, publishing the service's abstract address in the TON Blockchain may not be the best approach, because the abstract address might need to be changed quite often, and because it could make sense to provide several addresses, for reliability or load balancing purposes.
An alternative is to publish a public key into the TON Blockchain, and use a special DHT key indicating that public key as its "owner" in the TL description string (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) to publish an up-to-date list of the service's abstract addresses. This is one of the approaches exploited by TON Services.
#### 3.2.13. Locating owners of TON blockchain accounts [#3213-locating-owners-of-ton-blockchain-accounts]
In most cases, owners of TON blockchain accounts would not like to be associated with abstract network addresses, and especially IP addresses, because this can violate their privacy. In some cases, however, the owner of a TON blockchain account may want to publish one or several abstract addresses where she could be contacted.
A typical case is that of a node in the TON Payments "lightning network" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), the platform for instant cryptocurrency transfers. A public TON Payments node may want not only to establish payment channels with other peers, but also to publish an abstract network address that could be used to contact it at a later time for transferring payments along the already-established channels.
One option would be to include an abstract network address in the smart contract creating the payment channel. A more flexible option is to include a public key in the smart contract, and then use DHT as explained in [3.2.12](#3-2-12-locating-services).
The most natural way would be to use the same private key that controls the account in the TON Blockchain to sign and publish updates in the TON DHT about the abstract addresses associated with that account. This is done almost in the same way as described in [3.2.12](#3-2-12-locating-services); however, the DHT key employed would require a special key description, containing only the $\mathit{account\_id}$ itself, equal to SHA-256 of the "account description", which contains the public key of the account. The signature, included in the value of this DHT key, would contain the account description as well.
In this way, a mechanism for locating abstract network addresses of some owners of the TON Blockchain accounts becomes available.
#### 3.2.14. Locating abstract addresses [#3214-locating-abstract-addresses]
Notice that the TON DHT, while being implemented over TON ADNL, is itself used by the TON ADNL for several purposes.
The most important of them is to locate a node or its contact data starting from its 256-bit abstract address. This is necessary because the TON ADNL should be able to send datagrams to arbitrary 256-bit abstract addresses, even if no additional information is provided.
To this end, the 256-bit abstract address is simply looked up as a key in the DHT. Either a node with this address (i.e., using this address as a public semi-persistent DHT address) is found, in which case its IP address and port can be learned; or, an input tunnel description may be retrieved as the value of the key in question, signed by the correct private key, in which case this tunnel description would be used to send ADNL datagrams to the intended recipient.
Notice that in order to make an abstract address "public" (reachable from any nodes in the network), its owner must either use it as a semi-permanent DHT address, or publish (in the DHT key equal to the abstract address under consideration) an input tunnel description with another of its public abstract addresses (e.g., the semi-permanent address) as the tunnel's entry point. Another option would be to simply publish its IP address and UDP port.
***
### 3.3 Overlay Networks and Multicasting Messages [#33--overlay-networks-and-multicasting-messages]
In a multi-blockchain system like the TON Blockchain, even full nodes would normally be interested in obtaining updates (i.e., new blocks) only about some shardchains. To this end, a special overlay (sub)network must be built inside the TON Network, on top of the ADNL protocol discussed in [3.1](#3-1-abstract-datagram-network-layer), one for each shardchain.
Therefore, the need to build arbitrary overlay subnetworks, open to any nodes willing to participate, arises. Special gossip protocols, built upon ADNL, will be run in these overlay networks. In particular, these gossip protocols may be used to propagate (broadcast) arbitrary data inside such a subnetwork.
#### 3.3.1. Overlay networks [#331-overlay-networks]
An *overlay (sub)network* is simply a (virtual) network implemented inside some larger network. Usually only some nodes of the larger network participate in the overlay subnetwork, and only some "links" between these nodes, physical or virtual, are part of the overlay subnetwork.
In this way, if the encompassing network is represented as a graph (perhaps a full graph in the case of a datagram network such as ADNL, where any node can easily communicate to any other), the overlay subnetwork is a *subgraph* of this graph.
In most cases, the overlay network is implemented using some protocol built upon the network protocol of the larger network. It may use the same addresses as the larger network, or use custom addresses.
#### 3.3.2. Overlay networks in TON [#332-overlay-networks-in-ton]
Overlay networks in TON are built upon the ADNL protocol discussed in [3.1](#3-1-abstract-datagram-network-layer); they use 256-bit ADNL abstract addresses as addresses in the overlay networks as well. Each node usually selects one of its abstract addresses to double as its address in the overlay network.
In contrast to ADNL, the TON overlay networks usually do not support sending datagrams to arbitrary other nodes. Instead, some "semipermanent links" are established between some nodes (called "neighbors" with respect to the overlay network under consideration), and messages are usually forwarded along these links (i.e., from a node to one of its neighbors). In this way, a TON overlay network is a (usually not full) subgraph inside the (full) graph of the ADNL network.
Links to neighbors in TON overlay networks can be implemented using dedicated peer-to-peer ADNL channels (cf. [3.1.5](#3-1-5-channels-and-channel-identifiers)).
Each node of an overlay network maintains a list of neighbors (with respect to the overlay network), containing their abstract addresses (which they use to identify them in the overlay network) and some link data (e.g., the ADNL channel used to communicate with them).
#### 3.3.3. Private and public overlay networks [#333-private-and-public-overlay-networks]
Some overlay networks are *public*, meaning that any node can join them at will. Other are *private*, meaning that only certain nodes can be admitted (e.g., those that can prove their identities as validators.) Some private overlay networks can even be unknown to the "general public". The information about such overlay networks is made available only to certain trusted nodes; for example, it can be encrypted with a public key, and only nodes having a copy of the corresponding private key will be able to decrypt this information.
#### 3.3.4. Centrally controlled overlay networks [#334-centrally-controlled-overlay-networks]
Some overlay networks are *centrally controlled*, by one or several nodes, or by the owner of some widely-known public key. Others are *decentralized*, meaning that there are no specific nodes responsible for them.
#### 3.3.5. Joining an overlay network [#335-joining-an-overlay-network]
When a node wants to join an overlay network, it first must learn its 256-bit *network identifier*, usually equal to SHA-256 of the *description* of the overlay network—a TL-serialized object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) which may contain, for instance, the central authority of the overlay network (i.e., its public key and perhaps its abstract address,[33](#fn33) ) a string with the name of the overlay network, a TON Blockchain shard identifier if this is an overlay network related to that shard, and so on.
Sometimes it is possible to recover the overlay network description starting from the network identifier, simply by looking it up in the TON DHT. In other cases (e.g., for private overlay networks), one must obtain the network description along with the network identifier.
#### 3.3.6. Locating one member of the overlay network [#336-locating-one-member-of-the-overlay-network]
After a node learns the network identifier and the network description of the overlay network it wants to join, it must locate at least one node belonging to that network.
This is also needed for nodes that do not want to join the overlay network, but want just to communicate with it; for example, there might be an overlay network dedicated to collecting and propagating transaction candidates for a specific shardchain, and a client might want to connect to any node of this network to suggest a transaction.
The method used for locating members of an overlay network is defined in the description of that network. Sometimes (especially for private networks) one must already know a member node to be able to join. In other cases, the abstract addresses of some nodes are contained in the network description. A more flexible approach is to indicate in the network description only the central authority responsible for the network, and then the abstract addresses will be available through values of certain DHT keys, signed by that central authority.
Finally, truly decentralized public overlay networks can use the "distributed torrent-tracker" mechanism described in [3.2.10](#3-2-10-distributed-torrent-trackers-and-network-interest-groups-in-ton-dht), also implemented with the aid of the TON DHT.
#### 3.3.7. Locating more members of the overlay network. Creating links [#337-locating-more-members-of-the-overlay-network-creating-links]
Once one node of the overlay network is found, a special query may be sent to that node requesting a list of other members, for instance, neighbors of the node being queried, or a random selection thereof.
This enables the joining member to populate her "adjacency" or "neighbor list" with respect to the overlay network, by selecting some newly-learned network nodes and establishing links to them (i.e., dedicated ADNL point-to-point channels, as outlined in [3.3.2](#3-3-2-overlay-networks-in-ton)). After that, special messages are sent to all neighbors indicating that the new member is ready to work in the overlay network. The neighbors include their links to the new member in their neighbor lists.
#### 3.3.8. Maintaining the neighbor list [#338-maintaining-the-neighbor-list]
An overlay network node must update its neighbor list from time to time. Some neighbors, or at least links (channels) to them, may stop responding; in this case, these links must be marked as "suspended", some attempts to reconnect to such neighbors must be made, and, if these attempts fail, the links must be destroyed.
On the other hand, every node sometimes requests from a randomly chosen neighbor its list of neighbors (or some random selection thereof), and uses it to partially update its own neighbor list, by adding some newly-discovered nodes to it, and removing some of the old ones, either randomly or depending on their response times and datagram loss statistics.
#### 3.3.9. The overlay network is a random subgraph [#339-the-overlay-network-is-a-random-subgraph]
In this way, the overlay network becomes a random subgraph inside the ADNL network. If the degree of each vertex is at least three (i.e., if each node is connected to at least three neighbors), this random graph is known to be *connected* with a probability almost equal to one. More precisely, the probability of a random graph with $n$ vertices being *disconnected* is exponentially small, and this probability can be completely neglected if, say, $n\geq20$. (Of course, this does not apply in the case of a global network partition, when nodes on different sides of the partition have no chance to learn about each other.) On the other hand, if $n$ is smaller than 20, it would suffice to require each vertex to have, say, at least ten neighbors.
#### 3.3.10. TON overlay networks are optimized for lower latency [#3310-ton-overlay-networks-are-optimized-for-lower-latency]
TON overlay networks optimize the "random" network graph generated by the previous method as follows. Every node tries to retain at least three neighbors with the minimal round-trip time, changing this list of "fast neighbors" very rarely. At the same time, it also has at least three other "slow neighbors" that are chosen completely randomly, so that the overlay network graph would always contain a random subgraph. This is required to maintain connectivity and prevent splitting of the overlay network into several unconnected regional subnetworks. At least three "intermediate neighbors", which have intermediate round-trip times, bounded by a certain constant (actually, a function of the round-trip times of the fast and the slow neighbors), are also chosen and retained.
In this way, the graph of an overlay network still maintains enough randomness to be connected, but is optimized for lower latency and higher throughput.
#### 3.3.11. Gossip protocols in an overlay network [#3311-gossip-protocols-in-an-overlay-network]
An overlay network is often used to run one of the so-called *gossip protocols*, which achieve some global goal while letting every node interact only with its neighbors. For example, there are gossip protocols to construct an approximate list of all members of a (not too large) overlay network, or to compute an estimate of the number of members of an (arbitrarily large) overlay network, using only a bounded amount of memory at each node (cf. \[[15](#ref-15), 4.4.3] or [\[1\]](#ref-1) for details).
#### 3.3.12. Overlay network as a broadcast domain [#3312-overlay-network-as-a-broadcast-domain]
The most important gossip protocol running in an overlay network is the *broadcast protocol*, intended to propagate broadcast messages generated by any node of the network, or perhaps by one of the designated sender nodes, to all other nodes.
There are in fact several broadcast protocols, optimized for different use cases. The simplest of them receives new broadcast messages and relays them to all neighbors that have not yet sent a copy of that message themselves.
#### 3.3.13. More sophisticated broadcast protocols [#3313-more-sophisticated-broadcast-protocols]
Some applications may warrant more sophisticated broadcast protocols. For instance, for broadcasting messages of substantial size, it makes sense to send to the neighbors not the newly-received message itself, but its hash (or a collection of hashes of new messages). The neighbor may request the message itself after learning a previously unseen message hash, to be transferred, say, using the reliable large datagram protocol (RLDP) discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl). In this way, the new message will be downloaded from one neighbor only.
#### 3.3.14. Checking the connectivity of an overlay network [#3314-checking-the-connectivity-of-an-overlay-network]
The connectivity of an overlay network can be checked if there is a known node (e.g., the "owner" or the "creator" of the overlay network) that must be in this overlay network. Then the node in question simply broadcasts from time to time short messages containing the current time, a sequence number and its signature. Any other node can be sure that it is still connected to the overlay network if it has received such a broadcast not too long ago. This protocol can be extended to the case of several well-known nodes; for example, they all will send such broadcasts, and all other nodes will expect to receive broadcasts from more than half of the well-known nodes.
In the case of an overlay network used for propagating new blocks (or just new block headers) of a specific shardchain, a good way for a node to check connectivity is to keep track of the most recent block received so far. Because a block is normally generated every five seconds, if no new block is received for more than, say, thirty seconds, the node probably has been disconnected from the overlay network.
#### 3.3.15. Streaming broadcast protocol [#3315-streaming-broadcast-protocol]
Finally, there is a *streaming broadcast protocol* for TON overlay networks, used, for example, to propagate block candidates among validators of some shardchain ("shardchain task group"), who, of course, create a private overlay network for that purpose. The same protocol can be used to propagate new shardchain blocks to all full nodes for that shardchain.
This protocol has already been outlined in [2.6.10](#2-6-10-propagation-of-shardchain-block-candidates): the new (large) broadcast message is split into, say, $N$ one-kilobyte chunks; the sequence of these chunks is augmented to $M\geq N$ chunks by means of an erasure code such as the Reed–Solomon or a fountain code (e.g., the RaptorQ code [\[9\]](#ref-9) [\[14\]](#ref-14)), and these $M$ chunks are streamed to all neighbors in ascending chunk number order. The participating nodes collect these chunks until they can recover the original large message (one would have to successfully receive at least $N$ of the chunks for this), and then instruct their neighbors to stop sending new chunks of the stream, because now these nodes can generate the subsequent chunks on their own, having a copy of the original message. Such nodes continue to generate the subsequent chunks of the stream and send them to their neighbors, unless the neighbors in turn indicate that this is no longer necessary.
In this way, a node does not need to download a large message in its entirety before propagating it further. This minimizes broadcast latency, especially when combined with the optimizations described in [3.3.10](#3-3-10-ton-overlay-networks-are-optimized-for-lower-latency).
#### 3.3.16. Constructing new overlay networks based on existing ones [#3316-constructing-new-overlay-networks-based-on-existing-ones]
Sometimes one does not want to construct an overlay network from scratch. Instead, one or several previously existing overlay networks are known, and the membership of the new overlay network is expected to overlap significantly with the combined membership of these overlay networks.
An important example arises when a TON shardchain is split in two, or two sibling shardchains are merged into one (cf. [2.7](#2-7-splitting-and-merging-shardchains)). In the first case, the overlay networks used for propagating new blocks to full nodes must be constructed for each of the new shardchains; however, each of these new overlay networks can be expected to be contained in the block propagation network of the original shardchain (and comprise approximately half its members). In the second case, the overlay network for propagating new blocks of the merged shardchain will consist approximately of the union of members of the two overlay networks related to the two sibling shardchains being merged.
In such cases, the description of the new overlay network may contain an explicit or implicit reference to a list of related existing overlay networks. A node wishing to join the new overlay network may check whether it is already a member of one of these existing networks, and query its neighbors in these networks whether they are interested in the new network as well. In case of a positive answer, new point-to-point channels can be established to such neighbors, and they can be included in the neighbor list for the new overlay network.
This mechanism does not totally supplant the general mechanism described in [3.3.6](#3-3-6-locating-one-member-of-the-overlay-network) and [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links); rather, both are run in parallel and are used to populate the neighbor list. This is needed to prevent inadvertent splitting of the new overlay network into several unconnected subnetworks.
#### 3.3.17. Overlay networks within overlay networks [#3317-overlay-networks-within-overlay-networks]
Another interesting case arises in the implementation of *TON Payments* (a "lightning network" for instant off-chain value transfers; cf. [5.2](#5-2-payment-channel-network-or-lightning-network)). In this case, first an overlay network containing all transit nodes of the "lightning network" is constructed. However, some of these nodes have established payment channels in the blockchain; they must always be neighbors in this overlay network, in addition to any "random" neighbors selected by the general overlay network algorithms described in [3.3.6](#3-3-6-locating-one-member-of-the-overlay-network), [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links) and [3.3.8](#3-3-8-maintaining-the-neighbor-list). These "permanent links" to the neighbors with established payment channels are used to run specific lightning network protocols, thus effectively creating an overlay subnetwork (not necessarily connected, if things go awry) inside the encompassing (almost always connected) overlay network.
***
## 4 TON Services and Applications [#4--ton-services-and-applications]
We have discussed the TON Blockchain and TON Networking technologies at some length. Now we explain some ways in which they can be combined to create a wide range of services and applications, and discuss some of the services that will be provided by the TON Project itself, either from the very beginning or at a later time.
### 4.1 TON Service Implementation Strategies [#41--ton-service-implementation-strategies]
We start with a discussion of how different blockchain and network-related applications and services may be implemented inside the TON ecosystem. First of all, a simple classification is in order:
#### 4.1.1. Applications and services [#411-applications-and-services]
We will use the words "application" and "service" interchangeably. However, there is a subtle and somewhat vague distinction: an *application* usually provides some services directly to human users, while a *service* is usually exploited by other applications and services. For example, TON Storage is a service, because it is designed to keep files on behalf of other applications and services, even though a human user might use it directly as well. A hypothetical "Facebook in a blockchain" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)) or Telegram messenger, if made available through the TON Network (i.e., implemented as a "ton-service" c.f [4.1.6](#4-1-6-telegram-messenger-as-a-ton-service%3B-mtproto-over-rldp)), would rather be an *application*, even though some "bots" might access it automatically without human intervention.
#### 4.1.2. Location of the application: on-chain, off-chain or mixed [#412-location-of-the-application-on-chain-off-chain-or-mixed]
A service or an application designed for the TON ecosystem needs to keep its data and process that data somewhere. This leads to the following classification of applications (and services):
* *On-chain* applications (cf. [4.1.4](#4-1-4-pure-on-chain-applications%3A-distributed-applications%2C-or-dapps%2C-residing-in-the-blockchain)): All data and processing are in the TON Blockchain.
* *Off-chain* applications (cf. [4.1.5](#4-1-5-pure-network-services%3A-ton-sites-and-ton-services)): All data and processing are outside the TON Blockchain, on servers available through the TON Network.
* *Mixed* applications (cf. [4.1.7](#4-1-7-mixed-services%3A-partly-off-chain%2C-partly-on-chain)): Some, but not all, data and processing are in the TON Blockchain; the rest are on off-chain servers available through the TON Network.
#### 4.1.3. Centralization: centralized and decentralized, or distributed, applications [#413-centralization-centralized-and-decentralized-or-distributed-applications]
Another classification criterion is whether the application (or service) relies on a centralized server cluster, or is really "distributed" (cf. [4.1.9](#4-1-9-decentralized-mixed-services%2C-or-“fog-services”)). All on-chain applications are automatically decentralized and distributed. Off-chain and mixed applications may exhibit different degrees of centralization.
Now let us consider the above possibilities in more detail.
#### 4.1.4. Pure "on-chain" applications: distributed applications, or "dapps", residing in the blockchain [#414-pure-on-chain-applications-distributed-applications-or-dapps-residing-in-the-blockchain]
One of the possible approaches, mentioned in [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed), is to deploy a "distributed application" (commonly abbreviated as "dapp") completely in the TON Blockchain, as one smart contract or a collection of smart contracts. All data will be kept as part of the permanent state of these smart contracts, and all interaction with the project will be done by means of (TON Blockchain) messages sent to or received from these smart contracts.
We have already discussed in [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain) that this approach has its drawbacks and limitations. It has its advantages, too: such a distributed application needs no servers to run on or to store its data (it runs "in the blockchain"—i.e., on the validators' hardware), and enjoys the blockchain's extremely high (Byzantine) reliability and accessibility. The developer of such a distributed application does not need to buy or rent any hardware; all she needs to do is develop some software (i.e., the code for the smart contracts). After that, she will effectively rent the computing power from the validators, and will pay for it in Grams, either herself or by putting this burden on the shoulders of her users.
#### 4.1.5. Pure network services: "ton-sites" and "ton-services" [#415-pure-network-services-ton-sites-and-ton-services]
Another extreme option is to deploy the service on some servers and make it available to the users through the ADNL protocol described in [3.1](#3-1-abstract-datagram-network-layer), and maybe some higher level protocol such as the RLDP discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl), which can be used to send RPC queries to the service in any custom format and obtain answers to these queries. In this way, the service will be totally off-chain, and will reside in the TON Network, almost without using the TON Blockchain.
The TON Blockchain might be used only to locate the abstract address or addresses of the service, as outlined in [3.2.12](#3-2-12-locating-services), perhaps with the aid of a service such as the TON DNS (cf. [4.3.1](#4-3-1-ton-dns-a-mostly-on-chain-hierarchical-domain-name-service)) to facilitate translation of domain-like human-readable strings into abstract addresses.
To the extent the ADNL network (i.e., the TON Network) is similar to the Invisible Internet Project ($I^2P$), such (almost) purely network services are analogous to the so-called "eep-services" (i.e., services that have an $I^2P$-address as their entry point, and are available to clients through the $I^2P$ network). We will say that such purely network services residing in the TON Network are "ton-services".
An "eep-service" may implement HTTP as its client-server protocol; in the TON Network context, a "ton-service" might simply use RLDP (cf. [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl)) datagrams to transfer HTTP queries and responses to them. If it uses the TON DNS to allow its abstract address to be looked up by a human-readable domain name, the analogy to a web site becomes almost perfect. One might even write a specialized browser, or a special proxy ("ton-proxy") that is run locally on a user's machine, accepts arbitrary HTTP queries from an ordinary web browser the user employs (once the local IP address and the TCP port of the proxy are entered into the browser's configuration), and forwards these queries through the TON Network to the abstract address of the service. Then the user would have a browsing experience similar to that of the World Wide Web (WWW).
In the $I^2P$ ecosystem, such "eep-services" are called "eep-sites". One can easily create "ton-sites" in the TON ecosystem as well. This is facilitated somewhat by the existence of services such as the TON DNS, which exploit the TON Blockchain and the TON DHT to translate (TON) domain names into abstract addresses.
#### 4.1.6. Telegram Messenger as a ton-service; MTProto over RLDP [#416-telegram-messenger-as-a-ton-service-mtproto-over-rldp]
We would like to mention in passing that the MTProto protocol,[34](#fn34) used by Telegram Messenger[35](#fn35) for client-server interaction, can be easily embedded into the RLDP protocol discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl), thus effectively transforming Telegram into a ton-service. Because the TON Proxy technology can be switched on transparently for the end user of a ton-site or a ton-service, being implemented on a lower level than the RLDP and ADNL protocols (cf. [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), this would make Telegram effectively unblockable. Of course, other messaging and social networking services might benefit from this technology as well.
#### 4.1.7. Mixed services: partly off-chain, partly on-chain [#417-mixed-services-partly-off-chain-partly-on-chain]
Some services might use a mixed approach: do most of the processing off-chain, but also have some on-chain part (for example, to register their obligations towards their users, and vice versa). In this way, part of the state would still be kept in the TON Blockchain (i.e., an immutable public ledger), and any misbehavior of the service or of its users could be punished by smart contracts.
#### 4.1.8. Example: keeping files off-chain; TON Storage [#418-example-keeping-files-off-chain-ton-storage]
An example of such a service is given by *TON Storage*. In its simplest form, it allows users to store files off-chain, by keeping on-chain only a hash of the file to be stored, and possibly a smart contract where some other parties agree to keep the file in question for a given period of time for a pre-negotiated fee. In fact, the file may be subdivided into chunks of some small size (e.g., 1 kilobyte), augmented by an erasure code such as a Reed–Solomon or a fountain code, a Merkle tree hash may be constructed for the augmented sequence of chunks, and this Merkle tree hash might be published in the smart contract instead of or along with the usual hash of the file. This is somewhat reminiscent of the way files are stored in a torrent.
An even simpler form of storing files is completely off-chain: one might essentially create a "torrent" for a new file, and use TON DHT as a "distributed torrent tracker" for this torrent (cf. [3.2.10](#3-2-10-distributed-torrent-trackers-and-network-interest-groups-in-ton-dht)). This might actually work pretty well for popular files. However, one does not get any availability guarantees. For example, a hypothetical "blockchain Facebook" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)), which would opt to keep the profile photographs of its users completely off-chain in such "torrents", might risk losing photographs of ordinary (not especially popular) users, or at least risk being unable to present these photographs for prolonged periods. The TON Storage technology, which is mostly off-chain, but uses an on-chain smart contract to enforce availability of the stored files, might be a better match for this task.
#### 4.1.9. Decentralized mixed services, or "fog services" [#419-decentralized-mixed-services-or-fog-services]
So far, we have discussed *centralized* mixed services and applications. While their on-chain component is processed in a decentralized and distributed fashion, being located in the blockchain, their off-chain component relies on some servers controlled by the service provider in the usual centralized fashion. Instead of using some dedicated servers, computing power might be rented from a cloud computing service offered by one of the large companies. However, this would not lead to decentralization of the off-chain component of the service.
A decentralized approach to implementing the off-chain component of a service consists in creating a *market*, where anybody possessing the required hardware and willing to rent their computing power or disk space would offer their services to those needing them.
For example, there might exist a registry (which might also be called a "market" or an "exchange") where all nodes interested in keeping files of other users publish their contact information, along with their available storage capacity, availability policy, and prices. Those needing these services might look them up there, and, if the other party agrees, create smart contracts in the blockchain and upload files for off-chain storage. In this way a service like *TON Storage* becomes truly decentralized, because it does not need to rely on any centralized cluster of servers for storing files.
#### 4.1.10. Example: "fog computing" platforms as decentralized mixed services [#4110-example-fog-computing-platforms-as-decentralized-mixed-services]
Another example of such a decentralized mixed application arises when one wants to perform some specific computations (e.g., 3D rendering or training neural networks), often requiring specific and expensive hardware. Then those having such equipment might offer their services through a similar "exchange", and those needing such services would rent them, with the obligations of the sides registered by means of smart contracts. This is similar to what "fog computing" platforms, such as Golem ([https://golem.network/](https://golem.network/)) or SONM ([https://sonm.io/](https://sonm.io/)), promise to deliver.
#### 4.1.11. Example: TON Proxy is a fog service [#4111-example-ton-proxy-is-a-fog-service]
*TON Proxy* provides yet another example of a fog service, where nodes wishing to offer their services (with or without compensation) as tunnels for ADNL network traffic might register, and those needing them might choose one of these nodes depending on the price, latency and bandwidth offered. Afterwards, one might use payment channels provided by *TON Payments* for processing micropayments for the services of those proxies, with payments collected, for instance, for every 128 KiB transferred.
#### 4.1.12. Example: TON Payments is a fog service [#4112-example-ton-payments-is-a-fog-service]
The TON Payments platform (cf. [5](#5-ton-payments)) is also an example of such a decentralized mixed application.
### 4.2 Connecting Users and Service Providers [#42--connecting-users-and-service-providers]
We have seen in [4.1.9](#4-1-9-decentralized-mixed-services%2C-or-“fog-services”) that "fog services" (i.e., mixed decentralized services) will usually need some *markets*, *exchanges* or *registries*, where those needing specific services might meet those providing them.
Such markets are likely to be implemented as on-chain, off-chain or mixed services themselves, centralized or distributed.
#### 4.2.1. Example: connecting to TON Payments [#421-example-connecting-to-ton-payments]
For example, if one wants to use TON Payments (cf. [5](#5-ton-payments)), the first step would be to find at least some existing transit nodes of the "lightning network" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), and establish payment channels with them, if they are willing. Some nodes can be found with the aid of the "encompassing" overlay network, which is supposed to contain all transit lightning network nodes (cf. [3.3.17](#3-3-17-overlay-networks-within-overlay-networks)). However, it is not clear whether these nodes will be willing to create new payment channels. Therefore, a registry is needed where nodes ready to create new links can publish their contact information (e.g., their abstract addresses).
#### 4.2.2. Example: uploading a file into TON Storage [#422-example-uploading-a-file-into-ton-storage]
Similarly, if one wants to upload a file into the TON Storage, she must locate some nodes willing to sign a smart contract binding them to keep a copy of that file (or of any file below a certain size limit, for that matter). Therefore, a registry of nodes offering their services for storing files is needed.
#### 4.2.3. On-chain, mixed and off-chain registries [#423-on-chain-mixed-and-off-chain-registries]
Such a registry of service providers might be implemented completely on-chain, with the aid of a smart contract which would keep the registry in its permanent storage. However, this would be quite slow and expensive. A mixed approach is more efficient, where the relatively small and rarely changed on-chain registry is used only to point out some nodes (by their abstract addresses, or by their public keys, which can be used to locate actual abstract addresses as described in [3.2.12](#3-2-12-locating-services)), which provide off-chain (centralized) registry services.
Finally, a decentralized, purely off-chain approach might consist of a public overlay network (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)), where those willing to offer their services, or those looking to buy somebody's services, simply broadcast their offers, signed by their private keys. If the service to be provided is very simple, even broadcasting the offers might be not necessary: the approximate membership of the overlay network itself might be used as a "registry" of those willing to provide a particular service. Then a client requiring this service might locate (cf. [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links)) and query some nodes of this overlay network, and then query their neighbors, if the nodes already known are not ready to satisfy its needs.
#### 4.2.4. Registry or exchange in a side-chain [#424-registry-or-exchange-in-a-side-chain]
Another approach to implementing decentralized mixed registries consists in creating an independent specialized blockchain ("side-chain"), maintained by its own set of self-proclaimed validators, who publish their identities in an on-chain smart contract and provide network access to all interested parties to this specialized blockchain, collecting transaction candidates and broadcasting block updates through dedicated overlay networks (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). Then any full node for this sidechain can maintain its own copy of the shared registry (essentially equal to the global state of this side-chain), and process arbitrary queries related to this registry.
#### 4.2.5. Registry or exchange in a workchain [#425-registry-or-exchange-in-a-workchain]
Another option is to create a dedicated workchain inside the TON Blockchain, specialized for creating registries, markets and exchanges. This might be more efficient and less expensive than using smart contracts residing in the basic workchain (cf. [2.1.11](#2-1-11-basic-workchain-or-workchain-zero)). However, this would still be more expensive than maintaining registries in side-chains (cf. [4.2.4](#4-2-4-registry-or-exchange-in-a-side-chain)).
### 4.3 Accessing TON Services [#43---accessing-ton-services]
We have discussed in [4.1](#4-1-ton-service-implementation-strategies) the different approaches one might employ for creating new services and applications residing in the TON ecosystem. Now we discuss how these services might be accessed, and some of the "helper services" that will be provided by TON, including *TON DNS* and *TON Storage*.
#### 4.3.1. TON DNS: a mostly on-chain hierarchical domain name service [#431-ton-dns-a-mostly-on-chain-hierarchical-domain-name-service]
The *TON DNS* is a predefined service, which uses a collection of smart contracts to keep a map from human-readable domain names to (256-bit) addresses of ADNL network nodes and TON Blockchain accounts and smart contracts.
While anybody might in principle implement such a service using the TON Blockchain, it is useful to have such a predefined service with a well-known interface, to be used by default whenever an application or a service wants to translate human-readable identifiers into addresses.
#### 4.3.2. TON DNS use cases [#432-ton-dns-use-cases]
For example, a user looking to transfer some cryptocurrency to another user or to a merchant may prefer to remember a TON DNS domain name of the account of that user or merchant, instead of keeping their 256-bit account identifiers at hand and copy-pasting them into the recipient field in their light wallet client.
Similarly, TON DNS may be used to locate account identifiers of smart contracts or entry points of ton-services and ton-sites (cf. [4.1.5](#4-1-5-pure-network-services-ton-sites-and-ton-services)), enabling a specialized client ("ton-browser"), or a usual internet browser combined with a specialized ton-proxy extension or stand-alone application, to deliver a WWW-like browsing experience to the user.
#### 4.3.3. TON DNS smart contracts [#433-ton-dns-smart-contracts]
The TON DNS is implemented by means of a tree of special (DNS) smart contracts. Each DNS smart contract is responsible for registering subdomains of some fixed domain. The "root" DNS smart contract, where level one domains of the TON DNS system will be kept, is located in the masterchain. Its account identifier must be hardcoded into all software that wishes to access the TON DNS database directly.
Any DNS smart contract contains a hashmap, mapping variable-length null-terminated UTF-8 strings into their "values". This hashmap is implemented as a binary Patricia tree, similar to that described in [2.3.7](#2-3-7-definition-of-hashmap-type-as-a-patricia-tree) but supporting variable-length bitstrings as keys.
#### 4.3.4. Values of the DNS hashmap, or TON DNS records [#434-values-of-the-dns-hashmap-or-ton-dns-records]
As to the values, they are "TON DNS records" described by a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)). They consist of a "magic number", selecting one of the options supported, and then either an account identifier, or a smart-contract identifier, or an abstract network address (cf. [3.1](#3-1-abstract-datagram-network-layer)), or a public key used to locate abstract addresses of a service (cf. [3.2.12](#3-2-12-locating-services)), or a description of an overlay network, and so on. An important case is that of another DNS smart contract: in such a case, that smart contract is used to resolve subdomains of its domain. In this way, one can create separate registries for different domains, controlled by the owners of those domains.
These records may also contain an expiration time, a caching time (usually very large, because updating values in a blockchain too often is expensive), and in most cases a reference to the owner of the subdomain in question. The owner has the right to change this record (in particular, the owner field, thus transferring the domain to somebody else's control), and to prolong it.
#### 4.3.5. Registering new subdomains of existing domains [#435-registering-new-subdomains-of-existing-domains]
In order to register a new subdomain of an existing domain, one simply sends a message to the smart contract, which is the registrar of that domain, containing the subdomain (i.e., the key) to be registered, the value in one of several predefined formats, an identity of the owner, an expiration date, and some amount of cryptocurrency as determined by the domain's owner.
Subdomains are registered on a "first-come, first-served" basis.
#### 4.3.6. Retrieving data from a DNS smart contract [#436-retrieving-data-from-a-dns-smart-contract]
In principle, any full node for the masterchain or shardchain containing a DNS smart contract might be able to look up any subdomain in the database of that smart contract, if the structure and the location of the hashmap inside the persistent storage of the smart contract are known.
However, this approach would work only for certain DNS smart contracts. It would fail miserably if a non-standard DNS smart contract were used.
Instead, an approach based on *general smart contract interfaces and get methods* ([cf. 4.3.11](#4-3-11-get-methods-of-smart-contracts)) is used. Any DNS smart contract must define a get method with a known signature, which is invoked to look up a key. Since this approach makes sense for other smart contracts as well, especially those providing on-chain and mixed services, we explain it in some detail in [4.3.11](#4-3-11-get-methods-of-smart-contracts).
#### 4.3.7. Translating a TON DNS domain [#437-translating-a-ton-dns-domain]
Once any full node, acting by itself or on behalf of some light client, can look up entries in the database of any DNS smart contract, arbitrary TON DNS domain names can be recursively translated, starting from the well-known and fixed root DNS smart contract (account) identifier.
For example, if one wants to translate `A.B.C`, one looks up keys `.C`, `.B.C`, and `A.B.C` in the root domain database. If the first of them is not found, but the second is, and its value is a reference to another DNS smart contract, then `A` is looked up in the database of that smart contract and the final value is retrieved.
#### 4.3.8. Translating TON DNS domains for light nodes [#438-translating-ton-dns-domains-for-light-nodes]
In this way, a full node for the masterchain—and also for all shardchains involved in the domain look-up process—might translate any domain name into its current value without external help. A light node might request a full node to do this on its behalf and return the value, along with a Merkle proof (cf. [2.5.11](#2-5-11-merkle-proofs-as-query-responses-from-full-nodes)). This Merkle proof would enable the light node to verify that the answer is correct, so such TON DNS responses cannot be "spoofed" by a malicious interceptor, in contrast to the usual DNS protocol.
Because no node can be expected to be a full node with respect to all shardchains, actual TON DNS domain translation would involve a combination of these two strategies.
#### 4.3.9. Dedicated "TON DNS servers" [#439-dedicated-ton-dns-servers]
One might provide a simple "TON DNS server", which would receive RPC "DNS" queries (e.g., via the ADNL or RLDP protocols described in [3.1](#3-1-abstract-datagram-network-layer)), requesting that the server translate a given domain, process these queries by forwarding some subqueries to other (full) nodes if necessary, and return answers to the original queries, augmented by Merkle proofs if required.
Such "DNS servers" might offer their services (for free or not) to any other nodes and especially light clients, using one of the methods described in [4.2](#4-2-connecting-users-and-service-providers). Notice that these servers, if considered part of the TON DNS service, would effectively transform it from a distributed on-chain service into a distributed mixed service (i.e., a "fog service").
This concludes our brief overview of the TON DNS service, a scalable on-chain registry for human-readable domain names of TON Blockchain and TON Network entities.
#### 4.3.10. Accessing data kept in smart contracts [#4310-accessing-data-kept-in-smart-contracts]
We have already seen that it is sometimes necessary to access data stored in a smart contract without changing its state.
If one knows the details of the smart-contract implementation, one can extract all the needed information from the smart contract's persistent storage, available to all full nodes of the shardchain the smart contract resides in. However, this is quite an inelegant way of doing things, depending very much on the smart-contract implementation.
#### 4.3.11. "Get methods" of smart contracts [#4311-get-methods-of-smart-contracts]
A better way would be to define some *get methods* in the smart contract, that is, some types of inbound messages that do not affect the state of the smart contract when delivered, but generate one or more output messages containing the "result" of the get method. In this way, one can obtain data from a smart contract, knowing only that it implements a get method with a known signature (i.e., a known format of the inbound message to be sent and outbound messages to be received as a result).
This way is much more elegant and in line with object oriented programming (OOP). However, it has an obvious defect so far: one must actually commit a transaction into the blockchain (sending the get message to the smart contract), wait until it is committed and processed by the validators, extract the answer from a new block, and pay for gas (i.e., for executing the get method on the validators' hardware). This is a waste of resources: get methods do not change the state of the smart contract anyways, so they need not be executed in the blockchain.
#### 4.3.12. Tentative execution of get methods of smart contracts [#4312-tentative-execution-of-get-methods-of-smart-contracts]
We have already remarked (cf. [2.4.6](#2-4-6-external-messages-or-messages-from-nowhere)) that any full node can tentatively execute any method of any smart contract (i.e., deliver any message to a smart contract), starting from a given state of the smart contract, without actually committing the corresponding transaction. The full node can simply load the code of the smart contract under consideration into the TON VM, initialize its persistent storage from the global state of the shardchain (known to all full nodes of the shardchain), and execute the smart-contract code with the inbound message as its input parameter. The output messages created will yield the result of this computation.
In this way, any full node can evaluate arbitrary get methods of arbitrary smart contracts, provided their signature (i.e., the format of inbound and outbound messages) is known. The node may keep track of the cells of the shardchain state accessed during this evaluation, and create a Merkle proof of the validity of the computation performed, for the benefit of a light node that might have asked the full node to do so (cf. [2.5.11](#2-5-11-merkle-proofs-as-query-responses-from-full-nodes)).
#### 4.3.13. Smart-contract interfaces in TL-schemes [#4313-smart-contract-interfaces-in-tl-schemes]
Recall that the methods implemented by a smart contract (i.e., the input messages accepted by it) are essentially some TL-serialized objects, which can be described by a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)). The resulting output messages can be described by the same TL-scheme as well. In this way, the interface provided by a smart contract to other accounts and smart contracts may be formalized by means of a TL-scheme.
In particular, (a subset of) get methods supported by a smart contract can be described by such a formalized smart-contract interface.
#### 4.3.14. Public interfaces of a smart contract [#4314-public-interfaces-of-a-smart-contract]
Notice that a formalized smart-contract interface, either in form of a TL-scheme (represented as a TL source file; cf. [2.2.5](#2-2-5-tl-or-the-type-language)) or in serialized form,[36](#fn36) can be published—for example, in a special field in the smart-contract account description, stored in the blockchain, or separately, if this interface will be referred to many times. In the latter case a hash of the supported public interface may be incorporated into the smart-contract description instead of the interface description itself.
An example of such a public interface is that of a DNS smart contract, which is supposed to implement at least one standard get method for looking up subdomains (cf. [4.3.6](#4-3-6-retrieving-data-from-a-dns-smart-contract)). A standard method for registering new subdomains can be also included in the standard public interface of DNS smart contracts.
#### 4.3.15. User interface of a smart contract [#4315-user-interface-of-a-smart-contract]
The existence of a public interface for a smart contract has other benefits, too. For example, a wallet client application may download such an interface while examining a smart contract on the request of a user, and display a list of public methods (i.e., of available actions) supported by the smart contract, perhaps with some human-readable comments if any are provided in the formal interface. After the user selects one of these methods, a form may be automatically generated according to the TL-scheme, where the user will be prompted for all fields required by the chosen method and for the desired amount of cryptocurrency (e.g., Grams) to be attached to this request. Submitting this form will create a new blockchain transaction containing the message just composed, sent from the user's blockchain account.
In this way, the user will be able to interact with arbitrary smart contracts from the wallet client application in a user-friendly way by filling and submitting certain forms, provided these smart contracts have published their interfaces.
#### 4.3.16. User interface of a "ton-service" [#4316-user-interface-of-a-ton-service]
It turns out that ton-services (i.e., services residing in the TON Network and accepting queries through the ADNL and RLDP protocols of [3](#3-ton-networking); [cf. 4.1.5](#4-1-5-pure-network-services%3A-ton-sites-and-ton-services)) may also profit from having public interfaces, described by TL-schemes ([cf. 2.2.5](#2-2-5-tl%2C-or-the-type-language)). A client application, such as a light wallet or a ton-browser, might prompt the user to select one of the methods and to fill in a form with parameters defined by the interface, similarly to what has just been discussed in [4.3.15](#4-3-15-user-interface-of-a-smart-contract). The only difference is that the resulting TL-serialized message is not submitted as a transaction in the blockchain; instead, it is sent as an RPC query to the abstract address of the ton-service in question, and the response to this query is parsed and displayed according to the formal interface (i.e., a TL-scheme).
#### 4.3.17. Locating user interfaces via TON DNS [#4317-locating-user-interfaces-via-ton-dns]
The TON DNS record containing an abstract address of a ton-service or a smart-contract account identifier might also contain an optional field describing the public (user) interface of that entity, or several supported interfaces. Then the client application (be it a wallet, a ton-browser or a ton-proxy) will be able to download the interface and interact with the entity in question (be it a smart contract or a ton-service) in a uniform way.
#### 4.3.18. Blurring the distinction between on-chain and off-chain services [#4318-blurring-the-distinction-between-on-chain-and-off-chain-services]
In this way, the distinction between on-chain, off-chain and mixed services (cf. [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed)) is blurred for the end user: she simply enters the domain name of the desired service into the address line of her ton-browser or wallet, and the rest is handled seamlessly by the client application.
#### 4.3.19. A light wallet and TON entity explorer can be built into Telegram Messenger clients [#4319-a-light-wallet-and-ton-entity-explorer-can-be-built-into-telegram-messenger-clients]
An interesting opportunity arises at this point. A light wallet and TON entity explorer, implementing the above functionality, can be embedded into the Telegram Messenger smartphone client application, thus bringing the technology to more than 200 million people. Users would be able to send hyperlinks to TON entities and resources by including TON URIs (cf. [4.3.22](#4-3-22-hyperlink-urls-may-specify-some-parameters)) in messages; such hyperlinks, if selected, will be opened internally by the Telegram client application of the receiving party, and interaction with the chosen entity will begin.
#### 4.3.20. "ton-sites" as ton-services supporting an HTTP interface [#4320-ton-sites-as-ton-services-supporting-an-http-interface]
A *ton-site* is simply a ton-service that supports an HTTP interface, perhaps along with some other interfaces. This support may be announced in the corresponding TON DNS record.
#### 4.3.21. Hyperlinks [#4321-hyperlinks]
Notice that the HTML pages returned by ton-sites may contain *ton-hyperlinks*—that is, references to other ton-sites, smart contracts and accounts by means of specially crafted URI schemes (cf. [4.3.22](#4-3-22-hyperlink-urls-may-specify-some-parameters))—containing either abstract network addresses, account identifiers, or human-readable TON DNS domains. Then a "ton-browser" might follow such a hyperlink when the user selects it, detect the interface to be used, and display a user interface form as outlined in [4.3.15](#4-3-15-user-interface-of-a-smart-contract) and [4.3.16](#4-3-16-user-interface-of-a-ton-service).
#### 4.3.22. Hyperlink URLs may specify some parameters [#4322-hyperlink-urls-may-specify-some-parameters]
The hyperlink URLs may contain not only a (TON) DNS domain or an abstract address of the service in question, but also the name of the method to be invoked and some or all of its parameters. A possible URI scheme for this might look as follows:
```
ton:///?=&=...
```
When the user selects such a link in a ton-browser, either the action is performed immediately (especially if it is a get method of a smart contract, invoked anonymously), or a partially filled form is displayed, to be explicitly confirmed and submitted by the user (this may be required for payment forms).
#### 4.3.23. POST actions [#4323-post-actions]
A ton-site may embed into the HTML pages it returns some usual-looking POST forms, with POST actions referring either to ton-sites, ton-services or smart contracts by means of suitable (TON) URLs. In that case, once the user fills and submits that custom form, the corresponding action is taken, either immediately or after an explicit confirmation.
#### 4.3.24. TON WWW [#4324-ton-www]
All of the above will lead to the creation of a whole web of cross-referencing entities, residing in the TON Network, which would be accessible to the end user through a ton-browser, providing the user with a WWW-like browsing experience. For end users, this will finally make blockchain applications fundamentally similar to the web sites they are already accustomed to.
#### 4.3.25. Advantages of TON WWW [#4325-advantages-of-ton-www]
This "TON WWW" of on-chain and off-chain services has some advantages over its conventional counterpart. For example, payments are inherently integrated in the system. User identity can be always presented to the services (by means of automatically generated signatures on the transactions and RPC requests generated), or hidden at will. Services would not need to check and re-check user credentials; these credentials can be published in the blockchain once and for all. User network anonymity can be easily preserved by means of TON Proxy, and all services will be effectively unblockable. Micropayments are also possible and easy, because ton-browsers can be integrated with the TON Payments system.
***
## 5 TON Payments [#5--ton-payments]
The last component of the TON Project we will briefly discuss in this text is *TON Payments*, the platform for (micro)payment channels and "lightning network" value transfers. It would enable "instant" payments, without the need to commit all transactions into the blockchain, pay the associated transaction fees (e.g., for the gas consumed), and wait five seconds until the block containing the transactions in question is confirmed.
The overall overhead of such instant payments is so small that one can use them for micropayments. For example, a TON file-storing service might charge the user for every 128 KiB of downloaded data, or a paid TON Proxy might require some tiny micropayment for every 128 KiB of traffic relayed.
While *TON Payments* is likely to be released later than the core components of the TON Project, some considerations need to be made at the very beginning. For example, the TON Virtual Machine (TON VM; cf. [2.1.20](#2-1-20-ton-virtual-machine)), used to execute the code of TON Blockchain smart contracts, must support some special operations with Merkle proofs. If such support is not present in the original design, adding it at a later stage might become problematic (cf. [2.8.16](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)). We will see, however, that the TON VM comes with natural support for "smart" payment channels (cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels)) out of the box.
### 5.1 Payment Channels [#51--payment-channels]
We start with a discussion of point-to-point payment channels, and how they can be implemented in the TON Blockchain.
#### 5.1.1. The idea of a payment channel [#511-the-idea-of-a-payment-channel]
Suppose two parties, $A$ and $B$, know that they will need to make a lot of payments to each other in the future. Instead of committing each payment as a transaction in the blockchain, they create a shared "money pool" (or perhaps a small private bank with exactly two accounts), and contribute some funds to it: $A$ contributes $a$ coins, and $B$ contributes $b$ coins. This is achieved by creating a special smart contract in the blockchain, and sending the money to it.
Before creating the "money pool", the two sides agree to a certain protocol. They will keep track of the *state* of the pool—that is, of their balances in the shared pool. Originally, the state is $(a,b)$, meaning that $a$ coins actually belong to $A$, and $b$ coins belong to $B$. Then, if $A$ wants to pay $d$ coins to $B$, they can simply agree that the new state is $(a',b')=(a-d,b+d)$. Afterwards, if, say, $B$ wants to pay $d'$ coins to $A$, the state will become $(a'',b'')=(a'+d',b'-d')$, and so on.
All this updating of balances inside the pool is done completely off-chain. When the two parties decide to withdraw their due funds from the pool, they do so according to the final state of the pool. This is achieved by sending a special message to the smart contract, containing the agreed-upon final state $(a^*,b^*)$ along with the signatures of both $A$ and $B$. Then the smart contract sends $a^*$ coins to $A$, $b^*$ coins to $B$ and self-destructs.
This smart contract, along with the network protocol used by $A$ and $B$ to update the state of the pool, is a simple *payment channel between $A$ and $B$.* According to the classification described in [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed), it is a *mixed* service: part of its state resides in the blockchain (the smart contract), but most of its state updates are performed off-chain (by the network protocol). If everything goes well, the two parties will be able to perform as many payments to each other as they want (with the only restriction being that the "capacity" of the channel is not overrun—i.e., their balances in the payment channel both remain non-negative), committing only two transactions into the blockchain: one to open (create) the payment channel (smart contract), and another to close (destroy) it.
#### 5.1.2. Trustless payment channels [#512-trustless-payment-channels]
The previous example was somewhat unrealistic, because it assumes that both parties are willing to cooperate and will never cheat to gain some advantage. Imagine, for example, that $A$ will choose not to sign the final balance $(a',b')$ with $a'b$)—then the other party may submit proof of this misbehavior to a third method of the smart contract. The guilty party is punished immediately by losing its share in the payment channel completely.
This simple payment channel protocol is *fair* in the sense that any party can always get its due, with or without the cooperation of the other party, and is likely to lose all of its funds committed to the payment channel if it tries to cheat.
#### 5.1.4. Synchronous payment channel as a simple virtual blockchain with two validators [#514-synchronous-payment-channel-as-a-simple-virtual-blockchain-with-two-validators]
The above example of a simple synchronous payment channel can be recast as follows. Imagine that the sequence of states $S_0$, $S_1$, ..., $S_n$ is actually the sequence of blocks of a very simple blockchain. Each block of this blockchain contains essentially only the current state of the blockchain, and maybe a reference to the previous block (i.e., its hash). Both parties $A$ and $B$ act as validators for this blockchain, so every block must collect both of their signatures. The state $S_i$ of the blockchain defines the designated producer $o_i$ for the next block, so there is no race between $A$ and $B$ for producing the next block. Producer $A$ is allowed to create blocks that transfer funds from $A$ to $B$ (i.e., decrease the imbalance: $\delta_{i+1}\leq\delta_i$), and $B$ can only transfer funds from $B$ to $A$ (i.e., increase $\delta$).
If the two validators agree on the final block (and the final state) of the blockchain, it is finalized by collecting special "final" signatures of the two parties, and submitting them along with the final block to the channel smart contract for processing and re-distributing the money accordingly.
If a validator signs an invalid block, or creates a fork, or signs two different final blocks, it can be punished by presenting a proof of its misbehavior to the smart contract, which acts as an "on-chain arbiter" for the two validators; then the offending party will lose all its money kept in the payment channel, which is analogous to a validator losing its stake.
#### 5.1.5. Asynchronous payment channel as a virtual blockchain with two workchains [#515-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains]
The synchronous payment channel discussed in [5.1.3](#5-1-3-simple-bidirectional-synchronous-trustless-payment-channel) has a certain disadvantage: one cannot begin the next transaction (money transfer inside the payment channel) before the previous one is confirmed by the other party. This can be fixed by replacing the single virtual blockchain discussed in [5.1.4](#5-1-4-synchronous-payment-channel-as-a-simple-virtual-blockchain-with-two-validators) by a system of two interacting virtual workchains (or rather shardchains).
The first of these workchains contains only transactions by $A$, and its blocks can be generated only by $A$; its states are $S_i=(i,\phi_i,j,\psi_j)$, where $i$ is the block sequence number (i.e., the count of transactions, or money transfers, performed by $A$ so far), $\phi_i$ is the total amount transferred from $A$ to $B$ so far, $j$ is the sequence number of the most recent valid block in $B$'s blockchain that $A$ is aware of, and $\psi_j$ is the amount of money transferred from $B$ to $A$ in its $j$ transactions. A signature of $B$ put onto its $j$-th block should also be a part of this state. Hashes of the previous block of this workchain and of the $j$-th block of the other workchain may be also included. Validity conditions for $S_i$ include $\phi_i\geq 0$, $\phi_i\geq\phi_{i-1}$ if $i>0$, $\psi_j\geq0$, and $-a\leq\psi_j-\phi_i\leq b$.
Similarly, the second workchain contains only transactions by $B$, and its blocks are generated only by $B$; its states are $T_j=(j,\psi_j,i,\phi_i)$, with similar validity conditions.
Now, if $A$ wants to transfer some money to $B$, it simply creates a new block in its workchain, signs it, and sends to $B$, without waiting for confirmation.
The payment channel is finalized by $A$ signing (its version of) the final state of its blockchain (with its special "final signature"), $B$ signing the final state of its blockchain, and presenting these two final states to the clean finalization method of the payment channel smart contract. Unilateral finalization is also possible, but in that case the smart contract will have to wait for the other party to present its version of the final state, at least for some grace period.
#### 5.1.6. Unidirectional payment channels [#516-unidirectional-payment-channels]
If only $A$ needs to make payments to $B$ (e.g., $B$ is a service provider, and $A$ its client), then a unilateral payment channel can be created. Essentially, it is just the first workchain described in [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) without the second one. Conversely, one can say that the asynchronous payment channel described in [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) consists of two unidirectional payment channels, or "half-channels", managed by the same smart contract.
#### 5.1.7. More sophisticated payment channels. Promises [#517-more-sophisticated-payment-channels-promises]
We will see later in [5.2.4](#5-2-4-chain-money-transfers) that the "lightning network" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), which enables instant money transfers through chains of several payment channels, requires higher degrees of sophistication from the payment channels involved.
In particular, we want to be able to commit "promises", or "conditional money transfers": $A$ agrees to send $c$ coins to $B$, but $B$ will get the money only if a certain condition is fulfilled, for instance, if $B$ can present some string $u$ with $\text{Hash}(u)=v$ for a known value of $v$. Otherwise, $A$ can get the money back after a certain period of time.
Such a promise could easily be implemented on-chain by a simple smart contract. However, we want promises and other kinds of conditional money transfers to be possible off-chain, in the payment channel, because they considerably simplify money transfers along a chain of payment channels existing in the "lightning network" (cf. [5.2.4](#5-2-4-chain-money-transfers)).
The "payment channel as a simple blockchain" picture outlined in [5.1.4](#5-1-4-synchronous-payment-channel-as-a-simple-virtual-blockchain-with-two-validators) and [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) becomes convenient here. Now we consider a more complicated virtual blockchain, the state of which contains a set of such unfulfilled "promises", and the amount of funds locked in such promises. This blockchain—or the two workchains in the asynchronous case—will have to refer explicitly to the previous blocks by their hashes. Nevertheless, the general mechanism remains the same.
#### 5.1.8. Challenges for the sophisticated payment channel smart contracts [#518-challenges-for-the-sophisticated-payment-channel-smart-contracts]
Notice that, while the final state of a sophisticated payment channel is still small, and the "clean" finalization is simple (if the two sides have agreed on their amounts due, and both have signed their agreement, nothing else remains to be done), the unilateral finalization method and the method for punishing fraudulent behavior need to be more complex. Indeed, they must be able to accept Merkle proofs of misbehavior, and to check whether the more sophisticated transactions of the payment channel blockchain have been processed correctly.
In other words, the payment channel smart contract must be able to work with Merkle proofs, to check their "hash validity", and must contain an implementation of $\mathit{ev\_trans}$ and $\mathit{ev\_block}$ functions (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) for the payment channel (virtual) blockchain.
#### 5.1.9. TON VM support for "smart" payment channels [#519-ton-vm-support-for-smart-payment-channels]
The TON VM, used to run the code of TON Blockchain smart contracts, is up to the challenge of executing the smart contracts required for "smart", or sophisticated, payment channels (cf. [5.1.8](#5-1-8-challenges-for-the-sophisticated-payment-channel-smart-contracts)).
At this point the "everything is a bag of cells" paradigm ([cf. 2.5.14](#2-5-14-everything-is-a-bag-of-cells-philosophy)) becomes extremely convenient. Since all blocks (including the blocks of the ephemeral payment channel blockchain) are represented as bags of cells (and described by some algebraic data types), and the same holds for messages and Merkle proofs as well, a Merkle proof can easily be embedded into an inbound message sent to the payment channel smart contract. The "hash condition" of the Merkle proof will be checked automatically, and when the smart contract accesses the "Merkle proof" presented, it will work with it as if it were a value of the corresponding algebraic data type—albeit incomplete, with some subtrees of the tree replaced by special nodes containing the Merkle hash of the omitted subtree. Then the smart contract will work with that value, which might represent, for instance, a block of the payment channel (virtual) blockchain along with its state, and will evaluate the $\mathit{ev\_block}$ function (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) of that blockchain on this block and the previous state. Then either the computation finishes, and the final state can be compared with that asserted in the block, or an "absent node" exception is thrown while attempting to access an absent subtree, indicating that the Merkle proof is invalid.
In this way, the implementation of the verification code for smart payment channel blockchains turns out to be quite straightforward using TON Blockchain smart contracts. One might say that *the TON Virtual Machine comes with built-in support for checking the validity of other simple blockchains.* The only limiting factor is the size of the Merkle proof to be incorporated into the inbound message to the smart contract (i.e., into the transaction).
#### 5.1.10. Simple payment channel within a smart payment channel [#5110-simple-payment-channel-within-a-smart-payment-channel]
We would like to discuss the possibility of creating a simple (synchronous or asynchronous) payment channel inside an existing payment channel.
While this may seem somewhat convoluted, it is not much harder to understand and implement than the "promises" discussed in [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises). Essentially, instead of promising to pay $c$ coins to the other party if a solution to some hash problem is presented, $A$ promises to pay up to $c$ coins to $B$ according to the final settlement of some other (virtual) payment channel blockchain. Generally speaking, this other payment channel blockchain need not even be between $A$ and $B$; it might involve some other parties, say, $C$ and $D$, willing to commit $c$ and $d$ coins into their simple payment channel, respectively. (This possibility is exploited later in [5.2.5](#5-2-5-virtual-payment-channels-inside-a-chain-of-payment-channels).)
If the encompassing payment channel is asymmetric, two promises need to be committed into the two workchains: $A$ will promise to pay $-\delta$ coins to $B$ if the final settlement of the "internal" simple payment channel yields a negative final imbalance $\delta$ with $0\leq-\delta\leq c$; and $B$ will have to promise to pay $\delta$ to $A$ if $\delta$ is positive. On the other hand, if the encompassing payment channel is symmetric, this can be done by committing a single "simple payment channel creation" transaction with parameters $(c,d)$ into the single payment channel blockchain by $A$ (which would freeze $c$ coins belonging to $A$), and then committing a special "confirmation transaction" by $B$ (which would freeze $d$ coins of $B$).
We expect the internal payment channel to be extremely simple (e.g., the simple synchronous payment channel discussed in [5.1.3](#5-1-3-simple-bidirectional-synchronous-trustless-payment-channel)), to minimize the size of Merkle proofs to be submitted. The external payment channel will have to be "smart" in the sense described in [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises).
### 5.2 Payment Channel Network, or "Lightning Network" [#52--payment-channel-network-or-lightning-network]
Now we are ready to discuss the "lightning network" of TON Payments that enables instant money transfers between any two participating nodes.
#### 5.2.1. Limitations of payment channels [#521-limitations-of-payment-channels]
A payment channel is useful for parties who expect a lot of money transfers between them. However, if one needs to transfer money only once or twice to a particular recipient, creating a payment channel with her would be impractical. Among other things, this would imply freezing a significant amount of money in the payment channel, and would require at least two blockchain transactions anyway.
#### 5.2.2. Payment channel networks, or "lightning networks" [#522-payment-channel-networks-or-lightning-networks]
Payment channel networks overcome the limitations of payment channels by enabling money transfers along *chains* of payment channels. If $A$ wants to transfer money to $E$, she does not need to establish a payment channel with $E$. It would be sufficient to have a chain of payment channels linking $A$ with $E$ through several intermediate nodes—say, four payment channels: from $A$ to $B$, from $B$ to $C$, from $C$ to $D$ and from $D$ to $E$.
#### 5.2.3. Overview of payment channel networks [#523-overview-of-payment-channel-networks]
Recall that a *payment channel network*, known also as a "lightning network", consists of a collection of participating nodes, some of which have established long-lived payment channels between them. We will see in a moment that these payment channels will have to be "smart" in the sense of [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises). When a participating node $A$ wants to transfer money to any other participating node $E$, she tries to find a path linking $A$ to $E$ inside the payment channel network. When such a path is found, she performs a "chain money transfer" along this path.
#### 5.2.4. Chain money transfers [#524-chain-money-transfers]
Suppose that there is a chain of payment channels from $A$ to $B$, from $B$ to $C$, from $C$ to $D$, and from $D$ to $E$. Suppose, further, that $A$ wants to transfer $x$ coins to $E$.
A simplistic approach would be to transfer $x$ coins to $B$ along the existing payment channel, and ask him to forward the money further to $C$. However, it is not evident why $B$ would not simply take the money for himself. Therefore, one must employ a more sophisticated approach, not requiring all parties involved to trust each other.
This can be achieved as follows. $A$ generates a large random number $u$ and computes its hash $v=\text{Hash}(u)$. Then she creates a promise to pay $x$ coins to $B$ if a number $u$ with hash $v$ is presented (cf. [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises)), inside her payment channel with $B$. This promise contains $v$, but not $u$, which is still kept secret.
After that, $B$ creates a similar promise to $C$ in their payment channel. He is not afraid to give such a promise, because he is aware of the existence of a similar promise given to him by $A$. If $C$ ever presents a solution of the hash problem to collect $x$ coins promised by $B$, then $B$ will immediately submit this solution to $A$ to collect $x$ coins from $A$.
Then similar promises of $C$ to $D$ and of $D$ to $E$ are created. When the promises are all in place, $A$ triggers the transfer by communicating the solution $u$ to all parties involved—or just to $E$.
Some minor details are omitted in this description. For example, these promises must have different expiration times, and the amount promised might slightly differ along the chain ($B$ might promise only $x-\epsilon$ coins to $C$, where $\epsilon$ is a small pre-agreed transit fee). We ignore such details for the time being, because they are not too relevant for understanding how payment channels work and how they can be implemented in TON.
#### 5.2.5. Virtual payment channels inside a chain of payment channels [#525-virtual-payment-channels-inside-a-chain-of-payment-channels]
Now suppose that $A$ and $E$ expect to make a lot of payments to each other. They might create a new payment channel between them in the blockchain, but this would still be quite expensive, because some funds would be locked in this payment channel. Another option would be to use chain money transfers described in [5.2.4](#5-2-4-chain-money-transfers) for each payment. However, this would involve a lot of network activity and a lot of transactions in the virtual blockchains of all payment channels involved.
An alternative is to create a virtual payment channel inside the chain linking $A$ to $E$ in the payment channel network. For this, $A$ and $E$ create a (virtual) blockchain for their payments, as if they were going to create a payment channel in the blockchain. However, instead of creating a payment channel smart contract in the blockchain, they ask all intermediate payment channels—those linking $A$ to $B$, $B$ to $C$, etc.—to create simple payment channels inside them, bound to the virtual blockchain created by $A$ and $E$ (cf. [5.1.10](#5-1-10-simple-payment-channel-within-a-smart-payment-channel)). In other words, now a promise to transfer money according to the final settlement between $A$ and $E$ exists inside every intermediate payment channel.
If the virtual payment channel is unidirectional, such promises can be implemented quite easily, because the final imbalance $\delta$ is going to be non-positive, so simple payment channels can be created inside intermediate payment channels in the same order as described in [5.2.4](#5-2-4-chain-money-transfers). Their expiration times can also be set in the same way.
If the virtual payment channel is bidirectional, the situation is slightly more complicated. In that case, one should split the promise to transfer $\delta$ coins according to the final settlement into two half-promises, as explained in [5.1.10](#5-1-10-simple-payment-channel-within-a-smart-payment-channel): to transfer $\delta^-=\max(0,-\delta)$ coins in the forward direction, and to transfer $\delta^+=\max(0,\delta)$ in the backward direction. These half-promises can be created in the intermediate payment channels independently, one chain of half-promises in the direction from $A$ to $E$, and the other chain in the opposite direction.
#### 5.2.6. Finding paths in the lightning network [#526-finding-paths-in-the-lightning-network]
One point remains undiscussed so far: how will $A$ and $E$ find a path connecting them in the payment network? If the payment network is not too large, an OSPF-like protocol can be used: all nodes of the payment network create an overlay network (cf. [3.3.17](#3-3-17-overlay-networks-within-overlay-networks)), and then every node propagates all available link (i.e., participating payment channel) information to its neighbors by a gossip protocol. Ultimately, all nodes will have a complete list of all payment channels participating in the payment network, and will be able to find the shortest paths by themselves—for example, by applying a version of Dijkstra's algorithm modified to take into account the "capacities" of the payment channels involved (i.e., the maximal amounts that can be transferred along them). Once a candidate path is found, it can be probed by a special ADNL datagram containing the full path, and asking each intermediate node to confirm the existence of the payment channel in question, and to forward this datagram further according to the path. After that, a chain can be constructed, and a protocol for chain transfers (cf. [5.2.4](#5-2-4-chain-money-transfers)), or for creating a virtual payment channel inside a chain of payment channels (cf. [5.2.5](#5-2-5-virtual-payment-channels-inside-a-chain-of-payment-channels)), can be run.
#### 5.2.7. Optimizations [#527-optimizations]
Some optimizations might be done here. For example, only transit nodes of the lightning network need to participate in the OSPF-like protocol discussed in [5.2.6](#5-2-6-finding-paths-in-the-lightning-network). Two "leaf" nodes wishing to connect through the lightning network would communicate to each other the lists of transit nodes they are connected to (i.e., with which they have established payment channels). Then paths connecting transit nodes from one list to transit nodes from the other list can be inspected as outlined above in [5.2.6](#5-2-6-finding-paths-in-the-lightning-network).
#### 5.2.8. Conclusion [#528-conclusion]
We have outlined how the blockchain and network technologies of the TON project are adequate to the task of creating *TON Payments*, a platform for off-chain instant money transfers and micropayments. This platform can be extremely useful for services residing in the TON ecosystem, allowing them to easily collect micropayments when and where required.
## Conclusion [#conclusion]
We have proposed a scalable multi-blockchain architecture capable of supporting a massively popular cryptocurrency and decentralized applications with user-friendly interfaces.
To achieve the necessary scalability, we proposed the *TON Blockchain*, a "tightly-coupled" multi-blockchain system (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)) with bottom-up approach to sharding (cf. [2.8.12](#2-8-12-sharding-support) and [2.1.2](#2-1-2-infinite-sharding-paradigm)). To further increase potential performance, we introduced the 2-blockchain mechanism for replacing invalid blocks (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)) and Instant Hypercube Routing for faster communication between shards (cf. [2.4.20](#2-4-20-instant-hypercube-routing-fast-path-for-messages)). A brief comparison of the TON Blockchain to existing and proposed blockchain projects (cf. [2.8](#2-8-classification-of-blockchain-projects) and [2.9](#2-9-comparison-to-other-blockchain-projects)) highlights the benefits of this approach for systems that seek to handle millions of transactions per second.
The *TON Network*, described in Chapter [3](#3-ton-networking), covers the networking demands of the proposed multi-blockchain infrastructure. This network component may also be used in combination with the blockchain to create a wide spectrum of applications and services, impossible using the blockchain alone (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)). These services, discussed in Chapter [4](#4-ton-services-and-applications), include *TON DNS*, a service for translating human-readable object identifiers into their addresses; *TON Storage*, a distributed platform for storing arbitrary files; *TON Proxy*, a service for anonymizing network access and accessing TON-powered services; and *TON Payments* (cf. Chapter [5](#5-ton-payments)), a platform for instant off-chain money transfers across the TON ecosystem that applications may use for micropayments.
The TON infrastructure allows for specialized light client wallet and "ton-browser" desktop and smartphone applications that enable a browser-like experience for the end user (cf. [4.3.24](#4-3-24-ton-www)), making cryptocurrency payments and interaction with smart contracts and other services on the TON Platform accessible to the mass user. Such a light client can be integrated into the Telegram Messenger client (cf. [4.3.19](#4-3-19-a-light-wallet-and-ton-entity-explorer-can-be-built-into-telegram-messenger-clients)), thus eventually bringing a wealth of blockchain-based applications to hundreds of millions of users.
***
## A The TON Coin, or the Gram [#a--the-ton-coin-or-the-gram]
The principal cryptocurrency of the TON Blockchain, and in particular of its masterchain and basic workchain, is the *TON Coin*, also known as the *Gram* (GRM). It is used to make deposits required to become a validator; transaction fees, gas payments (i.e., smart-contract message processing fees) and persistent storage payments are also usually collected in Grams.
### A.1. Subdivision and terminology [#a1-subdivision-and-terminology]
A *Gram* is subdivided into one billion ($10^9$) smaller units, called *nanograms*, *ngrams* or simply *nanos*. All transfers and account balances are expressed as non-negative integer multiples of nanos. Other units include:
* A *nano*, *ngram* or *nanogram* is the smallest unit, equal to $10^{-9}$ Grams.
* A *micro* or *microgram* equals one thousand ($10^3$) nanos.
* A *milli* is one million ($10^6$) nanos, or one thousandth part ($10^{-3}$) of a Gram.
* A *Gram* equals one billion ($10^9$) nanos.
* A *kilogram*, or *kGram*, equals one thousand ($10^3$) Grams.
* A *megagram*, or *MGram*, equals one million ($10^6$) Grams, or $10^{15}$ nanos.
* Finally, a *gigagram*, or *GGram*, equals one billion ($10^9$) Grams, or $10^{18}$ nanos.
There will be no need for larger units, because the initial supply of Grams will be limited to five billion ($5\cdot10^9$) Grams (i.e., 5 Gigagrams).
### A.2. Smaller units for expressing gas prices [#a2-smaller-units-for-expressing-gas-prices]
If the necessity for smaller units arises, "specks" equal to $2^{-16}$ nanograms will be used. For example, gas prices may be indicated in specks. However, the actual fee to be paid, computed as the product of the gas price and the amount of gas consumed, will be always rounded down to the nearest multiple of $2^{16}$ specks and expressed as an integer number of nanos.
### A.3. Original supply, mining rewards and inflation [#a3-original-supply-mining-rewards-and-inflation]
The total supply of Grams is originally limited to $5$ Gigagrams (i.e., five billion Grams or $5\cdot10^{18}$ nanos).
This supply will increase very slowly, as rewards to validators for mining new masterchain and shardchain blocks accumulate. These rewards would amount to approximately $20\%$ (the exact number may be adjusted in future) of the validator's stake per year, provided the validator diligently performs its duties, signs all blocks, never goes offline and never signs invalid blocks. In this way, the validators will have enough profit to invest into better and faster hardware needed to process the ever growing quantity of users' transactions.
We expect that at most $10\%$[37](#fn37) of the total supply of Grams, on average, will be bound in validator stakes at any given moment. This will produce an inflation rate of $2\%$ per year, and as a result, will double the total supply of Grams (to ten Gigagrams) in 35 years. Essentially, this inflation represents a payment made by all members of the community to the validators for keeping the system up and running.
On the other hand, if a validator is caught misbehaving, a part or all of its stake will be taken away as a punishment, and a larger portion of it will subsequently be "burned", decreasing the total supply of Grams. This would lead to deflation. A smaller portion of the fine may be redistributed to the validator or the "fisherman" who committed a proof of the guilty validator's misbehavior.
### A.4. Original price of Grams [#a4-original-price-of-grams]
The price of the first Gram to be sold will equal approximately \$0.1 USD. Every subsequent Gram to be sold (by the TON Reserve, controlled by the TON Foundation) will be priced one billionth higher than the previous one. In this way, the $n$-th Gram to be put into circulation will be sold at approximately:
$$
p(n) \approx 0.1 \cdot (1 + 10^{-9})^n \quad \text{USD} \tag{26}
$$
or an approximately equivalent (because of quickly changing market exchange rates) amount of other (crypto)currencies, such as BTC or ETH.
#### A.4.1. Exponentially priced cryptocurrencies [#a41-exponentially-priced-cryptocurrencies]
We say that the Gram is an *exponentially priced cryptocurrency*, meaning that the price of the $n$-th Gram to be put into circulation is approximately $p(n)$ given by the formula
$$
p(n)=p_0\cdot e^{\alpha n} \tag{27}
$$
with specific values $p_0=0.1$ USD and $\alpha=10^{-9}$.
More precisely, a small fraction $dn$ of a new coin is worth $p(n)\,dn$ dollars, once $n$ coins are put into circulation. (Here $n$ is not necessarily an integer.)
Other important parameters of such a cryptocurrency include $n$, the total number of coins in circulation, and $N\geq n$, the total number of coins that can exist. For the Gram, $N=5\cdot 10^9$.
#### A.4.2. Total price of first $n$ coins [#a42-total-price-of-first-n-coins]
The total price $T(n)=\int_0^n p(n)\,dn\approx p(0)+p(1)+\cdots+p(n-1)$ of the first $n$ coins of an exponentially priced cryptocurrency (e.g., the Gram) to be put into circulation can be computed by
$$
T(n)=p_0\cdot\alpha^{-1}(e^{\alpha n}-1) \tag{28}
$$
#### A.4.3. Total price of next $\Delta n$ coins [#a43-total-price-of-next-delta-n-coins]
The total price $T(n+\Delta n)-T(n)$ of $\Delta n$ coins put into circulation after $n$ previously existing coins can be computed by
$$
T(n+\Delta n)-T(n)=p_0\cdot\alpha^{-1}(e^{\alpha(n+\Delta n)}-e^{\alpha n})=p(n)\cdot\alpha^{-1}(e^{\alpha\,\Delta n}-1) \quad (29)
$$
#### A.4.4. Buying next coins with total value $T$ [#a44-buying-next-coins-with-total-value-t]
Suppose that $n$ coins have already been put into circulation, and that one wants to spend $T$ (dollars) on buying new coins. The quantity of newly-obtained coins $\Delta n$ can be computed by putting $T(n+\Delta n)-T(n)=T$ into the ([29](#a-4-3-total-price-of-next-coins)), yielding
$$
\Delta n=\alpha^{-1}\log\left(1+\frac{T\cdot\alpha}{p(n)}\right) \tag{30}
$$
Of course, if $T\lll p(n)\alpha^{-1}$, then $\Delta n\approx T/p(n)$.
#### A.4.5. Market price of Grams [#a45-market-price-of-grams]
Of course, if the free market price falls below $p(n):=0.1\cdot (1+10^{-9})^n$, once $n$ Grams are put into circulation, nobody would buy new Grams from the TON Reserve; they would choose to buy their Grams on the free market instead, without increasing the total quantity of Grams in circulation. On the other hand, the market price of a Gram cannot become much higher than $p(n)$, otherwise it would make sense to obtain new Grams from the TON Reserve. This means that the market price of Grams would not be subject to sudden spikes (and drops); this is important because stakes (validator deposits) are frozen for at least one month, and gas prices cannot change too fast either. So, the overall economic stability of the system requires some mechanism that would prevent the exchange rate of the Gram from changing too drastically, such as the one described above.
#### A.4.6. Buying back the Grams [#a46-buying-back-the-grams]
If the market price of the Gram falls below $0.5\cdot p(n)$, when there are a total of $n$ Grams in circulation (i.e., not kept on a special account controlled by the TON Reserve), the TON Reserve reserves the right to buy some Grams back and decrease $n$, the total quantity of Grams in circulation. This may be required to prevent sudden falls of the Gram exchange rate.
#### A.4.7. Selling new Grams at a higher price [#a47-selling-new-grams-at-a-higher-price]
The TON Reserve will sell only up to one half (i.e., $2.5\cdot10^9$ Grams) of the total supply of Grams according to the price formula ([26](#a-4-original-price-of-grams)). It reserves the right not to sell any of the remaining Grams at all, or to sell them at a higher price than $p(n)$, but never at a lower price (taking into account the uncertainty of quickly changing exchange rates). The rationale here is that once at least half of all Grams have been sold, the total value of the Gram market will be sufficiently high, and it will be more difficult for outside forces to manipulate the exchange rate than it may be at the very beginning of the Gram's deployment.
### A.5. Using unallocated Grams [#a5-using-unallocated-grams]
The TON Reserve will use the bulk of "unallocated" Grams (approximately $5\cdot10^9-n$ Grams)—i.e., those residing in the special account of the TON Reserve and some other accounts explicitly linked to it—only as validator stakes (because the TON Foundation itself will likely have to provide most of the validators during the first deployment phase of the TON Blockchain), and for voting in the masterchain for or against proposals concerning changes in the "configurable parameters" and other protocol changes, in the way determined by the TON Foundation (i.e., its creators—the development team). This also means that the TON Foundation will have a majority of votes during the first deployment phase of the TON Blockchain, which may be useful if a lot of parameters end up needing to be adjusted, or if the need arises for hard or soft forks. Later, when less than half of all Grams remain under control of the TON Foundation, the system will become more democratic. Hopefully it will have become more mature by then, without the need to adjust parameters too frequently.
#### A.5.1. Some unallocated Grams will be given to developers [#a51-some-unallocated-grams-will-be-given-to-developers]
A predefined (relatively small) quantity of "unallocated" Grams (e.g., 200 Megagrams, equal to 4% of the total supply) will be transferred during the deployment of the TON Blockchain to a special account controlled by the TON Foundation, and then some "rewards" may be paid from this account to the developers of the open source TON software, with a minimum two-year vesting period.
#### A.5.2. The TON Foundation needs Grams for operational purposes [#a52-the-ton-foundation-needs-grams-for-operational-purposes]
Recall that the TON Foundation will receive the fiat and cryptocurrency obtained by selling Grams from the TON Reserve, and will use them for the development and deployment of the TON Project. For instance, the original set of validators, as well as an initial set of TON Storage and TON Proxy nodes may be installed by the TON Foundation.
While this is necessary for the quick start of the project, the ultimate goal is to make the project as decentralized as possible. To this end, the TON Foundation may need to encourage installation of third-party validators and TON Storage and TON Proxy nodes—for example, by paying them for storing old blocks of the TON Blockchain or proxying network traffic of a selected subset of services. Such payments will be made in Grams; therefore, the TON Foundation will need a significant amount of Grams for operational purposes.
#### A.5.3. Taking a pre-arranged amount from the Reserve [#a53-taking-a-pre-arranged-amount-from-the-reserve]
The TON Foundation will transfer to its account a small part of the TON Reserve—say, 10% of all coins (i.e. 500 Megagrams) after the end of the initial sale of Grams—to be used for its own purposes as outlined in [A.5.2](#a-5-2-the-ton-foundation-needs-grams-for-operational-purposes). This is best done simultaneously with the transfer of the funds intended for TON developers, as mentioned in [A.5.1](#a-5-1-some-unallocated-grams-will-be-given-to-developers).
After the transfers to the TON Foundation and the TON developers, the TON Reserve price $p(n)$ of the Gram will immediately rise by a certain amount, known in advance. For example, if 10% of all coins are transferred for the purposes of the TON Foundation, and 4% are transferred for the encouragement of the developers, then the total quantity $n$ of coins in circulation will immediately increase by $\Delta n=7\cdot10^8$, with the price of the Gram multiplying by $e^{\alpha\,\Delta n}=e^{0.7}\approx 2$ (i.e, doubling).
The remaining "unallocated" Grams will be used by the TON Reserve as explained above in [A.5](#a-5-using-unallocated-grams). If the TON Foundation needs any more Grams thereafter, it will simply convert into Grams some of the funds it had previously obtained during the sale of the coins, either on the free market or by buying Grams from the TON Reserve. To prevent excessive centralization, the TON Foundation will never endeavour to have more than 10% of the total amount of Grams (i.e., 500 Megagrams) on its account.
### A.6. Bulk sales of Grams [#a6-bulk-sales-of-grams]
When a lot of people simultaneously want to buy large amounts of Grams from the TON Reserve, it makes sense not to process their orders immediately, because this would lead to results very dependent on the timing of specific orders and their processing sequence.
Instead, orders for buying Grams may be collected during some pre-defined period of time (e.g., a day or a month) and then processed all together at once. If $k$ orders with $i$-th order worth $T_i$ dollars arrive, then the total amount $T=T_1+T_2+\cdots+T_k$ is used to buy $\Delta n$ new coins according to ([30](#a-4-4-buying-next-coins-with-total-value)), and the sender of the $i$-th order is allotted $\Delta n\cdot T_i/T$ of these coins. In this way, all buyers obtain their Grams at the same average price of $T/\Delta n$ USD per Gram.
After that, a new round of collecting orders for buying new Grams begins.
When the total value of Gram buying orders becomes low enough, this system of "bulk sales" may be replaced with a system of immediate sales of Grams from the TON Reserve according to the formula ([30](#a-4-4-buying-next-coins-with-total-value)).
The "bulk sales" mechanism will probably be used extensively during the initial phase of collecting investments in the TON Project.
***
## References [#references]
\[1] K. Birman, *Reliable Distributed Systems: Technologies, Web Services and Applications*, Springer, 2005.
\[2] V. Buterin, *Ethereum: A next-generation smart contract and decentralized application platform*, [https://github.com/ethereum/wiki/wiki/White-Paper](https://github.com/ethereum/wiki/wiki/White-Paper), 2013.
\[3] M. Ben-Or, B. Kelmer, T. Rabin, *Asynchronous secure computations with optimal resilience*, in *Proceedings of the thirteenth annual ACM symposium on Principles of distributed computing*, p. 183–192. ACM, 1994.
\[4] M. Castro, B. Liskov, et al., *Practical byzantine fault tolerance*, Proceedings of the Third Symposium on Operating Systems Design and Implementation (1999), p. 173–186, available at [http://pmg.csail.mit.edu/papers/osdi99.pdf](http://pmg.csail.mit.edu/papers/osdi99.pdf).
\[5] EOS.IO, *EOS.IO technical white paper*, [https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md](https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md), 2017.
\[6] D. Goldschlag, M. Reed, P. Syverson, *Onion Routing for Anonymous and Private Internet Connections*, Communications of the ACM, **42**, num. 2 (1999), [http://www.onion-router.net/Publications/CACM-1999.pdf](http://www.onion-router.net/Publications/CACM-1999.pdf).
\[7] L. Lamport, R. Shostak, M. Pease, *The byzantine generals problem*, ACM Transactions on Programming Languages and Systems, **4/3** (1982), p. 382–401.
\[8] S. Larimer, *The history of BitShares*, [https://docs.bitshares.org/bitshares/history.html](https://docs.bitshares.org/bitshares/history.html), 2013.
\[9] M. Luby, A. Shokrollahi, et al., *RaptorQ forward error correction scheme for object delivery*, IETF RFC 6330, [https://tools.ietf.org/html/rfc6330](https://tools.ietf.org/html/rfc6330), 2011.
\[10] P. Maymounkov, D. Mazières, *Kademlia: A peer-to-peer information system based on the XOR metric*, in *IPTPS '01 revised papers from the First International Workshop on Peer-to-Peer Systems*, p. 53–65, available at [http://pdos.csail.mit.edu/\~petar/papers/maymounkov-kademlia-lncs.pdf](http://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf), 2002.
\[11] A. Miller, Yu Xia, et al., *The honey badger of BFT protocols*, Cryptology e-print archive 2016/99, [https://eprint.iacr.org/2016/199.pdf](https://eprint.iacr.org/2016/199.pdf), 2016.
\[12] S. Nakamoto, *Bitcoin: A peer-to-peer electronic cash system*, [https://bitcoin.org/bitcoin.pdf](https://bitcoin.org/bitcoin.pdf), 2008.
\[13] S. Peyton Jones, *Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine*, Journal of Functional Programming **2** (2), p. 127–202, 1992.
\[14] A. Shokrollahi, M. Luby, *Raptor Codes*, IEEE Transactions on Information Theory **6**, no. 3–4 (2006), p. 212–322.
\[15] M. van Steen, A. Tanenbaum, *Distributed Systems, 3rd ed.*, 2017.
\[16] The Univalent Foundations Program, *Homotopy Type Theory: Univalent Foundations of Mathematics*, Institute for Advanced Study, 2013, available at [https://homotopytypetheory.org/book](https://homotopytypetheory.org/book).
\[17] G. Wood, *PolkaDot: vision for a heterogeneous multi-chain framework*, draft 1, [https://github.com/w3f/polkadot-white-paper/raw/master/PolkaDotPaper.pdf](https://github.com/w3f/polkadot-white-paper/raw/master/PolkaDotPaper.pdf), 2016.
***
## Footnotes [#footnotes]
1. [https://github.com/ethereum/wiki/wiki/Sharding-FAQ](https://github.com/ethereum/wiki/wiki/Sharding-FAQ) [Back ↑](#2-1-1-list-of-blockchain-types)
2. Actually, two-thirds by stake is enough to achieve consensus, but an effort is made to collect as many signatures as possible. [Back ↑](#2-1-15-generation-of-new-blocks-by-validators)
3. [https://coq.inria.fr](https://coq.inria.fr) [Back ↑](#2-2-4-dependent-type-theory-coq-and-tl)
4. [https://core.telegram.org/mtproto/TL](https://core.telegram.org/mtproto/TL) [Back ↑](#2-2-4-dependent-type-theory-coq-and-tl)
5. One can show that this encoding is optimal for approximately half of all edge labels of a Patricia tree with random or consecutive indices. Remaining edge labels are likely to be long (i.e., almost 256 bits long). Therefore, a nearly optimal encoding for edge labels is to use the above code with prefix 0 for "short" bit strings, and encode 1, then nine bits containing length $l=|s|$ of bitstring $s$, and then the $l$ bits of $s$ for "long" bitstrings (with $l\geq10$). [Back ↑](#2-3-8-merkle-patricia-trees)
6. A *light node* is a node that does not keep track of the full state of a shardchain; instead, it keeps minimal information such as the hashes of the several most recent blocks, and relies on information obtained from full nodes when it becomes necessary to inspect some parts of the full state. [Back ↑](#2-3-10-merkle-proofs)
7. A *full node* is a node keeping track of the complete up-to-date state of the shardchain in question. [Back ↑](#2-3-10-merkle-proofs)
8. These two descriptor bytes, present in any TVM cell, describe only the total number of references and the total number of raw bytes; references are kept together either before or after all raw bytes. [Back ↑](#2-3-12-peculiarities-of-ton-vm)
9. Actually, $\text{Leaf}$ and $\text{Node}$ are constructors of an auxiliary type, $\text{HashmapAux}(n,X)$. Type $\text{Hashmap}(n,X)$ has constructors $\text{Root}$ and $\text{EmptyRoot}$, with $\text{Root}$ containing a value of type $\text{HashmapAux}(n,X)$. [Back ↑](#2-3-12-peculiarities-of-ton-vm)
10. Logically; the "bag of cells" representation described in [2.5.5](#2-5-5-low-level-perspective%3A-bag-of-cells) identifies all duplicate cells, transforming this tree into a directed acyclic graph (dag) when serialized. [Back ↑](#2-3-14-tvm-cells)
11. A more expensive alternative is to publish such a "global" smart contract in the masterchain. [Back ↑](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)
12. This is a sort of "broadcast" feature for all shards, and as such, it must be quite expensive. [Back ↑](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)
13. The above needs to be literally true only for the basic workchain and its shardchains; other workchains may provide other ways of creating messages. [Back ↑](#2-4-11-creating-messages-smart-contracts-and-transactions)
14. As a degenerate case, this shardchain may coincide with the originating shardchain—for example, if we are working inside a workchain which has not yet been split. [Back ↑](#2-4-12-delivering-messages)
15. This is not necessarily the final version of the algorithm used to compute the next hop for hypercube routing. In particular, hexadecimal digits may be replaced by $r$-bit groups, with $r$ a configurable parameter, not necessarily equal to four. [Back ↑](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)
16. However, the validators have some incentive to do so as soon as possible, because they will be able to collect all forwarding fees associated with the message that have not yet been consumed along the slow path. [Back ↑](#2-4-20-instant-hypercube-routing-fast-path-for-messages)
17. In fact, one might temporarily or permanently disable the "instant delivery" mechanism altogether, and the system would continue working, albeit more slowly. [Back ↑](#2-4-20-instant-hypercube-routing-fast-path-for-messages)
18. One can show that, if Merkle proofs for all data stored in a tree of cells are needed equally often, one should use cells with $b+ch\approx 2(h+r)$ to minimize average Merkle proof size, where $h=32$ is the hash size in bytes, and $r\approx4$ is the "byte size" of a cell reference. In other words, a cell should contain either two references and a few raw bytes, or one reference and about 36 raw bytes, or no references at all with 72 raw bytes. [Back ↑](#2-5-5-low-level-perspective-bag-of-cells)
19. A better implementation would be to keep the state of the smart contract as a serialized string, if it is small, or in a separate $B$-tree, if it is large; then the top-level structure representing the state of a blockchain would be a $B$-tree, whose leaves are allowed to contain references to other $B$-trees. [Back ↑](#2-5-5-low-level-perspective-bag-of-cells)
20. It makes sense to generate and use a new key pair for every validator election. [Back ↑](#2-6-7-global-validator-set-election)
21. A possible exception is the state of output queues of the neighboring shardchains, needed to guarantee the message ordering requirements described in [2.4.21](#2-4-21-collecting-input-messages-from-output-queues-of-neighboring-shardchains), because the size of Merkle proofs might become prohibitive in this case. [Back ↑](#2-6-11-validation-of-block-candidates)
22. Actually, the shard configuration is completely determined by the last masterchain block; this simplifies getting access to the shard configuration. [Back ↑](#2-7-1-shard-configuration)
23. Unless some validators are temporarily or permanently banned because of signing invalid blocks—then they are automatically excluded from all task groups. [Back ↑](#2-7-4-validator-task-groups-for-new-shardchains)
24. More like 15, for the time being. However, some upgrades are being planned to make Ethereum transaction throughput several times larger. [Back ↑](#2-8-2-single-blockchain-vs-multi-blockchain-projects)
25. Some people even claim DPOS block generation times of half a second, which does not seem realistic if validators are scattered across several continents. [Back ↑](#2-8-5-comparison-of-dpos-and-bft-pos)
26. For instance, EOS, one of the best DPOS projects proposed up to this date, promises a 45-second confirmation and inter-blockchain interaction delay (cf. EOS White Paper, "Transaction Confirmation" and "Latency of Interchain Communication" sections). [Back ↑](#2-8-5-comparison-of-dpos-and-bft-pos)
27. For example, the Plasma project plans to use the Ethereum blockchain as its (external) masterchain; it does not interact much with Ethereum otherwise, and it could have been suggested and implemented by a team unrelated to the Ethereum project. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)
28. As of 2017, Ethereum is still struggling to transition from PoW to a combined PoW+PoS system; we hope it will become a truly PoS system someday. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)
29. There are sharding proposals for Ethereum dating back to 2015; it is unclear how they might be implemented and deployed without disrupting Ethereum or creating an essentially independent parallel project. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)
30. [https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/](https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/) [Back ↑](#2-9-5-casper)
31. [https://geti2p.net/en/docs/how/garlic-routing](https://geti2p.net/en/docs/how/garlic-routing) [Back ↑](#3-1-6-channel-as-a-tunnel-identifier)
32. If there are sufficiently many nodes in a bucket, it can be subdivided further into, say, eight sub-buckets depending on the top four bits of the Kademlia distance. This would speed up DHT lookups. [Back ↑](#3-2-6-kademlia-routing-table)
33. Alternatively, the abstract address might be stored in the DHT as explained in [3.2.12](#3-2-12-locating-services). [Back ↑](#3-3-5-joining-an-overlay-network)
34. [https://core.telegram.org/mtproto](https://core.telegram.org/mtproto) [Back ↑](#4-1-4-telegram-messenger-as-a-ton-service-mtproto-over-rldp)
35. [https://telegram.org/](https://telegram.org/) [Back ↑](#4-1-4-telegram-messenger-as-a-ton-service-mtproto-over-rldp)
36. TL-schemes can be TL-serialized themselves; cf. [https://core.telegram.org/mtproto/TL-tl](https://core.telegram.org/mtproto/TL-tl). [Back ↑](#4-3-14-public-interfaces-of-a-smart-contract)
37. The maximum total amount of validator stakes is a configurable parameter of the blockchain, so this restriction can be enforced by the protocol if necessary. [Back ↑](#a-3-original-supply-mining-rewards-and-inflation)
# Telegram Open Network Virtual Machine (/blockchain-basics/whitepapers/tvm)
**Author**: Nikolai Durov
**Date**: March 23, 2020
: [Original whitepaper, PDF](/resources/pdfs/tvm.pdf)
## Abstract [#abstract]
The aim of this text is to provide a description of the Telegram Open Network Virtual Machine (TON VM or TVM), used to execute smart contracts in the TON Blockchain.
## Introduction [#introduction]
The primary purpose of the Telegram Open Network Virtual Machine (TON VM or TVM) is to execute smart-contract code in the TON Blockchain. TVM must support all operations required to parse incoming messages and persistent data, and to create new messages and modify persistent data.
Additionally, TVM must meet the following requirements:
* It must provide for possible future extensions and improvements while retaining backward compatibility and interoperability, because the code of a smart contract, once committed into the blockchain, must continue working in a predictable manner regardless of any future modifications to the VM.
* It must strive to attain high "(virtual) machine code" density, so that the code of a typical smart contract occupies as little persistent blockchain storage as possible.
* It must be completely deterministic. In other words, each run of the same code with the same input data must produce the same result, regardless of specific software and hardware used. [1](#fn1)
The design of TVM is guided by these requirements. While this document describes a preliminary and experimental version of TVM,[2](#fn2) the backward compatibility mechanisms built into the system allow us to be relatively unconcerned with the efficiency of the operation encoding used for TVM code in this preliminary version.
TVM is not intended to be implemented in hardware (e.g., in a specialized microprocessor chip); rather, it should be implemented in software running on conventional hardware. This consideration lets us incorporate some high-level concepts and operations in TVM that would require convoluted microcode in a hardware implementation but pose no significant problems for a software implementation. Such operations are useful for achieving high code density and minimizing the byte (or storage cell) profile of smart-contract code when deployed in the TON Blockchain.
# 1 Overview [#1---overview]
This chapter provides an overview of the main features and design principles of TVM. More detail on each topic is provided in subsequent chapters.
## 1.0 Notation for bitstrings [#10---notation-for-bitstrings]
The following notation is used for bit strings (or *bitstrings*)—i.e., finite strings consisting of binary digits (bits), $\texttt{0}$ and $\texttt{1}$—throughout this document.
### 1.0.1. Hexadecimal notation for bitstrings [#101-hexadecimal-notation-for-bitstrings]
When the length of a bitstring is a multiple of four, we subdivide it into groups of four bits and represent each group by one of sixteen hexadecimal digits $\texttt{0}$--$\texttt{9}$, $\texttt{A}$--$\texttt{F}$ in the usual manner: $\texttt{0}_{16}\leftrightarrow\texttt{0000}$, $\texttt{1}_{16}\leftrightarrow\texttt{0001}$, $\ldots$, $\texttt{F}_{16}\leftrightarrow\texttt{1111}$. The resulting hexadecimal string is our equivalent representation for the original binary string.
### 1.0.2. Bitstrings of lengths not divisible by four [#102-bitstrings-of-lengths-not-divisible-by-four]
If the length of a binary string is not divisible by four, we augment it by one $\texttt{1}$ and several (maybe zero) $\texttt{0}$s at the end, so that its length becomes divisible by four, and then transform it into a string of hexadecimal digits as described above. To indicate that such a transformation has taken place, a special "completion tag" $\texttt{\_}$ is added to the end of the hexadecimal string. The reverse transformation (applied if the completion tag is present) consists in first replacing each hexadecimal digit by four corresponding bits, and then removing all trailing zeroes (if any) and the last $\texttt{1}$ immediately preceding them (if the resulting bitstring is non-empty at this point).
Notice that there are several admissible hexadecimal representations for the same bitstring. Among them, the shortest one is "canonical". It can be deterministically obtained by the above procedure.
For example, $\texttt{8A}$ corresponds to binary string $\texttt{10001010}$, while $\texttt{8A\_}$ and $\texttt{8A0\_}$ both correspond to $\texttt{100010}$. An empty bitstring may be represented by either ' ', '$\texttt{8\_}$', '$\texttt{0\_}$', '$\texttt{\_}$', or '$\texttt{00\_}$'.
### 1.0.3. Emphasizing that a string is a hexadecimal representation of a bitstring [#103-emphasizing-that-a-string-is-a-hexadecimal-representation-of-a-bitstring]
Sometimes we need to emphasize that a string of hexadecimal digits (with or without a $\texttt{\_}$ at the end) is the hexadecimal representation of a bitstring. In such cases, we either prepend $\texttt{x}$ to the resulting string (e.g., $\texttt{x8A}$), or prepend $\texttt{x\{}$ and append $\texttt{\}}$ (e.g., $\texttt{x\{2D9\_\}}$, which is $\texttt{00101101100}$). This should not be confused with hexadecimal numbers, usually prepended by $\texttt{0x}$ (e.g., $\texttt{0x2D9}$ or $\texttt{0x2d9}$, which is the integer 729).
### 1.0.4. Serializing a bitstring into a sequence of octets [#104-serializing-a-bitstring-into-a-sequence-of-octets]
When a bitstring needs to be represented as a sequence of 8-bit bytes (octets), which take values in integers $0\ldots255$, this is achieved essentially in the same fashion as above: we split the bitstring into groups of eight bits and interpret each group as the binary representation of an integer $0\ldots255$. If the length of the bitstring is not a multiple of eight, the bitstring is augmented by a binary $\texttt{1}$ and up to seven binary $\texttt{0}$s before being split into groups. The fact that such a completion has been applied is usually reflected by a "completion tag" bit.
For instance, $\texttt{00101101100}$ corresponds to the sequence of two octets $(\texttt{0x2d}, \texttt{0x90})$ (hexadecimal), or $(45,144)$ (decimal), along with a completion tag bit equal to $\texttt{1}$ (meaning that the completion has been applied), which must be stored separately.
In some cases, it is more convenient to assume the completion is enabled by default rather than store an additional completion tag bit separately. Under such conventions, $8n$-bit strings are represented by $n+1$ octets, with the last octet always equal to $\texttt{0x80}=128$.
## 1.1 TVM is a stack machine [#11---tvm-is-a-stack-machine]
First of all, *TVM is a stack machine*. This means that, instead of keeping values in some "variables" or "general-purpose registers", they are kept in a (LIFO) *stack*, at least from the "low-level" (TVM) perspective.[3](#fn3)
Most operations and user-defined functions take their arguments from the top of the stack, and replace them with their result. For example, the integer addition primitive (built-in operation) $\texttt{ADD}$ does not take any arguments describing which registers or immediate values should be added together and where the result should be stored. Instead, the two top values are taken from the stack, they are added together, and their sum is pushed into the stack in their place.
### 1.1.1. TVM values [#111-tvm-values]
The entities that can be stored in the TVM stack will be called *TVM values*, or simply *values* for brevity. They belong to one of several predefined *value types*. Each value belongs to exactly one value type. The values are always kept on the stack along with tags uniquely determining their types, and all built-in TVM operations (or *primitives*) only accept values of predefined types.
For example, the integer addition primitive $\texttt{ADD}$ accepts only two integer values, and returns one integer value as a result. One cannot supply $\texttt{ADD}$ with two strings instead of two integers expecting it to concatenate these strings or to implicitly transform the strings into their decimal integer values; any attempt to do so will result in a run-time type-checking exception.
### 1.1.2. Static typing, dynamic typing, and run-time type checking [#112-static-typing-dynamic-typing-and-run-time-type-checking]
In some respects TVM performs a kind of dynamic typing using run-time type checking. However, this does not make the TVM code a "dynamically typed language" like PHP or Javascript, because all primitives accept values and return results of predefined (value) types, each value belongs to strictly one type, and values are never implicitly converted from one type to another. If, on the other hand, one compares the TVM code to the conventional microprocessor machine code, one sees that the TVM mechanism of value tagging prevents, for example, using the address of a string as a number—or, potentially even more disastrously, using a number as the address of a string—thus eliminating the possibility of all sorts of bugs and security vulnerabilities related to invalid memory accesses, usually leading to memory corruption and segmentation faults. This property is highly desirable for a VM used to execute smart contracts in a blockchain. In this respect, TVM's insistence on tagging all values with their appropriate types, instead of reinterpreting the bit sequence in a register depending on the needs of the operation it is used in, is just an additional run-time type-safety mechanism.
An alternative would be to somehow analyze the smart-contract code for type correctness and type safety before allowing its execution in the VM, or even before allowing it to be uploaded into the blockchain as the code of a smart contract. Such a static analysis of code for a Turing-complete machine appears to be a time-consuming and non-trivial problem (likely to be equivalent to the stopping problem for Turing machines), something we would rather avoid in a blockchain smart-contract context.
One should bear in mind that one always can implement compilers from statically typed high-level smart-contract languages into the TVM code (and we do expect that most smart contracts for TON will be written in such languages), just as one can compile statically typed languages into conventional machine code (e.g., x86 architecture). If the compiler works correctly, the resulting machine code will never generate any run-time type-checking exceptions. All type tags attached to values processed by TVM will always have expected values and may be safely ignored during the analysis of the resulting TVM code, apart from the fact that the run-time generation and verification of these type tags by TVM will slightly slow down the execution of the TVM code.
### 1.1.3. Preliminary list of value types [#113-preliminary-list-of-value-types]
A preliminary list of value types supported by TVM is as follows:
* *Integer* — Signed 257-bit integers, representing integer numbers in the range $-2^{256}\ldots2^{256}-1$, as well as a special "not-a-number" value $\texttt{NaN}$.
* *Cell* — A *TVM cell* consists of at most 1023 bits of data, and of at most four references to other cells. All persistent data (including TVM code) in the TON Blockchain is represented as a [collection of TVM cells](/blockchain-basics/whitepapers/ton#2-5-14-“everything-is-a-bag-of-cells”-philosophy).
* *Tuple* — An ordered collection of up to 255 components, having arbitrary value types, possibly distinct. May be used to represent non-persistent values of arbitrary algebraic data types.
* *Null* — A type with exactly one value $\bot$, used for representing empty lists, empty branches of binary trees, absence of return value in some situations, and so on.
* *Slice* — A *TVM cell slice*, or *slice* for short, is a contiguous "sub-cell" of an existing cell, containing some of its bits of data and some of its references. Essentially, a slice is a read-only view for a subcell of a cell. Slices are used for unpacking data previously stored (or serialized) in a cell or a tree of cells.
* *Builder* — A *TVM cell builder*, or *builder* for short, is an "incomplete" cell that supports fast operations of appending bitstrings and cell references at its end. Builders are used for packing (or serializing) data from the top of the stack into new cells (e.g., before transferring them to persistent storage).
* *Continuation* — Represents an "execution token" for TVM, which may be invoked (executed) later. As such, it generalizes function addresses (i.e., function pointers and references), subroutine return addresses, instruction pointer addresses, exception handler addresses, closures, partial applications, anonymous functions, and so on.
This list of value types is incomplete and may be extended in future revisions of TVM without breaking the old TVM code, due mostly to the fact that all originally defined primitives accept only values of types known to them and will fail (generate a type-checking exception) if invoked on values of new types. Furthermore, existing value types themselves can also be extended in the future: for example, 257-bit *Integer* might become 513-bit *LongInteger*, with originally defined arithmetic primitives failing if either of the arguments or the result does not fit into the original subtype *Integer*. Backward compatibility with respect to the introduction of new value types and extension of existing value types will be discussed [later](#5-1-4-changing-the-behavior-of-old-operations).
## 1.2 Categories of TVM instructions [#12---categories-of-tvm-instructions]
TVM *instructions*, also called *primitives* and sometimes *(built-in) operations*, are the smallest operations atomically performed by TVM that can be present in the TVM code. They fall into several categories, depending on the [types of values](#1-1-3-preliminary-list-of-value-types) they work on. The most important of these categories are:
* *Stack (manipulation) primitives* — Rearrange data in the TVM stack, so that the other primitives and user-defined functions can later be called with correct arguments. Unlike most other primitives, they are polymorphic, i.e., work with values of arbitrary types.
* *Tuple (manipulation) primitives* — Construct, modify, and decompose *Tuple*s. Similarly to the stack primitives, they are polymorphic.
* *Constant* or *literal primitives* — Push into the stack some "constant" or "literal" values embedded into the TVM code itself, thus providing arguments to the other primitives. They are somewhat similar to stack primitives, but are less generic because they work with values of specific types.
* *Arithmetic primitives* — Perform the usual integer arithmetic operations on values of type *Integer*.
* *Cell (manipulation) primitives* — Create new cells and store data in them (*cell creation primitives*) or read data from previously created cells (*cell parsing primitives*). Because all memory and persistent storage of TVM consists of cells, these cell manipulation primitives actually correspond to "memory access instructions" of other architectures. Cell creation primitives usually work with values of type *Builder*, while cell parsing primitives work with *Slice*s.
* *Continuation* and *control flow primitives* — Create and modify *Continuation*s, as well as execute existing *Continuation*s in different ways, including conditional and repeated execution.
* *Custom* or *application-specific primitives* — Efficiently perform specific high-level actions required by the application (in our case, the TON Blockchain), such as computing hash functions, performing elliptic curve cryptography, sending new blockchain messages, creating new smart contracts, and so on. These primitives correspond to standard library functions rather than microprocessor instructions.
## 1.3 Control registers [#13---control-registers]
While TVM is a stack machine, some rarely changed values needed in almost all functions are better passed in certain special registers, and not near the top of the stack. Otherwise, a prohibitive number of stack reordering operations would be required to manage all these values.
To this end, the TVM model includes, apart from the stack, up to 16 special *control registers*, denoted by $\texttt{c0}$ to $\texttt{c15}$, or $\texttt{c}(0)$ to $\texttt{c}(15)$. The original version of TVM makes use of only some of these registers; the rest may be supported later.
### 1.3.1. Values kept in control registers [#131-values-kept-in-control-registers]
The values kept in control registers are of the same types as those kept on the stack. However, some control registers accept only values of specific types, and any attempt to load a value of a different type will lead to an exception.
### 1.3.2. List of control registers [#132-list-of-control-registers]
The original version of TVM defines and uses the following control registers:
* $\texttt{c0}$ — Contains the *next continuation* or *return continuation* (similar to the subroutine return address in conventional designs). This value must be a *Continuation*.
* $\texttt{c1}$ — Contains the *alternative (return) continuation*; this value must be a *Continuation*. It is used in some (experimental) control flow primitives, allowing TVM to define and call "subroutines with two exit points".
* $\texttt{c2}$ — Contains the *exception handler*. This value is a *Continuation*, invoked whenever an exception is triggered.
* $\texttt{c3}$ — Contains the *current dictionary*, essentially a hashmap containing the code of all functions used in the program. This value is also a [Continuation](#4-6-functions%2C-recursion%2C-and-dictionaries), not a *Cell* as one might expect.
* $\texttt{c4}$ — Contains the *root of persistent data*, or simply the *data*. This value is a *Cell*. When the code of a smart contract is invoked, $\texttt{c4}$ points to the root cell of its persistent data kept in the blockchain state. If the smart contract needs to modify this data, it changes $\texttt{c4}$ before returning.
* $\texttt{c5}$ — Contains the *output actions*. It is also a *Cell* initialized by a reference to an empty cell, but its final value is considered one of the smart contract outputs. For instance, the $\texttt{SENDMSG}$ primitive, specific for the TON Blockchain, simply inserts the message into a list stored in the output actions.
* $\texttt{c7}$ — Contains the *root of temporary data*. It is a *Tuple*, initialized by a reference to an empty *Tuple* before invoking the smart contract and discarded after its termination.[4](#fn4)
More control registers may be defined in the future for specific TON Blockchain or high-level programming language purposes, if necessary.
## 1.4 Total state of TVM (SCCCG) [#14---total-state-of-tvm-scccg]
The total state of TVM consists of the following components:
* *[Stack](#1-1-tvm-is-a-stack-machine)* — Contains zero or more [values](#1-1-1-tvm-values), each belonging to one of [value types](#1-1-3-preliminary-list-of-value-types).
* *Control registers* $\mathit{c0}$–$\mathit{c15}$ — Contain some [specific values](#1-3-2-list-of-control-registers). (Only seven control registers are used in the current version.)
* *Current continuation* $\mathit{cc}$ — Contains the current continuation (i.e., the code that would be normally executed after the current primitive is completed). This component is similar to the instruction pointer register ($\texttt{ip}$) in other architectures.
* *Current codepage* $\mathit{cp}$ — A special signed 16-bit integer value that selects the way the next TVM opcode will be decoded. For example, future versions of TVM might use different codepages to add new opcodes while preserving backward compatibility.
* *Gas limits* $\mathit{gas}$ — Contains four signed 64-bit integers: the current gas limit $g_l$, the maximal gas limit $g_m$, the remaining gas $g_r$, and the gas credit $g_c$. Always $0\leq g_l\leq g_m$, $g_c\geq0$, and $g_r\leq g_l+g_c$; $g_c$ is usually initialized by zero, $g_r$ is initialized by $g_l+g_c$ and gradually decreases as the TVM runs. When $g_r$ becomes negative or if the final value of $g_r$ is less than $g_c$, an *out of gas* exception is triggered.
Notice that there is no "return stack" containing the return addresses of all previously called but unfinished functions. Instead, only [control register $\texttt{c0}$](#4-1-9-subroutine-calls%3A-or-primitives) is used.
Also notice that there are no general-purpose registers, because [TVM is a stack machine](#1-1-tvm-is-a-stack-machine). So the above list, which can be summarized as "stack, control, continuation, codepage, and gas" (SCCCG), similarly to the classical SECD machine state ("stack, environment, control, dump"), is indeed the *total* state of TVM.[5](#fn5)
## 1.5 Integer arithmetic [#15---integer-arithmetic]
All arithmetic primitives of TVM operate on several arguments of type *Integer*, taken from the top of the stack, and return their results, of the same type, into the stack. Recall that *Integer* represents all integer values in the range $-2^{256}\leq x<2^{256}$, and additionally contains a special value $\texttt{NaN}$ ("not-a-number").
If one of the results does not fit into the supported range of integers—or if one of the arguments is a $\texttt{NaN}$—then this result or all of the results are replaced by a $\texttt{NaN}$, and (by default) an integer overflow exception is generated. However, special "quiet" versions of arithmetic operations will simply produce $\texttt{NaN}$s and keep going. If these $\texttt{NaN}$s end up being used in a "non-quiet" arithmetic operation, or in a non-arithmetic operation, an integer overflow exception will occur.
### 1.5.1. Absence of automatic conversion of integers [#151-absence-of-automatic-conversion-of-integers]
Notice that TVM *Integer*s are "mathematical" integers, and not 257-bit strings interpreted differently depending on the primitive used, as is common for other machine code designs. For example, TVM has only one multiplication primitive $\texttt{MUL}$, rather than two ($\texttt{MUL}$ for unsigned multiplication and $\texttt{IMUL}$ for signed multiplication) as occurs, for example, in the popular x86 architecture.
### 1.5.2. Automatic overflow checks [#152-automatic-overflow-checks]
Notice that all TVM arithmetic primitives perform overflow checks of the results. If a result does not fit into the *Integer* type, it is replaced by a $\texttt{NaN}$, and (usually) an exception occurs. In particular, the result is *not* automatically reduced modulo $2^{256}$ or $2^{257}$, as is common for most hardware machine code architectures.
### 1.5.3. Custom overflow checks [#153-custom-overflow-checks]
In addition to automatic overflow checks, TVM includes custom overflow checks, performed by primitives $\texttt{FITS}$ $n$ and $\texttt{UFITS}$ $n$, where $1\leq n\leq256$. These primitives check whether the value on (the top of) the stack is an integer $x$ in the range $-2^{n-1}\leq x<2^{n-1}$ or $0\leq x<2^n$, respectively, and replace the value with a $\texttt{NaN}$ and (optionally) generate an integer overflow exception if this is not the case. This greatly simplifies the implementation of arbitrary $n$-bit integer types, signed or unsigned: the programmer or the compiler must insert appropriate $\texttt{FITS}$ or $\texttt{UFITS}$ primitives either after each arithmetic operation (which is more reasonable, but requires more checks) or before storing computed values and returning them from functions. This is important for smart contracts, where unexpected integer overflows happen to be among the most common source of bugs.
### 1.5.4. Reduction modulo $2^n$ [#154-reduction-modulo-2n]
TVM also has a primitive $\texttt{MODPOW2}$ $n$, which reduces the integer at the top of the stack modulo $2^n$, with the result ranging from $0$ to $2^n-1$.
### 1.5.5. *Integer* is 257-bit, not 256-bit [#155-integer-is-257-bit-not-256-bit]
One can understand now why TVM's *Integer* is (signed) 257-bit, not 256-bit. The reason is that it is the smallest integer type containing both signed 256-bit integers and unsigned 256-bit integers, which does not require [automatic reinterpreting](#1-5-1-absence-of-automatic-conversion-of-integers) of the same 256-bit string depending on the operation used.
### 1.5.6. Division and rounding [#156-division-and-rounding]
The most important division primitives are $\texttt{DIV}$, $\texttt{MOD}$, and $\texttt{DIVMOD}$. All of them take two numbers from the stack, $x$ and $y$ ($y$ is taken from the top of the stack, and $x$ is originally under it), compute the quotient $q$ and remainder $r$ of the division of $x$ by $y$ (i.e., two integers such that $x=yq+r$ and $|r|<|y|$), and return either $q$, $r$, or both of them. If $y$ is zero, then all of the expected results are replaced by $\texttt{NaN}$s, and (usually) an integer overflow exception is generated.
The implementation of division in TVM somewhat differs from most other implementations with regards to rounding. By default, these primitives round to $-\infty$, meaning that $q=\lfloor x/y\rfloor$, and $r$ has the same sign as $y$. (Most conventional implementations of division use "rounding to zero" instead, meaning that $r$ has the same sign as $x$.) Apart from this "floor rounding", two other rounding modes are available, called "ceiling rounding" (with $q=\lceil x/y\rceil$, and $r$ and $y$ having opposite signs) and "nearest rounding" (with $q=\lfloor x/y+1/2\rfloor$ and $|r|\leq|y|/2$). These rounding modes are selected by using other division primitives, with letters $\texttt{C}$ and $\texttt{R}$ appended to their mnemonics. For example, $\texttt{DIVMODR}$ computes both the quotient and the remainder using rounding to the nearest integer.
### 1.5.7. Combined multiply-divide, multiply-shift, and shift-divide operations [#157-combined-multiply-divide-multiply-shift-and-shift-divide-operations]
To simplify implementation of fixed-point arithmetic, TVM supports combined multiply-divide, multiply-shift, and shift-divide operations with double-length (i.e., 514-bit) intermediate product. For example, $\texttt{MULDIVMODR}$ takes three integer arguments from the stack, $a$, $b$, and $c$, first computes $ab$ using a 514-bit intermediate result, and then divides $ab$ by $c$ using rounding to the nearest integer. If $c$ is zero or if the quotient does not fit into *Integer*, either two $\texttt{NaN}$s are returned, or an integer overflow exception is generated, depending on whether a quiet version of the operation has been used. Otherwise, both the quotient and the remainder are pushed into the stack.
***
# 2 The stack [#2---the-stack]
This chapter contains a general discussion and comparison of register and stack machines, expanded further in [Appendix C](#c-code-density-of-stack-and-register-machines), and describes the two main classes of stack manipulation primitives employed by TVM: the *basic* and the *compound stack manipulation primitives*. An informal explanation of their sufficiency for all stack reordering required for correctly invoking other primitives and user-defined functions is also provided. Finally, the problem of efficiently implementing TVM [stack manipulation primitives](#2-3-efficiency-of-stack-manipulation-primitives) will be discussed.
## 2.1 Stack calling conventions [#21----stack-calling-conventions]
A stack machine, such as TVM, uses the stack—and especially the values near the top of the stack—to pass arguments to called functions and primitives (such as built-in arithmetic operations) and receive their results. This section discusses the TVM stack calling conventions, introduces some notation, and compares TVM stack calling conventions with those of certain register machines.
### 2.1.1. Notation for "stack registers" [#211-notation-for-stack-registers]
Recall that a stack machine, as opposed to a more conventional register machine, lacks general-purpose registers. However, one can treat the values near the top of the stack as a kind of "stack registers".
We denote by $\texttt{s0}$ or $\texttt{s}(0)$ the value at the top of the stack, by $\texttt{s1}$ or $\texttt{s}(1)$ the value immediately under it, and so on. The total number of values in the stack is called its *depth*. If the depth of the stack is $n$, then $\texttt{s}(0)$, $\texttt{s}(1)$, $\ldots$, $\texttt{s}(n-1)$ are well-defined, while $\texttt{s}(n)$ and all subsequent $\texttt{s}(i)$ with $i>n$ are not. Any attempt to use $\texttt{s}(i)$ with $i\geq n$ should produce a stack underflow exception.
A compiler, or a human programmer in "TVM code", would use these "stack registers" to hold all declared variables and intermediate values, similarly to the way general-purpose registers are used on a register machine.
### 2.1.2. Pushing and popping values [#212-pushing-and-popping-values]
When a value $x$ is *pushed* into a stack of depth $n$, it becomes the new $\texttt{s0}$; at the same time, the old $\texttt{s0}$ becomes the new $\texttt{s1}$, the old $\texttt{s1}$—the new $\texttt{s2}$, and so on. The depth of the resulting stack is $n+1$.
Similarly, when a value $x$ is *popped* from a stack of depth $n\geq1$, it is the old value of $\texttt{s0}$ (i.e., the old value at the top of the stack). After this, it is removed from the stack, and the old $\texttt{s1}$ becomes the new $\texttt{s0}$ (the new value at the top of the stack), the old $\texttt{s2}$ becomes the new $\texttt{s1}$, and so on. The depth of the resulting stack is $n-1$.
If originally $n=0$, then the stack is *empty*, and a value cannot be popped from it. If a primitive attempts to pop a value from an empty stack, a *stack underflow* exception occurs.
### 2.1.3. Notation for hypothetical general-purpose registers [#213-notation-for-hypothetical-general-purpose-registers]
In order to compare stack machines with sufficiently general register machines, we will denote the general-purpose registers of a register machine by $\texttt{r0}$, $\texttt{r1}$, and so on, or by $\texttt{r}(0)$, $\texttt{r}(1)$, $\ldots$, $\texttt{r}(n-1)$, where $n$ is the total number of registers. When we need a specific value of $n$, we will use $n=16$, corresponding to the very popular x86-64 architecture.
### 2.1.4. The top-of-stack register $\texttt{s0}$ vs. the accumulator register $\texttt{r0}$ [#214-the-top-of-stack-register-texttts0-vs-the-accumulator-register-textttr0]
Some register machine architectures require one of the arguments for most arithmetic and logical operations to reside in a special register called the *accumulator*. In our comparison, we will assume that the accumulator is the general-purpose register $\texttt{r0}$; otherwise we could simply renumber the registers. In this respect, the accumulator is somewhat similar to the top-of-stack "register" $\texttt{s0}$ of a stack machine, because virtually all operations of a stack machine both use $\texttt{s0}$ as one of their arguments and return their result as $\texttt{s0}$.
### 2.1.5. Register calling conventions [#215-register-calling-conventions]
When compiled for a register machine, high-level language functions usually receive their arguments in certain registers in a predefined order. If there are too many arguments, these functions take the remainder from the stack (yes, a register machine usually has a stack, too!). Some register calling conventions pass no arguments in registers at all, however, and only use the stack (for example, the original calling conventions used in implementations of Pascal and C, although modern implementations of C use some registers as well).
For simplicity, we will assume that up to $m\leq n$ function arguments are passed in registers, and that these registers are $\texttt{r0}$, $\texttt{r1}$, $\ldots$, $\texttt{r}(m-1)$, in that order (if some other registers are used, we can simply renumber them).[6](#fn6)
### 2.1.6. Order of function arguments [#216-order-of-function-arguments]
If a function or primitive requires $m$ arguments $x_1$, $\ldots$, $x_m$, they are pushed by the caller into the stack in the same order, starting from $x_1$. Therefore, when the function or primitive is invoked, its first argument $x_1$ is in $\texttt{s}(m-1)$, its second argument $x_2$ is in $\texttt{s}(m-2)$, and so on. The last argument $x_m$ is in $\texttt{s0}$ (i.e., at the top of the stack). It is the called function or primitive's responsibility to remove its arguments from the stack.
In this respect the TVM stack calling conventions—obeyed, at least, by TVM primitives—match those of Pascal and Forth, and are the opposite of those of C (in which the arguments are pushed into the stack in the reverse order, and are removed by the caller after it regains control, not the callee).
Of course, an implementation of a high-level language for TVM might choose some other calling conventions for its functions, different from the default ones. This might be useful for certain functions—for instance, if the total number of arguments depends on the value of the first argument, as happens for "variadic functions" such as $\texttt{scanf}$ and $\texttt{printf}$. In such cases, the first one or several arguments are better passed near the top of the stack, not somewhere at some unknown location deep in the stack.
### 2.1.7. Arguments to arithmetic primitives on register machines [#217-arguments-to-arithmetic-primitives-on-register-machines]
On a stack machine, built-in arithmetic primitives (such as $\texttt{ADD}$ or $\texttt{DIVMOD}$) follow the same calling conventions as user-defined functions. In this respect, user-defined functions (for example, a function computing the square root of a number) might be considered as "extensions" or "custom upgrades" of the stack machine. This is one of the clearest advantages of stack machines (and of stack programming languages such as Forth) compared to register machines.
In contrast, arithmetic instructions (built-in operations) on register machines usually get their parameters from general-purpose registers encoded in the full opcode. A binary operation, such as $\texttt{SUB}$, thus requires two arguments, $\texttt{r}(i)$ and $\texttt{r}(j)$, with $i$ and $j$ specified by the instruction. A register $\texttt{r}(k)$ for storing the result also must be specified. Arithmetic operations can take several possible forms, depending on whether $i$, $j$, and $k$ are allowed to take arbitrary values:
* Three-address form — Allows the programmer to arbitrarily choose not only the two source registers $\texttt{r}(i)$ and $\texttt{r}(j)$, but also a separate destination register $\texttt{r}(k)$. This form is common for most RISC processors, and for the XMM and AVX SIMD instruction sets in the x86-64 architecture.
* Two-address form — Uses one of the two operand registers (usually $\texttt{r}(i)$) to store the result of an operation, so that $k=i$ is never indicated explicitly. Only $i$ and $j$ are encoded inside the instruction. This is the most common form of arithmetic operations on register machines, and is quite popular on microprocessors (including the x86 family).
* One-address form — Always takes one of the arguments from the accumulator $\texttt{r0}$, and stores the result in $\texttt{r0}$ as well; then $i=k=0$, and only $j$ needs to be specified by the instruction. This form is used by some simpler microprocessors (such as Intel 8080).
Note that this flexibility is available only for built-in operations, but not for user-defined functions. In this respect, register machines are not as easily "upgradable" as stack machines.[7](#fn7)
### 2.1.8. Return values of functions [#218-return-values-of-functions]
In stack machines such as TVM, when a function or primitive needs to return a result value, it simply pushes it into the stack (from which all arguments to the function have already been removed). Therefore, the caller will be able to access the result value through the top-of-stack "register" $\texttt{s0}$.
This is in complete accordance with Forth calling conventions, but differs slightly from Pascal and C calling conventions, where the accumulator register $\texttt{r0}$ is normally used for the return value.
### 2.1.9. Returning several values [#219-returning-several-values]
Some functions might want to return several values $y_1$, $\ldots$, $y_k$, with $k$ not necessarily equal to one. In these cases, the $k$ return values are pushed into the stack in their natural order, starting from $y_1$.
For example, the "divide with remainder" primitive $\texttt{DIVMOD}$ needs to return two values, the quotient $q$ and the remainder $r$. Therefore, $\texttt{DIVMOD}$ pushes $q$ and $r$ into the stack, in that order, so that the quotient is available thereafter at $\texttt{s1}$ and the remainder at $\texttt{s0}$. The net effect of $\texttt{DIVMOD}$ is to divide the original value of $\texttt{s1}$ by the original value of $\texttt{s0}$, and return the quotient in $\texttt{s1}$ and the remainder in $\texttt{s0}$. In this particular case the depth of the stack and the values of all other "stack registers" remain unchanged, because $\texttt{DIVMOD}$ takes two arguments and returns two results. In general, the values of other "stack registers" that lie in the stack below the arguments passed and the values returned are shifted according to the change of the depth of the stack.
In principle, some primitives and user-defined functions might return a variable number of result values. In this respect, the remarks above about [variadic functions](#2-1-6-order-of-function-arguments) apply: the total number of result values and their types should be determined by the values near the top of the stack. (For example, one might push the return values $y_1$, $\ldots$, $y_k$, and then push their total number $k$ as an integer. The caller would then determine the total number of returned values by inspecting $\texttt{s0}$.)
In this respect TVM, again, faithfully observes Forth calling conventions.
### 2.1.10. Stack notation [#2110-stack-notation]
When a stack of depth $n$ contains values $z_1$, $\ldots$, $z_n$, in that order, with $z_1$ the deepest element and $z_n$ the top of the stack, the contents of the stack are often represented by a list $z_1$ $z_2$ $\ldots$ $z_n$, in that order. When a primitive transforms the original stack state $S'$ into a new state $S''$, this is often written as $S'$ -- $S''$; this is the so-called *stack notation*. For example, the action of the division primitive $\texttt{DIV}$ can be described by $S$ $x$ $y$ -- $S$ $\lfloor x/y\rfloor$, where $S$ is any list of values. This is usually abbreviated as $x$ $y$ -- $\lfloor x/y\rfloor$, tacitly assuming that all other values deeper in the stack remain intact.
Alternatively, one can describe $\texttt{DIV}$ as a primitive that runs on a stack $S'$ of depth $n\geq2$, divides $\texttt{s1}$ by $\texttt{s0}$, and returns the floor-rounded quotient as $\texttt{s0}$ of the new stack $S''$ of depth $n-1$. The new value of $\texttt{s}(i)$ equals the old value of $\texttt{s}(i+1)$ for $1\leq i[8](#fn8)
Proceeding in this manner, we see that we can put the original values of $x$, $y$, and $z$—or their copies, if needed—into locations $\texttt{s2}$, $\texttt{s1}$, and $\texttt{s0}$, using a sequence of push and exchange operations ([2.2.4](#2-2-4-mnemonics-of-compound-stack-operations) and [2.2.5](#2-2-5-semantics-of-compound-stack-operations) for a more detailed explanation). In order to generate this sequence, the compiler will need to know only the three values $i$, $j$ and $k$, describing the old locations of variables or temporary values in question, and some flags describing whether each value will be needed thereafter or is needed only for this primitive or function call. The locations of other variables and temporary values will be affected in the process, but a compiler (or a human programmer) can easily track their new locations.
Similarly, if the results returned from a function need to be discarded or moved to other stack registers, a suitable sequence of exchange and pop operations will do the job. In the typical case of one return value in $\texttt{s0}$, this is achieved either by an $\texttt{XCHG s}(i)$ or a $\texttt{POP s}(i)$ (in most cases, a $\texttt{DROP}$) operation.[9](#fn9)
Rearranging the result value or values before returning from a function is essentially the same problem as arranging arguments for a function call, and is achieved similarly.
### 2.2.3. Compound stack manipulation primitives [#223-compound-stack-manipulation-primitives]
In order to improve the density of the TVM code and simplify development of compilers, compound stack manipulation primitives may be defined, each combining up to four exchange and push or exchange and pop basic primitives. Such compound stack operations might include, for example:
* $\texttt{XCHG2 s}(i)\texttt{,s}(j)$ — Equivalent to $\texttt{XCHG s1,s}(i)$; $\texttt{XCHG s}(j)$.
* $\texttt{PUSH2 s}(i)\texttt{,s}(j)$ — Equivalent to $\texttt{PUSH s}(i)$; $\texttt{PUSH s}(j+1)$.
* $\texttt{XCPU s}(i)\texttt{,s}(j)$ — Equivalent to $\texttt{XCHG s}(i)$; $\texttt{PUSH s}(j)$.
* $\texttt{PUXC s}(i)\texttt{,s}(j)$ — Equivalent to $\texttt{PUSH s}(i)$; $\texttt{SWAP}$; $\texttt{XCHG s}(j+1)$. When $j\neq i$ and $j\neq0$, it is also equivalent to $\texttt{XCHG s}(j)$; $\texttt{PUSH s}(i)$; $\texttt{SWAP}$.
* $\texttt{XCHG3 s}(i)\texttt{,s}(j)\texttt{,s}(k)$ — Equivalent to $\texttt{XCHG s2,s}(i)$; $\texttt{XCHG s1,s}(j)$; $\texttt{XCHG s}(k)$.
* $\texttt{PUSH3 s}(i)\texttt{,s}(j)\texttt{,s}(k)$ — Equivalent to $\texttt{PUSH s}(i)$; $\texttt{PUSH s}(j+1)$; $\texttt{PUSH s}(k+2)$.
Of course, such operations make sense only if they admit a more compact encoding than the equivalent sequence of basic operations. For example, if all top-of-stack exchanges, $\texttt{XCHG s1,s}(i)$ exchanges, and push and pop operations admit one-byte encodings, the only compound stack operations suggested above that might merit inclusion in the set of stack manipulation primitives are $\texttt{PUXC}$, $\texttt{XCHG3}$, and $\texttt{PUSH3}$.
These compound stack operations essentially augment other primitives (instructions) in the code with the "true" locations of their operands, somewhat similarly to what happens with two-address or three-address register machine code. However, instead of encoding these locations inside the opcode of the arithmetic or another instruction, as is customary for register machines, we indicate these locations in a preceding compound stack manipulation operation. The advantage of such an approach is that [user-defined functions](#2-1-7-arguments-to-arithmetic-primitives-on-register-machines) (or rarely used specific primitives added in a [future version](#c-3-sample-non-leaf-function) of TVM) can benefit from it as well.
### 2.2.4. Mnemonics of compound stack operations [#224-mnemonics-of-compound-stack-operations]
The mnemonics of [compound stack](#2-2-3-compound-stack-manipulation-primitives) operations, some examples of which have been provided are created as follows.
The $\gamma\geq2$ formal arguments $\texttt{s}(i_1)$, $\ldots$, $\texttt{s}(i_\gamma)$ to such an operation $O$ represent the values in the original stack that will end up in $\texttt{s}(\gamma-1)$, $\ldots$, $\texttt{s0}$ after the execution of this compound operation, at least if all $i_\nu$, $1\leq\nu\leq\gamma$, are distinct and at least $\gamma$. The mnemonic itself of the operation $O$ is a sequence of $\gamma$ two-letter strings $\texttt{PU}$ and $\texttt{XC}$, with $\texttt{PU}$ meaning that the corresponding argument is to be PUshed (i.e., a copy is to be created), and $\texttt{XC}$ meaning that the value is to be eXChanged (i.e., no other copy of the original value is created). Sequences of several $\texttt{PU}$ or $\texttt{XC}$ strings may be abbreviated to one $\texttt{PU}$ or $\texttt{XC}$ followed by the number of copies. (For instance, we write $\texttt{PUXC2PU}$ instead of $\texttt{PUXCXCPU}$.)
As an exception, if a mnemonic would consist of only $\texttt{PU}$ or only $\texttt{XC}$ strings, so that the compound operation is equivalent to a sequence of $m$ PUSHes or eXCHanGes, the notation $\texttt{PUSH}m$ or $\texttt{XCHG}m$ is used instead of $\texttt{PU}m$ or $\texttt{XC}m$.
### 2.2.5. Semantics of compound stack operations [#225-semantics-of-compound-stack-operations]
Each compound $\gamma$-ary operation $O$ $\texttt{s}(i_1)$,$\ldots$,$\texttt{s}(i_\gamma)$ is translated into an equivalent sequence of basic stack operations by induction in $\gamma$ as follows:
* As a base of induction, if $\gamma=0$, the only nullary compound stack operation corresponds to an empty sequence of basic stack operations.
* Equivalently, we might begin the induction from $\gamma=1$. Then $\texttt{PU s}(i)$ corresponds to the sequence consisting of one basic operation $\texttt{PUSH s}(i)$, and $\texttt{XC s}(i)$ corresponds to the one-element sequence consisting of $\texttt{XCHG s}(i)$.
* Otherwise, if $\gamma\geq2$, compound operation $O$ has one of two forms:
1. $O$ $\texttt{s}(i_1)$,$\ldots$,$\texttt{s}(i_\gamma)$, with $O=\texttt{XC}O'$, where $O'$ is a compound operation of arity $\gamma-1$ (i.e., the mnemonic of $O'$ consists of $\gamma-1$ strings $\texttt{XC}$ and $\texttt{PU}$). Let $\alpha$ be the total quantity of $\texttt{PU}$shes in $O$, and $\beta$ be that of e$\texttt{XC}$hanges, so that $\alpha+\beta=\gamma$. Then the original operation is translated into $\texttt{XCHG s}(\beta-1)\texttt{,s}(i_1)$, followed by the translation of $O'$ $\texttt{s}(i_2)$,$\ldots$,$\texttt{s}(i_\gamma)$, defined by the induction hypothesis.
2. $O$ $\texttt{s}(i_1)$,$\ldots$,$\texttt{s}(i_\gamma)$, with $O=\texttt{PU}O'$, where $O'$ is a compound operation of arity $\gamma-1$. Then the original operation is translated into $\texttt{PUSH s}(i_1)$; $\texttt{XCHG s}(\beta)$, followed by the translation of $O'$ $\texttt{s}(i_2+1)$,$\ldots$,$\texttt{s}(i_\gamma+1)$, defined by the induction hypothesis.[10](#fn10)
### 2.2.6. Stack manipulation instructions are polymorphic [#226-stack-manipulation-instructions-are-polymorphic]
Notice that the stack manipulation instructions are almost the only "polymorphic" primitives in TVM—i.e., they work with values of arbitrary types (including the value types that will appear only in future revisions of TVM). For example, $\texttt{SWAP}$ always interchanges the two top values of the stack, even if one of them is an integer and the other is a cell. Almost all other instructions, especially the data processing instructions (including arithmetic instructions), require each of their arguments to be of some fixed type (possibly different for different arguments).
## 2.3 Efficiency of stack manipulation primitives [#23---efficiency-of-stack-manipulation-primitives]
Stack manipulation primitives employed by a stack machine, such as TVM, have to be implemented very efficiently, because they constitute more than half of all the instructions used in a typical program. In fact, TVM performs all these instructions in a (small) constant time, regardless of the values involved (even if they represent very large integers or very large trees of cells).
### 2.3.1. Implementation of stack manipulation primitives: using references for operations instead of objects [#231-implementation-of-stack-manipulation-primitives-using-references-for-operations-instead-of-objects]
The efficiency of TVM's implementation of stack manipulation primitives results from the fact that a typical TVM implementation keeps in the stack not the value objects themselves, but only the references (pointers) to such objects. Therefore, a $\texttt{SWAP}$ instruction only needs to interchange the references at $\texttt{s0}$ and $\texttt{s1}$, not the actual objects they refer to.
### 2.3.2. Efficient implementation of $\texttt{DUP}$ and $\texttt{PUSH}$ instructions using copy-on-write [#232--efficient-implementation-of-textttdup-and-textttpush-instructions-using-copy-on-write]
Furthermore, a $\texttt{DUP}$ (or, more generally, $\texttt{PUSH s}(i)$) instruction, which appears to make a copy of a potentially large object, also works in small constant time, because it uses a copy-on-write technique of delayed copying: it copies only the reference instead of the object itself, but increases the "reference counter" inside the object, thus sharing the object between the two references. If an attempt to modify an object with a reference counter greater than one is detected, a separate copy of the object in question is made first (incurring a certain "non-uniqueness penalty" or "copying penalty" for the data manipulation instruction that triggered the creation of a new copy).
### 2.3.3. Garbage collecting and reference counting [#233-garbage-collecting-and-reference-counting]
When the reference counter of a TVM object becomes zero (for example, because the last reference to such an object has been consumed by a $\texttt{DROP}$ operation or an arithmetic instruction), it is immediately freed. Because cyclic references are impossible in TVM data structures, this method of reference counting provides a fast and convenient way of freeing unused objects, replacing slow and unpredictable garbage collectors.
### 2.3.4. Transparency of the implementation: Stack values are "values", not "references" [#234-transparency-of-the-implementation-stack-values-are-values-not-references]
Regardless of the implementation details just discussed, all stack values are really "values", not "references", from the perspective of the TVM programmer, similarly to the values of all types in functional programming languages. Any attempt to modify an existing object referred to from any other objects or stack locations will result in a transparent replacement of this object by its perfect copy before the modification is actually performed.
In other words, the programmer should always act as if the objects themselves were directly manipulated by stack, arithmetic, and other data transformation primitives, and treat the previous discussion only as an explanation of the high efficiency of the stack manipulation primitives.
### 2.3.5. Absence of circular references [#235-absence-of-circular-references]
One might attempt to create a circular reference between two cells, $A$ and $B$, as follows: first create $A$ and write some data into it; then create $B$ and write some data into it, along with a reference to previously constructed cell $A$; finally, add a reference to $B$ into $A$. While it may seem that after this sequence of operations we obtain a cell $A$, which refers to $B$, which in turn refers to $A$, this is not the case. In fact, we obtain a new cell $A'$, which contains a copy of the data originally stored into cell $A$ along with a reference to cell $B$, which contains a reference to (the original) cell $A$.
In this way the transparent copy-on-write mechanism and the "everything is a value" paradigm enable us to create new cells using only previously constructed cells, thus forbidding the appearance of circular references. This property also applies to all other data structures: for instance, the absence of circular references enables TVM to use reference counting to immediately free unused memory instead of relying on garbage collectors. Similarly, this property is crucial for storing data in the TON Blockchain.
***
# 3 Cells, memory, and persistent storage [#3---cells-memory-and-persistent-storage]
This chapter briefly describes TVM cells, used to represent all data structures inside the TVM memory and its persistent storage, and the basic operations used to create cells, write (or serialize) data into them, and read (or deserialize) data from them.
## 3.1 Generalities on cells [#31---generalities-on-cells]
This section presents a classification and general descriptions of cell types.
### 3.1.1. TVM memory and persistent storage consist of cells [#311-tvm-memory-and-persistent-storage-consist-of-cells]
Recall that the TVM memory and persistent storage consist of *(TVM) cells*. Each cell contains up to 1023 bits of data and up to four references to other cells.[11](#fn11) [Circular references](#2-3-5-absence-of-circular-references) are forbidden and cannot be created by means of TVM. In this way, all cells kept in TVM memory and persistent storage constitute a directed acyclic graph (DAG).
### 3.1.2. Ordinary and exotic cells [#312-ordinary-and-exotic-cells]
Apart from the data and references, a cell has a *cell type*, encoded by an integer $-1\ldots255$. A cell of type $-1$ is called *ordinary*; such cells do not require any special processing. Cells of other types are called *exotic*, and may be *loaded*—automatically replaced by other cells when an attempt to deserialize them (i.e., to convert them into a *Slice* by a $\texttt{CTOS}$ instruction) is made. They may also exhibit a non-trivial behavior when their hashes are computed.
The most common use for exotic cells is to represent some other cells—for instance, cells present in an external library, or pruned from the original tree of cells when a Merkle proof has been created.
The type of an exotic cell is stored as the first eight data bits of its data. If an exotic cell has less than eight data bits, it is invalid.
### 3.1.3. The level of a cell [#313-the-level-of-a-cell]
Every cell $c$ has another attribute $\text{Lvl}(c)$ called its *(de Brujn) level*, which currently takes integer values in the range $0\ldots3$. The level of an ordinary cell is always equal to the maximum of the levels of all its children $c_i$:
$$
\text{Lvl}(c)=\max_{1\leq i\leq r}\text{Lvl}(c_i) \tag{1}
$$
for an ordinary cell $c$ containing $r$ references to cells $c_1$, $\ldots$, $c_r$. If $r=0$, $\text{Lvl}(c)=0$. Exotic cells may have different rules for setting their level.
A cell's level affects the number of *higher hashes* it has. More precisely, a level $l$ cell has $l$ higher hashes $\text{Hash}_1(c)$, $\ldots$, $\text{Hash}_l(c)$ in addition to its representation hash $\text{Hash}(c)=\text{Hash}_\infty(c)$. Cells of non-zero level appear inside *Merkle proofs* and *Merkle updates*, after some branches of the tree of cells representing a value of an abstract data type are pruned.
### 3.1.4. Standard cell representation [#314-standard-cell-representation]
When a cell needs to be transferred by a network protocol or stored in a disk file, it must be *serialized*. The standard representation $\text{CellRepr}(c)=\text{CellRepr}_\infty(c)$ of a cell $c$ as an octet (byte) sequence is constructed as follows:
1. Two descriptor bytes $d_1$ and $d_2$ are serialized first. Byte $d_1$ equals $r+8s+32l$, where $0\leq r\leq 4$ is the quantity of cell references contained in the cell, $0\leq l\leq 3$ is the level of the cell, and $0\leq s\leq 1$ is $1$ for exotic cells and $0$ for ordinary cells. Byte $d_2$ equals $\lfloor b/8\rfloor+\lceil b/8\rceil$, where $0\leq b\leq 1023$ is the quantity of data bits in $c$.
2. Then the data bits are serialized as $\lceil b/8\rceil$ 8-bit octets (bytes). If $b$ is not a multiple of eight, a binary $\texttt{1}$ and up to six binary $\texttt{0}$s are appended to the data bits. After that, the data is split into $\lceil b/8\rceil$ eight-bit groups, and each group is interpreted as an unsigned big-endian integer $0\ldots 255$ and stored into an octet.
3. Finally, each of the $r$ cell references is represented by 32 bytes containing the 256-bit [representation hash](#3-1-5-the-representation-hash-of-a-cell) $\text{Hash}(c_i)$ of the cell $c_i$ referred to.
In this way, $2+\lceil b/8\rceil+32r$ bytes of $\text{CellRepr}(c)$ are obtained.
### 3.1.5. The representation hash of a cell [#315-the-representation-hash-of-a-cell]
The 256-bit *representation hash* or simply *hash* $\text{Hash}(c)$ of a cell $c$ is recursively defined as the SHA-256 of the standard representation of the cell $c$:
$$
\text{Hash}(c):=\text{Sha256}\bigl(\text{CellRepr}(c)\bigr) \tag{2}
$$
Notice that [cyclic cell references](#2-3-5-absence-of-circular-references) are not allowed and cannot be created by means of the TVM, so this recursion always ends, and the representation hash of any cell is well-defined.
### 3.1.6. The higher hashes of a cell [#316-the-higher-hashes-of-a-cell]
Recall that a cell $c$ of level $l$ has $l$ higher hashes $\text{Hash}_i(c)$, $1\leq i\leq l$, as well. Exotic cells have their own rules for computing their higher hashes. Higher hashes $\text{Hash}_i(c)$ of an ordinary cell $c$ are computed similarly to its representation hash, but using the higher hashes $\text{Hash}_i(c_j)$ of its children $c_j$ instead of their representation hashes $\text{Hash}(c_j)$. By convention, we set $\text{Hash}_\infty(c):=\text{Hash}(c)$, and $\text{Hash}_i(c):=\text{Hash}_\infty(c)=\text{Hash}(c)$ for all $i>l$.[12](#fn12)
### 3.1.7. Types of exotic cells [#317-types-of-exotic-cells]
TVM currently supports the following cell types:
* Type $-1$: *Ordinary cell* — Contains up to 1023 bits of data and up to four cell references.
* Type 1: *Pruned branch cell $c$* — May have any level $1\leq l\leq 3$. It contains exactly $8+256l$ data bits: first an 8-bit integer equal to 1 (representing the cell's type), then its $l$ higher hashes $\text{Hash}_1(c)$, $\ldots$, $\text{Hash}_l(c)$. The level $l$ of a pruned branch cell may be called its *de Brujn index*, because it determines the outer Merkle proof or Merkle update during the construction of which the branch has been pruned. An attempt to load a pruned branch cell usually leads to an exception.
* Type 2: *Library reference cell* — Always has level 0, and contains $8+256$ data bits, including its 8-bit type integer 2 and the representation hash $\text{Hash}(c')$ of the library cell being referred to. When loaded, a library reference cell may be transparently replaced by the cell it refers to, if found in the current *library context*.
* Type 3: *Merkle proof cell $c$* — Has exactly one reference $c_1$ and level $0\leq l\leq 3$, which must be one less than the level of its only child $c_1$:
$$
\text{Lvl}(c)=\max(\text{Lvl}(c_1)-1,0) \tag{3}
$$
The $8+256$ data bits of a Merkle proof cell contain its 8-bit type integer 3, followed by $\text{Hash}_1(c_1)$ (assumed to be equal to $\text{Hash}(c_1)$ if $\text{Lvl}(c_1)=0$). The higher hashes $\text{Hash}_i(c)$ of $c$ are computed similarly to the higher hashes of an ordinary cell, but with $\text{Hash}_{i+1}(c_1)$ used instead of $\text{Hash}_i(c_1)$. When loaded, a Merkle proof cell is replaced by $c_1$.
* Type 4: *Merkle update cell $c$* — Has two children $c_1$ and $c_2$. Its level $0\leq l\leq 3$ is given by
$$
\text{Lvl}(c)=\max(\text{Lvl}(c_1)-1,\text{Lvl}(c_2)-1,0) \tag{4}
$$
A Merkle update behaves like a Merkle proof for both $c_1$ and $c_2$, and contains $8+256+256$ data bits with $\text{Hash}_1(c_1)$ and $\text{Hash}_1(c_2)$. However, an extra requirement is that *all pruned branch cells $c'$ that are descendants of $c_2$ and are bound by $c$ must also be descendants of $c_1$.*[13](#fn13) When a Merkle update cell is loaded, it is replaced by $c_2$.
### 3.1.8. All values of algebraic data types are trees of cells [#318-all-values-of-algebraic-data-types-are-trees-of-cells]
Arbitrary values of arbitrary algebraic data types (e.g., all types used in functional programming languages) can be serialized into trees of cells (of level 0), and such representations are used for representing such values within TVM. The [copy-on-write mechanism](#2-3-2-efficient-implementation-of-and-instructions-using-copy-on-write) allows TVM to identify cells containing the same data and references, and to keep only one copy of such cells. This actually transforms a tree of cells into a directed acyclic graph (with the additional property that all its vertices be accessible from a marked vertex called the "root"). However, this is a storage optimization rather than an essential property of TVM. From the perspective of a TVM code programmer, one should think of TVM data structures as trees of cells.
### 3.1.9. TVM code is a tree of cells [#319-tvm-code-is-a-tree-of-cells]
The TVM code itself is also represented by a tree of cells. Indeed, TVM code is simply a value of some complex algebraic data type, and as such, it can be serialized into a tree of cells.
The exact way in which the TVM code (e.g., TVM assembly code) is transformed into a tree of cells is explained later ([4.1.4](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop) and [5.2](#5-2-instruction-encoding)), in sections discussing control flow instructions, continuations, and TVM instruction encoding.
### 3.1.10. "Everything is a bag of cells" paradigm [#3110-everything-is-a-bag-of-cells-paradigm]
All the data used by the TON Blockchain, including the blocks themselves and the blockchain state, can be represented—and are represented—as collections, or [bags of cells](/blockchain-basics/whitepapers/ton#2-5-14-“everything-is-a-bag-of-cells”-philosophy). We see that TVM's [structure of data](#3-1-8-all-values-of-algebraic-data-types-are-trees-of-cells) and [code](#3-1-9-tvm-code-is-a-tree-of-cells) nicely fits into this "everything is a bag of cells" paradigm. In this way, TVM can naturally be used to execute smart contracts in the TON Blockchain, and the TON Blockchain can be used to store the code and persistent data of these smart contracts between invocations of TVM. (Of course, both TVM and the TON Blockchain have been designed so that this would become possible.)
## 3.2 Data manipulation instructions and cells [#32---data-manipulation-instructions-and-cells]
The next large group of TVM instructions consists of *data manipulation instructions*, also known as *cell manipulation instructions* or simply *cell instructions*. They correspond to memory access instructions of other architectures.
### 3.2.1. Classes of cell manipulation instructions [#321-classes-of-cell-manipulation-instructions]
The TVM cell instructions are naturally subdivided into two principal classes:
* *Cell creation instructions* or *serialization instructions*, used to construct new cells from values previously kept in the stack and previously constructed cells.
* *Cell parsing instructions* or *deserialization instructions*, used to extract data previously stored into cells by cell creation instructions.
Additionally, there are *exotic cell instructions* used to create and inspect [exotic cells](#3-1-2-ordinary-and-exotic-cells), which in particular are used to represent pruned branches of Merkle proofs and Merkle proofs themselves.
### 3.2.2. *Builder* and *Slice* values [#322-builder-and-slice-values]
Cell creation instructions usually work with [Builder values](#1-1-3-preliminary-list-of-value-types), which can be kept only in the stack. Such values represent partially constructed cells, for which fast operations for appending bitstrings, integers, other cells, and references to other cells can be defined. Similarly, cell parsing instructions make heavy use of *Slice* values, which represent either the remainder of a partially parsed cell, or a value (subcell) residing inside such a cell and extracted from it by a parsing instruction.
### 3.2.3. *Builder* and *Slice* values exist only as stack values [#323-builder-and-slice-values-exist-only-as-stack-values]
Notice that *Builder* and *Slice* objects appear only as values in a TVM stack. They cannot be stored in "memory" (i.e., trees of cells) or "persistent storage" (which is also a bag of cells). In this sense, there are far more *Cell* objects than *Builder* or *Slice* objects in a TVM environment, but, somewhat paradoxically, a TVM program sees *Builder* and *Slice* objects in its stack more often than *Cell*s. In fact, a TVM program does not have much use for *Cell* values, because they are immutable and opaque; all cell manipulation primitives require that a *Cell* value be transformed into either a *Builder* or a *Slice* first, before it can be modified or inspected.
### 3.2.4. TVM has no separate *Bitstring* value type [#324-tvm-has-no-separate-bitstring-value-type]
Notice that TVM offers no separate bitstring value type. Instead, bitstrings are represented by *Slices* that happen to have no references at all, but can still contain up to 1023 data bits.
### 3.2.5. Cells and cell primitives are bit-oriented, not byte-oriented [#325-cells-and-cell-primitives-are-bit-oriented-not-byte-oriented]
An important point is that *TVM regards data kept in cells as sequences (strings, streams) of (up to 1023) bits, not of bytes*. In other words, TVM is a *bit-oriented machine*, not a byte-oriented machine. If necessary, an application is free to use, say, 21-bit integer fields inside records serialized into TVM cells, thus using fewer persistent storage bytes to represent the same data.
### 3.2.6. Taxonomy of cell creation (serialization) primitives [#326-taxonomy-of-cell-creation-serialization-primitives]
Cell creation primitives usually accept a *Builder* argument and an argument representing the value to be serialized. Additional arguments controlling some aspects of the serialization process (e.g., how many bits should be used for serialization) can be also provided, either in the stack or as an immediate value inside the instruction. The result of a cell creation primitive is usually another *Builder*, representing the concatenation of the original builder and the serialization of the value provided.
Therefore, one can suggest a classification of cell serialization primitives according to the answers to the following questions:
* Which is the type of values being serialized?
* How many bits are used for serialization? If this is a variable number, does it come from the stack, or from the instruction itself?
* What happens if the value does not fit into the prescribed number of bits? Is an exception generated, or is a success flag equal to zero silently returned in the top of stack?
* What happens if there is insufficient space left in the *Builder*? Is an exception generated, or is a zero success flag returned along with the unmodified original *Builder*?
The mnemonics of cell serialization primitives usually begin with $\texttt{ST}$. Subsequent letters describe the following attributes:
* The type of values being serialized and the serialization format (e.g., $\texttt{I}$ for signed integers, $\texttt{U}$ for unsigned integers).
* The source of the field width in bits to be used (e.g., $\texttt{X}$ for integer serialization instructions means that the bit width $n$ is supplied in the stack; otherwise it has to be embedded into the instruction as an immediate value).
* The action to be performed if the operation cannot be completed (by default, an exception is generated; "quiet" versions of serialization instructions are marked by a $\texttt{Q}$ letter in their mnemonics).
This classification scheme is used to create a more complete taxonomy of [cell serialization primitives](#a-7-1-cell-serialization-primitives).
### 3.2.7. Integer serialization primitives [#327-integer-serialization-primitives]
Integer serialization primitives can be classified according to the above taxonomy as well. For example:
* There are signed and unsigned (big-endian) integer serialization primitives.
* The size $n$ of the bit field to be used ($1\leq n\leq 257$ for signed integers, $0\leq n\leq 256$ for unsigned integers) can either come from the top of stack or be embedded into the instruction itself.
* If the integer $x$ to be serialized is not in the range $-2^{n-1}\leq x<2^{n-1}$ (for signed integer serialization) or $0\leq x<2^n$ (for unsigned integer serialization), a range check exception is usually generated, and if $n$ bits cannot be stored into the provided *Builder*, a cell overflow exception is usually generated.
* Quiet versions of serialization instructions do not throw exceptions; instead, they push $-1$ on top of the resulting *Builder* upon success, or return the original *Builder* with $0$ on top of it to indicate failure.
Integer serialization instructions have mnemonics like $\texttt{STU 20}$ ("store an unsigned 20-bit integer value") or $\texttt{STIXQ}$ ("quietly store an integer value of variable length provided in the stack"). The full list of these [instructions](#a-7-1-cell-serialization-primitives)—includes their mnemonics, descriptions, and opcodes.
### 3.2.8. Integers in cells are big-endian by default [#328-integers-in-cells-are-big-endian-by-default]
Notice that the default order of bits in *Integers* serialized into *Cells* is *big-endian*, not little-endian.[14](#fn14) In this respect *TVM is a big-endian machine*. However, this affects only the serialization of integers inside cells. The internal representation of the *Integer* value type is implementation-dependent and irrelevant for the operation of TVM. Besides, there are some special primitives such as $\texttt{STULE}$ for (de)serializing little-endian integers, which must be stored into an integral number of bytes (otherwise "little-endianness" does not make sense, unless one is also willing to revert the order of bits inside octets). Such primitives are useful for interfacing with the little-endian world—for instance, for parsing custom-format messages arriving to a TON Blockchain smart contract from the outside world.
### 3.2.9. Other serialization primitives [#329-other-serialization-primitives]
Other cell creation primitives serialize bitstrings (i.e., cell slices without references), either taken from the stack or supplied as literal arguments; cell slices (which are concatenated to the cell builder in an obvious way); other *Builders* (which are also concatenated); and cell references ($\texttt{STREF}$).
### 3.2.10. Other cell creation primitives [#3210-other-cell-creation-primitives]
In addition to the cell serialization primitives for certain built-in value types described above, there are simple primitives that create a new empty *Builder* and push it into the stack ($\texttt{NEWC}$), or transform a *Builder* into a *Cell* ($\texttt{ENDC}$), thus finishing the cell creation process. An $\texttt{ENDC}$ can be combined with a $\texttt{STREF}$ into a single instruction $\texttt{ENDCST}$, which finishes the creation of a cell and immediately stores a reference to it in an "outer" *Builder*. There are also primitives that obtain the quantity of data bits or references already stored in a *Builder*, and check how many data bits or references can be stored.
### 3.2.11. Taxonomy of cell deserialisation primitives [#3211-taxonomy-of-cell-deserialisation-primitives]
Cell parsing, or deserialization, [primitives](#3-2-6-taxonomy-of-cell-creation-serialization-primitives) can be classified with the following modifications:
* They work with *Slices* (representing the remainder of the cell being parsed) instead of *Builders*.
* They return deserialized values instead of accepting them as arguments.
* They may come in two flavors, depending on whether they remove the deserialized portion from the *Slice* supplied ("fetch operations") or leave it unmodified ("prefetch operations").
* Their mnemonics usually begin with $\texttt{LD}$ (or $\texttt{PLD}$ for prefetch operations) instead of $\texttt{ST}$.
For example, an unsigned big-endian 20-bit integer previously serialized into a cell by a $\texttt{STU 20}$ instruction is likely to be deserialized later by a matching $\texttt{LDU 20}$ instruction.
Again, more detailed information about these instructions is provided in [A.7.2](#a-7-2-cell-deserialization-primitives).
### 3.2.12. Other cell slice primitives [#3212-other-cell-slice-primitives]
In addition to the cell deserialisation primitives outlined above, TVM provides some obvious primitives for initializing and completing the cell deserialization process. For instance, one can convert a *Cell* into a *Slice* ($\texttt{CTOS}$), so that its deserialisation might begin; or check whether a *Slice* is empty, and generate an exception if it is not ($\texttt{ENDS}$); or deserialize a cell reference and immediately convert it into a *Slice* ($\texttt{LDREFTOS}$, equivalent to two instructions $\texttt{LDREF}$ and $\texttt{CTOS}$).
### 3.2.13. Modifying a serialized value in a cell [#3213-modifying-a-serialized-value-in-a-cell]
The reader might wonder how the values serialized inside a cell may be modified. Suppose a cell contains three serialized 29-bit integers, $(x,y,z)$, representing the coordinates of a point in space, and we want to replace $y$ with $y'=y+1$, leaving the other coordinates intact. How would we achieve this?
TVM does not offer any ways to modify existing values ([2.3.4](#2-3-4-transparency-of-the-implementation:-stack-values-are-“values”,-not-“references”) and [2.3.5](#2-3-5-absence-of-circular-references)), so our example can only be accomplished with a series of operations as follows:
1. Deserialize the original cell into three *Integer*s $x$, $y$, $z$ in the stack (e.g., by $\texttt{CTOS}$; $\texttt{LDI 29}$; $\texttt{LDI 29}$; $\texttt{LDI 29}$; $\texttt{ENDS}$).
2. Increase $y$ by one (e.g., by $\texttt{SWAP}$; $\texttt{INC}$; $\texttt{SWAP}$).
3. Finally, serialize the resulting *Integer*s into a new cell (e.g., by $\texttt{XCHG s2}$; $\texttt{NEWC}$; $\texttt{STI 29}$; $\texttt{STI 29}$; $\texttt{STI 29}$; $\texttt{ENDC}$).
### 3.2.14. Modifying the persistent storage of a smart contract [#3214-modifying-the-persistent-storage-of-a-smart-contract]
If the TVM code wants to modify its persistent storage, represented by the tree of cells rooted at $\texttt{c4}$, it simply needs to rewrite control register $\texttt{c4}$ by the root of the tree of cells containing the new value of its persistent storage. (If only part of the persistent storage needs to be [modified](#3-2-13-modifying-a-serialized-value-in-a-cell).)
***
## 3.3 Hashmaps, or dictionaries [#33---hashmaps-or-dictionaries]
*Hashmaps*, or *dictionaries*, are a specific data structure represented by a tree of cells. Essentially, a hashmap represents a map from *keys*, which are bitstrings of either fixed or variable length, into *values* of an arbitrary type $X$, in such a way that fast lookups and modifications be possible. While any such structure might be inspected or modified with the aid of generic cell serialization and deserialization primitives, TVM introduces special primitives to facilitate working with these hashmaps.
### 3.3.1. Basic hashmap types [#331-basic-hashmap-types]
The two most basic hashmap types predefined in TVM are *HashmapE* $n$ $X$ or *HashmapE*$(n,X)$, which represents a partially defined map from $n$-bit strings (called *keys*) for some fixed $0\leq n\leq 1023$ into *values* of some type $X$, and *Hashmap*$(n,X)$, which is similar to *HashmapE*$(n,X)$ but is not allowed to be empty (i.e., it must contain at least one key-value pair).
Other hashmap types are also available—for example, one with keys of arbitrary length up to some predefined bound (up to 1023 bits).
### 3.3.2. Hashmaps as Patricia trees [#332-hashmaps-as-patricia-trees]
The abstract representation of a hashmap in TVM is a *Patricia tree*, or a *compact binary trie*. It is a binary tree with edges labelled by bitstrings, such that the concatenation of all edge labels on a path from the root to a leaf equals a key of the hashmap. The corresponding value is kept in this leaf (for hashmaps with keys of fixed length), or optionally in the intermediate vertices as well (for hashmaps with keys of variable length). Furthermore, any intermediate vertex must have two children, and the label of the left child must begin with a binary zero, while the label of the right child must begin with a binary one. This enables us not to store the first bit of the edge labels explicitly.
It is easy to see that any collection of key-value pairs (with distinct keys) is represented by a unique Patricia tree.
### 3.3.3. Serialization of hashmaps [#333-serialization-of-hashmaps]
The serialization of a hashmap into a tree of cells (or, more generally, into a *Slice*) is defined by the following TL-B scheme:[15](#fn15)
```
bit#_ _:(## 1) = Bit;
hm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)
{n = (~m) + l} node:(HashmapNode m X) = Hashmap n X;
hmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;
hmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X)
right:^(Hashmap n X) = HashmapNode (n + 1) X;
hml_short$0 {m:#} {n:#} len:(Unary ~n)
s:(n * Bit) = HmLabel ~n m;
hml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;
hml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m;
unary_zero$0 = Unary ~0;
unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);
hme_empty$0 {n:#} {X:Type} = HashmapE n X;
hme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X;
true#_ = True;
_ {n:#} _:(Hashmap n True) = BitstringSet n;
```
### 3.3.4. Brief explanation of TL-B schemes [#334-brief-explanation-of-tl-b-schemes]
A TL-B scheme, like the one above, includes the following components.
The right-hand side of each "equation" is a *type*, either simple (such as $\texttt{Bit}$ or $\texttt{True}$) or parametrized (such as $\texttt{Hashmap}$ $n$ $X$). The parameters of a type must be either natural numbers (i.e., non-negative integers, which are required to fit into 32 bits in practice), such as $n$ in $\texttt{Hashmap}$ $n$ $X$, or other types, such as $X$ in $\texttt{Hashmap}$ $n$ $X$.
The left-hand side of each equation describes a way to define, or even to serialize, a value of the type indicated in the right-hand side. Such a description begins with the name of a *constructor*, such as $\texttt{hm\_edge}$ or $\texttt{hml\_long}$, immediately followed by an optional *constructor tag*, such as #\_ or \$10, which describes the bitstring used to encode (serialize) the constructor in question. Such tags may be given in either binary (after a dollar sign) or [hexadecimal notation](#1-0-notation-for-bitstrings) (after a hash sign), using the conventions. If a tag is not explicitly provided, TL-B computes a default 32-bit constructor tag by hashing the text of the "equation" defining this constructor in a certain fashion. Therefore, empty tags must be explicitly provided by #\_ or $\_. All constructor names must be distinct, and constructor tags for the same type must constitute a prefix code (otherwise the deserialization would not be unique).
The constructor and its optional tag are followed by *field definitions*. Each field definition is of the form $\textit{ident}:\textit{type-expr}$, where $\textit{ident}$ is an identifier with the name of the field[16](#fn16) (replaced by an underscore for anonymous fields), and $\textit{type-expr}$ is the field's type. The type provided here is a *type expression*, which may include simple types or parametrized types with suitable parameters. *Variables*—i.e., the (identifiers of the) previously defined fields of types $\#$ (natural numbers) or $\textit{Type}$ (type of types)—may be used as parameters for the parametrized types. The serialization process recursively serializes each field according to its type, and the serialization of a value ultimately consists of the concatenation of bitstrings representing the constructor (i.e., the constructor tag) and the field values.
Some fields may be *implicit*. Their definitions are surrounded by curly braces, which indicate that the field is not actually present in the serialization, but that its value must be deduced from other data (usually the parameters of the type being serialized).
Some occurrences of "variables" (i.e., already-defined fields) are prefixed by a tilde. This indicates that the variable's occurrence is used in the opposite way of the default behavior: in the left-hand side of the equation, it means that the variable will be deduced (computed) based on this occurrence, instead of substituting its previously computed value; in the right-hand side, conversely, it means that the variable will not be deduced from the type being serialized, but rather that it will be computed during the deserialization process. In other words, a tilde transforms an "input argument" into an "output argument", and vice versa.[17](#fn17)
Finally, some equalities may be included in curly brackets as well. These are certain "equations", which must be satisfied by the "variables" included in them. If one of the variables is prefixed by a tilde, its value will be uniquely determined by the values of all other variables participating in the equation (which must be known at this point) when the definition is processed from the left to the right.
A caret (^) preceding a type $X$ means that instead of serializing a value of type $X$ as a bitstring inside the current cell, we place this value into a separate cell, and add a reference to it into the current cell. Therefore `^`$X$ means "the type of references to cells containing values of type $X$".
Parametrized type $\texttt{\#<= }p$ with $p:\texttt{\#}$ (this notation means "$p$ of type $\texttt{\#}$", i.e., a natural number) denotes the subtype of the natural numbers type $\texttt{\#}$, consisting of integers $0\ldots p$; it is serialized into $\lceil\log_2(p+1)\rceil$ bits as an unsigned big-endian integer. Type $\texttt{\#}$ by itself is serialized as an unsigned 32-bit integer. Parametrized type $\texttt{\#\# }b$ with $b:\texttt{\#<=}31$ is equivalent to $\texttt{\#<= }2^b-1$ (i.e., it is an unsigned $b$-bit integer).
### 3.3.5. Application to the serialization of hashmaps [#335-application-to-the-serialization-of-hashmaps]
Let us explain the net result of applying the [general rules](#3-3-4-brief-explanation-of-tl-b-schemes) to the [TL-B scheme](#3-3-3-serialization-of-hashmaps).
Suppose we wish to serialize a value of type *HashmapE* $n$ $X$ for some integer $0\leq n\leq 1023$ and some type $X$ (i.e., a dictionary with $n$-bit keys and values of type $X$, admitting an abstract representation as a [Patricia tree](#3-3-2-hashmaps-as-patricia-trees)).
First of all, if our dictionary is empty, it is serialized into a single binary $\texttt{0}$, which is the tag of nullary constructor $\texttt{hme\_empty}$. Otherwise, its serialization consists of a binary $\texttt{1}$ (the tag of $\texttt{hme\_root}$), along with a reference to a cell containing the serialization of a value of type *Hashmap* $n$ $X$ (i.e., a necessarily non-empty dictionary).
The only way to serialize a value of type *Hashmap* $n$ $X$ is given by the $\texttt{hm\_edge}$ constructor, which instructs us to serialize first the label $\texttt{label}$ of the edge leading to the root of the subtree under consideration (i.e., the common prefix of all keys in our (sub)dictionary). This label is of type $\texttt{HmLabel}$ $l^\perp$ $n$, which means that it is a bitstring of length at most $n$, serialized in such a way that the true length $l$ of the label, $0\leq l\leq n$, becomes known from the [serialization](#3-3-6-serialization-of-labels) of the label.
The label must be followed by the serialization of a $\texttt{node}$ of type $\texttt{HashmapNode}$ $m$ $X$, where $m=n-l$. It corresponds to a vertex of the Patricia tree, representing a non-empty subdictionary of the original dictionary with $m$-bit keys, obtained by removing from all the keys of the original subdictionary their common prefix of length $l$.
If $m=0$, a value of type $\texttt{HashmapNode}$ $0$ $X$ is given by the $\texttt{hmn\_leaf}$ constructor, which describes a leaf of the Patricia tree—or, equivalently, a subdictionary with $0$-bit keys. A leaf simply consists of the corresponding $\texttt{value}$ of type $X$ and is serialized accordingly.
On the other hand, if $m>0$, a value of type $\texttt{HashmapNode}$ $m$ $X$ corresponds to a fork (i.e., an intermediate node) in the Patricia tree, and is given by the $\texttt{hmn\_fork}$ constructor. Its serialization consists of $\texttt{left}$ and $\texttt{right}$, two references to cells containing values of type $\texttt{Hashmap}$ $m-1$ $X$, which correspond to the left and the right child of the intermediate node in question—or, equivalently, to the two subdictionaries of the original dictionary consisting of key-value pairs with keys beginning with a binary $\texttt{0}$ or a binary $\texttt{1}$, respectively. Because the first bit of all keys in each of these subdictionaries is known and fixed, it is removed, and the resulting (necessarily non-empty) subdictionaries are recursively serialized as values of type $\texttt{Hashmap}$ $m-1$ $X$.
### 3.3.6. Serialization of labels [#336-serialization-of-labels]
There are several ways to serialize a label of length at most $n$, if its exact length is $l\leq n$ (recall that the exact length must be deducible from the serialization of the label itself, while the upper bound $n$ is known before the label is serialized or deserialized). These ways are described by the three constructors $\texttt{hml\_short}$, $\texttt{hml\_long}$, and $\texttt{hml\_same}$ of type $\texttt{HmLabel}$ $l^\perp$ $n$:
* $\texttt{hml\_short}$ — Describes a way to serialize "short" labels, of small length $l\leq n$. Such a serialization consists of a binary $\texttt{0}$ (the constructor tag of $\texttt{hml\_short}$), followed by $l$ binary $\texttt{1}$s and one binary $\texttt{0}$ (the unary representation of the length $l$), followed by $l$ bits comprising the label itself.
* $\texttt{hml\_long}$ — Describes a way to serialize "long" labels, of arbitrary length $l\leq n$. Such a serialization consists of a binary $\texttt{10}$ (the constructor tag of $\texttt{hml\_long}$), followed by the big-endian binary representation of the length $0\leq l\leq n$ in $\lceil\log_2(n+1)\rceil$ bits, followed by $l$ bits comprising the label itself.
* $\texttt{hml\_same}$ — Describes a way to serialize "long" labels, consisting of $l$ repetitions of the same bit $v$. Such a serialization consists of $\texttt{11}$ (the constructor tag of $\texttt{hml\_same}$), followed by the bit $v$, followed by the length $l$ stored in $\lceil\log_2(n+1)\rceil$ bits as before.
Each label can always be serialized in at least two different fashions, using $\texttt{hml\_short}$ or $\texttt{hml\_long}$ constructors. Usually the shortest serialization (and in the case of a tie—the lexicographically smallest among the shortest) is preferred and is generated by TVM hashmap primitives, while the other variants are still considered valid.
This label encoding scheme has been designed to be efficient for dictionaries with "random" keys (e.g., hashes of some data), as well as for dictionaries with "regular" keys (e.g., big-endian representations of integers in some range).
### 3.3.7. An example of dictionary serialization [#337-an-example-of-dictionary-serialization]
Consider a dictionary with three 16-bit keys 13, 17, and 239 (considered as big-endian integers) and corresponding 16-bit values 169, 289, and 57121.
In binary form:
```
0000000000001101 => 0000000010101001
0000000000010001 => 0000000100100001
0000000011101111 => 1101111100100001
```
The corresponding Patricia tree consists of a root $A$, two intermediate nodes $B$ and $C$, and three leaf nodes $D$, $E$, and $F$, corresponding to 13, 17, and 239, respectively. The root $A$ has only one child, $B$; the label on the edge $AB$ is $00000000=0^8$. The node $B$ has two children: its left child is an intermediate node $C$ with the edge $BC$ labelled by $(0)00$, while its right child is the leaf $F$ with $BF$ labelled by $(1)1101111$. Finally, $C$ has two leaf children $D$ and $E$, with $CD$ labelled by $(0)1101$ and $CE$—by $(1)0001$.
The corresponding value of type $\texttt{HashmapE}$ 16 ($\texttt{\#\#}$ 16) may be written in human-readable form as:
```
(hme_root$1
root:^(hm_edge label:(hml_same$11 v:0 n:8) node:(hm_fork
left:^(hm_edge label:(hml_short$0 len:$110 s:$00)
node:(hm_fork
left:^(hm_edge label:(hml_long$10 n:4 s:$1101)
node:(hm_leaf value:169))
right:^(hm_edge label:(hml_long$10 n:4 s:$0001)
node:(hm_leaf value:289))))
right:^(hm_edge label:(hml_long$10 n:7 s:$1101111)
node:(hm_leaf value:57121)))))
```
The serialization of this data structure into a tree of cells consists of six cells with the following binary data contained in them:
```
A := 1
A.0 := 11 0 01000
A.0.0 := 0 110 00
A.0.0.0 := 10 100 1101 0000000010101001
A.0.0.1 := 10 100 0001 0000000100100001
A.0.1 := 10 111 1101111 1101111100100001
```
Here $A$ is the root cell, $A.0$ is the cell at the first reference of $A$, $A.1$ is the cell at the second reference of $A$, and so on. This tree of cells can be represented more compactly using the [hexadecimal notation](#1-0-notation-for-bitstrings), using indentation to reflect the tree-of-cells structure:
```
C_
C8
62_
A68054C_
A08090C_
BEFDF21
```
A total of 93 data bits and 5 references in 6 cells have been used to serialize this dictionary. Notice that a straightforward representation of three 16-bit keys and their corresponding 16-bit values would already require 96 bits (albeit without any references), so this particular serialization turns out to be quite efficient.
### 3.3.8. Ways to describe the serialization of type $X$ [#338-ways-to-describe-the-serialization-of-type-x]
Notice that the built-in TVM primitives for dictionary manipulation need to know something about the serialization of type $X$; otherwise, they would not be able to work correctly with $\mathit{Hashmap}$ $n$ $X$, because values of type $X$ are immediately contained in the Patricia tree leaf cells. There are several options available to describe the serialization of type $X$:
* The simplest case is when $X = \text{\textasciicircum}Y$ for some other type $Y$. In this case the serialization of $X$ itself always consists of one reference to a cell, which in fact must contain a value of type $Y$, something that is not relevant for dictionary manipulation primitives.
* Another simple case is when the serialization of any value of type $X$ always consists of $0\leq b\leq 1023$ data bits and $0\leq r\leq 4$ references. Integers $b$ and $r$ can then be passed to a dictionary manipulation primitive as a simple description of $X$. (Notice that the previous case corresponds to $b=0$, $r=1$.)
* A more sophisticated case can be described by four integers $1\leq b_0,b_1\leq 1023$, $0\leq r_0,r_1\leq 4$, with $b_i$ and $r_i$ used when the first bit of the serialization equals $i$. When $b_0=b_1$ and $r_0=r_1$, this case reduces to the previous one.
* Finally, the most general description of the serialization of a type $X$ is given by a *splitting function* $\mathit{split}_X$ for $X$, which accepts one *Slice* parameter $s$, and returns two *Slice*s, $s'$ and $s''$, where $s'$ is the only prefix of $s$ that is the serialization of a value of type $X$, and $s''$ is the remainder of $s$. If no such prefix exists, the splitting function is expected to throw an exception. Notice that a compiler for a high-level language, which supports some or all algebraic TL-B types, is likely to automatically generate splitting functions for all types defined in the program.
### 3.3.9. A simplifying assumption on the serialization of $X$ [#339-a-simplifying-assumption-on-the-serialization-of-x]
One may notice that values of type $X$ always occupy the remaining part of an $\texttt{hm\_edge}$/$\texttt{hme\_leaf}$ cell inside the serialization of a *HashmapE* $n$ $X$. Therefore, if we do not insist on strict validation of all dictionaries accessed, we may assume that everything left unparsed in an $\texttt{hm\_edge}$/$\texttt{hme\_leaf}$ cell after deserializing its $\texttt{label}$ is a value of type $X$. This greatly simplifies the creation of dictionary manipulation primitives, because in most cases they turn out not to need any information about $X$ at all.
### 3.3.10. Basic dictionary operations [#3310-basic-dictionary-operations]
Let us present a classification of basic operations with dictionaries (i.e., values $D$ of type *HashmapE* $n$ $X$):
* $\text{Get}(D,k)$ — Given $D$:*HashmapE*$(n,X)$ and a key $k:n\cdot\texttt{bit}$, returns the corresponding value $D[k]:X^?$ kept in $D$.
* $\text{Set}(D,k,x)$ — Given $D$:*HashmapE*$(n,X)$, a key $k:n\cdot\texttt{bit}$, and a value $x:X$, sets $D'[k]$ to $x$ in a [copy](#2-3-4-transparency-of-the-implementation%3A-stack-values-are-“values”%2C-not-“references”) $D'$ of $D$, and returns the resulting dictionary $D'$.
* $\text{Add}(D,k,x)$ — Similar to $\text{Set}$, but adds the key-value pair $(k,x)$ to $D$ only if key $k$ is absent in $D$.
* $\text{Replace}(D,k,x)$ — Similar to $\text{Set}$, but changes $D'[k]$ to $x$ only if key $k$ is already present in $D$.
* $\text{GetSet}$, $\text{GetAdd}$, $\text{GetReplace}$ — Similar to $\text{Set}$, $\text{Add}$, and $\text{Replace}$, respectively, but returns the old value of $D[k]$ as well.
* $\text{Delete}(D,k)$ — Deletes key $k$ from dictionary $D$, and returns the resulting dictionary $D'$.
* $\text{GetMin}(D)$, $\text{GetMax}(D)$ — Gets the minimal or maximal key $k$ from dictionary $D$, along with the associated value $x:X$.
* $\text{RemoveMin}(D)$, $\text{RemoveMax}(D)$ — Similar to $\text{GetMin}$ and $\text{GetMax}$, but also removes the key in question from dictionary $D$, and returns the modified dictionary $D'$. May be used to iterate over all elements of $D$, effectively using (a copy of) $D$ itself as an iterator.
* $\text{GetNext}(D,k)$ — Computes the minimal key $k'>k$ (or $k'\geq k$ in a variant) and returns it along with the corresponding value $x':X$. May be used to iterate over all elements of $D$.
* $\text{GetPrev}(D,k)$ — Computes the maximal key $k'[18](#fn18)
* $\text{ForEachRev}(D,f)$ — Similar to $\text{ForEach}$, but processes all key-value pairs in reverse order.
* $\text{TreeReduce}(D,o,f,g)$ — Given $D$:*HashmapE*$(n,X)$, a value $o:X$, and two functions $f:X\to Y$ and $g:Y\times Y\to Y$, performs a "tree reduction" of $D$ by first applying $f$ to all the leaves, and then using $g$ to compute the value corresponding to a fork starting from the values assigned to its children.[19](#fn19)
### 3.3.11. Taxonomy of dictionary primitives [#3311-taxonomy-of-dictionary-primitives]
The [dictionary primitives](#a-10-dictionary-manipulation-primitives), can be classified according to the following categories:
* Which [dictionary operation](#3-3-10-basic-dictionary-operations) do they perform?
* Are they specialized for the case $X = \text{\textasciicircum}Y$ If so, do they represent values of type $Y$ by *Cell*s or by *Slice*s? (Generic versions always represent values of type $X$ as *Slice*s.)
* Are the dictionaries themselves passed and returned as *Cell*s or as *Slice*s? (Most primitives represent dictionaries as *Slice*s.)
* Is the key length $n$ fixed inside the primitive, or is it passed in the stack?
* Are the keys represented by *Slice*s, or by signed or unsigned *Integer*s?
In addition, TVM includes special serialization/deserialization primitives, such as $\texttt{STDICT}$, $\texttt{LDDICT}$, and $\texttt{PLDDICT}$. They can be used to extract a dictionary from a serialization of an encompassing object, or to insert a dictionary into such a serialization.
***
## 3.4 Hashmaps with variable-length keys [#34---hashmaps-with-variable-length-keys]
TVM provides some support for [dictionaries, or hashmaps](#3-3-hashmaps%2C-or-dictionaries), with variable-length keys, in addition to its support for dictionaries with fixed-length keys.
### 3.4.1. Serialization of dictionaries with variable-length keys [#341-serialization-of-dictionaries-with-variable-length-keys]
The [serialization](#3-3-3-serialization-of-hashmaps) of a *VarHashmap* into a tree of cells (or, more generally, into a *Slice*) is defined by a TL-B scheme:
```
vhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)
{n = (~m) + l} node:(VarHashmapNode m X)
= VarHashmap n X;
vhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X;
vhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X)
right:^(VarHashmap n X) value:(Maybe X)
= VarHashmapNode (n + 1) X;
vhmn_cont$1 {n:#} {X:Type} branch:bit child:^(VarHashmap n X)
value:X = VarHashmapNode (n + 1) X;
nothing$0 {X:Type} = Maybe X;
just$1 {X:Type} value:X = Maybe X;
vhme_empty$0 {n:#} {X:Type} = VarHashmapE n X;
vhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X)
= VarHashmapE n X;
```
### 3.4.2. Serialization of prefix codes [#342-serialization-of-prefix-codes]
One special case of a dictionary with variable-length keys is that of a *prefix code*, where the keys cannot be prefixes of each other. Values in such dictionaries may occur only in the leaves of a Patricia tree.
The serialization of a prefix code is defined by the following TL-B scheme:
```
phm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)
{n = (~m) + l} node:(PfxHashmapNode m X)
= PfxHashmap n X;
phmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X;
phmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X)
right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X;
phme_empty$0 {n:#} {X:Type} = PfxHashmapE n X;
phme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X)
= PfxHashmapE n X;
```
***
# 4 Control flow, continuations, and exceptions [#4----control-flow-continuations-and-exceptions]
This chapter describes *continuations*, which may represent execution tokens and exception handlers in TVM. Continuations are deeply involved with the control flow of a TVM program; in particular, subroutine calls and conditional and iterated execution are implemented in TVM using special primitives that accept one or more continuations as their arguments.
We conclude this chapter with a discussion of the problem of recursion and of families of mutually recursive functions, exacerbated by the fact that cyclic references are not allowed in TVM data structures (including TVM code).
## 4.1 Continuations and subroutines [#41---continuations-and-subroutines]
Recall that [Continuation values](#1-1-3-preliminary-list-of-value-types) represent "execution tokens" that can be executed later—for example, by $\texttt{EXECUTE}$=$\texttt{CALLX}$ ("execute" or "call indirect") or $\texttt{JMPX}$ ("jump indirect") primitives. As such, the continuations are heavily used by control flow primitives, enabling subroutine calls, conditional expressions, loops, and so on.
### 4.1.1. Ordinary continuations [#411-ordinary-continuations]
The most common kind of continuations are the *ordinary continuations*, containing the following data:
* A *Slice* $\texttt{code}$ ([1.1.3](#1-1-3-preliminary-list-of-value-types) and [3.2.2](#3-2-2-builder-and-slice-values)), containing (the remainder of) the TVM code to be executed.
* A (possibly empty) *Stack* $\texttt{stack}$, containing the original contents of the stack for the code to be executed.
* A (possibly empty) list $\texttt{save}$ of pairs $(\texttt{c}(i),v_i)$ (also called "savelist"), containing the values of control registers to be restored before the execution of the code.
* A 16-bit integer value $\texttt{cp}$, selecting the TVM codepage used to interpret the TVM code from $\texttt{code}$.
* An optional non-negative integer $\texttt{nargs}$, indicating the number of arguments expected by the continuation.
### 4.1.2. Simple ordinary continuations [#412-simple-ordinary-continuations]
In most cases, the ordinary continuations are the simplest ones, having empty $\texttt{stack}$ and $\texttt{save}$. They consist essentially of a reference $\texttt{code}$ to (the remainder of) the code to be executed, and of the codepage $\texttt{cp}$ to be used while decoding the instructions from this code.
### 4.1.3. Current continuation cc [#413-current-continuation-cc]
The "current continuation" $\texttt{cc}$ is an important part of the total state of TVM, representing the code being executed right now. In particular, what we call [the current stack](#1-1-tvm-is-a-stack-machine) (or simply "the stack") when discussing all other primitives is in fact the stack of the current continuation. All other components of the total state of TVM may be also thought of as parts of the current continuation $\texttt{cc}$; however, they may be extracted from the current continuation and kept separately as part of the total state for performance reasons. This is why we describe the stack, the control registers, and the codepage as separate parts of the [TVM state](#1-4-total-state-of-tvm-scccg).
### 4.1.4. Normal work of TVM, or the main loop [#414-normal-work-of-tvm-or-the-main-loop]
TVM usually performs the following operations:
If the current continuation $\texttt{cc}$ is an ordinary one, it decodes the first instruction from the *Slice* $\texttt{code}$, similarly to the way other cells are deserialized by TVM $\texttt{LD*}$ primitives ([3.2](#3-2-data-manipulation-instructions-and-cells) and [3.2.11](#3-2-11-taxonomy-of-cell-deserialisation-primitives)): it decodes the opcode first, and then the parameters of the instruction (e.g., 4-bit fields indicating "stack registers" involved for stack manipulation primitives, or constant values for "push constant" or "literal" primitives). The remainder of the *Slice* is then put into the $\texttt{code}$ of the new $\texttt{cc}$, and the decoded operation is executed on the current stack. This entire process is repeated until there are no operations left in $\texttt{cc.code}$.
If the $\texttt{code}$ is empty (i.e., contains no bits of data and no references), or if a (rarely needed) explicit subroutine return ($\texttt{RET}$) instruction is encountered, the current continuation is discarded, and the "return continuation" from control register $\texttt{c0}$ is [loaded](#4-1-6-switching-to-another-continuation:-and) into $\texttt{cc}$ instead.[20](#fn20) Then the execution continues by parsing operations from the new current continuation.
### 4.1.5. Extraordinary continuations [#415-extraordinary-continuations]
In addition to the [ordinary continuations](#4-1-1-ordinary-continuations), TVM includes some *extraordinary continuations*, representing certain less common states. Examples of extraordinary continuations include:
* The continuation $\texttt{ec\_quit}$ with its parameter set to zero, which represents the end of the work of TVM. This continuation is the original value of $\texttt{c0}$ when TVM begins executing the code of a smart contract.
* The continuation $\texttt{ec\_until}$, which contains references to two other continuations (ordinary or not) representing the body of the loop being executed and the code to be executed after the loop.
Execution of an extraordinary continuation by TVM depends on its specific class, and [differs](#4-1-4-normal-work-of-tvm,-or-the-main-loop) from the operations for ordinary continuations.[21](#fn21)
### 4.1.6. Switching to another continuation: $\texttt{JMP}$ and $\texttt{RET}$ [#416-switching-to-another-continuation-textttjmp-and-textttret]
The process of switching to another continuation $c$ may be performed by such instructions as $\texttt{JMPX}$ (which takes $c$ from the stack) or $\texttt{RET}$ (which uses $\texttt{c0}$ as $c$). This process is slightly more complex than simply setting the value of $\texttt{cc}$ to $c$: before doing this, either all values or the top $n$ values in the current stack are moved to the stack of the continuation $c$, and only then is the remainder of the current stack discarded.
If all values need to be moved (the most common case), and if the continuation $c$ has an empty stack (also the most common case; notice that extraordinary continuations are assumed to have an empty stack), then the new stack of $c$ equals the stack of the current continuation, so we can simply transfer the current stack in its entirety to $c$. (If we keep the current stack as a separate part of the total state of TVM, we have to do nothing at all.)
### 4.1.7. Determining the number $n$ of arguments passed to the next continuation $c$ [#417-determining-the-number-n-of-arguments-passed-to-the-next-continuation-c]
By default, $n$ equals the depth of the current stack. However, if $c$ has an explicit value of $\texttt{nargs}$ (number of arguments to be provided), then $n$ is computed as $n'$, equal to $c$.$\texttt{nargs}$ minus the current depth of $c$'s stack.
Furthermore, there are special forms of $\texttt{JMPX}$ and $\texttt{RET}$ that provide an explicit value $n''$, the number of parameters from the current stack to be passed to continuation $c$. If $n''$ is provided, it must be less than or equal to the depth of the current stack, or else a stack underflow exception occurs. If both $n'$ and $n''$ are provided, we must have $n'\leq n''$, in which case $n=n'$ is used. If $n''$ is provided and $n'$ is not, then $n=n''$ is used.
One could also imagine that the default value of $n''$ equals the depth of the original stack, and that $n''$ values are always removed from the top of the original stack even if only $n'$ of them are actually moved to the stack of the next continuation $c$. Even though the remainder of the current stack is discarded afterwards, this description will become useful later.
### 4.1.8. Restoring control registers from the new continuation $c$ [#418-restoring-control-registers-from-the-new-continuation-c]
After the new stack is computed, the values of control registers present in $c$.$\texttt{save}$ are restored accordingly, and the current codepage $\texttt{cp}$ is also set to $c$.$\texttt{cp}$. Only then does TVM set $\texttt{cc}$ equal to the new $c$ and begin its execution.[22](#fn22)
### 4.1.9. Subroutine calls: $\texttt{CALLX}$ or $\texttt{EXECUTE}$ primitives [#419-subroutine-calls-textttcallx-or-textttexecute-primitives]
The execution of continuations as subroutines is slightly more complicated than switching to continuations.
Consider the $\texttt{CALLX}$ or $\texttt{EXECUTE}$ primitive, which takes a continuation $c$ from the (current) stack and executes it as a subroutine.
Apart from doing the stack manipulations described in [4.1.6](#4-1-6-switching-to-another-continuation:-and) and [4.1.7](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) and setting the new [control registers](#4-1-8-restoring-control-registers-from-the-new-continuation), these primitives perform several additional steps:
1. After the top $n''$ values are [removed](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) from the current stack, the (usually empty) remainder is not discarded, but instead is stored in the (old) current continuation $\texttt{cc}$.
2. The old value of the special register $\texttt{c0}$ is saved into the (previously empty) savelist $\texttt{cc.save}$.
3. The continuation $\texttt{cc}$ thus modified is not discarded, but instead is set as the new $\texttt{c0}$, which performs the role of "next continuation" or "return continuation" for the subroutine being called.
4. After that, the switching to $c$ continues as before. In particular, some control registers are restored from $c$.$\texttt{save}$, potentially overwriting the value of $\texttt{c0}$ set in the previous step. (Therefore, a good optimization would be to check that $\texttt{c0}$ is present in $c$.$\texttt{save}$ from the very beginning, and skip the three previous steps as useless in this case.)
In this way, the called subroutine can return control to the caller by switching the current continuation to the return continuation saved in $\texttt{c0}$. Nested subroutine calls work correctly because the previous value of $\texttt{c0}$ ends up saved into the new $\texttt{c0}$'s control register savelist $\texttt{c0.save}$, from which it is restored later.
### 4.1.10. Determining the number of arguments passed to and/or return values accepted from a subroutine [#4110-determining-the-number-of-arguments-passed-to-andor-return-values-accepted-from-a-subroutine]
Similarly to $\texttt{JMPX}$ and $\texttt{RET}$, $\texttt{CALLX}$ also has special (rarely used) forms, which allow us to explicitly specify the number $n''$ of arguments passed from the current stack to the called subroutine (by default, $n''$ equals the depth of the current stack, i.e., it is passed in its entirety). Furthermore, a second number $n'''$ can be specified, used to set $\texttt{nargs}$ of the modified $\texttt{cc}$ continuation before storing it into the new $\texttt{c0}$; the new $\texttt{nargs}$ equals the depth of the old stack minus $n''$ plus $n'''$. This means that the caller is willing to pass exactly $n''$ arguments to the called subroutine, and is willing to accept exactly $n'''$ results in their stead.
Such forms of $\texttt{CALLX}$ and $\texttt{RET}$ are mostly intended for library functions that accept functional arguments and want to invoke them safely. Another application is related to the "virtualization support" of TVM, which enables TVM code to run other TVM code inside a "virtual TVM machine". Such virtualization techniques might be useful for implementing sophisticated [payment channels](/blockchain-basics/whitepapers/ton#5-ton-payments) in the TON Blockchain.
### 4.1.11. $\texttt{CALLCC}$: call with current continuation [#4111-textttcallcc-call-with-current-continuation]
Notice that TVM supports a form of the "call with current continuation" primitive. Namely, primitive $\texttt{CALLCC}$ is similar to $\texttt{CALLX}$ or $\texttt{JMPX}$ in that it takes a continuation $c$ from the stack and switches to it; however, $\texttt{CALLCC}$ does not discard the previous current continuation $c'$ (as $\texttt{JMPX}$ does) and does not write $c'$ to $\texttt{c0}$ (as $\texttt{CALLX}$ does), but rather pushes $c'$ into the (new) stack as an extra argument to $c$. The primitive $\texttt{JMPXDATA}$ does a similar thing, but pushes only the (remainder of the) code of the previous current continuation as a *Slice*.
## 4.2 Control flow primitives: conditional and iterated execution [#42---control-flow-primitives-conditional-and-iterated-execution]
### 4.2.1. Conditional execution: $\texttt{IF}$, $\texttt{IFNOT}$, $\texttt{IFELSE}$ [#421-conditional-execution-textttif-textttifnot-textttifelse]
An important modification of $\texttt{EXECUTE}$ (or $\texttt{CALLX}$) consists in its conditional forms. For example, $\texttt{IF}$ accepts an integer $x$ and a continuation $c$, and executes $c$ (in the same way as $\texttt{EXECUTE}$ would do it) only if $x$ is non-zero; otherwise both values are simply discarded from the stack. Similarly, $\texttt{IFNOT}$ accepts $x$ and $c$, but executes $c$ only if $x=0$. Finally, $\texttt{IFELSE}$ accepts $x$, $c$, and $c'$, removes these values from the stack, and executes $c$ if $x\neq0$ or $c'$ if $x=0$.
### 4.2.2. Iterated execution and loops [#422-iterated-execution-and-loops]
More sophisticated modifications of $\texttt{EXECUTE}$ include:
* $\texttt{REPEAT}$ — Takes an integer $n$ and a continuation $c$, and executes $c$ $n$ times.[23](#fn23)
* $\texttt{WHILE}$ — Takes $c'$ and $c''$, executes $c'$, and then takes the top value $x$ from the stack. If $x$ is non-zero, it executes $c''$ and then begins a new loop by executing $c'$ again; if $x$ is zero, it stops.
* $\texttt{UNTIL}$ — Takes $c$, executes it, and then takes the top integer $x$ from the stack. If $x$ is zero, a new iteration begins; if $x$ is non-zero, the previously executed code is resumed.
### 4.2.3. Constant, or literal, continuations [#423-constant-or-literal-continuations]
We see that we can create arbitrarily complex conditional expressions and loops in the TVM code, provided we have a means to push constant continuations into the stack. In fact, TVM includes special versions of "literal" or "constant" primitives that cut the next $n$ bytes or bits from the remainder of the current code $\texttt{cc.code}$ into a cell slice, and then push it into the stack not as a *Slice* (as a $\texttt{PUSHSLICE}$ does) but as a simple ordinary *Continuation* (which has only $\texttt{code}$ and $\texttt{cp}$).
The simplest of these primitives is $\texttt{PUSHCONT}$, which has an immediate argument $n$ describing the number of subsequent bytes (in a byte-oriented version of TVM) or bits to be converted into a simple continuation. Another primitive is $\texttt{PUSHREFCONT}$, which removes the first cell reference from the current continuation $\texttt{cc.code}$, converts the cell referred to into a cell slice, and finally converts the cell slice into a simple continuation.
### 4.2.4. Constant continuations combined with conditional or iterated execution primitives [#424-constant-continuations-combined-with-conditional-or-iterated-execution-primitives]
Because constant continuations are very often used as arguments to conditional or iterated execution primitives, combined versions of these primitives (e.g., $\texttt{IFCONT}$ or $\texttt{UNTILREFCONT}$) may be defined in a future revision of TVM, which combine a $\texttt{PUSHCONT}$ or $\texttt{PUSHREFCONT}$ with another primitive. If one inspects the resulting code, $\texttt{IFCONT}$ looks very much like the more customary "conditional-branch-forward" instruction.
## 4.3 Operations with continuations [#43--operations-with-continuations]
### 4.3.1 Continuations are opaque [#431--continuations-are-opaque]
Notice that all continuations are *opaque*, at least in the current version of TVM, meaning that there is no way to modify a continuation or inspect its internal data. Almost the only use of a continuation is to supply it to a control flow primitive.
While there are some arguments in favor of including support for non-opaque continuations in TVM (along with opaque continuations, which are required for virtualization), the current revision offers no such support.
### 4.3.2. Allowed operations with continuations [#432-allowed-operations-with-continuations]
However, some operations with opaque continuations are still possible, mostly because they are equivalent to operations of the kind "create a new continuation, which will do something special, and then invoke the original continuation". Allowed operations with continuations include:
* Push one or several values into the stack of a continuation $c$ (thus creating a partial application of a function, or a closure).
* Set the saved value of a control register $\texttt{c}(i)$ inside the savelist $c$.$\texttt{save}$ of a continuation $c$. If there is already a value for the control register in question, this operation silently does nothing.
### 4.3.3. Example: operations with control registers [#433-example-operations-with-control-registers]
TVM has some primitives to set and inspect the values of control registers. The most important of them are $\texttt{PUSH c}(i)$ (pushes the current value of $\texttt{c}(i)$ into the stack) and $\texttt{POP c}(i)$ (sets the value of $\texttt{c}(i)$ from the stack, if the supplied value is of the correct type). However, there is also a modified version of the latter instruction, called $\texttt{POPSAVE c}(i)$, which saves the old value of $\texttt{c}(i)$ (for $i>0$) into the [continuation](#4-3-2-allowed-operations-with-continuations) at $\texttt{c0}$ before setting the new value.
### 4.3.4. Example: setting the number of arguments to a function in its code [#434-example-setting-the-number-of-arguments-to-a-function-in-its-code]
The primitive $\texttt{LEAVEARGS}$ $n$ demonstrates another application of continuations in an operation: it leaves only the top $n$ values of the current stack, and moves the remainder to the stack of the continuation in $\texttt{c0}$. This primitive enables a called function to "return" unneeded arguments to its caller's stack, which is useful in some situations (e.g., those related to exception handling).
### 4.3.5. Boolean circuits [#435-boolean-circuits]
A continuation $c$ may be thought of as a piece of code with two optional exit points kept in the savelist of $c$: the principal exit point given by $c$.$\texttt{c0}$:=$c$.$\texttt{save}$($\texttt{c0}$), and the auxiliary exit point given by $c$.$\texttt{c1}$:=$c$.$\texttt{save}$($\texttt{c1}$). If executed, a continuation performs whatever action it was created for, and then (usually) transfers control to the principal exit point, or, on some occasions, to the auxiliary exit point. We sometimes say that a continuation $c$ with both exit points $c$.$\texttt{c0}$ and $c$.$\texttt{c1}$ defined is a *two-exit continuation*, or a *boolean circuit*, especially if the choice of the exit point depends on some internally-checked condition.
### 4.3.6. Composition of continuations [#436-composition-of-continuations]
One can *compose* two continuations $c$ and $c'$ simply by setting $c$.$\texttt{c0}$ or $c$.$\texttt{c1}$ to $c'$. This creates a new continuation denoted by $c\circ_0c'$ or $c\circ_1c'$, which differs from $c$ in its savelist. (Recall that if the savelist of $c$ already has an entry corresponding to the control register in question, such an operation silently [does nothing](#4-3-2-allowed-operations-with-continuations).
By composing continuations, one can build chains or other graphs, possibly with loops, representing the control flow. In fact, the resulting graph resembles a flow chart, with the boolean circuits corresponding to the "condition nodes" (containing code that will transfer control either to $\texttt{c0}$ or to $\texttt{c1}$ depending on some condition), and the one-exit continuations corresponding to the "action nodes".
### 4.3.7. Basic continuation composition primitives [#437-basic-continuation-composition-primitives]
Two basic primitives for composing continuations are $\texttt{COMPOS}$ (also known as $\texttt{SETCONT c0}$ and $\texttt{BOOLAND}$) and $\texttt{COMPOSALT}$ (also known as $\texttt{SETCONT c1}$ and $\texttt{BOOLOR}$), which take $c$ and $c'$ from the stack, set $c$.$\texttt{c0}$ or $c$.$\texttt{c1}$ to $c'$, and return the resulting continuation $c''=c\circ_0c'$ or $c\circ_1c'$. All other continuation composition operations can be expressed in terms of these two primitives.
### 4.3.8. Advanced continuation composition primitives [#438-advanced-continuation-composition-primitives]
However, TVM can compose continuations not only taken from stack, but also taken from $\texttt{c0}$ or $\texttt{c1}$, or from the current continuation $\texttt{cc}$; likewise, the result may be pushed into the stack, stored into either $\texttt{c0}$ or $\texttt{c1}$, or used as the new current continuation (i.e., the control may be transferred to it). Furthermore, TVM can define conditional composition primitives, performing some of the above actions only if an integer value taken from the stack is non-zero.
For instance, $\texttt{EXECUTE}$ can be described as $\texttt{cc}\leftarrow c\circ_0\texttt{cc}$, with continuation $c$ taken from the original stack. Similarly, $\texttt{JMPX}$ is $\texttt{cc}\leftarrow c$, and $\texttt{RET}$ (also known as $\texttt{RETTRUE}$ in a boolean circuit context) is $\texttt{cc}\leftarrow\texttt{c0}$. Other interesting primitives include $\texttt{THENRET}$ ($c'\leftarrow c\circ_0\texttt{c0}$) and $\texttt{ATEXIT}$ ($\texttt{c0}\leftarrow c\circ_0\texttt{c0}$).
Finally, some "experimental" primitives also involve $\texttt{c1}$ and $\circ_1$. For example:
* $\texttt{RETALT}$ or $\texttt{RETFALSE}$ does $\texttt{cc}\leftarrow\texttt{c1}$.
* Conditional versions of $\texttt{RET}$ and $\texttt{RETALT}$ may also be useful: $\texttt{RETBOOL}$ takes an integer $x$ from the stack, and performs $\texttt{RETTRUE}$ if $x\neq0$, $\texttt{RETFALSE}$ otherwise.
* $\texttt{INVERT}$ does $\texttt{c0}\leftrightarrow\texttt{c1}$; if the two continuations in $\texttt{c0}$ and $\texttt{c1}$ represent the two branches we should select depending on some boolean expression, $\texttt{INVERT}$ negates this expression on the outer level.
* $\texttt{INVERTCONT}$ does $c$.$\texttt{c0}\leftrightarrow c$.$\texttt{c1}$ to a continuation $c$ taken from the stack.
* Variants of $\texttt{ATEXIT}$ include $\texttt{ATEXITALT}$ ($\texttt{c1}\leftarrow c\circ_1\texttt{c1}$) and $\texttt{SETEXITALT}$ ($\texttt{c1}\leftarrow (c\circ_0\texttt{c0})\circ_1\texttt{c1}$).
* $\texttt{BOOLEVAL}$ takes a continuation $c$ from the stack and does $\texttt{cc}\leftarrow \bigl((c\circ_0(\texttt{PUSH}\,-1))\circ_1(\texttt{PUSH}\,0)\bigr)\circ_0\texttt{cc}$. If $c$ represents a boolean circuit, the net effect is to evaluate it and push either $-1$ or $0$ into the stack before continuing.
## 4.4 Continuations as objects [#44--continuations-as-objects]
### 4.4.1. Representing objects using continuations [#441-representing-objects-using-continuations]
Object-oriented programming in Smalltalk (or Objective C) style may be implemented with the aid of continuations. For this, an object is represented by a special continuation $o$. If it has any data fields, they can be kept in the stack of $o$, making $o$ a partial application (i.e., a continuation with a non-empty stack).
When somebody wants to invoke a method $m$ of $o$ with arguments $x_1$, $x_2$, $\ldots$, $x_n$, she pushes the arguments into the stack, then pushes a magic number corresponding to the method $m$, and then executes $o$ passing $n+1$ [arguments](#4-1-10-determining-the-number-of-arguments-passed-to-and%2For-return-values-accepted-from-a-subroutine). Then $o$ uses the top-of-stack integer $m$ to select the branch with the required method, and executes it. If $o$ needs to modify its state, it simply computes a new continuation $o'$ of the same sort (perhaps with the same code as $o$, but with a different initial stack). The new continuation $o'$ is returned to the caller along with whatever other return values need to be returned.
### 4.4.2. Serializable objects [#442-serializable-objects]
Another way of representing Smalltalk-style objects as continuations, or even as trees of cells, consists in using the $\texttt{JMPREFDATA}$ primitive (a [variant](#4-1-11-%3A-call-with-current-continuation) of $\texttt{JMPXDATA}$), which takes the first cell reference from the code of the current continuation, transforms the cell referred to into a simple ordinary continuation, and transfers control to it, first pushing the remainder of the current continuation as a *Slice* into the stack. In this way, an object might be represented by a cell $\tilde o$ that contains $\texttt{JMPREFDATA}$ at the beginning of its data, and the actual code of the object in the first reference (one might say that the first reference of cell $\tilde o$ is the *class* of object $\tilde o$). Remaining data and references of this cell will be used for storing the fields of the object.
Such objects have the advantage of being trees of cells, and not just continuations, meaning that they can be stored into the persistent storage of a TON smart contract.
### 4.4.3. Unique continuations and capabilities [#443-unique-continuations-and-capabilities]
It might make sense (in a future revision of TVM) to mark some continuations as *unique*, meaning that they cannot be copied, even in a delayed manner, by increasing their reference counter to a value greater than one. If an opaque continuation is unique, it essentially becomes a *capability*, which can either be used by its owner exactly once or be transferred to somebody else.
For example, imagine a continuation that [represents](#4-4-1-representing-objects-using-continuations) the output stream to a printer (this is an example of a continuation used as an object). When invoked with one integer argument $n$, this continuation outputs the character with code $n$ to the printer, and returns a new continuation of the same kind reflecting the new state of the stream. Obviously, copying such a continuation and using the two copies in parallel would lead to some unintended side effects; marking it as unique would prohibit such adverse usage.
## 4.5 Exception handling [#45--exception-handling]
TVM's exception handling is quite simple and consists in a transfer of control to the continuation kept in control register $\texttt{c2}$.
### 4.5.1. Two arguments of the exception handler: exception parameter and exception number [#451-two-arguments-of-the-exception-handler-exception-parameter-and-exception-number]
Every exception is characterized by two arguments: the *exception number* (an *Integer*) and the *exception parameter* (any value, most often a zero *Integer*). Exception numbers 0–31 are reserved for TVM, while all other exception numbers are available for user-defined exceptions.
### 4.5.2. Primitives for throwing an exception [#452-primitives-for-throwing-an-exception]
There are several special primitives used for throwing an exception. The most general of them, $\texttt{THROWANY}$, takes two arguments, $v$ and $0\leq n<2^{16}$, from the stack, and throws the exception with number $n$ and value $v$. There are variants of this primitive that assume $v$ to be a zero integer, store $n$ as a literal value, and/or are conditional on an integer value taken from the stack. User-defined exceptions may use arbitrary values as $v$ (e.g., trees of cells) if needed.
### 4.5.3. Exceptions generated by TVM [#453-exceptions-generated-by-tvm]
Of course, some exceptions are generated by normal primitives. For example, an arithmetic overflow exception is generated whenever the result of an arithmetic operation does not fit into a signed 257-bit integer. In such cases, the arguments of the exception, $v$ and $n$, are determined by TVM itself.
### 4.5.4. Exception handling [#454-exception-handling]
The exception handling itself consists in a control transfer to the exception handler—i.e., the continuation specified in control register $\texttt{c2}$, with $v$ and $n$ supplied as the two arguments to this continuation, as if a $\texttt{JMP}$ to $\texttt{c2}$ had been requested with $n''=2$ arguments ([4.1.7](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) and [4.1.6](#4-1-6-switching-to-another-continuation:-and)). As a consequence, $v$ and $n$ end up in the top of the stack of the exception handler. The remainder of the old stack is discarded.
Notice that if the continuation in $\texttt{c2}$ has a value for $\texttt{c2}$ in its savelist, it will be used to set up the new value of $\texttt{c2}$ before executing the exception handler. In particular, if the exception handler invokes $\texttt{THROWANY}$, it will re-throw the original exception with the restored value of $\texttt{c2}$. This trick enables the exception handler to handle only some exceptions, and pass the rest to an outer exception handler.
### 4.5.5. Default exception handler [#455-default-exception-handler]
When an instance of TVM is created, $\texttt{c2}$ contains a reference to the "default exception handler continuation", which is an $\texttt{ec\_fatal}$ [extraordinary continuation](#4-1-5-extraordinary-continuations). Its execution leads to the termination of the execution of TVM, with the arguments $v$ and $n$ of the exception returned to the outside caller. In the context of the TON Blockchain, $n$ will be stored as a part of the transaction's result.
### 4.5.6. $\texttt{TRY}$ primitive [#456-texttttry-primitive]
A $\texttt{TRY}$ primitive can be used to implement C++- like exception handling. This primitive accepts two continuations, $c$ and $c'$. It stores the old value of $\texttt{c2}$ into the savelist of $c'$, sets $\texttt{c2}$ to $c'$, and executes $c$ just as $\texttt{EXECUTE}$ would, but additionally saving the old value of $\texttt{c2}$ into the savelist of the new $\texttt{c0}$ as well. Usually a version of the $\texttt{TRY}$ primitive with an explicit number of arguments $n''$ passed to the continuation $c$ is used.
The net result is roughly equivalent to C$++$'s $\texttt{try}$ \{ $c$ } $\texttt{catch(...)}$ \{ $c'$ } operator.
### 4.5.7. List of predefined exceptions [#457-list-of-predefined-exceptions]
Predefined exceptions of TVM correspond to exception numbers $n$ in the range 0–31. They include:
* *Normal termination* ($n=0$) — Should never be generated, but it is useful for some tricks.
* *Alternative termination* ($n=1$) — Again, should never be generated.
* *Stack underflow* ($n=2$) — Not enough arguments in the stack for a primitive.
* *Stack overflow* ($n=3$) — More values have been stored on a stack than allowed by this version of TVM.
* *Integer overflow* ($n=4$) — Integer does not fit into $-2^{256}\leq x<2^{256}$, or a division by zero has occurred.
* *Range check error* ($n=5$) — Integer out of expected range.
* *Invalid opcode* ($n=6$) — Instruction or its immediate arguments cannot be decoded.
* *Type check error* ($n=7$) — An argument to a primitive is of incorrect value type.
* *Cell overflow* ($n=8$) — Error in one of the serialization primitives.
* *Cell underflow* ($n=9$) — Deserialization error.
* *Dictionary error* ($n=10$) — Error while deserializing a dictionary object.
* *Unknown error* ($n=11$) — Unknown error, may be thrown by user programs.
* *Fatal error* ($n=12$) — Thrown by TVM in situations deemed impossible.
* *Out of gas* ($n=13$) — Thrown by TVM when the remaining gas ($g_r$) becomes negative. This exception usually cannot be caught and leads to an immediate termination of TVM.
Most of these exceptions have no parameter (i.e., use a zero integer instead). The order in which these exceptions are checked is outlined [below](#4-5-8-order-of-stack-underflow,-type-check,-and-range-check-exceptions).
### 4.5.8. Order of stack underflow, type check, and range check exceptions [#458-order-of-stack-underflow-type-check-and-range-check-exceptions]
All TVM primitives first check whether the stack contains the required number of arguments, generating a stack underflow exception if this is not the case. Only then are the type tags of the arguments and their ranges (e.g., if a primitive expects an argument not only to be an *Integer*, but also to be in the range from 0 to 256) checked, starting from the value in the top of the stack (the last argument) and proceeding deeper into the stack. If an argument's type is incorrect, a type-checking exception is generated; if the type is correct, but the value does not fall into the expected range, a range check exception is generated.
Some primitives accept a variable number of arguments, depending on the values of some small fixed subset of arguments located near the top of the stack. In this case, the above procedure is first run for all arguments from this small subset. Then it is repeated for the remaining arguments, once their number and types have been determined from the arguments already processed.
## 4.6 Functions, recursion, and dictionaries [#46---functions-recursion-and-dictionaries]
### 4.6.1. The problem of recursion [#461-the-problem-of-recursion]
The [conditional and iterated](#4-2-control-flow-primitives:-conditional-and-iterated-execution) execution primitives—along with the unconditional branch, call, and return [primitives](#4-1-continuations-and-subroutines)—enable one to implement more or less arbitrary code with nested loops and conditional expressions, with one notable exception: one can only create new constant continuations from parts of the current continuation. (In particular, one cannot invoke a subroutine from itself in this way.) Therefore, the code being executed—i.e., the current continuation—gradually becomes smaller and smaller.[24](#fn24)
### 4.6.2. Y-combinator solution: pass a continuation as an argument to itself [#462-y-combinator-solution-pass-a-continuation-as-an-argument-to-itself]
One way of dealing with the problem of recursion is by passing a copy of the continuation representing the body of a recursive function as an extra argument to itself. Consider, for example, the following code for a factorial function:
```
71 PUSHINT 1
9C PUSHCONT {
22 PUSH s2
72 PUSHINT 2
B9 LESS
DC IFRET
59 ROTREV
21 PUSH s1
A8 MUL
01 SWAP
A5 DEC
02 XCHG s2
20 DUP
D9 JMPX
}
20 DUP
D8 EXECUTE
30 DROP
31 NIP
```
This roughly corresponds to defining an auxiliary function $\mathit{body}$ with three arguments $n$, $x$, and $f$, such that $\mathit{body}(n,x,f)$ equals $x$ if $n<2$ and $f(n-1,nx,f)$ otherwise, then invoking $\mathit{body}(n,1,\mathit{body})$ to compute the factorial of $n$.
The recursion is then implemented with the aid of the $\texttt{DUP}$; $\texttt{EXECUTE}$ construction, or $\texttt{DUP}$; $\texttt{JMPX}$ in the case of tail recursion. This trick is equivalent to applying $Y$-combinator to a function $\mathit{body}$.
### 4.6.3. A variant of Y-combinator solution [#463-a-variant-of-y-combinator-solution]
Another way of recursively computing the factorial, more closely following the classical recursive definition
$$
\mathit{fact}(n):=\begin{cases}1&\quad\text{if }n<2,\\n\cdot\mathit{fact}(n-1)&\quad\text{otherwise}\end{cases} \tag{5}
$$
is as follows:
```asm
9D PUSHCONT {
21 OVER
C102 LESSINT 2
92 PUSHCONT {
5B 2DROP
71 PUSHINT 1
}
E0 IFJMP
21 OVER
A5 DEC
01 SWAP
20 DUP
D8 EXECUTE
A8 MUL
}
20 DUP
D9 JMPX
```
This definition of the factorial function is two bytes shorter than the previous one, but it uses general recursion instead of tail recursion, so it cannot be easily transformed into a loop.
### 4.6.4. Comparison: non-recursive definition of the factorial function [#464-comparison-non-recursive-definition-of-the-factorial-function]
Incidentally, a non-recursive definition of the factorial with the aid of a $\texttt{REPEAT}$ loop is also possible, and it is much shorter than both recursive definitions:
```asm
71 PUSHINT 1
01 SWAP
20 DUP
94 PUSHCONT {
66 TUCK
A8 MUL
01 SWAP
A5 DEC
}
E4 REPEAT
30 DROP
```
### 4.6.5. Several mutually recursive functions [#465-several-mutually-recursive-functions]
If one has a collection $f_1$, $\ldots$, $f_n$ of mutually recursive functions, one can use the same trick by passing the whole collection of continuations $\{f_i\}$ in the stack as an extra $n$ arguments to each of these functions. However, as $n$ grows, this becomes more and more cumbersome, since one has to reorder these extra arguments in the stack to work with the "true" arguments, and then push their copies into the top of the stack before any recursive call.
### 4.6.6. Combining several functions into one tuple [#466-combining-several-functions-into-one-tuple]
One might also combine a collection of continuations representing functions $f_1$, $\ldots$, $f_n$ into a "tuple" ${\mathbf f}:=(f_1,\ldots,f_n)$, and pass this tuple as one stack element ${\mathbf f}$. For instance, when $n\leq4$, each function can be represented by a cell $\tilde f_i$ (along with the tree of cells rooted in this cell), and the tuple may be represented by a cell $\tilde{\mathbf f}$, which has references to its component cells $\tilde f_i$. However, this would lead to the necessity of "unpacking" the needed component from this tuple before each recursive call.
### 4.6.7. Combining several functions into a selector function [#467-combining-several-functions-into-a-selector-function]
Another approach is to combine several functions $f_1$, $\ldots$, $f_n$ into one "selector function" $f$, which takes an extra argument $i$, $1\leq i\leq n$, from the top of the stack, and invokes the appropriate function $f_i$. Stack machines such as TVM are well-suited to this approach, because they do not require the functions $f_i$ to have the same number and types of arguments. Using this approach, one would need to pass only one extra argument, $f$, to each of these functions, and push into the stack an extra argument $i$ before each recursive call to $f$ to select the correct function to be called.
### 4.6.8. Using a dedicated register to keep the selector function [#468-using-a-dedicated-register-to-keep-the-selector-function]
However, even if we use one of the two previous approaches to combine all functions into one extra argument, passing this argument to all mutually recursive functions is still quite cumbersome and requires a lot of additional stack manipulation operations. Because this argument changes very rarely, one might use a dedicated register to keep it and transparently pass it to all functions called. This is the approach used by TVM by default.
### 4.6.9. Special register $c3$ for the selector function [#469-special-register-c3-for-the-selector-function]
In fact, TVM uses a dedicated register $\texttt{c3}$ to keep the continuation representing the current or global "selector function", which can be used to invoke any of a family of mutually recursive functions. [Special primitives](#a-8-7-dictionary-subroutine-calls-and-jumps) $\texttt{CALL}$ $nn$ or $\texttt{CALLDICT}$ $nn$ are equivalent to $\texttt{PUSHINT}$ $nn$; $\texttt{PUSH c3}$; $\texttt{EXECUTE}$, and similarly $\texttt{JMP}$ $nn$ or $\texttt{JMPDICT}$ $nn$ are equivalent to $\texttt{PUSHINT}$ $nn$; $\texttt{PUSH c3}$; $\texttt{JMPX}$. In this way a TVM program, which ultimately is a large collection of mutually recursive functions, may initialize $\texttt{c3}$ with the correct selector function representing the family of all the functions in the program, and then use $\texttt{CALL}$ $nn$ to invoke any of these functions by its index (sometimes also called the *selector* of a function).
### 4.6.10. Initialization of $c3$ [#4610-initialization-of-c3]
A TVM program might initialize $\texttt{c3}$ by means of a $\texttt{POP c3}$ instruction. However, because this usually is the very first action undertaken by a program (e.g., a smart contract), TVM makes some provisions for the automatic initialization of $\texttt{c3}$. Namely, $\texttt{c3}$ is initialized by the code (the initial value of $\texttt{cc}$) of the program itself, and an extra zero (or, in some cases, some other predefined number $s$) is pushed into the stack before the program's execution. This is approximately equivalent to invoking $\texttt{JMPDICT 0}$ (or $\texttt{JMPDICT}$ $s$) at the very beginning of a program—i.e., the function with index zero is effectively the `main()` function for the program.
### 4.6.11. Creating selector functions and $\texttt{switch}$ statements [#4611-creating-selector-functions-and-textttswitch-statements]
TVM makes special provisions for simple and concise implementation of selector functions (which usually constitute the top level of a TVM program) or, more generally, arbitrary `switch` or `case` statements (which are also useful in TVM programs). The most important [primitives](#a-8-2-conditional-control-flow-primitives) included for this purpose are $\texttt{IFBITJMP}$, $\texttt{IFNBITJMP}$, $\texttt{IFBITJMPREF}$, and $\texttt{IFNBITJMPREF}$. They effectively enable one to combine subroutines, kept either in separate cells or as subslices of certain cells, into a binary decision tree with decisions made according to the indicated bits of the integer passed in the top of the stack.
Another instruction, useful for the implementation of [sum-product](#a-7-2-cell-deserialization-primitives) types, is $\texttt{PLDUZ}$. This instruction preloads the first several bits of a *Slice* into an *Integer*, which can later be inspected by $\texttt{IFBITJMP}$ and other similar instructions.
### 4.6.12. Alternative: using a hashmap to select the correct function [#4612-alternative-using-a-hashmap-to-select-the-correct-function]
Yet another alternative is to use a [Hashmap](#3-3-hashmaps%2C-or-dictionaries) to hold the "collection" or "dictionary" of the code of all functions in a program, and use the [hashmap lookup primitives](#a-10-dictionary-manipulation-primitives) to select the code of the required function, which can then be $\texttt{BLESS}$ed into a [continuation](#a-8-5-creating-simple-continuations-and-closures) and executed. Special combined "lookup, bless, and execute" primitives, such as $\texttt{DICTIGETJMP}$ and $\texttt{DICTIGETEXEC}$, are also [available](#a-10-11-special-dictionary-and-prefix-code-dictionary-operations%2C-and-constant-dictionaries). This approach may be more efficient for larger programs and `switch` statements.
***
# 5. Codepages and instruction encoding [#5-codepages-and-instruction-encoding]
This chapter describes the codepage mechanism, which allows TVM to be flexible and extendable while preserving backward compatibility with respect to previously generated code.
We also discuss some general considerations about instruction encodings (applicable to arbitrary machine code, not just TVM), as well as the implications of these considerations for TVM and the choices made while designing TVM's (experimental) codepage zero. The instruction encodings themselves are presented later in [Appendix A](#a-instructions-and-opcodes).
## 5.1 Codepages and interoperability of different TVM versions [#51---codepages-and-interoperability-of-different-tvm-versions]
The *codepages* are an essential mechanism of backward compatibility and of future extensions to TVM. They enable transparent execution of code written for different revisions of TVM, with transparent interaction between instances of such code. The mechanism of the codepages, however, is general and powerful enough to enable some other originally unintended applications.
### 5.1.1. Codepages in continuations [#511-codepages-in-continuations]
Every [ordinary continuation](#4-1-1-ordinary-continuations) contains a 16-bit *codepage* field $\texttt{cp}$, which determines the codepage that will be used to execute its code. If a [continuation](#4-2-3-constant%2C-or-literal%2C-continuations) is created by a $\texttt{PUSHCONT}$ or similar primitive, it usually inherits the current codepage (i.e., the codepage of $\texttt{cc}$).[25](#fn25)
### 5.1.2. Current codepage [#512-current-codepage]
The [current codepage](#1-4-total-state-of-tvm-scccg) $\texttt{cp}$ is the codepage of the current continuation $\texttt{cc}$. It determines the way the next instruction will be decoded from $\texttt{cc.code}$, the remainder of the current continuation's code. Once the instruction has been decoded and executed, it determines the next value of the current codepage. In most cases, the current codepage is left unchanged.
On the other hand, all primitives that switch the current continuation load the new value of $\texttt{cp}$ from the new current continuation. In this way, all code in continuations is always interpreted exactly as it was intended to be.
### 5.1.3. Different versions of TVM may use different codepages [#513-different-versions-of-tvm-may-use-different-codepages]
Different versions of TVM may use different codepages for their code. For example, the original version of TVM might use codepage zero. A newer version might use codepage one, which contains all the previously defined opcodes, along with some newly defined ones, using some of the previously unused opcode space. A subsequent version might use yet another codepage, and so on.
However, a newer version of TVM will execute old code for codepage zero exactly as before. If the old code contained an opcode used for some new operations that were undefined in the original version of TVM, it will still generate an invalid opcode exception, because the new operations are absent in codepage zero.
### 5.1.4. Changing the behavior of old operations [#514-changing-the-behavior-of-old-operations]
New codepages can also change the effects of some operations present in the old codepages while preserving their opcodes and mnemonics.
For example, imagine a future 513-bit upgrade of TVM (replacing the current 257-bit design). It might use a 513-bit *Integer* type within the same arithmetic primitives as before. However, while the opcodes and instructions in the new codepage would look exactly like the old ones, they would work differently, accepting 513-bit integer arguments and results. On the other hand, during the execution of the same code in codepage zero, the new machine would generate exceptions whenever the integers used in arithmetic and other primitives do not fit into 257 bits.[26](#fn26) In this way, the upgrade would not change the behavior of the old code.
### 5.1.5. Improving instruction encoding [#515-improving-instruction-encoding]
Another application for codepages is to change instruction encodings, reflecting improved knowledge of the actual frequencies of such instructions in the code base. In this case, the new codepage will have exactly the same instructions as the old one, but with different encodings, potentially of differing lengths. For example, one might create an experimental version of the first version of TVM, using a (prefix) bitcode instead of the original bytecode, aiming to achieve higher code density.
### 5.1.6. Making instruction encoding context-dependent [#516-making-instruction-encoding-context-dependent]
Another way of using codepages to improve code density is to use several codepages with different subsets of the whole instruction set defined in each of them, or with the whole instruction set defined, but with different length encodings for the same instructions in different codepages.
Imagine, for instance, a "stack manipulation" codepage, where stack manipulation primitives have short encodings at the expense of all other operations, and a "data processing" codepage, where all other operations are shorter at the expense of stack manipulation operations. If stack manipulation operations tend to come one after another, we can automatically switch to "stack manipulation" codepage after executing any such instruction. When a data processing instruction occurs, we switch back to "data processing" codepage. If conditional probabilities of the class of the next instruction depending on the class of the previous instruction are considerably different from corresponding unconditional probabilities, this technique—automatically switching into stack manipulation mode to rearrange the stack with shorter instructions, then switching back—might considerably improve the code density.
### 5.1.7. Using codepages for status and control flags [#517-using-codepages-for-status-and-control-flags]
Another potential application of multiple codepages inside the same revision of TVM consists in switching between several codepages depending on the result of the execution of some instructions.
For example, imagine a version of TVM that uses two new codepages, 2 and 3. Most operations do not change the current codepage. However, the integer comparison operations will switch to codepage 2 if the condition is false, and to codepage 3 if it is true. Furthermore, a new operation $\texttt{?EXECUTE}$, similar to $\texttt{EXECUTE}$, will indeed be equivalent to $\texttt{EXECUTE}$ in codepage 3, but will instead be a $\texttt{DROP}$ in codepage 2. Such a trick effectively uses bit 0 of the current codepage as a status flag.
Alternatively, one might create a couple of codepages—say, 4 and 5—which differ only in their cell deserialisation primitives. For instance, in codepage 4 they might work as before, while in codepage 5 they might deserialize data not from the beginning of a *Slice*, but from its end. Two new instructions—say, $\texttt{CLD}$ and $\texttt{STD}$—might be used for switching to codepage 4 or codepage 5. Clearly, we have now described a status flag, affecting the execution of some instructions in a certain new manner.
### 5.1.8. Setting the codepage in the code itself [#518-setting-the-codepage-in-the-code-itself]
For convenience, we reserve some opcode in all [codepages](#a-13-codepage-primitives)—say, $\texttt{FF}$ $n$—for the instruction $\texttt{SETCP}$ $n$, with $n$ from 0 to 255. Then by inserting such an instruction into the very beginning of (the main function of) a program (e.g., a TON Blockchain smart contract) or a library function, we can ensure that the code will always be executed in the intended codepage.
## 5.2 Instruction encoding [#52--instruction-encoding]
This section discusses the general principles of instruction encoding valid for all codepages and all versions of TVM. Later, [5.3](#5-3-instruction-encoding-in-codepage-zero) discusses the choices made for the experimental "codepage zero".
### 5.2.1. Instructions are encoded by a binary prefix code [#521-instructions-are-encoded-by-a-binary-prefix-code]
All complete instructions (i.e., instructions along with all their parameters, such as the names of stack registers $s(i)$ or other embedded constants) of a TVM codepage are encoded by a *binary prefix code*. This means that a (finite) binary string (i.e., a bitstring) corresponds to each complete instruction, in such a way that binary strings corresponding to different complete instructions do not coincide, and no binary string among the chosen subset is a prefix of another binary string from this subset.
### 5.2.2. Determining the first instruction from a code stream [#522-determining-the-first-instruction-from-a-code-stream]
As a consequence of this encoding method, any binary string admits at most one prefix, which is an encoding of some complete instruction. In particular, the code $\texttt{cc.code}$ of the current continuation (which is a *Slice*, and thus a bitstring along with some cell references) admits at most one such prefix, which corresponds to the (uniquely determined) instruction that TVM will execute first. After execution, this prefix is removed from the code of the current continuation, and the next instruction can be decoded.
### 5.2.3. Invalid opcode [#523-invalid-opcode]
If no prefix of $\texttt{cc.code}$ encodes a valid instruction in the current codepage, an invalid opcode [exception](#4-5-7-list-of-predefined-exceptions) is generated. However, the case of an empty $\texttt{cc.code}$ is treated [separately](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop) (the exact behavior may depend on the current codepage).
### 5.2.4. Special case: end-of-code padding [#524-special-case-end-of-code-padding]
As an exception to the above rule, some codepages may accept some values of $\texttt{cc.code}$ that are too short to be valid instruction encodings as additional variants of $\texttt{NOP}$, thus effectively using the same procedure for them as for an empty $\texttt{cc.code}$. Such bitstrings may be used for padding the code near its end.
For example, if [binary string](#1-0-3-emphasizing-that-a-string-is-a-hexadecimal-representation-of-a-bitstring) $\texttt{00000000}$ (i.e., $\texttt{x00}$, is used in a codepage to encode $\texttt{NOP}$, its proper prefixes cannot encode any instructions. So this codepage may accept $\texttt{0}$, $\texttt{00}$, $\texttt{000}$, $\ldots$, $\texttt{0000000}$ as variants of $\texttt{NOP}$ if this is all that is left in $\texttt{cc.code}$, instead of generating an invalid opcode exception.
Such a padding may be useful, for example, if the $\texttt{PUSHCONT}$ primitive creates only [continuations](#4-2-3-constant%2C-or-literal%2C-continuations) with code consisting of an integral number of bytes, but not all instructions are encoded by an integral number of bytes.
### 5.2.5. TVM code is a bitcode, not a bytecode [#525-tvm-code-is-a-bitcode-not-a-bytecode]
Recall that TVM is a bit-oriented machine in the sense that its *Cell*s (and *Slice*s) are naturally considered as [sequences of bits](#3-2-5-cells-and-cell-primitives-are-bit-oriented,-not-byte-oriented), not just of octets (bytes). Because the TVM code is also kept in cells ([3.1.9](#3-1-9-tvm-code-is-a-tree-of-cells) and [4.1.4](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop)), there is no reason to use only bitstrings of length divisible by eight as encodings of complete instructions. In other words, generally speaking, *the TVM code is a bitcode, not a bytecode*.
That said, some codepages (such as our experimental codepage zero) may opt to use a bytecode (i.e., to use only encodings consisting of an integral number of bytes)—either for simplicity, or for the ease of debugging and of studying memory (i.e., cell) dumps.[27](#fn27)
### 5.2.6. Opcode space used by a complete instruction [#526-opcode-space-used-by-a-complete-instruction]
Recall from coding theory that the lengths of bitstrings $l_i$ used in a binary prefix code satisfy Kraft–McMillan inequality $\sum_i2^{-l_i}\leq1$. This is applicable in particular to the (complete) instruction encoding used by a TVM codepage. We say that *a particular complete instruction* (or, more precisely, *the encoding of a complete instruction*) *utilizes the portion $2^{-l}$ of the opcode space*, if it is encoded by an $l$-bit string. One can see that all complete instructions together utilize at most $1$ (i.e., "at most the whole opcode space").
### 5.2.7. Opcode space used by an instruction, or a class of instructions [#527-opcode-space-used-by-an-instruction-or-a-class-of-instructions]
The above terminology is extended to instructions (considered with all admissible values of their parameters), or even classes of instructions (e.g., all arithmetic instructions). We say that an (incomplete) instruction, or a class of instructions, occupies portion $\alpha$ of the opcode space, if $\alpha$ is the sum of the portions of the opcode space occupied by all complete instructions belonging to that class.
### 5.2.8. Opcode space for bytecodes [#528-opcode-space-for-bytecodes]
A useful approximation of the above definitions is as follows: Consider all 256 possible values for the first byte of an instruction encoding. Suppose that $k$ of these values correspond to the specific instruction or class of instructions we are considering. Then this instruction or class of instructions occupies approximately the portion $k/256$ of the opcode space.
This approximation shows why all instructions cannot occupy together more than the portion $256/256=1$ of the opcode space, at least without compromising the uniqueness of instruction decoding.
### 5.2.9. Almost optimal encodings [#529-almost-optimal-encodings]
Coding theory tells us that in an optimally dense encoding, the portion of the opcode space used by a complete instruction ($2^{-l}$, if the complete instruction is encoded in $l$ bits) should be approximately equal to the probability or frequency of its occurrence in real programs.[28](#fn28) The same should hold for (incomplete) instructions, or primitives (i.e., generic instructions without specified values of parameters), and for classes of instructions.
### 5.2.10. Example: stack manipulation primitives [#5210-example-stack-manipulation-primitives]
For instance, if stack manipulation instructions constitute approximately half of all instructions in a typical TVM program, one should allocate approximately half of the opcode space for encoding stack manipulation instructions. One might reserve the first bytes ("opcodes") $\texttt{0x00}$-$\texttt{0x7f}$ for such instructions. If a quarter of these instructions are $\texttt{XCHG}$, it would make sense to reserve $\texttt{0x00}$-$\texttt{0x1f}$ for $\texttt{XCHG}$s. Similarly, if half of all $\texttt{XCHG}$s involve the top of stack $\texttt{s0}$, it would make sense to use $\texttt{0x00}$-$\texttt{0x0f}$ to encode $\texttt{XCHG s0,s}(i)$.
### 5.2.11. Simple encodings of instructions [#5211-simple-encodings-of-instructions]
In most cases, *simple* encodings of complete instructions are used. Simple encodings begin with a fixed bitstring called the *opcode* of the instruction, followed by, say, 4-bit fields containing the indices $i$ of stack registers $\texttt{s}(i)$ specified in the instruction, followed by all other constant (literal, immediate) parameters included in the complete instruction. While simple encodings may not be exactly optimal, they admit short descriptions, and their decoding and encoding can be easily implemented.
If a (generic) instruction uses a simple encoding with an $l$-bit opcode, then the instruction will utilize $2^{-l}$ portion of the opcode space. This observation might be useful for considerations described in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives).
### 5.2.12. Optimizing code density further: Huffman codes [#5212-optimizing-code-density-further-huffman-codes]
One might construct optimally dense binary code for the set of all complete instructions, provided their probabilities or frequences in real code are known. This is the well-known Huffman code (for the given probability distribution). However, such code would be highly unsystematic and hard to decode.
### 5.2.13. Practical instruction encodings [#5213-practical-instruction-encodings]
In practice, instruction encodings used in TVM and other virtual machines offer a compromise between code density and ease of encoding and decoding. Such a compromise may be achieved by selecting [simple encodings](#5-2-11-simple-encodings-of-instructions) for all instructions (maybe with separate simple encodings for some often used variants, such as $\texttt{XCHG s0,s}(i)$ among all $\texttt{XCHG s}(i)\texttt{,s}(j)$), and allocating opcode space for such simple encodings using the heuristics outlined in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives); this is the approach currently used in TVM.
***
## 5.3 Instruction encoding in codepage zero [#53---instruction-encoding-in-codepage-zero]
This section provides details about the experimental instruction encoding for codepage zero, as described elsewhere in this [document](#a-instructions-and-opcodes) and used in the preliminary test version of TVM.
### 5.3.1. Upgradability [#531-upgradability]
First of all, even if this preliminary version somehow gets into the production version of the TON Blockchain, the [codepage mechanism](#5-1-codepages-and-interoperability-of-different-tvm-versions) enables us to introduce better versions later without compromising backward compatibility.[29](#fn29) So in the meantime, we are free to experiment.
### 5.3.2. Choice of instructions [#532-choice-of-instructions]
We opted to include many "experimental" and not strictly necessary instructions in codepage zero just to see how they might be used in real code. For example, we have both the [basic](#2-2-1-basic-stack-manipulation-primitives) and the [compound](#2-2-3-compound-stack-manipulation-primitives) stack manipulation primitives, as well as some "unsystematic" ones such as $\texttt{ROT}$ (mostly borrowed from Forth). If such primitives are rarely used, their inclusion just wastes some part of the opcode space and makes the encodings of other instructions slightly less effective, something we can afford at this stage of TVM's development.
### 5.3.3. Using experimental instructions [#533-using-experimental-instructions]
Some of these experimental instructions have been assigned quite long opcodes, just to fit more of them into the opcode space. One should not be afraid to use them just because they are long; if these instructions turn out to be useful, they will receive shorter opcodes in future revisions. Codepage zero is not meant to be fine-tuned in this respect.
### 5.3.4. Choice of bytecode [#534-choice-of-bytecode]
We opted to use a bytecode (i.e., to use encodings of complete instructions of lengths divisible by eight). While this may not produce optimal code density, because such a length restriction makes it more difficult to match portions of opcode space used for the encoding of instructions with estimated frequencies of these instructions in TVM code [5.2.11](#5-2-11-simple-encodings-of-instructions) and [5.2.9](#5-2-9-almost-optimal-encodings)), such an approach has its advantages: it admits a simpler instruction decoder and simplifies [debugging](#5-2-5-tvm-code-is-a-bitcode%2C-not-a-bytecode).
After all, we do not have enough data on the relative frequencies of different instructions right now, so our code density optimizations are likely to be very approximate at this stage. The ease of debugging and experimenting and the simplicity of implementation are more important at this point.
### 5.3.5. Simple encodings for all instructions [#535-simple-encodings-for-all-instructions]
For similar reasons, we opted to use simple encodings for all instructions ([5.2.11](#5-2-11-simple-encodings-of-instructions) and [5.2.13](#5-2-13-practical-instruction-encodings)), with separate [simple encodings](#5-2-13-practical-instruction-encodings) for some very frequently used subcases. That said, we tried to distribute opcode space using the heuristics described in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives).
### 5.3.6. Lack of context-dependent encodings [#536-lack-of-context-dependent-encodings]
This version of TVM also does not use [context-dependent encodings](#5-1-6-making-instruction-encoding-context-dependent). They may be added at a later stage, if deemed useful.
### 5.3.7. The list of all instructions [#537-the-list-of-all-instructions]
The list of all instructions available in codepage zero, along with their encodings and (in some cases) short descriptions, may be found in [Appendix A](#a-instructions-and-opcodes).
***
# A Instructions and opcodes [#a---instructions-and-opcodes]
This appendix lists all [instructions](#5-3-instruction-encoding-in-codepage-zero) available in the (experimental) codepage zero of TVM.
We list the instructions in lexicographical opcode order. However, the opcode space is distributed in such way as to make all instructions in each category (e.g., arithmetic primitives) have neighboring opcodes. So we first list a number of stack manipulation primitives, then constant primitives, arithmetic primitives, comparison primitives, cell primitives, continuation primitives, dictionary primitives, and finally application-specific primitives.
We use [hexadecimal notation](#1-0-notation-for-bitstrings) for bitstrings. Stack registers $\texttt{s}(i)$ usually have $0\leq i\leq 15$, and $i$ is encoded in a 4-bit field (or, on a few rare occasions, in an 8-bit field). Other immediate parameters are usually 4-bit, 8-bit, or variable length.
The [stack notation](#2-1-10-stack-notation) is extensively used throughout this appendix.
## A.1 Gas prices [#a1--gas-prices]
The gas price for most primitives equals the *basic gas price*, computed as $P_b:=10+b+5r$, where $b$ is the instruction length in bits and $r$ is the number of cell references included in the instruction. When the gas price of an instruction differs from this basic price, it is indicated in parentheses after its mnemonics, either as *($x$)*, meaning that the total gas price equals $x$, or as *(+$x$)*, meaning $P_b+x$. Apart from integer constants, the following expressions may appear:
* $C_r$ — The total price of "reading" cells (i.e., transforming cell references into cell slices). Currently equal to 100 or 25 gas units per cell depending on whether it is the first time a cell with this hash is being "read" during the current run of the VM or not.
* $L$ — The total price of loading cells. Depends on the loading action required.
* $B_w$ — The total price of creating new *Builder*s. Currently equal to 0 gas units per builder.
* $C_w$ — The total price of creating new *Cell*s from *Builder*s. Currently equal to 500 gas units per cell.
By default, the gas price of an instruction equals $P:=P_b+C_r+L+B_w+C_w$.
## A.2 Stack manipulation primitives [#a2---stack-manipulation-primitives]
This section includes both the [basic](#2-2-1-basic-stack-manipulation-primitives) and the [compound](#2-2-3-compound-stack-manipulation-primitives) stack manipulation primitives, as well as some "unsystematic" ones. Some compound stack manipulation primitives, such as $\texttt{XCPU}$ or $\texttt{XCHG2}$, turn out to have the same length as an equivalent sequence of simpler operations. We have included these primitives regardless, so that they can easily be allocated shorter opcodes in a future revision of TVM—or removed for good.
Some stack manipulation instructions have two mnemonics: one Forth-style (e.g., $\texttt{-ROT}$), the other conforming to the usual rules for identifiers (e.g., $\texttt{ROTREV}$). Whenever a stack manipulation primitive (e.g., $\texttt{PICK}$) accepts an integer parameter $n$ from the stack, it must be within the range $0\ldots255$; otherwise a range check exception happens before any further checks.
### A.2.1. Basic stack manipulation primitives [#a21-basic-stack-manipulation-primitives]
* $\texttt{00}$ — $\texttt{NOP}$, does nothing.
* $\texttt{01}$ — $\texttt{XCHG s1}$, also known as $\texttt{SWAP}$.
* $\texttt{0}i$ — $\texttt{XCHG s}(i)$ or $\texttt{XCHG s0,s}(i)$, interchanges the top of the stack with $\texttt{s}(i)$, $1\leq i\leq 15$.
* $\texttt{10}ij$ — $\texttt{XCHG s}(i)\texttt{,s}(j)$, $1\leq i0$.
* $\texttt{B9}$ — $\texttt{LESS}$ ($x$ $y$ -- $xy$).
* $\texttt{BD}$ — $\texttt{NEQ}$ ($x$ $y$ -- $x\neq y$), equivalent to $\texttt{EQUAL}$; $\texttt{NOT}$.
* $\texttt{BE}$ — $\texttt{GEQ}$ ($x$ $y$ -- $x\geq y$), equivalent to $\texttt{LESS}$; $\texttt{NOT}$.
* $\texttt{BF}$ — $\texttt{CMP}$ ($x$ $y$ -- $\text{sgn}(x-y)$), computes the sign of $x-y$: $-1$ if $xy$. No integer overflow can occur here unless $x$ or $y$ is a $\texttt{NaN}$.
* $\texttt{C0}yy$ — $\texttt{EQINT}$ $yy$ ($x$ -- $x=yy$) for $-2^7\leq yy<2^7$.
* $\texttt{C000}$ — $\texttt{ISZERO}$, checks whether an integer is zero. Corresponds to Forth's $\texttt{0=}$.
* $\texttt{C1}yy$ — $\texttt{LESSINT}$ $yy$ ($x$ -- $xyy$) for $-2^7\leq yy<2^7$.
* $\texttt{C200}$ — $\texttt{ISPOS}$, checks whether an integer is positive. Corresponds to Forth's $\texttt{0>}$.
* $\texttt{C2FF}$ — $\texttt{ISNNEG}$, checks whether an integer is non-negative.
* $\texttt{C3}yy$ — $\texttt{NEQINT}$ $yy$ ($x$ -- $x\neq yy$) for $-2^7\leq yy<2^7$.
* $\texttt{C4}$ — $\texttt{ISNAN}$ ($x$ -- $x=\texttt{NaN}$), checks whether $x$ is a $\texttt{NaN}$.
* $\texttt{C5}$ — $\texttt{CHKNAN}$ ($x$ -- $x$), throws an arithmetic overflow exception if $x$ is a $\texttt{NaN}$.
* $\texttt{C6}$ — reserved for integer comparison.
### A.6.2. Other comparison [#a62-other-comparison]
Most of these "other comparison" primitives actually compare the data portions of *Slice*s as bitstrings.
* $\texttt{C700}$ — $\texttt{SEMPTY}$ ($s$ -- $s=\emptyset$), checks whether a *Slice* $s$ is empty (i.e., contains no bits of data and no cell references).
* $\texttt{C701}$ — $\texttt{SDEMPTY}$ ($s$ -- $s\approx\emptyset$), checks whether *Slice* $s$ has no bits of data.
* $\texttt{C702}$ — $\texttt{SREMPTY}$ ($s$ -- $r(s)=0$), checks whether *Slice* $s$ has no references.
* $\texttt{C703}$ — $\texttt{SDFIRST}$ ($s$ -- $s_0=1$), checks whether the first bit of *Slice* $s$ is a one.
* $\texttt{C704}$ — $\texttt{SDLEXCMP}$ ($s$ $s'$ -- $c$), compares the data of $s$ lexicographically with the data of $s'$, returning $-1$, 0, or 1 depending on the result.
* $\texttt{C705}$ — $\texttt{SDEQ}$ ($s$ $s'$ -- $s\approx s'$), checks whether the data parts of $s$ and $s'$ coincide, equivalent to $\texttt{SDLEXCMP}$; $\texttt{ISZERO}$.
* $\texttt{C708}$ — $\texttt{SDPFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a prefix of $s'$.
* $\texttt{C709}$ — $\texttt{SDPFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a prefix of $s$, equivalent to $\texttt{SWAP}$; $\texttt{SDPFX}$.
* $\texttt{C70A}$ — $\texttt{SDPPFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a proper prefix of $s'$ (i.e., a prefix distinct from $s'$).
* $\texttt{C70B}$ — $\texttt{SDPPFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a proper prefix of $s$.
* $\texttt{C70C}$ — $\texttt{SDSFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a suffix of $s'$.
* $\texttt{C70D}$ — $\texttt{SDSFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a suffix of $s$.
* $\texttt{C70E}$ — $\texttt{SDPSFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a proper suffix of $s'$.
* $\texttt{C70F}$ — $\texttt{SDPSFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a proper suffix of $s$.
* $\texttt{C710}$ — $\texttt{SDCNTLEAD0}$ ($s$ -- $n$), returns the number of leading zeroes in $s$.
* $\texttt{C711}$ — $\texttt{SDCNTLEAD1}$ ($s$ -- $n$), returns the number of leading ones in $s$.
* $\texttt{C712}$ — $\texttt{SDCNTTRAIL0}$ ($s$ -- $n$), returns the number of trailing zeroes in $s$.
* $\texttt{C713}$ — $\texttt{SDCNTTRAIL1}$ ($s$ -- $n$), returns the number of trailing ones in $s$.
## A.7 Cell primitives [#a7-cell-primitives]
The cell primitives are mostly either *cell serialization primitives*, which work with *Builder*s, or *cell deserialization primitives*, which work with *Slice*s.
### A.7.1. Cell serialization primitives [#a71-cell-serialization-primitives]
All these primitives first check whether there is enough space in the Builder, and only then check the range of the value being serialized.
* $\texttt{C8}$ — $\texttt{NEWC}$ ( -- $b$), creates a new empty *Builder*.
* $\texttt{C9}$ — $\texttt{ENDC}$ ($b$ -- $c$), converts a *Builder* into an ordinary *Cell*.
* $\texttt{CA}cc$ — $\texttt{STI}$ $cc+1$ ($x$ $b$ -- $b'$), stores a signed $cc+1$-bit integer $x$ into *Builder* $b$ for $0\leq cc\leq 255$, throws a range check exception if $x$ does not fit into $cc+1$ bits.
* $\texttt{CB}cc$ — $\texttt{STU}$ $cc+1$ ($x$ $b$ -- $b'$), stores an unsigned $cc+1$-bit integer $x$ into *Builder* $b$. In all other respects it is similar to $\texttt{STI}$.
* $\texttt{CC}$ — $\texttt{STREF}$ ($c$ $b$ -- $b'$), stores a reference to *Cell* $c$ into *Builder* $b$.
* $\texttt{CD}$ — $\texttt{STBREFR}$ or $\texttt{ENDCST}$ ($b$ $b''$ -- $b$), equivalent to $\texttt{ENDC}$; $\texttt{SWAP}$; $\texttt{STREF}$.
* $\texttt{CE}$ — $\texttt{STSLICE}$ ($s$ $b$ -- $b'$), stores *Slice* $s$ into *Builder* $b$.
* $\texttt{CF00}$ — $\texttt{STIX}$ ($x$ $b$ $l$ -- $b'$), stores a signed $l$-bit integer $x$ into $b$ for $0\leq l\leq 257$.
* $\texttt{CF01}$ — $\texttt{STUX}$ ($x$ $b$ $l$ -- $b'$), stores an unsigned $l$-bit integer $x$ into $b$ for $0\leq l\leq 256$.
* $\texttt{CF02}$ — $\texttt{STIXR}$ ($b$ $x$ $l$ -- $b'$), similar to $\texttt{STIX}$, but with arguments in a different order.
* $\texttt{CF03}$ — $\texttt{STUXR}$ ($b$ $x$ $l$ -- $b'$), similar to $\texttt{STUX}$, but with arguments in a different order.
* $\texttt{CF04}$ — $\texttt{STIXQ}$ ($x$ $b$ $l$ -- $x$ $b$ $f$ or $b'$ $0$), a quiet version of $\texttt{STIX}$. If there is no space in $b$, sets $b'=b$ and $f=-1$. If $x$ does not fit into $l$ bits, sets $b'=b$ and $f=1$. If the operation succeeds, $b'$ is the new *Builder* and $f=0$. However, $0\leq l\leq 257$, with a range check exception if this is not so.
* $\texttt{CF05}$ — $\texttt{STUXQ}$ ($x$ $b$ $l$ -- $b'$ $f$).
* $\texttt{CF06}$ — $\texttt{STIXRQ}$ ($b$ $x$ $l$ -- $b$ $x$ $f$ or $b'$ $0$).
* $\texttt{CF07}$ — $\texttt{STUXRQ}$ ($b$ $x$ $l$ -- $b$ $x$ $f$ or $b'$ $0$).
* $\texttt{CF08}cc$ — a longer version of $\texttt{STI}$ $cc+1$.
* $\texttt{CF09}cc$ — a longer version of $\texttt{STU}$ $cc+1$.
* $\texttt{CF0A}cc$ — $\texttt{STIR}$ $cc+1$ ($b$ $x$ -- $b'$), equivalent to $\texttt{SWAP}$; $\texttt{STI}$ $cc+1$.
* $\texttt{CF0B}cc$ — $\texttt{STUR}$ $cc+1$ ($b$ $x$ -- $b'$), equivalent to $\texttt{SWAP}$; $\texttt{STU}$ $cc+1$.
* $\texttt{CF0C}cc$ — $\texttt{STIQ}$ $cc+1$ ($x$ $b$ -- $x$ $b$ $f$ or $b'$ $0$).
* $\texttt{CF0D}cc$ — $\texttt{STUQ}$ $cc+1$ ($x$ $b$ -- $x$ $b$ $f$ or $b'$ $0$).
* $\texttt{CF0E}cc$ — $\texttt{STIRQ}$ $cc+1$ ($b$ $x$ -- $b$ $x$ $f$ or $b'$ $0$).
* $\texttt{CF0F}cc$ — $\texttt{STURQ}$ $cc+1$ ($b$ $x$ -- $b$ $x$ $f$ or $b'$ $0$).
* $\texttt{CF10}$ — a longer version of $\texttt{STREF}$ ($c$ $b$ -- $b'$).
* $\texttt{CF11}$ — $\texttt{STBREF}$ ($b'$ $b$ -- $b''$), equivalent to $\texttt{SWAP}$; $\texttt{STBREFREV}$.
* $\texttt{CF12}$ — a longer version of $\texttt{STSLICE}$ ($s$ $b$ -- $b'$).
* $\texttt{CF13}$ — $\texttt{STB}$ ($b'$ $b$ -- $b''$), appends all data from *Builder* $b'$ to *Builder* $b$.
* $\texttt{CF14}$ — $\texttt{STREFR}$ ($b$ $c$ -- $b'$).
* $\texttt{CF15}$ — $\texttt{STBREFR}$ ($b$ $b'$ -- $b''$), a longer encoding of $\texttt{STBREFR}$.
* $\texttt{CF16}$ — $\texttt{STSLICER}$ ($b$ $s$ -- $b'$).
* $\texttt{CF17}$ — $\texttt{STBR}$ ($b$ $b'$ -- $b''$), concatenates two *Builder*s, equivalent to $\texttt{SWAP}$; $\texttt{STB}$.
* $\texttt{CF18}$ — $\texttt{STREFQ}$ ($c$ $b$ -- $c$ $b$ $-1$ or $b'$ $0$).
* $\texttt{CF19}$ — $\texttt{STBREFQ}$ ($b'$ $b$ -- $b'$ $b$ $-1$ or $b''$ $0$).
* $\texttt{CF1A}$ — $\texttt{STSLICEQ}$ ($s$ $b$ -- $s$ $b$ $-1$ or $b'$ $0$).
* $\texttt{CF1B}$ — $\texttt{STBQ}$ ($b'$ $b$ -- $b'$ $b$ $-1$ or $b''$ $0$).
* $\texttt{CF1C}$ — $\texttt{STREFRQ}$ ($b$ $c$ -- $b$ $c$ $-1$ or $b'$ $0$).
* $\texttt{CF1D}$ — $\texttt{STBREFRQ}$ ($b$ $b'$ -- $b$ $b'$ $-1$ or $b''$ $0$).
* $\texttt{CF1E}$ — $\texttt{STSLICERQ}$ ($b$ $s$ -- $b$ $s$ $-1$ or $b''$ $0$).
* $\texttt{CF1F}$ — $\texttt{STBRQ}$ ($b$ $b'$ -- $b$ $b'$ $-1$ or $b''$ $0$).
* $\texttt{CF20}$ — $\texttt{STREFCONST}$, equivalent to $\texttt{PUSHREF}$; $\texttt{STREFR}$.
* $\texttt{CF21}$ — $\texttt{STREF2CONST}$, equivalent to $\texttt{STREFCONST}$; $\texttt{STREFCONST}$.
* $\texttt{CF23}$ — $\texttt{ENDXC}$ ($b$ $x$ -- $c$), if $x\neq0$, creates a *special* or [exotic cell](#3-1-2-ordinary-and-exotic-cells) from *Builder* $b$. The type of the exotic cell must be stored in the first 8 bits of $b$. If $x=0$, it is equivalent to $\texttt{ENDC}$. Otherwise some validity checks on the data and references of $b$ are performed before creating the exotic cell.
* $\texttt{CF28}$ — $\texttt{STILE4}$ ($x$ $b$ -- $b'$), stores a little-endian signed 32-bit integer.
* $\texttt{CF29}$ — $\texttt{STULE4}$ ($x$ $b$ -- $b'$), stores a little-endian unsigned 32-bit integer.
* $\texttt{CF2A}$ — $\texttt{STILE8}$ ($x$ $b$ -- $b'$), stores a little-endian signed 64-bit integer.
* $\texttt{CF2B}$ — $\texttt{STULE8}$ ($x$ $b$ -- $b'$), stores a little-endian unsigned 64-bit integer.
* $\texttt{CF30}$ — $\texttt{BDEPTH}$ ($b$ -- $x$), returns the depth of *Builder* $b$. If no cell references are stored in $b$, then $x=0$; otherwise $x$ is one plus the maximum of depths of cells referred to from $b$.
* $\texttt{CF31}$ — $\texttt{BBITS}$ ($b$ -- $x$), returns the number of data bits already stored in *Builder* $b$.
* $\texttt{CF32}$ — $\texttt{BREFS}$ ($b$ -- $y$), returns the number of cell references already stored in $b$.
* $\texttt{CF33}$ — $\texttt{BBITREFS}$ ($b$ -- $x$ $y$), returns the numbers of both data bits and cell references in $b$.
* $\texttt{CF35}$ — $\texttt{BREMBITS}$ ($b$ -- $x'$), returns the number of data bits that can still be stored in $b$.
* $\texttt{CF36}$ — $\texttt{BREMREFS}$ ($b$ -- $y'$).
* $\texttt{CF37}$ — $\texttt{BREMBITREFS}$ ($b$ -- $x'$ $y'$).
* $\texttt{CF38}cc$ — $\texttt{BCHKBITS}$ $cc+1$ ($b$ --), checks whether $cc+1$ bits can be stored into $b$, where $0\leq cc\leq 255$.
* $\texttt{CF39}$ — $\texttt{BCHKBITS}$ ($b$ $x$ -- ), checks whether $x$ bits can be stored into $b$, $0\leq x\leq 1023$. If there is no space for $x$ more bits in $b$, or if $x$ is not within the range $0\ldots1023$, throws an exception.
* $\texttt{CF3A}$ — $\texttt{BCHKREFS}$ ($b$ $y$ -- ), checks whether $y$ references can be stored into $b$, $0\leq y\leq 7$.
* $\texttt{CF3B}$ — $\texttt{BCHKBITREFS}$ ($b$ $x$ $y$ -- ), checks whether $x$ bits and $y$ references can be stored into $b$, $0\leq x\leq 1023$, $0\leq y\leq 7$.
* $\texttt{CF3C}cc$ — $\texttt{BCHKBITSQ}$ $cc+1$ ($b$ -- $?$), checks whether $cc+1$ bits can be stored into $b$, where $0\leq cc\leq 255$.
* $\texttt{CF3D}$ — $\texttt{BCHKBITSQ}$ ($b$ $x$ -- $?$), checks whether $x$ bits can be stored into $b$, $0\leq x\leq 1023$.
* $\texttt{CF3E}$ — $\texttt{BCHKREFSQ}$ ($b$ $y$ -- $?$), checks whether $y$ references can be stored into $b$, $0\leq y\leq 7$.
* $\texttt{CF3F}$ — $\texttt{BCHKBITREFSQ}$ ($b$ $x$ $y$ -- $?$), checks whether $x$ bits and $y$ references can be stored into $b$, $0\leq x\leq 1023$, $0\leq y\leq 7$.
* $\texttt{CF40}$ — $\texttt{STZEROES}$ ($b$ $n$ -- $b'$), stores $n$ binary zeroes into *Builder* $b$.
* $\texttt{CF41}$ — $\texttt{STONES}$ ($b$ $n$ -- $b'$), stores $n$ binary ones into *Builder* $b$.
* $\texttt{CF42}$ — $\texttt{STSAME}$ ($b$ $n$ $x$ -- $b'$), stores $n$ binary $x$es ($0\leq x\leq1$) into *Builder* $b$.
* $\texttt{CFC0\_xysss}$ — $\texttt{STSLICECONST}$ $sss$ ($b$ -- $b'$), stores a constant subslice $sss$ consisting of $0\leq x\leq 3$ references and up to $8y+1$ data bits, with $0\leq y\leq 7$. Completion bit is assumed.
* $\texttt{CF81}$ — $\texttt{STSLICECONST '0'}$ or $\texttt{STZERO}$ ($b$ -- $b'$), stores one binary zero.
* $\texttt{CF83}$ — $\texttt{STSLICECONST '1'}$ or $\texttt{STONE}$ ($b$ -- $b'$), stores one binary one.
* $\texttt{CFA2}$ — equivalent to $\texttt{STREFCONST}$.
* $\texttt{CFA3}$ — almost equivalent to $\texttt{STSLICECONST '1'}$; $\texttt{STREFCONST}$.
* $\texttt{CFC2}$ — equivalent to $\texttt{STREF2CONST}$.
* $\texttt{CFE2}$ — $\texttt{STREF3CONST}$.
### A.7.2. Cell deserialization primitives [#a72-cell-deserialization-primitives]
* $\texttt{D0}$ — $\texttt{CTOS}$ ($c$ -- $s$), converts a *Cell* into a *Slice*. Notice that $c$ must be either an ordinary cell, or an [exotic cell](#3-1-2-ordinary-and-exotic-cells) which is automatically *loaded* to yield an ordinary cell $c'$, converted into a *Slice* afterwards.
* $\texttt{D1}$ — $\texttt{ENDS}$ ($s$ -- ), removes a *Slice* $s$ from the stack, and throws an exception if it is not empty.
* $\texttt{D2}$ $cc$ — $\texttt{LDI}$ $cc+1$ ($s$ -- $x$ $s'$), loads (i.e., parses) a signed $cc+1$-bit integer $x$ from *Slice* $s$, and returns the remainder of $s$ as $s'$.
* $\texttt{D3}$ $cc$ — $\texttt{LDU}$ $cc+1$ ($s$ -- $x$ $s'$), loads an unsigned $cc+1$-bit integer $x$ from *Slice* $s$.
* $\texttt{D4}$ — $\texttt{LDREF}$ ($s$ -- $c$ $s'$), loads a cell reference $c$ from $s$.
* $\texttt{D5}$ — $\texttt{LDREFRTOS}$ ($s$ -- $s'$ $s''$), equivalent to $\texttt{LDREF}$; $\texttt{SWAP}$; $\texttt{CTOS}$.
* $\texttt{D6}$ $cc$ — $\texttt{LDSLICE}$ $cc+1$ ($s$ -- $s''$ $s'$), cuts the next $cc+1$ bits of $s$ into a separate *Slice* $s''$.
* $\texttt{D700}$ — $\texttt{LDIX}$ ($s$ $l$ -- $x$ $s'$), loads a signed $l$-bit ($0\leq l\leq 257$) integer $x$ from *Slice* $s$, and returns the remainder of $s$ as $s'$.
* $\texttt{D701}$ — $\texttt{LDUX}$ ($s$ $l$ -- $x$ $s'$), loads an unsigned $l$-bit integer $x$ from (the first $l$ bits of) $s$, with $0\leq l\leq 256$.
* $\texttt{D702}$ — $\texttt{PLDIX}$ ($s$ $l$ -- $x$), preloads a signed $l$-bit integer from *Slice* $s$, for $0\leq l\leq 257$.
* $\texttt{D703}$ — $\texttt{PLDUX}$ ($s$ $l$ -- $x$), preloads an unsigned $l$-bit integer from $s$, for $0\leq l\leq 256$.
* $\texttt{D704}$ — $\texttt{LDIXQ}$ ($s$ $l$ -- $x$ $s'$ $-1$ or $s$ $0$), quiet version of $\texttt{LDIX}$: loads a signed $l$-bit integer from $s$ similarly to $\texttt{LDIX}$, but returns a success flag, equal to $-1$ on success or to $0$ on failure (if $s$ does not have $l$ bits), instead of throwing a cell underflow exception.
* $\texttt{D705}$ — $\texttt{LDUXQ}$ ($s$ $l$ -- $x$ $s'$ $-1$ or $s$ $0$), quiet version of $\texttt{LDUX}$.
* $\texttt{D706}$ — $\texttt{PLDIXQ}$ ($s$ $l$ -- $x$ $-1$ or $0$), quiet version of $\texttt{PLDIX}$.
* $\texttt{D707}$ — $\texttt{PLDUXQ}$ ($s$ $l$ -- $x$ $-1$ or $0$), quiet version of $\texttt{PLDUX}$.
* $\texttt{D708}$ $cc$ — $\texttt{LDI}$ $cc+1$ ($s$ -- $x$ $s'$), a longer encoding for $\texttt{LDI}$.
* $\texttt{D709}$ $cc$ — $\texttt{LDU}$ $cc+1$ ($s$ -- $x$ $s'$), a longer encoding for $\texttt{LDU}$.
* $\texttt{D70A}$ $cc$ — $\texttt{PLDI}$ $cc+1$ ($s$ -- $x$), preloads a signed $cc+1$-bit integer from *Slice* $s$.
* $\texttt{D70B}$ $cc$ — $\texttt{PLDU}$ $cc+1$ ($s$ -- $x$), preloads an unsigned $cc+1$-bit integer from $s$.
* $\texttt{D70C}$ $cc$ — $\texttt{LDIQ}$ $cc+1$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), a quiet version of $\texttt{LDI}$.
* $\texttt{D70D}$ $cc$ — $\texttt{LDUQ}$ $cc+1$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), a quiet version of $\texttt{LDU}$.
* $\texttt{D70E}$ $cc$ — $\texttt{PLDIQ}$ $cc+1$ ($s$ -- $x$ $-1$ or $0$), a quiet version of $\texttt{PLDI}$.
* $\texttt{D70F}$ $cc$ — $\texttt{PLDUQ}$ $cc+1$ ($s$ -- $x$ $-1$ or $0$), a quiet version of $\texttt{PLDU}$.
* $\texttt{D714\_}c$ — $\texttt{PLDUZ}$ $32(c+1)$ ($s$ -- $s$ $x$), preloads the first $32(c+1)$ bits of *Slice* $s$ into an unsigned integer $x$, for $0\leq c\leq 7$. If $s$ is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with $\texttt{IFBITJMP}$ and similar instructions.
* $\texttt{D718}$ — $\texttt{LDSLICEX}$ ($s$ $l$ -- $s''$ $s'$), loads the first $0\leq l\leq 1023$ bits from *Slice* $s$ into a separate *Slice* $s''$, returning the remainder of $s$ as $s'$.
* $\texttt{D719}$ — $\texttt{PLDSLICEX}$ ($s$ $l$ -- $s''$), returns the first $0\leq l\leq 1023$ bits of $s$ as $s''$.
* $\texttt{D71A}$ — $\texttt{LDSLICEXQ}$ ($s$ $l$ -- $s''$ $s'$ $-1$ or $s$ $0$), a quiet version of $\texttt{LDSLICEX}$.
* $\texttt{D71B}$ — $\texttt{PLDSLICEXQ}$ ($s$ $l$ -- $s'$ $-1$ or $0$), a quiet version of $\texttt{LDSLICEXQ}$.
* $\texttt{D71C}$ $cc$ — $\texttt{LDSLICE}$ $cc+1$ ($s$ -- $s''$ $s'$), a longer encoding for $\texttt{LDSLICE}$.
* $\texttt{D71D}$ $cc$ — $\texttt{PLDSLICE}$ $cc+1$ ($s$ -- $s''$), returns the first $0= 1 }
rewrite_pfx:(bits depth) = Anycast;
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
_ _:MsgAddressInt = MsgAddress;
_ _:MsgAddressExt = MsgAddress;
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddress dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
```
A deserialized $\texttt{MsgAddress}$ is represented by a *Tuple* $t$ as follows:
* $\texttt{addr\_none}$ is represented by $t=(0)$, i.e., a *Tuple* containing exactly one *Integer* equal to zero.
* $\texttt{addr\_extern}$ is represented by $t=(1,s)$, where *Slice* $s$ contains the field $\texttt{external\_address}$. In other words, $t$ is a pair (a *Tuple* consisting of two entries), containing an *Integer* equal to one and *Slice* $s$.
* $\texttt{addr\_std}$ is represented by $t=(2,u,x,s)$, where $u$ is either a *Null* (if $\texttt{anycast}$ is absent) or a *Slice* $s'$ containing $\texttt{rewrite\_pfx}$ (if $\texttt{anycast}$ is present). Next, *Integer* $x$ is the $\texttt{workchain\_id}$, and *Slice* $s$ contains the $\texttt{address}$.
* $\texttt{addr\_var}$ is represented by $t=(3,u,x,s)$, where $u$, $x$, and $s$ have the same meaning as for $\texttt{addr\_std}$.
The following primitives, which use the above conventions, are defined:
* $\texttt{FA40}$ — $\texttt{LDMSGADDR}$ ($s$ - $s'$ $s''$), loads from *CellSlice* $s$ the only prefix that is a valid $\texttt{MsgAddress}$, and returns both this prefix $s'$ and the remainder $s''$ of $s$ as *CellSlice*s.
* $\texttt{FA41}$ — $\texttt{LDMSGADDRQ}$ ($s$ - $s'$ $s''$ $-1$ or $s$ $0$), a quiet version of $\texttt{LDMSGADDR}$: on success, pushes an extra $-1$; on failure, pushes the original $s$ and a zero.
* $\texttt{FA42}$ — $\texttt{PARSEMSGADDR}$ ($s$ - $t$), decomposes *CellSlice* $s$ containing a valid $\texttt{MsgAddress}$ into a *Tuple* $t$ with separate fields of this $\texttt{MsgAddress}$. If $s$ is not a valid $\texttt{MsgAddress}$, a cell deserialization exception is thrown.
* $\texttt{FA43}$ — $\texttt{PARSEMSGADDRQ}$ ($s$ - $t$ $-1$ or $0$), a quiet version of $\texttt{PARSEMSGADDR}$: returns a zero on error instead of throwing an exception.
* $\texttt{FA44}$ — $\texttt{REWRITESTDADDR}$ ($s$ - $x$ $y$), parses *CellSlice* $s$ containing a valid $\texttt{MsgAddressInt}$ (usually a $\texttt{msg\_addr\_std}$), applies rewriting from the $\texttt{anycast}$ (if present) to the same-length prefix of the address, and returns both the workchain $x$ and the 256-bit address $y$ as *Integer*s. If the address is not 256-bit, or if $s$ is not a valid serialization of $\texttt{MsgAddressInt}$, throws a cell deserialization exception.
* $\texttt{FA45}$ — $\texttt{REWRITESTDADDRQ}$ ($s$ - $x$ $y$ $-1$ or $0$), a quiet version of primitive $\texttt{REWRITESTDADDR}$.
* $\texttt{FA46}$ — $\texttt{REWRITEVARADDR}$ ($s$ - $x$ $s'$), a variant of $\texttt{REWRITESTDADDR}$ that returns the (rewritten) address as a *Slice* s, even if it is not exactly 256 bit long (represented by a $\texttt{msg\_addr\_var}$).
* $\texttt{FA47}$ — $\texttt{REWRITEVARADDRQ}$ ($s$ - $x$ $s'$ $-1$ or $0$), a quiet version of primitive $\texttt{REWRITEVARADDR}$.
* $\texttt{FA48}$-$\texttt{FA5F}$ — Reserved for message and address manipulation primitives.
### A.11.10. Outbound message and output action primitives [#a1110-outbound-message-and-output-action-primitives]
* $\texttt{FB00}$ — $\texttt{SENDRAWMSG}$ ($c$ $x$ - ), sends a raw message contained in *Cell* $c$, which should contain a correctly serialized object $\texttt{Message}$ $X$, with the only exception that the source address is allowed to have dummy value $\texttt{addr\_none}$ (to be automatically replaced with the current smart-contract address), and $\texttt{ihr\_fee}$, $\texttt{fwd\_fee}$, $\texttt{created\_lt}$ and $\texttt{created\_at}$ fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter $x$ contains the flags. Currently $x=0$ is used for ordinary messages; $x=128$ is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); $x=64$ is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); $x'=x+1$ means that the sender wants to pay transfer fees separately; $x'=x+2$ means that any errors arising while processing this message during the action phase should be ignored. Finally, $x'=x+32$ means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with $+128$.
* $\texttt{FB02}$ — $\texttt{RAWRESERVE}$ ($x$ $y$ - ), creates an output action which would reserve exactly $x$ nanograms (if $y=0$), at most $x$ nanograms (if $y=2$), or all but $x$ nanograms (if $y=1$ or $y=3$), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying $x$ nanograms (or $b-x$ nanograms, where $b$ is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit $+2$ in $y$ means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit $+8$ in $y$ means $x\leftarrow -x$ before performing any further actions. Bit $+4$ in $y$ means that $x$ is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently $x$ must be a non-negative integer, and $y$ must be in the range $0\ldots 15$.
* $\texttt{FB03}$ — $\texttt{RAWRESERVEX}$ ($x$ $D$ $y$ - ), similar to $\texttt{RAWRESERVE}$, but also accepts a dictionary $D$ (represented by a *Cell* or *Null*) with extra currencies. In this way currencies other than Grams can be reserved.
* $\texttt{FB04}$ — $\texttt{SETCODE}$ ($c$ - ), creates an output action that would change this smart contract code to that given by *Cell* $c$. Notice that this change will take effect only after the successful termination of the current run of the smart contract.
* $\texttt{FB06}$ — $\texttt{SETLIBCODE}$ ($c$ $x$ - ), creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in *Cell* $c$. If $x=0$, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If $x=1$, the library is added as a private library, and if $x=2$, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to $x$. Values of $x$ other than $0\ldots 2$ are invalid.
* $\texttt{FB07}$ — $\texttt{CHANGELIB}$ ($h$ $x$ - ), creates an output action similarly to $\texttt{SETLIBCODE}$, but instead of the library code accepts its hash as an unsigned 256-bit integer $h$. If $x\neq0$ and the library with hash $h$ is absent from the library collection of this smart contract, this output action will fail.
* $\texttt{FB08}$-$\texttt{FB3F}$ — Reserved for output action primitives.
## A.12 Debug primitives [#a12--debug-primitives]
Opcodes beginning with $\texttt{FE}$ are reserved for the *debug primitives*. These primitives have known fixed operation length, and behave as (multibyte) NOP operations. In particular, they never change the stack contents, and never throw exceptions, unless there are not enough bits to completely decode the opcode. However, when invoked in a TVM instance with debug mode enabled, these primitives can produce specific output into the text debug log of the TVM instance, never affecting the TVM state (so that from the perspective of TVM the behavior of debug primitives in debug mode is exactly the same). For instance, a debug primitive might dump all or some of the values near the top of the stack, display the current state of TVM and so on.
### A.12.1. Debug primitives as multibyte NOPs [#a121-debug-primitives-as-multibyte-nops]
* $\texttt{FE}nn$ — $\texttt{DEBUG}$ $nn$, for $0\leq nn<240$, is a two-byte NOP.
* $\texttt{FEF}nssss$ — $\texttt{DEBUGSTR}$ $ssss$, for $0\leq n<16$, is an $(n+3)$-byte NOP, with the $(n+1)$-byte "contents string" $ssss$ skipped as well.
### A.12.2. Debug primitives as operations without side-effect [#a122-debug-primitives-as-operations-without-side-effect]
Next we describe the debug primitives that might (and actually are) implemented in a version of TVM. Notice that another TVM implementation is free to use these codes for other debug purposes, or treat them as multibyte NOPs. Whenever these primitives need some arguments from the stack, they inspect these arguments, but leave them intact in the stack. If there are insufficient values in the stack, or they have incorrect types, debug primitives may output error messages into the debug log, or behave as NOPs, but they cannot throw exceptions.
* $\texttt{FE00}$ — $\texttt{DUMPSTK}$, dumps the stack (at most the top 255 values) and shows the total stack depth.
* $\texttt{FE0}n$ — $\texttt{DUMPSTKTOP}$ $n$, $1\leq n<15$, dumps the top $n$ values from the stack, starting from the deepest of them. If there are $d[30](#fn30)
***
# C Code density of stack and register machines [#c---code-density-of-stack-and-register-machines]
This appendix extends the general consideration of [stack manipulation](#2-2-stack-manipulation-primitives) primitives, explaining the choice of such primitives for TVM, with a comparison of stack machines and register machines in terms of the quantity of primitives used and the code density. We do this by comparing the machine code that might be generated by an optimizing compiler for the same source files, for different (abstract) stack and register machines.
It turns out that the stack machines (at least those equipped with the [basic stack manipulation](#2-2-1-basic-stack-manipulation-primitives) primitives have far superior code density. Furthermore, the stack machines have excellent extendability with respect to additional arithmetic and arbitrary data processing operations, especially if one considers machine code automatically generated by optimizing compilers.
## C.1 Sample leaf function [#c1---sample-leaf-function]
We start with a comparison of machine code generated by an (imaginary) optimizing compiler for several abstract register and stack machines, corresponding to the same high-level language source code that contains the definition of a leaf function (i.e., a function that does not call any other functions). For both the register machines and stack machines, we observe the notation and [conventions](#2-1-stack-calling-conventions).
### C.1.1. Sample source file for a leaf function [#c11-sample-source-file-for-a-leaf-function]
The source file we consider contains one function $f$ that takes six integer arguments $a$, $b$, $c$, $d$, $e$, and $f$ and returns two integer values, $x$ and $y$, which are the solutions of the system of two linear equations:
$$
\begin{cases}
ax + by = e \\
cx + dy = f
\end{cases}
\tag{6}
$$
The source code of the function, in a programming language similar to C, might look as follows:
```
(int, int) f(int a, int b, int c, int d, int e, int f) {
int D = a*d - b*c;
int Dx = e*d - b*f;
int Dy = a*f - e*c;
return (Dx / D, Dy / D);
}
```
We assume that the [register machines](#2-1-stack-calling-conventions) we consider accept the six parameters $a$ $\ldots$ $f$ in registers $\texttt{r0}$ $\ldots$ $\texttt{r5}$, and return the two values $x$ and $y$ in $\texttt{r0}$ and $\texttt{r1}$. We also assume that the register machines have 16 registers, and that the stack machine can directly access $\texttt{s0}$ to $\texttt{s15}$ by its stack manipulation primitives; the stack machine will accept the parameters in $\texttt{s5}$ to $\texttt{s0}$, and return the two values in $\texttt{s0}$ and $\texttt{s1}$, somewhat similarly to the register machine. Finally, we assume at first that the register machine is allowed to destroy values in all registers (which is slightly unfair towards the stack machine); this assumption will be revisited later.
### C.1.2. Three-address register machine [#c12-three-address-register-machine]
The machine code (or rather the corresponding assembly code) for a three-address [register machine](#2-1-7-arguments-to-arithmetic-primitives-on-register-machines)) might look as follows:
```
IMUL r6,r0,r3 // r6 := r0 * r3 = ad
IMUL r7,r1,r2 // r7 := bc
SUB r6,r6,r7 // r6 := ad-bc = D
IMUL r3,r4,r3 // r3 := ed
IMUL r1,r1,r5 // r1 := bf
SUB r3,r3,r1 // r3 := ed-bf = Dx
IMUL r1,r0,r5 // r1 := af
IMUL r7,r4,r2 // r7 := ec
SUB r1,r1,r7 // r1 := af-ec = Dy
IDIV r0,r3,r6 // x := Dx/D
IDIV r1,r1,r6 // y := Dy/D
RET
```
We have used 12 operations and at least 23 bytes (each operation uses $3\times 4=12$ bits to indicate the three registers involved, and at least 4 bits to indicate the operation performed; thus we need two or three bytes to encode each operation). A more realistic estimate would be 34 (three bytes for each arithmetic operation) or 31 bytes (two bytes for addition and subtraction, three bytes for multiplication and division).
### C.1.3. Two-address register machine [#c13-two-address-register-machine]
The machine code for a two-address register machine might look as follows:
```
MOV r6,r0 // r6 := r0 = a
MOV r7,r1 // r7 := b
IMUL r6,r3 // r6 := r6*r3 = ad
IMUL r7,r2 // r7 := bc
IMUL r3,r4 // r3 := de
IMUL r1,r5 // r1 := bf
SUB r6,r7 // r6 := ad-bc = D
IMUL r5,r0 // r5 := af
SUB r3,r1 // r3 := de-bf = Dx
IMUL r2,r4 // r2 := ce
MOV r0,r3 // r0 := Dx
SUB r5,r2 // r5 := af-ce = Dy
IDIV r0,r6 // r0 := x = Dx/D
MOV r1,r5 // r1 := Dy
IDIV r1,r6 // r1 := Dy/D
RET
```
We have used 16 operations; optimistically assuming each of them (with the exception of $\texttt{RET}$) can be encoded by two bytes, this code would require 31 bytes.[31](#fn31)
### C.1.4. One-address register machine [#c14-one-address-register-machine]
The machine code for a one-address register machine might look as follows:
```
MOV r8,r0 // r8 := r0 = a
XCHG r1 // r0 <-> r1; r0 := b, r1 := a
MOV r6,r0 // r6 := b
IMUL r2 // r0 := r0*r2; r0 := bc
MOV r7,r0 // r7 := bc
MOV r0,r8 // r0 := a
IMUL r3 // r0 := ad
SUB r7 // r0 := ad-bc = D
XCHG r1 // r1 := D, r0 := b
IMUL r5 // r0 := bf
XCHG r3 // r0 := d, r3 := bf
IMUL r4 // r0 := de
SUB r3 // r0 := de-bf = Dx
IDIV r1 // r0 := Dx/D = x
XCHG r2 // r0 := c, r2 := x
IMUL r4 // r0 := ce
XCHG r5 // r0 := f, r5 := ce
IMUL r8 // r0 := af
SUB r5 // r0 := af-ce = Dy
IDIV r1 // r0 := Dy/D = y
MOV r1,r0 // r1 := y
MOV r0,r2 // r0 := x
RET
```
We have used 23 operations; if we assume one-byte encoding for all arithmetic operations and $\texttt{XCHG}$, and two-byte encodings for $\texttt{MOV}$, the total size of the code will be 29 bytes. Notice, however, that to obtain the compact code shown above we had to choose a specific order of computation, and made heavy use of the commutativity of multiplication. (For example, we compute $bc$ before $af$, and $af-bc$ immediately after $af$.) It is not clear whether a compiler would be able to make all such optimizations by itself.
### C.1.5. Stack machine with basic stack primitives [#c15-stack-machine-with-basic-stack-primitives]
The machine code for a stack machine equipped with [basic stack manipulation](#2-2-1-basic-stack-manipulation-primitives) primitives might look as follows:
```
PUSH s5 // a b c d e f a
PUSH s3 // a b c d e f a d
IMUL // a b c d e f ad
PUSH s5 // a b c d e f ad b
PUSH s5 // a b c d e f ad b c
IMUL // a b c d e f ad bc
SUB // a b c d e f ad-bc
XCHG s3 // a b c ad-bc e f d
PUSH s2 // a b c ad-bc e f d e
IMUL // a b c ad-bc e f de
XCHG s5 // a de c ad-bc e f b
PUSH s1 // a de c ad-bc e f b f
IMUL // a de c ad-bc e f bf
XCHG s1,s5 // a f c ad-bc e de bf
SUB // a f c ad-bc e de-bf
XCHG s3 // a f de-bf ad-bc e c
IMUL // a f de-bf ad-bc ec
XCHG s3 // a ec de-bf ad-bc f
XCHG s1,s4 // ad-bc ec de-bf a f
IMUL // D ec Dx af
XCHG s1 // D ec af Dx
XCHG s2 // D Dx af ec
SUB // D Dx Dy
XCHG s1 // D Dy Dx
PUSH s2 // D Dy Dx D
IDIV // D Dy x
XCHG s2 // x Dy D
IDIV // x y
RET
```
We have used 29 operations; assuming one-byte encodings for all stack operations involved (including $\texttt{XCHG s1,s}(i)$), we have used 29 code bytes as well. Notice that with one-byte encoding, the "unsystematic" operation $\texttt{ROT}$ (equivalent to $\texttt{XCHG s1}$; $\texttt{XCHG s2}$) would reduce the operation and byte count to 28. This shows that such "unsystematic" operations, borrowed from Forth, may indeed reduce the code size on some occasions.
Notice as well that we have implicitly used the commutativity of multiplication in this code, computing $de-bf$ instead of $ed-bf$ as specified in high-level language source code. If we were not allowed to do so, an extra $\texttt{XCHG s1}$ would need to be inserted before the third $\texttt{IMUL}$, increasing the total size of the code by one operation and one byte.
The code presented above might have been produced by a rather unsophisticated compiler that simply computed all expressions and subexpressions in the order they appear, then rearranged the arguments near the [top of the stack](#2-2-2-basic-stack-manipulation-primitives-suffice) before each operation. The only "manual" optimization done here involves computing $ec$ before $af$; one can check that the other order would lead to slightly shorter code of 28 operations and bytes (or 29, if we are not allowed to use the commutativity of multiplication), but the $\texttt{ROT}$ optimization would not be applicable.
### C.1.6. Stack machine with compound stack primitives [#c16-stack-machine-with-compound-stack-primitives]
A stack machine with [compound stack](#2-2-3-compound-stack-manipulation-primitives) primitives would not significantly improve code density of the code presented above, at least in terms of bytes used. The only difference is that, if we were not allowed to use commutativity of multiplication, the extra $\texttt{XCHG s1}$ inserted before the third $\texttt{IMUL}$ might be combined with two previous operations $\texttt{XCHG s3}$, $\texttt{PUSH s2}$ into one compound operation $\texttt{PUXC s2,s3}$; we provide the resulting code below. To make this less redundant, we show a version of the code that computes subexpression $af$ before $ec$ as specified in the original source file. We see that this replaces six operations (starting from line 15) with five other operations, and disables the $\texttt{ROT}$ optimization:
```
PUSH s5 // a b c d e f a
PUSH s3 // a b c d e f a d
IMUL // a b c d e f ad
PUSH s5 // a b c d e f ad b
PUSH s5 // a b c d e f ad b c
IMUL // a b c d e f ad bc
SUB // a b c d e f ad-bc
PUXC s2,s3 // a b c ad-bc e f e d
IMUL // a b c ad-bc e f ed
XCHG s5 // a ed c ad-bc e f b
PUSH s1 // a ed c ad-bc e f b f
IMUL // a ed c ad-bc e f bf
XCHG s1,s5 // a f c ad-bc e ed bf
SUB // a f c ad-bc e ed-bf
XCHG s4 // a ed-bf c ad-bc e f
XCHG s1,s5 // e Dx c D a f
IMUL // e Dx c D af
XCHG s2 // e Dx af D c
XCHG s1,s4 // D Dx af e c
IMUL // D Dx af ec
SUB // D Dx Dy
XCHG s1 // D Dy Dx
PUSH s2 // D Dy Dx D
IDIV // D Dy x
XCHG s2 // x Dy D
IDIV // x y
RET
```
We have used a total of 27 operations and 28 bytes, the same as the previous version (with the $\texttt{ROT}$ optimization). However, we did not use the commutativity of multiplication here, so we can say that compound stack manipulation primitives enable us to reduce the code size from 29 to 28 bytes.
Yet again, notice that the above code might have been generated by an unsophisticated compiler. Manual optimizations might lead to more compact code; for instance, we could use compound operations such as $\texttt{XCHG3}$ to prepare in advance not only the correct values of $\texttt{s0}$ and $\texttt{s1}$ for the next arithmetic operation, but also the value of $\texttt{s2}$ for the arithmetic operation after that. The next section provides an example of such an optimization.
### C.1.7. Stack machine with compound stack primitives and manually optimized code [#c17-stack-machine-with-compound-stack-primitives-and-manually-optimized-code]
The previous version of code for a stack machine with compound stack primitives can be manually optimized as follows.
By interchanging $\texttt{XCHG}$ operations with preceding $\texttt{XCHG}$, $\texttt{PUSH}$, and arithmetic operations whenever possible, we obtain code fragment $\texttt{XCHG s2,s6}$; $\texttt{XCHG s1,s0}$; $\texttt{XCHG s0,s5}$, which can then be replaced by compound operation $\texttt{XCHG3 s6,s0,s5}$. This compound operation would admit a two-byte encoding, thus leading to 27-byte code using only 21 operations:
```
PUSH2 s5,s2 // a b c d e f a d
IMUL // a b c d e f ad
PUSH2 s5,s4 // a b c d e f ad b c
IMUL // a b c d e f ad bc
SUB // a b c d e f ad-bc
PUXC s2,s3 // a b c ad-bc e f e d
IMUL // a b c D e f ed
XCHG3 s6,s0,s5 // (same as XCHG s2,s6; XCHG s1,s0; XCHG s0,s5)
// e f c D a ed b
PUSH s5 // e f c D a ed b f
IMUL // e f c D a ed bf
SUB // e f c D a ed-bf
XCHG s4 // e Dx c D a f
IMUL // e Dx c D af
XCHG2 s4,s2 // D Dx af e c
IMUL // D Dx af ec
SUB // D Dx Dy
XCPU s1,s2 // D Dy Dx D
IDIV // D Dy x
XCHG s2 // x Dy D
IDIV // x y
RET
```
It is interesting to note that this version of stack machine code contains only 9 stack manipulation primitives for 11 arithmetic operations. It is not clear, however, whether an optimizing compiler would be able to reorganize the code in such a manner by itself.
## C.2 Comparison of machine code for sample leaf function [#c2---comparison-of-machine-code-for-sample-leaf-function]
[Table 1](#table-1) summarizes the properties of machine code corresponding to the [same source file](#c-1-1-sample-source-file-for-a-leaf-function), generated for a hypothetical [three-address register machine](#c-1-2-three-address-register-machine), with both "optimistic" and "realistic" instruction encodings; a [two-address machine](#c-1-3-two-address-register-machine); a [one-address machine](#c-1-4-one-address-register-machine); and a stack machine, similar to TVM, using either only the [basic stack manipulation](#c-1-5-stack-machine-with-basic-stack-primitives) primitives or both the basic and the [composite stack](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code) primitives.
The meaning of the columns in [Table 1](#table-1) is as follows:
* "Operations" — The quantity of instructions used, split into "data" (i.e., register move and exchange instructions for register machines, and stack manipulation instructions for stack machines) and "arithmetic" (instructions for adding, subtracting, multiplying and dividing integer numbers). The "total" is one more than the sum of these two, because there is also a one-byte $\texttt{RET}$ instruction at the end of machine code.
* "Code bytes" — The total amount of code bytes used.
* "Opcode space" — The portion of "opcode space" (i.e., of possible choices for the first byte of the encoding of an instruction) used by data and arithmetic instructions in the assumed instruction encoding. For example, the "optimistic" encoding for the three-address machine assumes two-byte encodings for all arithmetic instructions *op* $\texttt{r}(i)\texttt{, r}(j)\texttt{, r}(k)$. Each arithmetic instruction would then consume portion $16/256=1/16$ of the opcode space. Notice that for the stack machine we have assumed one-byte encodings for $\texttt{XCHG s}(i)$, $\texttt{PUSH s}(i)$ and $\texttt{POP s}(i)$ in all cases, augmented by $\texttt{XCHG s1,s}(i)$ for the basic stack instructions case only. As for the compound stack operations, we have assumed two-byte encodings for $\texttt{PUSH3}$, $\texttt{XCHG3}$, $\texttt{XCHG2}$, $\texttt{XCPU}$, $\texttt{PUXC}$, $\texttt{PUSH2}$, but not for $\texttt{XCHG s1,s}(i)$.
| Machine | Operations | | | Code bytes | | | Opcode space | | |
| --------------- | ---------- | ----- | ----- | ---------- | ----- | --------- | ------------ | ---------- | ------ |
| | data | arith | total | data | arith | **total** | data | **arith** | total |
| 3-addr. (opt.) | 0 | 11 | 12 | 0 | 22 | **23** | 0/256 | **64/256** | 65/256 |
| 3-addr. (real.) | 0 | 11 | 12 | 0 | 30 | **31** | 0/256 | **34/256** | 35/256 |
| 2-addr. | 4 | 11 | 16 | 8 | 22 | **31** | 1/256 | **4/256** | 6/256 |
| 1-addr. | 11 | 11 | 23 | 17 | 11 | **29** | 17/256 | **64/256** | 82/256 |
| stack (basic) | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |
| stack (comp.) | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |
**Table 1.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function). The two most important columns, reflecting code density and extendability to other operations, are marked by bold font. Smaller values are better in both of these columns.
The "code bytes" column reflects the density of the code for the specific sample source. However, "opcode space" is also important, because it reflects the extendability of the achieved density to other classes of operations (e.g., if one were to complement arithmetic operations with string manipulation operations and so on). Here the "arithmetic" subcolumn is more important than the "data" subcolumn, because no further data manipulation operations would be required for such extensions.
We see that the three-address register machine with the "optimistic" encoding, assuming two-byte encodings for all three-register arithmetic operations, achieves the best code density, requiring only 23 bytes. However, this comes at a price: each arithmetic operation consumes 1/16 of the opcode space, so the four operations already use a quarter of the opcode space. At most 11 other operations, arithmetic or not, might be added to this architecture while preserving such high code density. On the other hand, when we consider the "realistic" encoding for the three-address machine, using two-byte encodings only for the most frequently used addition/subtraction operations (and longer encodings for less frequently used multiplication/division operations, reflecting the fact that the possible extension operations would likely fall in this class), then the three-address machine ceases to offer such attractive code density.
In fact, the two-address machine becomes equally attractive at this point: it is capable of achieving the same code size of 31 bytes as the three-address machine with the "realistic" encoding, using only 6/256 of the opcode space for this! However, 31 bytes is the worst result in this table.
The one-address machine uses 29 bytes, slightly less than the two-address machine. However, it utilizes a quarter of the opcode space for its arithmetic operations, hampering its extendability. In this respect it is similar to the three-address machine with the "optimistic" encoding, but requires 29 bytes instead of 23! So there is no reason to use the one-address machine at all, in terms of extendability (reflected by opcode space used for arithmetic operations) compared to code density.
Finally, the stack machine wins the competition in terms of code density (27 or 28 bytes), losing only to the three-address machine with the "optimistic" encoding (which, however, is terrible in terms of extendability).
To summarize: the two-address machine and stack machine achieve the best extendability with respect to additional arithmetic or data processing instructions (using only 1/256 of code space for each such instruction), while the stack machine additionally achieves the best code density by a small margin. The stack machine utilizes a significant part of its code space (more than a quarter) for data (i.e., stack) manipulation instructions; however, this does not seriously hamper extendability, because the stack manipulation instructions occupy a constant part of the opcode space, regardless of all other instructions and extensions.
While one might still be tempted to use a two-address register machine, we will explain [shortly](#c-3-sample-non-leaf-function) why the two-address register machine offers worse code density and extendability in practice than it appears based on this table.
As for the choice between a stack machine with only basic stack manipulation primitives or one supporting compound stack primitives as well, the case for the more sophisticated stack machine appears to be weaker: it offers only one or two fewer bytes of code at the expense of using considerably more opcode space for stack manipulation, and the optimized code using these additional instructions is hard for programmers to write and for compilers to automatically generate.
### C.2.1. Register calling conventions: some registers must be preserved by functions [#c21-register-calling-conventions-some-registers-must-be-preserved-by-functions]
Up to this point, we have considered the machine code of only one function, without taking into account the interplay between this function and other functions in the same program.
Usually a program consists of more than one function, and when a function is not a "simple" or "leaf" function, it must call other functions. Therefore, it becomes important whether a called function preserves all or at least some registers. If it preserves all registers except those used to return results, the caller can safely keep its local and temporary variables in certain registers; however, the callee needs to save all the registers it will use for its temporary values somewhere (usually into the stack, which also exists on register machines), and then restore the original values. On the other hand, if the called function is allowed to destroy all registers, it can be written in the manner described in [C.1.2](#c-1-2-three-address-register-machine), [C.1.3](#c-1-3-two-address-register-machine), and [C.1.4](#c-1-4-one-address-register-machine), but the caller will now be responsible for saving all its temporary values into the stack before the call, and restoring these values afterwards.
In most cases, calling conventions for register machines require preservation of some but not all registers. We will assume that $m\leq n$ registers will be preserved by functions (unless they are used for return values), and that these registers are $\texttt{r}$ $(n-m)$ $\ldots$ $\texttt{r}$ $(n-1)$. Case $m=0$ corresponds to the case "the callee is free to destroy all registers" considered so far; it is quite painful for the caller. Case $m=n$ corresponds to the case "the callee must preserve all registers"; it is quite painful for the callee, as we will see in a moment. Usually a value of $m$ around $n/2$ is used in practice.
The following sections consider cases $m=0$, $m=8$, and $m=16$ for our register machines with $n=16$ registers.
### C.2.2. Case $m=0$: no registers to preserve [#c22-case-m0-no-registers-to-preserve]
This case has been considered and summarized in [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) and [Table 1](#table-1) above.
### C.2.3. Case $m=n=16$: all registers must be preserved [#c23-case-mn16-all-registers-must-be-preserved]
This case is the most painful one for the called function. It is especially difficult for leaf functions like the one we have been considering, which do not benefit at all from the fact that other functions preserve some registers when called—they do not call any functions, but instead must preserve all registers themselves.
In order to estimate the consequences of assuming $m=n=16$, we will assume that all our register machines are equipped with a stack, and with one-byte instructions $\texttt{PUSH r}(i)$ and $\texttt{POP r}(i)$, which push or pop a register into/from the stack. For example, the [three-address machine](#c-1-2-three-address-register-machine) code destroys the values in registers $\texttt{r2}$, $\texttt{r3}$, $\texttt{r6}$, and $\texttt{r7}$; this means that the code of this function must be augmented by four instructions $\texttt{PUSH r2}$; $\texttt{PUSH r3}$; $\texttt{PUSH r6}$; $\texttt{PUSH r7}$ at the beginning, and by four instructions $\texttt{POP r7}$; $\texttt{POP r6}$; $\texttt{POP r3}$; $\texttt{POP r2}$ right before the $\texttt{RET}$ instruction, in order to restore the original values of these registers from the stack. These four additional $\texttt{PUSH}$/$\texttt{POP}$ pairs would increase the operation count and code size in bytes by $4\times 2=8$. A similar analysis can be done for other register machines as well, leading to [Table 2](#table-2).
| Machine | $\mathit{r}$ | Operations | | | Code bytes | | | Opcode space | | |
| --------------- | ------------ | ---------- | ----- | ----- | ---------- | ----- | --------- | ------------ | ---------- | ------- |
| | | data | arith | total | data | arith | **total** | data | **arith** | total |
| 3-addr. (opt.) | *4* | 8 | 11 | 20 | 8 | 22 | **31** | 32/256 | **64/256** | 97/256 |
| 3-addr. (real.) | *4* | 8 | 11 | 20 | 8 | 30 | **39** | 32/256 | **34/256** | 67/256 |
| 2-addr. | *5* | 14 | 11 | 26 | 18 | 22 | **41** | 33/256 | **4/256** | 38/256 |
| 1-addr. | *6* | 23 | 11 | 35 | 29 | 11 | **41** | 49/256 | **64/256** | 114/256 |
| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |
| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |
**Table 2.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming all of the 16 registers must be preserved by called functions ($m=n=16$). The new column labeled $r$ denotes the number of registers to be saved and restored, leading to $2r$ more operations and code bytes compared to [Table 1](#table-1). Newly-added $\texttt{PUSH}$ and $\texttt{POP}$ instructions for register machines also utilize 32/256 of the opcode space. The two rows corresponding to stack machines remain unchanged.
We see that under these assumptions the stack machines are the obvious winners in terms of code density, and are in the winning group with respect to extendability.
### C.2.4. Case $m = 8$, $n = 16$: registers $\texttt{r8}$ $\ldots$ $\texttt{r15}$ must be preserved [#c24-case-m--8-n--16-registers-textttr8-ldots-textttr15-must-be-preserved]
The analysis of this case is similar to the previous one. The results are summarized in [Table 3](#table-3).
| Machine | $\mathit{r}$ | Operations | | | Code bytes | | | Opcode space | | |
| --------------- | ------------ | ---------- | ----- | ----- | ---------- | ----- | --------- | ------------ | ---------- | ------- |
| | | data | arith | total | data | arith | **total** | data | **arith** | total |
| 3-addr. (opt.) | *0* | 0 | 11 | 12 | 0 | 22 | **23** | 32/256 | **64/256** | 97/256 |
| 3-addr. (real.) | *0* | 0 | 11 | 12 | 0 | 30 | **31** | 32/256 | **34/256** | 67/256 |
| 2-addr. | *0* | 4 | 11 | 16 | 8 | 22 | **31** | 33/256 | **4/256** | 38/256 |
| 1-addr. | *1* | 13 | 11 | 25 | 19 | 11 | **31** | 49/256 | **64/256** | 114/256 |
| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |
| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |
**Table 3.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming that only the last 8 of the 16 registers must be preserved by called functions ($m=8$, $n=16$). This table is similar to [Table 2](#table-2), but has smaller values of $r$.
Notice that the resulting table is very similar to [Table 1](#table-1), apart from the "Opcode space" columns and the row for the one-address machine. Therefore, the conclusions of [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) still apply in this case, with some minor modifications. We must emphasize, however, that *these conclusions are valid only for leaf functions, i.e., functions that do not call other functions*. Any program aside from the very simplest will have many non-leaf functions, especially if we are minimizing resulting machine code size (which prevents inlining of functions in most cases).
### C.2.5. A fairer comparison using a binary code instead of a byte code [#c25-a-fairer-comparison-using-a-binary-code-instead-of-a-byte-code]
The reader may have noticed that our preceding discussion of $k$-address register machines and stack machines depended very much on our insistence that complete instructions be encoded by an integer number of bytes. If we had been allowed to use a "bit" or "binary code" instead of a byte code for encoding instructions, we could more evenly balance the opcode space used by different machines. For instance, the opcode of `SUB` for a three-address machine had to be either 4-bit (good for code density, bad for opcode space) or 12-bit (very bad for code density), because the complete instruction has to occupy a multiple of eight bits (e.g., 16 or 24 bits), and $3\cdot 4=12$ of those bits have to be used for the three register names.
Therefore, let us get rid of this restriction.
Now that we can use any number of bits to encode an instruction, we can choose all opcodes of the same length for all the machines considered. For instance, all arithmetic instructions can have 8-bit opcodes, as the stack machine does, using $1/256$ of the opcode space each; then the three-address register machine will use 20 bits to encode each complete arithmetic instruction. All $\texttt{MOV}$s, $\texttt{XCHG}$s, $\texttt{PUSH}$es, and $\texttt{POP}$s on register machines can be assumed to have 4-bit opcodes, because this is what we do for the most common stack manipulation primitives on a stack machine. The results of these changes are shown in [Table 4](#table-4).
We can see that the performance of the various machines is much more balanced, with the stack machine still the winner in terms of the code density, but with the three-address machine enjoying the second place it really merits. If we were to consider the decoding speed and the possibility of parallel execution of instructions, we would have to choose the three-address machine, because it uses only 12 instructions instead of 21.
| Machine | $\mathit{r}$ | Operations | | | Code bytes | | | Opcode space | | |
| ------------- | ------------ | ---------- | ----- | ----- | ---------- | ----- | --------- | ------------ | --------- | ------ |
| | | data | arith | total | data | arith | **total** | data | **arith** | total |
| 3-addr. | *0* | 0 | 11 | 12 | 0 | 27.5 | **28.5** | 64/256 | **4/256** | 69/256 |
| 2-addr. | *0* | 4 | 11 | 16 | 6 | 22 | **29** | 64/256 | **4/256** | 69/256 |
| 1-addr. | *1* | 13 | 11 | 25 | 16 | 16.5 | **32.5** | 64/256 | **4/256** | 69/256 |
| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |
| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |
**Table 4.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming that only 8 of the 16 registers must be preserved by functions ($m=8$, $n=16$). This time we can use fractions of bytes to encode instructions, so as to match opcode space used by different machines. All arithmetic instructions have 8-bit opcodes, all data/stack manipulation instructions have 4-bit opcodes. In other respects this table is similar to [Table 3](#table-3).
***
## C.3 Sample non-leaf function [#c3---sample-non-leaf-function]
This section compares the machine code for different register machines for a sample non-leaf function. Again, we assume that either $m=0$, $m=8$, or $m=16$ registers are preserved by called functions, with $m=8$ representing the compromise made by most modern compilers and operating systems.
### C.3.1. Sample source code for a non-leaf function [#c31-sample-source-code-for-a-non-leaf-function]
A sample source file may be obtained by replacing the built-in integer type with a custom *Rational* type, represented by a pointer to an object in memory, in our function for solving systems of [two linear equations](#c-1-1-sample-source-file-for-a-leaf-function):
```
struct Rational;
typedef struct Rational *num;
extern num r_add(num, num);
extern num r_sub(num, num);
extern num r_mul(num, num);
extern num r_div(num, num);
(num, num) r_f(num a, num b, num c, num d, num e, num f) {
num D = r_sub(r_mul(a, d), r_mul(b, c)); // a*d-b*c
num Dx = r_sub(r_mul(e, d), r_mul(b, f)); // e*d-b*f
num Dy = r_sub(r_mul(a, f), r_mul(e, c)); // a*f-e*c
return (r_div(Dx, D), r_div(Dy, D)); // Dx/D, Dy/D
}
```
We will ignore all questions related to allocating new objects of type *Rational* in memory (e.g., in heap), and to preventing memory leaks. We may assume that the called subroutines $\texttt{r\_sub}$, $\texttt{r\_mul}$, and so on allocate new objects simply by advancing some pointer in a pre-allocated buffer, and that unused objects are later freed by a garbage collector, external to the code being analysed.
Rational numbers will now be represented by pointers, addresses, or references, which will fit into registers of our hypothetical register machines or into the stack of our stack machines. If we want to use TVM as an instance of these stack machines, we should use values of type *Cell* to represent such references to objects of type *Rational* in memory.
We assume that subroutines (or functions) are called by a special $\texttt{CALL}$ instruction, which is encoded by three bytes, including the specification of the function to be called (e.g., the index in a "global function table").
### C.3.2. Three-address and two-address register machines, $m=0$ preserved registers [#c32-three-address-and-two-address-register-machines-m0-preserved-registers]
Because our sample function does not use built-in arithmetic instructions at all, compilers for our hypothetical three-address and two-address register machines will produce the same machine code. Apart from the previously introduced $\texttt{PUSH r}(i)$ and $\texttt{POP r}(i)$ one-byte instructions, we assume that our two- and three-address machines support the following two-byte instructions: $\texttt{MOV r}(i)\texttt{,s}(j)$, $\texttt{MOV s}(j)\texttt{,r}(i)$, and $\texttt{XCHG r}(i)\texttt{,s}(j)$, for $0\leq i,j\leq 15$. Such instructions occupy only 3/256 of the opcode space, so their addition seems quite natural.
We first assume that $m=0$ (i.e., that all subroutines are free to destroy the values of all registers). In this case, our machine code for $\texttt{r\_f}$ does not have to preserve any registers, but has to save all registers containing useful values into the stack before calling any subroutines. A size-optimizing compiler might produce the following code:
```
PUSH r4 // STACK: e
PUSH r1 // STACK: e b
PUSH r0 // .. e b a
PUSH r6 // .. e b a f
PUSH r2 // .. e b a f c
PUSH r3 // .. e b a f c d
MOV r0,r1 // b
MOV r1,r2 // c
CALL r_mul // bc
PUSH r0 // .. e b a f c d bc
MOV r0,s4 // a
MOV r1,s1 // d
CALL r_mul // ad
POP r1 // bc; .. e b a f c d
CALL r_sub // D:=ad-bc
XCHG r0,s4 // b ; .. e D a f c d
MOV r1,s2 // f
CALL r_mul // bf
POP r1 // d ; .. e D a f c
PUSH r0 // .. e D a f c bf
MOV r0,s5 // e
CALL r_mul // ed
POP r1 // bf; .. e D a f c
CALL r_sub // Dx:=ed-bf
XCHG r0,s4 // e ; .. Dx D a f c
POP r1 // c ; .. Dx D a f
CALL r_mul // ec
XCHG r0,s1 // a ; .. Dx D ec f
POP r1 // f ; .. Dx D ec
CALL r_mul // af
POP r1 // ec; .. Dx D
CALL r_sub // Dy:=af-ec
XCHG r0,s1 // Dx; .. Dy D
MOV r1,s0 // D
CALL r_div // x:=Dx/D
XCHG r0,s1 // Dy; .. x D
POP r1 // D ; .. x
CALL r_div // y:=Dy/D
MOV r1,r0 // y
POP r0 // x ; ..
RET
```
We have used 41 instructions: 17 one-byte (eight $\texttt{PUSH}$/$\texttt{POP}$ pairs and one $\texttt{RET}$), 13 two-byte ($\texttt{MOV}$ and $\texttt{XCHG}$; out of them 11 "new" ones, involving the stack), and 11 three-byte ($\texttt{CALL}$), for a total of $17\cdot1+13\cdot2+11\cdot3=76$ bytes.[32](#fn32)
### C.3.3. Three-address and two-address register machines, $m=8$ preserved registers [#c33-three-address-and-two-address-register-machines-m8-preserved-registers]
Now we have eight registers, $\texttt{r8}$ to $\texttt{r15}$, that are preserved by subroutine calls. We might keep some intermediate values there instead of pushing them into the stack. However, the penalty for doing so consists in a $\texttt{PUSH}$/$\texttt{POP}$ pair for every such register that we choose to use, because our function is also required to preserve its original value. It seems that using these registers under such a penalty does not improve the density of the code, so the optimal code for three- and two-address machines for $m=8$ [preserved registers](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers) is the same, with a total of 42 instructions and 74 code bytes.
### C.3.4. Three-address and two-address register machines, $m=16$ preserved registers [#c34-three-address-and-two-address-register-machines-m16-preserved-registers]
This time *all* registers must be preserved by the subroutines, excluding those used for returning the results. This means that our code must preserve the original values of $\texttt{r2}$ to $\texttt{r5}$, as well as any other registers it uses for temporary values. A straightforward way of writing the code of our subroutine would be to push registers $\texttt{r2}$ up to, say, $\texttt{r8}$ into the stack, then perform all the operations required, using $\texttt{r6}$—$\texttt{r8}$ for intermediate values, and finally restore registers from the stack. However, this would not optimize code size. We choose another approach:
```
PUSH r0 // STACK: a
PUSH r1 // STACK: a b
MOV r0,r1 // b
MOV r1,r2 // c
CALL r_mul // bc
PUSH r0 // .. a b bc
MOV r0,s2 // a
MOV r1,r3 // d
CALL r_mul // ad
POP r1 // bc; .. a b
CALL r_sub // D:=ad-bc
XCHG r0,s0 // b; .. a D
MOV r1,r5 // f
CALL r_mul // bf
PUSH r0 // .. a D bf
MOV r0,r4 // e
MOV r1,r3 // d
CALL r_mul // ed
POP r1 // bf; .. a D
CALL r_sub // Dx:=ed-bf
XCHG r0,s1 // a ; .. Dx D
MOV r1,r5 // f
CALL r_mul // af
PUSH r0 // .. Dx D af
MOV r0,r4 // e
MOV r1,r2 // c
CALL r_mul // ec
MOV r1,r0 // ec
POP r0 // af; .. Dx D
CALL r_sub // Dy:=af-ec
XCHG r0,s1 // Dx; .. Dy D
MOV r1,s0 // D
CALL r_div // x:=Dx/D
XCHG r0,s1 // Dy; .. x D
POP r1 // D ; .. x
CALL r_div // y:=Dy/D
MOV r1,r0 // y
POP r0 // x
RET
```
We have used 39 instructions: 11 one-byte, 17 two-byte (among them 5 "new" instructions), and 11 three-byte, for a total of $11\cdot1+17\cdot2+11\cdot3=78$ bytes. Somewhat paradoxically, the code size in bytes is slightly longer than in the [previous case](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers), contrary to what one might have expected. This is partially due to the fact that we have assumed two-byte encodings for "new" $\texttt{MOV}$ and $\texttt{XCHG}$ instructions involving the stack, similarly to the "old" instructions. Most existing architectures (such as x86-64) use longer encodings (maybe even twice as long) for their counterparts of our "new" move and exchange instructions compared to the "usual" register-register ones. Taking this into account, we see that we would have obtained here 83 bytes (versus 87 for the [code](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers)) assuming three-byte encodings of new operations, and 88 bytes (versus 98) assuming four-byte encodings. This shows that, for two-address architectures without optimized encodings for register-stack move and exchange operations, $m=16$ preserved registers might result in slightly shorter code for some non-leaf functions, at the expense of leaf functions [C.2.3](#c-2-3-case-%3A-all-registers-must-be-preserved) and [C.2.4](#c-2-4-case-%2C-%3A-registers-must-be-preserved), which would become considerably longer.
### C.3.5. One-address register machine, $m=0$ preserved registers [#c35-one-address-register-machine-m0-preserved-registers]
For our one-address register machine, we assume that new register-stack instructions work through the accumulator only. Therefore, we have three new instructions, $\texttt{LD s}(j)$ (equivalent to $\texttt{MOV r0,s}(j)$ of two-address machines), $\texttt{ST s}(j)$ (equivalent to $\texttt{MOV s}(j)\texttt{,r0}$), and $\texttt{XCHG s}(j)$ (equivalent to $\texttt{XCHG r0,s}(j)$). To make the comparison with two-address machines more interesting, we assume one-byte encodings for these new instructions, even though this would consume $48/256=3/16$ of the opcode space.
By adapting the [code](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers) to the one-address machine, we obtain the following:
```
PUSH r4 // STACK: e
PUSH r1 // STACK: e b
PUSH r0 // .. e b a
PUSH r6 // .. e b a f
PUSH r2 // .. e b a f c
PUSH r3 // .. e b a f c d
LD s1 // r0:=c
XCHG r1 // r0:=b, r1:=c
CALL r_mul // bc
PUSH r0 // .. e b a f c d bc
LD s1 // d
XCHG r1 // r1:=d
LD s4 // a
CALL r_mul // ad
POP r1 // bc; .. e b a f c d
CALL r_sub // D:=ad-bc
XCHG s4 // b ; .. e D a f c d
XCHG r1
LD s2 // f
XCHG r1 // r0:=b, r1:=f
CALL r_mul // bf
POP r1 // d ; .. e D a f c
PUSH r0 // .. e D a f c bf
LD s5 // e
CALL r_mul // ed
POP r1 // bf; .. e D a f c
CALL r_sub // Dx:=ed-bf
XCHG s4 // e ; .. Dx D a f c
POP r1 // c ; .. Dx D a f
CALL r_mul // ec
XCHG s1 // a ; .. Dx D ec f
POP r1 // f ; .. Dx D ec
CALL r_mul // af
POP r1 // ec; .. Dx D
CALL r_sub // Dy:=af-ec
XCHG s1 // Dx; .. Dy D
POP r1 // D ; .. Dy
PUSH r1 // .. Dy D
CALL r_div // x:=Dx/D
XCHG s1 // Dy; .. x D
POP r1 // D ; .. x
CALL r_div // y:=Dy/D
XCHG r1 // r1:=y
POP r0 // r0:=x ; ..
RET
```
We have used 45 instructions: 34 one-byte and 11 three-byte, for a total of 67 bytes. Compared to the 76 bytes used by [two- and three-address machines](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers), we see that, again, the one-address register machine code may be denser than that of two-register machines, at the expense of utilizing more [opcode space](#c-2-comparison-of-machine-code-for-sample-leaf-function). However, this time the extra 3/16 of the opcode space was used for data manipulation instructions, which do not depend on specific arithmetic operations or user functions invoked.
### C.3.6. One-address register machine, $m=8$ preserved registers [#c36-one-address-register-machine-m8-preserved-registers]
As explained [above](#c-3-3-three-address-and-two-address-register-machines%2C-preserved-registers), the preservation of $\texttt{r8}$—$\texttt{r15}$ between subroutine calls does not improve the size of our previously written code, so the one-address machine will use for $m=8$ the same [code](#c-3-5-one-address-register-machine%2C-preserved-registers).
### C.3.7. One-address register machine, $m=16$ preserved registers [#c37-one-address-register-machine-m16-preserved-registers]
We simply adapt the [code](#c-3-4-three-address-and-two-address-register-machines%2C-preserved-registers) to the one-address register machine:
```
PUSH r0 // STACK: a
PUSH r1 // STACK: a b
MOV r0,r1 // b
MOV r1,r2 // c
CALL r_mul // bc
PUSH r0 // .. a b bc
LD s2 // a
MOV r1,r3 // d
CALL r_mul // ad
POP r1 // bc; .. a b
CALL r_sub // D:=ad-bc
XCHG s0 // b; .. a D
MOV r1,r5 // f
CALL r_mul // bf
PUSH r0 // .. a D bf
MOV r0,r4 // e
MOV r1,r3 // d
CALL r_mul // ed
POP r1 // bf; .. a D
CALL r_sub // Dx:=ed-bf
XCHG s1 // a ; .. Dx D
MOV r1,r5 // f
CALL r_mul // af
PUSH r0 // .. Dx D af
MOV r0,r4 // e
MOV r1,r2 // c
CALL r_mul // ec
MOV r1,r0 // ec
POP r0 // af; .. Dx D
CALL r_sub // Dy:=af-ec
XCHG s1 // Dx; .. Dy D
POP r1 // D ; .. Dy
PUSH r1 // .. Dy D
CALL r_div // x:=Dx/D
XCHG s1 // Dy; .. x D
POP r1 // D ; .. x
CALL r_div // y:=Dy/D
MOV r1,r0 // y
POP r0 // x
RET
```
We have used 40 instructions: 18 one-byte, 11 two-byte, and 11 three-byte, for a total of $18\cdot1+11\cdot2+11\cdot3=73$ bytes.
### C.3.8. Stack machine with basic stack primitives [#c38-stack-machine-with-basic-stack-primitives]
We reuse the [code](#c-1-5-stack-machine-with-basic-stack-primitives), simply replacing arithmetic primitives (VM instructions) with subroutine calls. The only substantive modification is the insertion of the previously optional $\texttt{XCHG s1}$ before the third multiplication, because even an optimizing compiler cannot now know whether $\texttt{CALL r\_mul}$ is a commutative operation. We have also used the "tail recursion optimization" by replacing the final $\texttt{CALL r\_div}$ followed by $\texttt{RET}$ with $\texttt{JMP r\_div}$.
```
PUSH s5 // a b c d e f a
PUSH s3 // a b c d e f a d
CALL r_mul // a b c d e f ad
PUSH s5 // a b c d e f ad b
PUSH s5 // a b c d e f ad b c
CALL r_mul // a b c d e f ad bc
CALL r_sub // a b c d e f ad-bc
XCHG s3 // a b c ad-bc e f d
PUSH s2 // a b c ad-bc e f d e
XCHG s1 // a b c ad-bc e f e d
CALL r_mul // a b c ad-bc e f ed
XCHG s5 // a ed c ad-bc e f b
PUSH s1 // a ed c ad-bc e f b f
CALL r_mul // a ed c ad-bc e f bf
XCHG s1,s5 // a f c ad-bc e ed bf
CALL r_sub // a f c ad-bc e ed-bf
XCHG s3 // a f ed-bf ad-bc e c
CALL r_mul // a f ed-bf ad-bc ec
XCHG s3 // a ec ed-bf ad-bc f
XCHG s1,s4 // ad-bc ec ed-bf a f
CALL r_mul // D ec Dx af
XCHG s1 // D ec af Dx
XCHG s2 // D Dx af ec
CALL r_sub // D Dx Dy
XCHG s1 // D Dy Dx
PUSH s2 // D Dy Dx D
CALL r_div // D Dy x
XCHG s2 // x Dy D
JMP r_div // x y
```
We have used 29 instructions; assuming one-byte encodings for all stack operations, and three-byte encodings for $\texttt{CALL}$ and $\texttt{JMP}$ instructions, we end up with 51 bytes.
### C.3.9. Stack machine with compound stack primitives [#c39-stack-machine-with-compound-stack-primitives]
We again reuse the [code](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code), replacing arithmetic primitives with subroutine calls and making the tail recursion optimization:
```
PUSH2 s5,s2 // a b c d e f a d
CALL r_mul // a b c d e f ad
PUSH2 s5,s4 // a b c d e f ad b c
CALL r_mul // a b c d e f ad bc
CALL r_sub // a b c d e f ad-bc
PUXC s2,s3 // a b c ad-bc e f e d
CALL r_mul // a b c D e f ed
XCHG3 s6,s0,s5 // (same as XCHG s2,s6; XCHG s1,s0; XCHG s0,s5)
// e f c D a ed b
PUSH s5 // e f c D a ed b f
CALL r_mul // e f c D a ed bf
CALL r_sub // e f c D a ed-bf
XCHG s4 // e Dx c D a f
CALL r_mul // e Dx c D af
XCHG2 s4,s2 // D Dx af e c
CALL r_mul // D Dx af ec
CALL r_sub // D Dx Dy
XCPU s1,s2 // D Dy Dx D
CALL r_div // D Dy x
XCHG s2 // x Dy D
JMP r_div // x y
```
This code uses only 20 instructions, 9 stack-related and 11 control flow-related ($\texttt{CALL}$ and $\texttt{JMP}$), for a total of 48 bytes.
## C.4 Comparison of machine code for sample non-leaf function [#c4---comparison-of-machine-code-for-sample-non-leaf-function]
[Table 5](#table-5) summarizes the properties of machine code corresponding to the [same source file](#c-3-1-sample-source-code-for-a-non-leaf-function). We consider only the "realistically" encoded three-address machines. Three-address and two-address machines have the same code density properties, but differ in the utilization of opcode space. The one-address machine, somewhat surprisingly, managed to produced shorter code than the two-address and three-address machines, at the expense of using up more than half of all opcode space. The stack machine is the obvious winner in this code density contest, without compromizing its excellent extendability (measured in opcode space used for arithmetic and other data transformation instructions).
| Machine | $m$ | **Operations** | | | **Code bytes** | | | **Opcode space** | | |
| ------------- | ----- | -------------- | ----- | ----- | -------------- | ----- | --------- | ---------------- | ---------- | ------- |
| | | data | cont. | total | data | cont. | **total** | data | **arith** | total |
| 3-addr. | *0,8* | 29 | 12 | 41 | 42 | 34 | **76** | 35/256 | **34/256** | 72/256 |
| | *16* | 27 | 12 | 39 | 44 | 34 | **78** | | | |
| 2-addr. | *0,8* | 29 | 12 | 41 | 42 | 34 | **76** | 37/256 | **4/256** | 44/256 |
| | *16* | 27 | 12 | 39 | 44 | 34 | **78** | | | |
| 1-addr. | *0,8* | 33 | 12 | 45 | 33 | 34 | **67** | 97/256 | **64/256** | 164/256 |
| | *16* | 28 | 12 | 40 | 39 | 34 | **73** | | | |
| stack (basic) | $-$ | 18 | 11 | 29 | 18 | 33 | **51** | 64/256 | **4/256** | 71/256 |
| stack (comp.) | $-$ | 9 | 11 | 20 | 15 | 33 | **48** | 84/256 | **4/256** | 91/256 |
**Table 5**: A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample non-leaf function](#c-3-1-sample-source-code-for-a-non-leaf-function), assuming $m$ of the 16 registers must be preserved by called subroutines.
### C.4.1. Combining with results for leaf functions [#c41-combining-with-results-for-leaf-functions]
It is instructive to compare this table with the results in [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) for a sample leaf function, summarized in [Table 1](#table-1) (for $m=0$ preserved registers) and the very similar [Table 3](#table-3) (for $m=8$ preserved registers), and, if one is still interested in case $m=16$ (which turned out to be worse than $m=8$ in almost all situations), also to [Table 2](#table-2).
We see that the stack machine beats all register machines on non-leaf functions. As for the leaf functions, only the three-address machine with the "optimistic" encoding of arithmetic instructions was able to beat the stack machine, winning by 15%, by compromising its extendability. However, the same three-address machine produces 25% longer code for non-leaf functions. If a typical program consists of a mixture of leaf and non-leaf functions in approximately equal proportion, then the stack machine will still win.
### C.4.2. A fairer comparison using a binary code instead of a byte code [#c42-a-fairer-comparison-using-a-binary-code-instead-of-a-byte-code]
Similarly to [C.2.5](#c-2-5-a-fairer-comparison-using-a-binary-code-instead-of-a-byte-code), we may offer a fairer comparison of different register machines and the stack machine by using arbitrary binary codes instead of byte codes to encode instructions, and matching the opcode space used for data manipulation and arithmetic instructions by different machines. The results of this modified comparison are summarized in [Table 6](#table-6). We see that the stack machines still win by a large margin, while using less opcode space for stack/data manipulation.
| Machine | $m$ | **Operations** | | | **Code bytes** | | | **Opcode space** | | |
| ------------- | ----- | -------------- | ----- | ----- | -------------- | ----- | --------- | ---------------- | --------- | ------- |
| | | data | cont. | total | data | cont. | **total** | data | **arith** | total |
| 3-addr. | *0,8* | 29 | 12 | 41 | 35.5 | 34 | **69.5** | 110/256 | **4/256** | 117/256 |
| | *16* | 27 | 12 | 39 | 35.5 | 34 | **69.5** | | | |
| 2-addr. | *0,8* | 29 | 12 | 41 | 35.5 | 34 | **69.5** | 110/256 | **4/256** | 117/256 |
| | *16* | 27 | 12 | 39 | 35.5 | 34 | **69.5** | | | |
| 1-addr. | *0,8* | 33 | 12 | 45 | 33 | 34 | **67** | 112/256 | **4/256** | 119/256 |
| | *16* | 28 | 12 | 40 | 33.5 | 34 | **67.5** | | | |
| stack (basic) | $-$ | 18 | 11 | 29 | 18 | 33 | **51** | 64/256 | **4/256** | 71/256 |
| stack (comp.) | $-$ | 9 | 11 | 20 | 15 | 33 | **48** | 84/256 | **4/256** | 91/256 |
**Table 6**: A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample non-leaf function](#c-3-1-sample-source-code-for-a-non-leaf-function), assuming $m$ of the 16 registers must be preserved by called subroutines. This time we use fractions of bytes to encode instructions, enabling a fairer comparison. Otherwise, this table is similar to [Table 5](#table-5).
### C.4.3. Comparison with real machines [#c43-comparison-with-real-machines]
Note that our hypothetical register machines have been considerably optimized to produce shorter code than actually existing register machines; the latter are subject to other design considerations apart from code density and extendability, such as backward compatibility, faster instruction decoding, parallel execution of neighboring instructions, ease of automatically producing optimized code by compilers, and so on.
For example, the very popular two-address register architecture x86-64 produces code that is approximately twice as long as our "ideal" results for the two-address machines. On the other hand, our results for the stack machines are directly applicable to TVM, which has been explicitly designed with the considerations presented in this appendix in mind. Furthermore, the actual TVM code is even *shorter* (in bytes) than shown in [Table 5](#table-5) because of the presence of the two-byte $\texttt{CALL}$ instruction, allowing TVM to call up to 256 user-defined functions from the dictionary at $\texttt{c3}$. This means that one should subtract 10 bytes from the results for stack machines in [Table 5](#table-5) if one wants to specifically consider TVM, rather than an abstract stack machine; this produces a code size of approximately 40 bytes (or shorter), almost half that of an abstract two-address or three-address machine.
### C.4.4. Automatic generation of optimized code [#c44-automatic-generation-of-optimized-code]
An interesting point is that the stack machine code in our samples might have been generated automatically by a very simple optimizing compiler, which rearranges values near the top of the stack appropriately before invoking each primitive or calling a function as explained in [2.2.2](#2-2-2-basic-stack-manipulation-primitives-suffice) and [2.2.5](#2-2-5-semantics-of-compound-stack-operations). The only exception is the unimportant [manual](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code) $\texttt{XCHG3}$ optimization, which enabled us to shorten the code by one more byte.
By contrast, the heavily optimized (with respect to size) code for register machines shown in [C.3.2](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers) and [C.3.3](#c-3-3-three-address-and-two-address-register-machines%2C-preserved-registers) is unlikely to be produced automatically by an optimizing compiler. Therefore, if we had compared compiler-generated code instead of manually-generated code, the advantages of stack machines with respect to code density would have been even more striking.
## References [#references]
\[1] N. Durov, *Telegram Open Network*, 2017.
## Footnotes [#footnotes]
**1** For example, there are no floating-point arithmetic operations (which could be efficiently implemented using hardware-supported *double* type on most modern CPUs) present in TVM, because the result of performing such operations is dependent on the specific underlying hardware implementation and rounding mode settings. Instead, TVM supports special integer arithmetic operations, which can be used to simulate fixed-point arithmetic if needed. [Back ↑](#ref-fn1)
**2** The production version will likely require some tweaks and modifications prior to launch, which will become apparent only after using the experimental version in the test environment for some time. [Back ↑](#ref-fn2)
**3** A high-level smart-contract language might create a visibility of variables for the ease of programming; however, the high-level source code working with variables will be translated into TVM machine code keeping all the values of these variables in the TVM stack. [Back ↑](#ref-fn3)
**4** In the TON Blockchain context, `c7` is initialized with a singleton *Tuple*, the only component of which is a *Tuple* containing blockchain-specific data. The smart contract is free to modify `c7` to store its temporary data provided the first component of this *Tuple* remains intact. [Back ↑](#ref-fn4)
**5** Strictly speaking, there is also the current *library context*, which consists of a dictionary with 256-bit keys and cell values, used to load library reference cells of [Types of exotic cells](#3-1-7-types-of-exotic-cells). [Back ↑](#ref-fn5)
**6** Our inclusion of `r0` here creates a minor conflict with our assumption that the accumulator register, if present, is also `r0`; for simplicity, we will resolve this problem by assuming that the first argument to a function is passed in the accumulator. [Back ↑](#ref-fn6)
**7** For instance, if one writes a function for extracting square roots, this function will always accept its argument and return its result in the same registers, in contrast with a hypothetical built-in square root instruction, which could allow the programmer to arbitrarily choose the source and destination registers. Therefore, a user-defined function is tremendously less flexible than a built-in instruction on a register machine. [Back ↑](#ref-fn7)
**8** Of course, if the second option is used, this will destroy the original arrangement of $x$ in the top of the stack. In this case, one should either issue a `SWAP` before `XCHG s(j')`, or replace the previous operation `XCHG s(i)` with `XCHG s1, s(i)`, so that $x$ is exchanged with `s1` from the beginning. [Back ↑](#ref-fn8)
**9** Notice that the most common `XCHG s(i)` operation is not really required here if we do not insist on keeping the same temporary value or variable always in the same stack location, but rather keep track of its subsequent locations. We will move it to some other location while preparing the arguments to the next primitive or function call. [Back ↑](#ref-fn9)
**10** An alternative, arguably better, translation of `PU`$O'$ `s(i_1)`,...,`s(i_γ)` consists of the translation of $O'$ `s(i_2)`,...,`s(i_γ)`, followed by `PUSH s(i_1+α-1)`; `XCHG s(γ-1)`. [Back ↑](#ref-fn10)
**11** From the perspective of low-level cell operations, these data bits and cell references are not intermixed. In other words, an (ordinary) cell essentially is a couple consisting of a list of up to 1023 bits and of a list of up to four cell references, without prescribing an order in which the references and the data bits should be deserialized, even though TL-B schemes appear to suggest such an order. [Back ↑](#ref-fn11)
**12** From a theoretical perspective, we might say that a cell $c$ has an infinite sequence of hashes $(\text{Hash}_i(c))_{i\geq1}$, which eventually stabilizes: $\text{Hash}_i(c)\to\text{Hash}_\infty(c)$. Then the level $l$ is simply the largest index $i$, such that $\text{Hash}_i(c)\neq\text{Hash}_\infty(c)$. [Back ↑](#ref-fn12)
**13** A pruned branch cell $c'$ of level $l$ is *bound* by a Merkle (proof or update) cell $c$ if there are exactly $l$ Merkle cells on the path from $c$ to its descendant $c'$, including $c$. [Back ↑](#ref-fn13)
**14** Negative numbers are represented using two's complement. For instance, integer $-17$ is serialized by instruction `STI 8` into bitstring `xEF`. [Back ↑](#ref-fn14)
**15** A description of an older version of TL may be found at [https://core.telegram.org/mtproto/TL](https://core.telegram.org/mtproto/TL). [Back ↑](#ref-fn15)
**16** The field's name is useful for representing values of the type being defined in human-readable form, but it does not affect the binary serialization. [Back ↑](#ref-fn16)
**17** This is the "linear negation" operation $(-)^\perp$ of linear logic, hence our notation `~`. [Back ↑](#ref-fn17)
**18** In fact, $f$ may receive $m$ extra arguments and return $m$ modified values, which are passed to the next invocation of $f$. This may be used to implement "map" and "reduce" operations with dictionaries. [Back ↑](#ref-fn18)
**19** Versions of this operation may be introduced where $f$ and $g$ receive an additional bitstring argument, equal to the key (for leaves) or to the common prefix of all keys (for forks) in the corresponding subtree. [Back ↑](#ref-fn19)
**20** If there are no bits of data left in `code`, but there is still exactly one reference, an implicit `JMP` to the cell at that reference is performed instead of an implicit `RET`. [Back ↑](#ref-fn20)
**21** Technically, TVM may simply invoke a virtual method `run()` of the continuation currently in `cc`. [Back ↑](#ref-fn21)
**22** The already used savelist `cc.save` of the new `cc` is emptied before the execution starts. [Back ↑](#ref-fn22)
**23** The implementation of `REPEAT` involves an extraordinary continuation that remembers the remaining number of iterations, the body of the loop $c$, and the return continuation $c'$. (The latter term represents the remainder of the body of the function that invoked `REPEAT`, which would be normally stored in `c0` of the new `cc`.) [Back ↑](#ref-fn23)
**24** An important point here is that the tree of cells representing a TVM program cannot have cyclic references, so using `CALLREF` along with a reference to a cell higher up the tree would not work. [Back ↑](#ref-fn24)
**25** This is not exactly true. A more precise statement is that usually the codepage of the newly-created continuation is a known function of the current codepage. [Back ↑](#ref-fn25)
**26** This is another important mechanism of backward compatibility. All values of newly-added types, as well as values belonging to extended original types that do not belong to the original types (e.g., 513-bit integers that do not fit into 257 bits in the example above), are treated by all instructions (except stack manipulation instructions, which are naturally polymorphic, [Polymorphism of stack manipulation primitives](#2-3-3-polymorphism-of-stack-manipulation-primitives)) in the old codepages as "values of incorrect type", and generate type-checking exceptions accordingly. [Back ↑](#ref-fn26)
**27** If the cell dumps are hexadecimal, encodings consisting of an integral number of hexadecimal digits (i.e., having length divisible by four bits) might be equally convenient. [Back ↑](#ref-fn27)
**28** Notice that it is the probability of occurrence in the code that counts, not the probability of being executed. An instruction occurring in the body of a loop executed a million times is still counted only once. [Back ↑](#ref-fn28)
**29** Notice that any modifications after launch cannot be done unilaterally; rather they would require the support of at least two-thirds of validators. [Back ↑](#ref-fn29)
**30** The preliminary version of TVM does not use codepage -2 for this purpose. This may change in the future. [Back ↑](#ref-fn30)
**31** It is interesting to compare this code with that generated by optimizing C compilers for the x86-64 architecture. First of all, the integer division operation for x86-64 uses the one-address form, with the (double-length) dividend to be supplied in accumulator pair `r2:r0`. The quotient is also returned in `r0`. As a consequence, two single-to-double extension operations (`CDQ` or `CQO`) and at least one move operation need to be added. Secondly, the encoding used for arithmetic and move operations is less optimistic than in our example above, requiring about three bytes per operation on average. As a result, we obtain a total of 43 bytes for 32-bit integers, and 68 bytes for 64-bit integers. [Back ↑](#ref-fn31)
**32** Code produced for this function by an optimizing compiler for x86-64 architecture with size-optimization enabled actually occupied 150 bytes, due mostly to the fact that actual instruction encodings are about twice as long as we had optimistically assumed. [Back ↑](#ref-fn32)
# Builders and Slices (/blockchain-basics/tvm/builders-and-slices)
In TVM, the `Cell` type contains only metadata of the cell: level, hashes, and depths. To read actual data, TVM need to *load* cell from celldb, key-value storage of the node, which stores cells by their representation hashes. [`CTOS`](/blockchain-basics/tvm/instructions#d0-ctos) instruction loads a cell by its metadata from `Cell` type, and provides a `Slice`, a read-only wrapper for the cell's content. To simplify coding cell deserializers in smart contracts, instead of behaving like a simple bit/ref array, `Slice` is a "read cursor": it allows loading a piece of data from the beginning of the slice, returning that data and the slice that contains remaining data. On the other hand, there is a `Builder` type, which provides a convenient way to serialize data to a cell. Only the `Cell` type can be used outside of TVM: in output actions and in persistent storage.
## Builder [#builder]
Builder provides a way to construct a cell from a sequence of values of the following TVM types: integers, cells (as references), slices, and builders. Tuples, continuations, and `null` are not serializable.
For example, serialize the following numbers to a cell:
```
1 (uint4)
2 (uint4)
-1 (int8)
```
First, create an empty builder using [`NEWC`](/blockchain-basics/tvm/instructions#c8-newc):
```fift Fift
NEWC // returns empty builder x{}
```
Then, put a number on the stack:
```fift Fift
1 INT // stack: x{} 1
```
And call [`STU`](/blockchain-basics/tvm/instructions#cb-stu) ("STore Unsigned integer") to store integer into builder (swapping builder and value to meet `STU` input order):
```fift Fift
SWAP // stack: 1 x{}
4 STU // stack: x{0001}
```
Then, store the other two numbers:
```fift Fift
2 INT // x{0001} 2
SWAP // 2 x{0001}
4 STU // x{00010010}
-1 INT // x{00010010} -1
SWAP // -1 x{00010010}
8 STI // x{0001001011111111}
```
And, finally, [`ENDC`](/blockchain-basics/tvm/instructions#c9-endc) instruction finalizes the builder to a cell.
## Slice [#slice]
Slice allows reading data back from a cell, field by field. For example, deserialize bitstring `x{0001001011111111}` created above.
[`CTOS`](/blockchain-basics/tvm/instructions#d0-ctos) ("Cell TO Slice") loads a `Cell` to a `Slice`.
```fift Fift
// assume a cell with bitstring x{0001001011111111} is on the stack
CTOS // x{0001001011111111}
```
Then, call [`LDU`](/blockchain-basics/tvm/instructions#d3-ldu) ("LoaD Unsigned integer") to read first value (`uint4`).
```fift Fift
4 LDU // 1 x{001011111111}
```
`LDU` takes the first 4 bits from a slice and creates a new slice without these 4 bits: `x{0001|001011111111}` slices into a number `0001` and a slice `x{001011111111}`.
Similarly, read another two numbers:
```fift Fift
4 LDU // 1 2 x{11111111}
8 LDI // 1 2 -1 x{}
```
A common way to ensure there is no data left inside the slice is to call [`ENDS`](/blockchain-basics/tvm/instructions#d1-ends).
# Continuations (/blockchain-basics/tvm/continuations)
[Continuation](https://en.wikipedia.org/wiki/Continuation) is a value that contains executable code. Continuations are used whenever non-linear code execution is required:
* conditions
* loops
* function calls
* throwing and catching exceptions
Continuation can be thought as "pointer to a code", with an important distinction that, unlike pointers on other machines, it's not a number.
## Ordinary continuation [#ordinary-continuation]
The most common kind of continuations are the ordinary continuations, which are just code Slices, containing (the remainder of) TVM bitcode. Optionally, it can contain any of the additional parameters:
* **Stack**. A list of values that will be pushed on stack before continuation is executed.
* **Savelist**. A list of values for registers before continuation is executed.
* **Codepage**. Bitcode version used to run this continuation.
* **Number of arguments (`nargs`)**. Number of values from call-side stack to push onto new stack before continuation is executed.
## Control flow [#control-flow]
### Jumps [#jumps]
The simplest way to change `cc` is to use [`JMPREF`](/blockchain-basics/tvm/instructions#db3d-jmpref) instruction. It just sets `cc` to the reference operand of `JMPREF` (stack and registers are not affected).
The following rules are applied during the jump:
* Initialize a new stack with the target continuation initial stack
* Move `nargs` elements from the caller stack to the new stack, if the target continuation has `nargs`
* If the target continuation `nargs` is not defined, move all elements from the caller stack to the new stack
* Pop register values from target continuation savelist
Due to the limitation of the `Cell` type, one continuation can contain no more than 1023 bits of bitcode. To execute longer functions, we could pass `JMPREF` as a last instruction, which will continue execution of a function in a new continuation.
```fift Fift
// some instructions
<{
// next instructions that exceed the 1023-bit limit are placed in a child cell
}> JMPREF
```
To simplify things, TVM has an *implicit jump* mechanism, which automatically jumps to the next reference of `cc` when there are no more instructions to execute.
### Calls [#calls]
*Call* is a special type of jump, which also saves `cc` to `c0`, so the callee can pass execution back to the caller. That is how [`CALLREF`](/blockchain-basics/tvm/instructions#db3c-callref) works.
```fift Fift
2 PUSHINT
3 PUSHINT
<{
ADD
}> CALLREF // returns 5
```
After `ADD` is executed, there are no more instructions to execute in `cc`, and also no references for implicit jumps. *Implicit return* sets `cc` back to `c0`, which was a previous `cc`. Let's look at the *composition* of continuations which `CALLREF` produces:
During the call, the remaining of the current continuation is saved to `c0`. Also, current `c0` is pushed to the savelist of `cc` to restore its original value after return. If we would call function `f1`, then call `f2` inside `f1` and `f3` inside `f2`, there will be a callstack formed by savelists of continuations: `c0` value inside `f3` can be represented as `(rest of f2) ◦0 (rest of f1) ◦0 (rest of the caller)`. `a ◦i b` is a continuation composition operator, which saves continuation `b` as a ci register of continuation `b`, so, we can say that `b` is executed after `a` by register ci .
## Extraordinary continuations [#extraordinary-continuations]
### Quit [#quit]
**TL-B**: `vmc_quit$1000 exit_code:int32 = VmCont`
Exits TVM with `exit_code`. During [initialization of TVM](/blockchain-basics/tvm/initialization), `c0` is set to `Quit(0)`, and `c1` to `Quit(1)`.
### ExcQuit [#excquit]
**TL-B**: `vmc_quit_exc$1001 = VmCont`
Default exception handler. Terminates TVM with exception code popped from the stack. During [initialization of TVM](/blockchain-basics/tvm/initialization), `c2` is set to `ExcQuit`.
### PushInt [#pushint]
**TL-B**: `vmc_pushint$1111 value:int32 next:^VmCont = VmCont`
Pushes `value` on the stack and jumps to `next`. This continuation is only used in [`BOOLEVAL`](/blockchain-basics/tvm/instructions#edf9-booleval) instruction.
### Envelope [#envelope]
**TL-B**: `vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont`
Updates current VM state with `cdata` and jumps to `next`.
### Repeat [#repeat]
**TL-B**: `vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont`
Executes `body` `count` times, then jumps to `after`. Under the hood, it just sets `body` `c0` to `Repeat(count - 1, body, after)` if `count > 0`, otherwise jumps to `after`. Used in [`REPEAT`](/blockchain-basics/tvm/instructions#e4-repeat) and variants.
### Again [#again]
**TL-B**: `vmc_again$110001 body:^VmCont = VmCont`
Executes `body` infinite times by setting `body` `c0` to `Again(body)`. Used in [`AGAIN`](/blockchain-basics/tvm/instructions#ea-again) and variants.
### Until [#until]
**TL-B**: `vmc_until$110000 body:^VmCont after:^VmCont = VmCont`
Pops bool from stack, jumps to `body` with `c0 = Until(body, after)` if bool is `false`, otherwise jumps to `after`. Used in [`UNTIL`](/blockchain-basics/tvm/instructions#e6-until) and variants.
### WhileCondition [#whilecondition]
**TL-B**: `vmc_while_cond$110010 cond:^VmCont body:^VmCont after:^VmCont = VmCont`
Represents a branching point of a while loop. Pops a bool from the stack, jumps to `body` with `c0 = WhileBody(cond, body, after)` if the bool is `true`, otherwise jumps to `after`. Used in [`WHILE`](/blockchain-basics/tvm/instructions#e8-while) and variants.
### WhileBody [#whilebody]
**TL-B**: `vmc_while_body$110011 cond:^VmCont body:^VmCont after:^VmCont = VmCont`
Represents a delayed iteration of a while loop. Jumps to `cond` with `c0 = WhileCondition(cond, body, after)`. It is assumed that the evaluation of `cond` leaves a bool at the top of the stack for the following `WhileCondition` to check. Used in [`WHILE`](/blockchain-basics/tvm/instructions#e8-while) and variants.
# Exit codes (/blockchain-basics/tvm/exit-codes)
An exit code is a 32-bit signed integer that indicates whether the compute or action phase of the transaction was successful. If not, it holds the code of the exception that occurred.
Each transaction on TON Blockchain consists of multiple phases. An *exit code* is a 32-bit signed integer that indicates whether the [compute](#compute) or [action](#action) phase of the transaction was successful, and if not, holds the code of the exception that occurred. Each exit code represents its own exception or the resulting state of the transaction.
Exit codes 0 and 1 indicate normal (successful) execution of the [compute phase](#compute). Exit (or [result](#action)) code 0 indicates normal (successful) execution of the [action phase](#action). Any other exit code indicates that a certain exception has occurred and that the transaction was not successful in one way or another, i.e., the transaction was reverted or the inbound message has bounced back.
TON Blockchain reserves exit code values from 0 to 127. The range from 256 to 65535 is free for developer-defined exit codes.
While an exit (or [result](#action)) code is a 32-bit signed integer on TON Blockchain, an attempt to throw an exit code outside the bounds of a 16-bit unsigned integer ($0 - 65535$) will cause an error with [exit code 5](#5%3A-integer-out-of-expected-range). This is done intentionally to prevent some exit codes from being produced artificially, such as [exit code -14](#-14%3A-out-of-gas-error).
## Table of exit codes [#table-of-exit-codes]
The following table lists exit codes with their origin (where they can occur) and a short description for each.
| Exit code | Origin | Brief description |
| :----------------------------------------------------------- | :---------------------------------- | :----------------------------------------------------------------------------------------------------- |
| [0](#0%3A-normal-termination) | [Compute][c] and [action][a] phases | Standard successful execution exit code. |
| [1](#1%3A-alternative-termination) | [Compute phase][c] | Alternative successful execution exit code. Reserved, but does not occur. |
| [2](#2%3A-stack-underflow) | [Compute phase][c] | Stack underflow. |
| [3](#3%3A-stack-overflow) | [Compute phase][c] | Stack overflow. |
| [4](#4%3A-integer-overflow) | [Compute phase][c] | Integer overflow. |
| [5](#5%3A-integer-out-of-expected-range) | [Compute phase][c] | Range check error — an integer is out of its expected range. |
| [6](#6%3A-invalid-opcode) | [Compute phase][c] | Invalid [TVM][tvm] opcode. |
| [7](#7%3A-type-check-error) | [Compute phase][c] | Type check error. |
| [8](#8%3A-cell-overflow) | [Compute phase][c] | Cell overflow. |
| [9](#9%3A-cell-underflow) | [Compute phase][c] | Cell underflow. |
| [10](#10%3A-dictionary-error) | [Compute phase][c] | Dictionary error. |
| [11](#11%3A-%22unknown%22-error) | [Compute phase][c] | Described in [TVM][tvm] docs as "Unknown error, may be thrown by user programs." |
| [12](#12%3A-fatal-error) | [Compute phase][c] | Fatal error. Thrown by [TVM][tvm] in situations deemed impossible. |
| [13](#13%3A-out-of-gas-error) | [Compute phase][c] | Out of gas error. |
| [-14](#-14%3A-out-of-gas-error) | [Compute phase][c] | Same as 13. Negative, so that it [cannot be faked](#13%3A-out-of-gas-error). |
| [14](#14%3A-virtualization-error) | [Compute phase][c] | VM virtualization error. Reserved, but never thrown. |
| [32](#32%3A-action-list-is-invalid) | [Action phase][a] | Action list is invalid. |
| [33](#33%3A-action-list-is-too-long) | [Action phase][a] | Action list is too long. |
| [34](#34%3A-invalid-or-unsupported-action) | [Action phase][a] | Action is invalid or not supported. |
| [35](#35%3A-invalid-source-address-in-outbound-message) | [Action phase][a] | Invalid source address in outbound message. |
| [36](#36%3A-invalid-destination-address-in-outbound-message) | [Action phase][a] | Invalid destination address in outbound message. |
| [37](#37%3A-not-enough-toncoin) | [Action phase][a] | Not enough Toncoin. |
| [38](#38%3A-not-enough-extra-currencies) | [Action phase][a] | Not enough extra currencies. |
| [39](#39%3A-outbound-message-does-not-fit-into-cell) | [Action phase][a] | Outbound message does not fit into a cell after rewriting. |
| [40](#40%3A-cannot-process-message) | [Action phase][a] | Cannot process a message — not enough funds, the message is too large, or its Merkle depth is too big. |
| [41](#41%3A-library-reference-is-null) | [Action phase][a] | Library reference is null during library change action. |
| [42](#42%3A-library-change-action-error) | [Action phase][a] | Library change action error. |
| [43](#43%3A-library-limits-exceeded) | [Action phase][a] | Exceeded the maximum number of cells in the library or the maximum depth of the Merkle tree. |
| [50](#50%3A-account-state-size-exceeded-limits) | [Action phase][a] | Account state size exceeded limits. |
{/* NOTE: Some might depend on a phase; in such cases, the table entry might be:
| number | [Compute][c] and [action][a] phases | Depends on the phase.
*/}
Often enough, you might encounter the exit code 65535 (or `0xffff`), which usually means the same as the [exit code 130](#130%3A-) — the received opcode is unknown to the contract, as no receivers were expecting it. When writing contracts, the exit code 65535 is set by the developers and not by [TVM][tvm] or the Tolk compiler.
[c]: /tvm/overview#compute-phase
[a]: /tvm/overview#action-phase
## Exit codes in Blueprint projects [#exit-codes-in-blueprint-projects]
In [Blueprint][bp] tests, exit codes from the [compute phase](#compute) are specified in the `exitCode` field of the object argument for the `toHaveTransaction()` method of the `expect()` matcher. The field for the [result](#action) codes (exit codes from the [action phase](#action)) in the same `toHaveTransaction()` method is called `actionResultCode`.
{/*
Read more about expecting specific exit codes: [Transactions with intentional errors](/blockchain-basics/contract-dev/blueprint/debug#tests-errors).
*/}
Additionally, one can examine the result of sending a message to a contract and discover the phases of each transaction and their values, including exit (or result) codes for the [compute phase](#compute) (or [action phase](#action)).
Note that to do so, you'll have to perform a couple of type checks first:
```ts
it('tests something, you name it', async () => {
// Send a specific message to our contract and store the results
const res = await your_contract_name.send({/* … */});
// Now, we have access to an array of executed transactions,
// with the second one (index 1) being the one we look for
const tx = res.transactions[1]!;
// To do something useful with it, let's ensure that its type is 'generic'
// and that the compute phase in it wasn't skipped
if (tx.description.type === "generic"
&& tx.description.computePhase.type === "vm") {
// Finally, we're able to freely peek into the transaction for general details,
// such as printing out the exit code of the compute phase if we so desire
console.log(tx.description.computePhase.exitCode);
}
});
```
## Compute and action phases [#compute-and-action-phases]
### 0: Normal termination [#0-normal-termination]
This exit (or [result](#action)) code indicates the successful completion of the [compute phase](#compute) (or [action phase](#action)) of the transaction.
## Compute phase [#compute-phase]
[TVM][tvm] initialization and all computations occur in the [compute phase][c].
If the compute phase fails (the resulting exit code is neither [0](#0%3A-normal-termination) nor [1](#1%3A-alternative-termination)), the transaction skips the [action phase](#action) and proceeds to the bounce phase. In this phase, a bounce message is formed for transactions initiated by the inbound message.
### 1: Alternative termination [#1-alternative-termination]
This is an alternative exit code for the successful execution of the [compute phase](#compute). It is reserved but never occurs.
### 2: Stack underflow [#2-stack-underflow]
If an operation consumes more elements than exist on the stack, an error with exit code 2 is thrown: `Stack underflow`.
```tolk title="Tolk"
fun drop(): void asm "DROP"
fun onInternalMessage() {
try {
// Removes 100 elements from the stack, causing an underflow
repeat(100){
drop();
}
} catch(exitCode) {
// exitCode is 2
assert (exitCode == 2) throw 1111;
}
}
```
### 3: Stack overflow [#3-stack-overflow]
If there are too many elements copied into a closure continuation, an error with exit code 3 is thrown: `Stack overflow`. This occurs rarely unless you're deep in the [Fift and TVM assembly](/blockchain-basics/languages/fift/fift-and-tvm-assembly) trenches:
```tolk title="Tolk"
// Remember kids, don't try to overflow the stack at home!
fun stackOverflow(): void asm
"""
x{} SLICE // s
BLESS // c
0 SETNUMARGS // c'
2 PUSHINT // c' 2
SWAP // 2 c'
1 -1 SETCONTARGS // ← this blows up
"""
fun onInternalMessage() {
try {
stackOverflow();
} catch(exitCode) {
// exitCode is 3
assert (exitCode == 3) throw 1111;
}
}
```
### 4: Integer overflow [#4-integer-overflow]
If the value in a calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or there's an attempt to divide or perform modulo by zero, an error with exit code 4 is thrown: `Integer overflow`.
```tolk title="Tolk"
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun pow2(y: int): int asm "POW2"
fun onInternalMessage() {
var x = -pow2(255) - pow2(255);
var zero = x - x;
try {
touch(-x); // integer overflow by negation
// since the max positive value is 2^{256} - 1
} catch(exitCode) {
// exitCode is 4
assert (exitCode == 4) throw 1111;
}
try {
touch(x / zero); // division by zero!
} catch (exitCode) {
// exitCode is 4
assert (exitCode == 4) throw 1111;
}
try {
touch(x * x * x); // integer overflow!
} catch (exitCode) {
// exitCode is 4
assert (exitCode == 4) throw 1111;
}
// There can also be an integer overflow when performing:
// addition (+),
// subtraction (-),
// division (/) by a negative number or modulo (%) by zero
}
```
### 5: Integer out of expected range [#5-integer-out-of-expected-range]
A range check error occurs when some integer is out of its expected range. Any attempt to store an unexpected amount of data or specify an out-of-bounds value throws an error with exit code 5: `Integer out of expected range`.
Examples of specifying an out-of-bounds value:
```tolk title="Tolk"
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun pow2(y: int): int asm "POW2"
fun onInternalMessage() {
try {
// Repeat only operates on an inclusive range from 1 to 2^{31} - 1
// Any valid integer value greater than that causes an error with exit code 5
repeat (pow2(55)) {
touch("smash. I. must.");
}
} catch(exitCode) {
// exitCode is 5
assert (exitCode == 5) throw 1111;
}
try {
// Builder.storeUint() function can only use up to 256 bits, thus 512 is too much:
touch(beginCell().storeUint(-1, 512).toCell());
} catch (exitCode) {
// exitCode is 5
assert (exitCode == 5) throw 1111;
}
try {
touch(beginCell().storeUint(100, 2).toCell()); // maximum value is 2^{2} - 1 = 3 < 100
}
catch(exitCode) {
// exitCode is 5
assert (exitCode == 5) throw 1111;
}
try {
val deployMsg = createMessage({
bounce: false,
dest: {
workchain: 0,
stateInit: {
code: beginCell().endCell(),
data: beginCell().endCell(),
},
toShard: {
fixedPrefixLength: pow2(52), // but fixedPrefixLength is uint5
closeTo: contract.getAddress()
},
},
value: 1,
body: beginCell().endCell(),
});
deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
} catch (exitCode) {
// exitCode is 5
assert (exitCode == 5) throw 1111;
}
}
```
### 6: Invalid opcode [#6-invalid-opcode]
If you specify an instruction that is not defined in the current [TVM][tvm] version or attempt to set an unsupported [code page][tvm], an error with exit code 6 is thrown: `Invalid opcode`.
```tolk title="Tolk"
// There's no such code page, and an attempt to set it fails
fun invalidOpcode(): void asm "42 SETCP"
fun onInternalMessage() {
try {
invalidOpcode();
} catch (exitCode) {
// exitCode is 6
assert (exitCode == 6) throw 1111;
}
}
```
### 7: Type check error [#7-type-check-error]
If an argument to a primitive is of an incorrect value type or there is any other mismatch in types during the [compute phase](#compute), an error with exit code 7 is thrown: `Type check error`.
```tolk title="Tolk"
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
// The actual returned value type doesn't match the declared one
fun typeCheckError(): cell asm "42 PUSHINT";
fun onInternalMessage() {
try {
// it isn't cell
touch(typeCheckError().beginParse());
} catch (exitCode) {
// exitCode is 7
assert (exitCode == 7) throw 1111;
}
}
```
### 8: Cell overflow [#8-cell-overflow]
To construct a `cell`, a `builder` primitive is used. If you try to store more than 1023 bits of data or more than four references to other cells, an error with exit code 8 is thrown: `Cell overflow`.
This error can be triggered by manual construction of the cells via relevant methods, such as `storeInt()`, or when using structs, their convenience methods.
```tolk title="Tolk"
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun onInternalMessage() {
// Too many bits
try {
val data = beginCell()
.storeInt(0, 250)
.storeInt(0, 250)
.storeInt(0, 250)
.storeInt(0, 250)
.storeInt(0, 24) // 1024 bits!
.toCell();
touch(data);
} catch (exitCode) {
// exitCode is 8
assert (exitCode == 8) throw 1111;
}
// Too many refs
try {
val data = beginCell()
.storeRef(beginCell().endCell())
.storeRef(beginCell().endCell())
.storeRef(beginCell().endCell())
.storeRef(beginCell().endCell())
.storeRef(beginCell().endCell()) // 5 refs!
.toCell();
touch(data);
} catch (exitCode) {
// exitCode is 8
assert (exitCode == 8) throw 1111;
}
}
```
### 9: Cell underflow [#9-cell-underflow]
To parse a `cell`, a `slice` primitive is used. If you try to load more data or references than a `slice` contains, an error with exit code 9 is thrown: `Cell underflow`.
The most common cause of this error is a mismatch between the expected and actual memory layouts of the cells, so it's recommended to use Tolk structs for parsing the cells instead of manual parsing via relevant methods, such as `loadInt()`.
```tolk title="Tolk"
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun onInternalMessage() {
// Too few bits
try {
touch(beginCell().endCell().beginParse().loadInt(1)); // 0 bits!
} catch (exitCode) {
// exitCode is 9
assert (exitCode == 9) throw 1111;
}
// Too few refs
try {
touch(beginCell().endCell().beginParse().loadRef()); // 0 refs!
} catch (exitCode) {
// exitCode is 9
assert (exitCode == 9) throw 1111;
}
}
```
### 10: Dictionary error [#10-dictionary-error]
In Tolk, the `map` type is an abstraction over the ["hash" map dictionaries of TVM](/blockchain-basics/languages/func/dictionaries).
If there is incorrect manipulation of dictionaries, such as improper assumptions about their memory layout, an error with exit code 10 is thrown: `Dictionary error`. Note that Tolk prevents you from getting this error unless you perform [TVM assembly](/blockchain-basics/languages/fift/fift-and-tvm-assembly) work yourself:
```tolk title="Tolk"
import "@stdlib/tvm-dicts";
fun touch(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun cast(y: T): U asm "NOP"
fun cell?.addIntToIDict(mutate self, key: int, number: int): void {
return self.iDictSetBuilder(32, key, beginCell().storeInt(number, 32));
}
fun onInternalMessage() {
var dict = createEmptyDict();
dict.addIntToIDict(0, 0);
dict.addIntToIDict(1, 1);
// The Int to Int dictionary is being misinterpreted as a map
val m: map = cast(dict);
try {
// And the error happens only when we touch it
touch(m.get(0).isFound);
} catch (exitCode) {
// exitCode is 10
assert (exitCode == 10) throw 1111;
}
}
```
### 11: "Unknown" error [#11-unknown-error]
Described in the [TVM][tvm] docs as "Unknown error, may be thrown by user programs," although most commonly used for problems with queuing a message send or problems with getters.
In particular, if you try to send an ill-formed message on-chain or to call a non-existent getter function off-chain, an exit code 11 will be thrown.
```tolk title="Tolk"
fun sendMessage(msg: cell, mode: int): void asm "SENDMSG"
fun onInternalMessage() {
try {
// fails in the Compute phase when the message is ill-formed
sendMessage(beginCell().endCell(), 0);
} catch (exitCode) {
// exitCode is 11
assert (exitCode == 11) throw 1111;
}
}
```
### 12: Fatal error [#12-fatal-error]
Fatal error. Thrown by TVM in situations deemed impossible.
### 13: Out of gas error [#13-out-of-gas-error]
If there isn't enough gas to complete computations in the [compute phase](#compute), an error with exit code 13 is thrown: `Out of gas error`.
However, this code isn't immediately shown as is — instead, the bitwise NOT operation is applied, changing the value from 13 to -14. Only then is the code displayed.
This is done to prevent the resulting code (-14) from being produced artificially in user contracts, as all functions that can throw an exit code can only specify integers in the range from 0 to 65535 inclusive.
```tolk title="Tolk"
import "@stdlib/gas-payments";
fun onInternalMessage() {
setGasLimit(100);
}
```
### -14: Out of gas error [#-14-out-of-gas-error]
See [exit code 13](#13%3A-out-of-gas-error).
### 14: Virtualization error [#14-virtualization-error]
Virtualization error related to pruned branch cells. Reserved but never thrown.
## Action phase [#action-phase]
The [action phase][a] is processed after the successful execution of the [compute phase](#compute). It attempts to perform the actions stored in the action list by [TVM][tvm] during the compute phase.
Some actions may fail during processing, in which case those actions may be skipped or the whole transaction may revert, depending on the mode of actions. The code indicating the resulting state of the [action phase][a] is called a *result code*. Since it is also a 32-bit signed integer that essentially serves the same purpose as the *exit code* of the [compute phase](#compute), it is common to call the result code an exit code as well.
### 32: Action list is invalid [#32-action-list-is-invalid]
If the list of actions contains exotic cells, an action entry cell does not have references, or some action entry cell cannot be parsed, an error with exit code 32 is thrown: `Action list is invalid`.
Aside from this exit code, there is a boolean flag `valid`, which you can find under `description.actionPhase.valid` in the transaction results when working with [Sandbox and Blueprint](#blueprint). A transaction can set this flag to `false` even when there is some other exit code thrown from the action phase.
### 33: Action list is too long [#33-action-list-is-too-long]
If there are more than 255 actions queued for execution, the [action phase](#action) will throw an error with an exit code 33: `Action list is too long`.
```tolk title="Tolk"
import "@stdlib/gas-payments";
fun onInternalMessage() {
// For example, let's attempt to queue the reservation of a specific amount of nanoToncoins
// This won't fail in the compute phase, but will result in exit code 33 in the action phase
repeat (256) {
reserveToncoinsOnBalance(1000000, RESERVE_MODE_AT_MOST);
}
}
```
### 34: Invalid or unsupported action [#34-invalid-or-unsupported-action]
There are only four supported actions at the moment: changing the contract code, sending a message, reserving a specific amount of nanoToncoin, and changing the library cell. If there is any issue with the specified action (invalid message, unsupported action, etc.), an error with exit code 34 is thrown: `Invalid or unsupported action`.
```tolk title="Tolk"
fun onInternalMessage() {
// For example, let's try to send an ill-formed message:
// won't fail in the compute phase, but will result in exit code 34 in the Action phase
sendRawMessage(beginCell().endCell(), 0);
}
```
### 35: Invalid source address in outbound message [#35-invalid-source-address-in-outbound-message]
If the source address in the outbound message is not equal to `addr_none` or to the address of the contract that initiated this message, an error with exit code 35 is thrown: `Invalid source address in outbound message`.
### 36: Invalid destination address in outbound message [#36-invalid-destination-address-in-outbound-message]
If the destination address in the outbound message is invalid, e.g., it does not conform to the relevant [TL-B][tlb] schemas, contains an unknown workchain ID, or has an invalid length for the given workchain, an error with exit code 36 is thrown: `Invalid destination address in outbound message`.
If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.
### 37: Not enough Toncoin [#37-not-enough-toncoin]
If all funds of the inbound message with base `mode` 64 set have already been consumed and there are not enough funds to pay for the failed action, or the [TL-B][tlb] layout of the provided value (`CurrencyCollection`) is invalid, or there are not enough funds to pay forward fees or not enough funds after deducting fees, an error with exit code 37 is thrown: `Not enough Toncoin`.
If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.
### 38: Not enough extra currencies [#38-not-enough-extra-currencies]
Besides the native currency, Toncoin, TON Blockchain supports up to $2^{32}$ extra currencies. They differ from creating new Jettons because extra currencies are natively supported — one can potentially just specify an additional `HashmapE` of extra currency amounts in addition to the Toncoin amount in the internal message to another contract. Unlike Jettons, extra currencies can only be stored and transferred and do not have any other functionality.
When there is not enough extra currency to send the specified amount, an exit code 38 is thrown: `Not enough extra currencies`.
### 39: Outbound message does not fit into cell [#39-outbound-message-does-not-fit-into-cell]
When processing the message, TON Blockchain tries to pack it according to the relevant TL-B schemas, and if it cannot, an error with exit code 39 is thrown: `Outbound message doesn't fit into a cell`.
If attempts at sending the message fail multiple times and the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.
### 40: Cannot process message [#40-cannot-process-message]
If there are not enough funds to process all the cells in a message, the message is too large, or its Merkle depth is too big, an error with exit code 40 is thrown: `Cannot process a message`.
If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.
### 41: Library reference is null [#41-library-reference-is-null]
If a library reference is required during a library change action but is null, an error with exit code 41 is thrown: `Library reference is null`.
### 42: Library change action error [#42-library-change-action-error]
If there's an error during an attempt at a library change action, an error with exit code 42 is thrown: `Library change action error`.
### 43: Library limits exceeded [#43-library-limits-exceeded]
If the maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded, an error with exit code 43 is thrown: `Library limits exceeded`.
### 50: Account state size exceeded limits [#50-account-state-size-exceeded-limits]
If the account state (contract storage, essentially) exceeds any of the limits specified in [config param 43 of TON Blockchain](/blockchain-basics/primitives/config#param-43) by the end of the [action phase](#action), an error with exit code 50 is thrown: `Account state size exceeded limits`.
If the configuration is absent, the default values are:
* `max_msg_bits` is equal to $2^{21}$ — maximum message size in bits.
* `max_msg_cells` is equal to $2^{13}$ — maximum number of cells a message can occupy.
* `max_library_cells` is equal to 1000 — maximum number of cells that can be used as library reference cells.
* `max_vm_data_depth` is equal to $2^{9}$ — maximum cells depth in messages and account state.
* `ext_msg_limits.max_size` is equal to 65535 — maximum external message size in bits.
* `ext_msg_limits.max_depth` is equal to $2^{9}$ — maximum external message depth.
* `max_acc_state_cells` is equal to $2^{16}$ — maximum number of cells that an account state can occupy.
* `max_acc_state_bits` is equal to $2^{16} \times 1023$ — maximum account state size in bits.
* `max_acc_public_libraries` is equal to $2^{8}$ — maximum number of library reference cells that an account state can use on the masterchain.
* `defer_out_queue_size_limit` is equal to $2^{8}$ — maximum number of outbound messages to be queued (regarding validators and collators).
{/* NOTE: Reserved a section until Tolk introduces any custom exit codes.
## Tolk compiler
Tolk utilizes exit codes from 128 to 255. Note that exit codes used by Tolk indicate contract errors which can occur when using Tolk-generated code and are therefore thrown in the transaction's [compute phase](#compute), not during compilation.
*/}
[tlb]: /languages/tl-b/overview
[tvm]: /tvm/overview
[bp]: /contract-dev/blueprint/overview
[sb]: https://github.com/ton-org/sandbox
[jest]: https://jestjs.io
# Gas (/blockchain-basics/tvm/gas)
Each instruction executed in TVM consumes gas. All instructions consume *basic gas*, which is calculated from the size of the instruction in the bitcode. Some instructions may consume *extra gas*, which is often not fixed but calculated based on the input data.
## Basic gas usage (per bit of executed code) [#basic-gas-usage-per-bit-of-executed-code]
Each instruction consumes a fixed amount of `10` gas and `1` gas for each bit of this instruction, not including variable-length operands and references.
Examples:
| Instruction | TL-B | Gas | Notes |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`NEWC`](/blockchain-basics/tvm/instructions#c8-newc) | `#C8` | `18` | 8-bit prefix without operands |
| [`STU`](/blockchain-basics/tvm/instructions#cb-stu) | `#CB` `cc:uint8` | `26` | 8-bit prefix, 8-bit operand |
| [`PUSHINT_LONG`](/blockchain-basics/tvm/instructions#82-pushint_long) | `#82` `l:(## 5)` `xxx:(int (8 * l + 19))` | `23` | 8-bit prefix, 5-bit operand, length of `xxx` depends on `l`, so it is not included |
| [`STSLICE_CONST`](/blockchain-basics/tvm/instructions#cfc0_-stsliceconst) | `#CFC0_` `x:(## 2)` `y:(## 3)` `c:(x * ^Cell)` `sss:((8 * y + 2) * Bit)` | `24` | 9-bit prefix (`CF` is 8 bits, `C0_` is `C_`, which is just bit `1`), 2-bit and 3-bit operands, refs `c` and variable-length `sss` are not included |
## Cell operations [#cell-operations]
When any instruction internally finalizes a `Builder` to a `Cell`, it consumes `500` gas. When a `Cell` is loaded as a `Slice`, it consumes `100` gas for the first access in current smart contract invocation, and `25` gas for each subsequent load from cache. Cells are identified by representation hash, e.g., loading cell with the same hash for the second time will always cost `25` gas.
This applies to all instructions that internally operate with cells (including dictionary operations). The only exceptions are:
* `BTOS` converts a `Builder` to a `Slice` without consuming gas for cell operations.
* `HASHBU` computes hash without consuming gas for converting `Builder` to a `Cell`
## Exceptions [#exceptions]
TVM consumes `50` gas when any exception is thrown, both explicitly by [`THROW`](/blockchain-basics/tvm/instructions#f2c4_-throw)-like instructions or implicitly during execution of other instructions. This happens before the jump to the exception handler `c2`.
## Implicit jumps and returns [#implicit-jumps-and-returns]
When the current continuation ends and there is a remaining reference, TVM jumps to it and consumes `10` gas. When there are no instructions to execute and references to jump to, implicit return to `c0` occurs, which consumes `5` gas.
## Nested continuations [#nested-continuations]
Calling more than `8` extraordinary continuations in a chain consumes `1` gas for each subsequent continuation.
## Tuple operations [#tuple-operations]
[`TUPLE`](/blockchain-basics/tvm/instructions#6f0-tuple), [`TUPLEVAR`](/blockchain-basics/tvm/instructions#6f80-tuplevar), [`UNTUPLE`](/blockchain-basics/tvm/instructions#6f2-untuple), [`UNTUPLEVAR`](/blockchain-basics/tvm/instructions#6f82-untuplevar), [`UNPACKFIRST`](/blockchain-basics/tvm/instructions#6f3-unpackfirst), [`UNPACKFIRSTVAR`](/blockchain-basics/tvm/instructions#6f83-unpackfirstvar), [`EXPLODE`](/blockchain-basics/tvm/instructions#6f4-explode), [`EXPLODEVAR`](/blockchain-basics/tvm/instructions#6f84-explodevar) consumes `1` gas for each entry been pushed or popped into a tuple. [`TPUSH`](/blockchain-basics/tvm/instructions#6f8c-tpush), [`TPOP`](/blockchain-basics/tvm/instructions#6f8d-tpop), [`SETINDEX`](/blockchain-basics/tvm/instructions#6f5-setindex), [`SETINDEXVAR`](/blockchain-basics/tvm/instructions#6f85-setindexvar), [`SETINDEXQ`](/blockchain-basics/tvm/instructions#6f7-setindexq)/[`SETINDEXVARQ`](/blockchain-basics/tvm/instructions#6f87-setindexvarq) consumes `len(tuple)` gas for the resulting tuple size after push/pop/set. Same applies to instructions operating with `c7`: [`SETGLOB`](/blockchain-basics/tvm/instructions#f87_-setglob)/[`SETGLOBVAR`](/blockchain-basics/tvm/instructions#f860-setglobvar), [`RANDU256`](/blockchain-basics/tvm/instructions#f810-randu256)/[`RAND`](/blockchain-basics/tvm/instructions#f811-rand), [`SETRAND`](/blockchain-basics/tvm/instructions#f814-setrand), [`ADDRAND`](/blockchain-basics/tvm/instructions#f815-addrand).
## Stack operations [#stack-operations]
TVM consumes 1 gas for each stack element deeper than 32 elements inside the resulting new stack each time stack gets copied: when calling or jumping to a continuation with a non-empty argument number, an initial stack, or both, when extending a continuation stack using [`SETCONTARGS`](/blockchain-basics/tvm/instructions#ec-setcontargs_n) and similar instructions, when using [`RUNVM`](/blockchain-basics/tvm/instructions#db4-runvm) (both for initial and resulting stacks of the vm).
## Extra currency [#extra-currency]
The first `5` executions of `GETEXTRABALANCE` consume at most `26 + 200` gas each. The subsequent executions incur the full gas cost of `26` (normal instruction cost) plus gas for loading cells (up to `3300` if the dictionary has maximum depth).
## RUNVM [#runvm]
[`RUNVM`](/blockchain-basics/tvm/instructions#db4-runvm) and [`RUNVMX`](/blockchain-basics/tvm/instructions#db50-runvmx) consume `40` extra gas before starting a VM.
## Cryptography [#cryptography]
### CHKSIGNS/CHKSIGNU [#chksignschksignu]
[`CHKSIGNS`](/blockchain-basics/tvm/instructions#f911-chksigns) and [`CHKSIGNU`](/blockchain-basics/tvm/instructions#f910-chksignu) can be invoked `10` times without extra gas cost. Next checks will cost `4000` gas each.
### HASHEXT [#hashext]
`HASHEXT*` instructions always consume `1` extra gas for each part of the input. Additionally, the following gas is consumed for each hashed byte:
| Algorithm | Gas consumed |
| --------- | ------------- |
| SHA256 | 1/33 per byte |
| SHA512 | 1/16 per byte |
| BLAKE2B | 1/19 per byte |
| KECCAK256 | 1/11 per byte |
| KECCAK512 | 1/6 per byte |
Only the integer part of the gas is consumed; for example, 0-32 bytes of SHA256 cost 0 gas, 33-64 bytes cost 1 gas, and so on.
### RIST255 [#rist255]
Instructions consume constant extra gas.
| Instruction | Extra gas |
| ------------------------------------------------------------------------------- | --------- |
| [`RIST255_FROMHASH`](/blockchain-basics/tvm/instructions#f920-rist255_fromhash) | 600 |
| [`RIST255_VALIDATE`](/blockchain-basics/tvm/instructions#f921-rist255_validate) | 200 |
| [`RIST255_ADD`](/blockchain-basics/tvm/instructions#f922-rist255_add) | 600 |
| [`RIST255_MUL`](/blockchain-basics/tvm/instructions#f924-rist255_mul) | 2000 |
| [`RIST255_MULBASE`](/blockchain-basics/tvm/instructions#f925-rist255_mulbase) | 750 |
### Other instructions [#other-instructions]
[`ECRECOVER`](/blockchain-basics/tvm/instructions#f912-ecrecover) consumes 1500 extra gas.
`SECP256K1_XONLY_PUBKEY_TWEAK_ADD` consumes 1250 extra gas.
[`P256_CHKSIGNU`](/blockchain-basics/tvm/instructions#f914-p256_chksignu) and [`P256_CHKSIGNS`](/blockchain-basics/tvm/instructions#f915-p256_chksigns) consume 3500 extra gas.
### BLS [#bls]
#### Signature verification and aggregation [#signature-verification-and-aggregation]
| Instruction | Gas consumed | Notes |
| ----------------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------- |
| [`BLS_VERIFY`](/blockchain-basics/tvm/instructions#f93000-bls_verify) | `61000` | |
| [`BLS_AGGREGATE`](/blockchain-basics/tvm/instructions#f93001-bls_aggregate) | `-2650 + 4350 * n` | `n` is the number of signatures aggregated. |
| [`BLS_FASTAGGREGATEVERIFY`](/blockchain-basics/tvm/instructions#f93002-bls_fastaggregateverify) | `58000 + 3000 * n` | `n` is the number of public keys verified against one message/signature pair. |
| [`BLS_AGGREGATEVERIFY`](/blockchain-basics/tvm/instructions#f93003-bls_aggregateverify) | `38500 + 22500 * n` | `n` is the number of `(public key, message)` pairs checked against one signature. |
#### G1 group helpers [#g1-group-helpers]
| Instruction | Gas consumed |
| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| [`BLS_G1_ADD`](/blockchain-basics/tvm/instructions#f93010-bls_g1_add) / [`BLS_G1_SUB`](/blockchain-basics/tvm/instructions#f93011-bls_g1_sub) | `3900` |
| [`BLS_G1_NEG`](/blockchain-basics/tvm/instructions#f93012-bls_g1_neg) | `750` |
| [`BLS_G1_MUL`](/blockchain-basics/tvm/instructions#f93013-bls_g1_mul) | `5200` |
| [`BLS_MAP_TO_G1`](/blockchain-basics/tvm/instructions#f93016-bls_map_to_g1) | `2350` |
| [`BLS_G1_INGROUP`](/blockchain-basics/tvm/instructions#f93017-bls_g1_ingroup) | `2950` |
[`BLS_G1_MULTIEXP`](/blockchain-basics/tvm/instructions#f93014-bls_g1_multiexp) consumes `11375 + 630 * n + (8820 * n) / max(log₂ n, 4)` extra gas, where `n` is the number of `(point, scalar)` pairs.
Instructions [`BLS_G1_ZERO`](/blockchain-basics/tvm/instructions#f93015-bls_g1_zero) and [`BLS_G1_ISZERO`](/blockchain-basics/tvm/instructions#f93018-bls_g1_iszero) do not charge additional gas.
#### G2 group helpers [#g2-group-helpers]
| Instruction | Gas consumed |
| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| [`BLS_G2_ADD`](/blockchain-basics/tvm/instructions#f93020-bls_g2_add) / [`BLS_G2_SUB`](/blockchain-basics/tvm/instructions#f93021-bls_g2_sub) | `6100` |
| [`BLS_G2_NEG`](/blockchain-basics/tvm/instructions#f93022-bls_g2_neg) | `1550` |
| [`BLS_G2_MUL`](/blockchain-basics/tvm/instructions#f93023-bls_g2_mul) | `10550` |
| [`BLS_MAP_TO_G2`](/blockchain-basics/tvm/instructions#f93026-bls_map_to_g2) | `7950` |
| [`BLS_G2_INGROUP`](/blockchain-basics/tvm/instructions#f93027-bls_g2_ingroup) | `4250` |
[`BLS_G2_MULTIEXP`](/blockchain-basics/tvm/instructions#f93024-bls_g2_multiexp) consumes `30388 + 1280 * n + (22840 * n) / max(log₂ n, 4)` gas, where `n` is the number of `(point, scalar)` pairs.
Instructions [`BLS_G2_ZERO`](/blockchain-basics/tvm/instructions#f93025-bls_g2_zero) and [`BLS_G2_ISZERO`](/blockchain-basics/tvm/instructions#f93028-bls_g2_iszero) do not charge additional gas.
#### Pairing and constants [#pairing-and-constants]
| Instruction | Gas consumed | Notes |
| ----------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------- |
| [`BLS_PAIRING`](/blockchain-basics/tvm/instructions#f93030-bls_pairing) | `20000 + 11800 * n` | `n` is the number of `(G1, G2)` pairs supplied for the pairing product check. |
[`BLS_PUSHR`](/blockchain-basics/tvm/instructions#f93031-bls_pushr) do not charge additional gas.
## `GasLimits` structure [#gaslimits-structure]
TVM has inner structure `GasLimits` for gas manipulations. Its fields are:
* `gas_max`: the equivalent of contract's balance at the start of the compute phase in gas units.
* `gas_limit`: the amount of gas that can be consumed during the virtual machine execution. At the start of the execution, it equals:
* minimum of `gas_max` and the amount of gas that can be bought with the incoming message value (i.e., the amount of TON coins attached to the message) in the case of an internal message;
* `0` in the case of an external message.
* `gas_credit`: the amount of free gas that can be spent during the execution before accepting an external message. At the start of the execution, it equals:
* minimum of `gas_max` and corresponding value in configuration parameter `20` for masterchain and `21` for basechain in the case of an external message;
* `0` in the case of an internal message.
* `gas_remaining`: the amount of available but not spent gas. At the start of the execution, it equals `gas_limit + gas_credit`. It decreases after each instruction execution by the amount of gas consumed by the instruction.
* `gas_base`: an auxiliary parameter that is necessary for rebasing and shows the initial value of `gas_remaining`. At the start of the execution, it equals `gas_remaining`.
Instructions `SETGASLIMIT` and `ACCEPT` change all above values except `gas_max`:
* `SETGASLIMIT` sets `gas_limit` to the minimum of the indicated value and `gas_max`, `gas_credit` to zero, `gas_base` to the new `gas_limit`, and `gas_remaining` to `gas_remaining + (new gas_base - old gas_base)`.
* `ACCEPT` is equivalent to `SETGASLIMIT` with the new gas limit equal to `2**63 - 1` (the maximum value of a signed 64-bits integer).
The final value (in gas units) that will be deducted from contract's balance after the execution is `gas_base - gas_remaining`. Note that this value will be deducted if and only if after the execution `gas_credit` is zero, i.e. if `SETGASLIMIT` or `ACCEPT` was called at least once during the execution in the case of incoming external message. Without condition `gas_credit == 0`, there will be no commit of the new code and data.
# Get methods (/blockchain-basics/tvm/get-method)
Get methods are smart contract methods that are supposed to be executed off-chain. They are useful for structured retrieval of data from a smart contract ([`get_collection_data` get-method on an NFT collection](/blockchain-basics/standard/tokens/nft/nft-reference#return-collection-data)), and for any logic that is a part of a smart contract but is needed off-chain ([`get_nft_address_by_index` get-method on an NFT collection](/blockchain-basics/standard/tokens/nft/nft-reference#return-item-address-by-index)). Under the hood of APIs, this happens by fetching the actual state of the smart contract from the blockchain and executing TVM to get the result. This process is purely read-only and does not modify the blockchain state in any way.
## Defining [#defining]
Get methods are processed by the [function selector](/blockchain-basics/tvm/registers#c3-%E2%80%94-function-selector). By convention, the ID of a get method is calculated as `crc16("name") | 0x10000` where `name` is set by the developer. This simplifies practical usage because a human-readable name has to be used instead of some arbitrary number.
The algorithm used for hashing is CRC‑16/XMODEM (`poly=0x1021`, `init=0x0000`, `refin=false`, `refout=false`, `xorout=0x0000`).
A minimal example of a smart contract that has a get method that follows the ID convention:
```fift
"Asm.fif" include
<{
// The ID from the top of the stack is compared with 97865
97865 EQINT
// If ID != 97865, an 11 error is thrown by convention
11 THROWIFNOT
// Otherwise, 123 is pushed as the result
123 PUSHINT
}>s
```
But in practice, it is easier to use `PROGRAM{` from the Fift assembler that handles function selector logic.
```fift
"Asm.fif" include
PROGRAM{
DECLPROC main
// crc16("get_x") | 0x10000 = 97865
97865 DECLMETHOD get_x
main PROC:<{
}>
get_x PROC:<{
123 PUSHINT
}>
}END>s
```
The above is equivalent to the following Tolk code, which compiles to almost identical Fift code.
```tolk title="Tolk"
fun main() { }
get fun get_x(): int {
return 123;
}
```
## Executing [#executing]
In order to execute a get method, the actual state of the smart contract has to be fetched, and TVM has to be executed with [c7](/blockchain-basics/tvm/registers#c7-%E2%80%94-environment-information-and-global-variables) initialized and the desired parameters pushed on the stack.
### Local way [#local-way]
With all the required values known, it is possible to execute a get method completely locally. A minimal example that uses a placeholder c7 for simplicity, as it is only necessary when the get method uses data from it during execution:
```fift
"Asm.fif" include
// example code
// could also be defined as a constant cell without using assembly
PROGRAM{
DECLPROC main
97865 DECLMETHOD get_x
main PROC:<{
}>
get_x PROC:<{
123 PUSHINT
}>
}END>s constant code
// example data
// empty in this case
constant data
// example c7
// placeholder for simplicity
0 tuple 0x076ef1ea , 1 tuple constant c7
// execute method 97865
97865 code data c7 runvmctx .s
// result: 123 0 C{96A296D224F285C67BEE93C30F8A309157F0DAA35DC5B87E410B78630A09CFC7}
// where:
// 123 is the value returned by the get method
// 0 is the exit code
// C{...} is a new data cell
```
Note that if the get method uses some values from c7, for example with instructions such as `NOW` or `MYCODE`, the c7 tuple should be populated according to its [structure](/blockchain-basics/tvm/registers#c7-%E2%80%94-environment-information-and-global-variables).
### Decentralized way [#decentralized-way]
The process of fetching the actual contract state and initializing c7 can be handled by [liteserver](/blockchain-basics/nodes/overview) for easier execution. To execute a get method via liteserver, the request follows the [`liteServer.runSmcMethod` TL schema](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/tl/generate/scheme/lite_api.tl#L90).
In that request, `params:bytes` is a [BoC](/blockchain-basics/primitives/serialization/boc) of a serialized [`VmStack`](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/block/block.tlb#L891) object containing the stack with arguments.
The response follows the [liteServer.runMethodResult TL schema](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/tl/generate/scheme/lite_api.tl#L39). Apart from the values used for initialization and proofs, the result is included as `result:mode.2?bytes`, which is a BoC of a serialized `VmStack` object, similarly to the request.
An example execution via liteclient that handles serialization:
```text
runmethod UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI get_public_key
```
Result:
```text
arguments: [ 78748 ]
result: [ 37001869727465363790964079650574219024351072622925678701060821828351030750605 ]
```
### High-level API [#high-level-api]
The easiest path is using a high-level API, such as [TON Center](/applications/api/toncenter/introduction). It has a [`/api/v3/runGetMethod`](/applications/api/toncenter/v3/apiv2/run-get-method) endpoint that takes a smart contract address, a get method name, and arguments and returns the resulting stack. Example usage:
```bash
curl -X 'POST' \
'https://toncenter.com/api/v3/runGetMethod' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"address": "EQBG-g6ahkAUGWpefWbx-D_9sQ8oWbvy6puuq78U2c4NUDFS",
"method": "get_nft_address_by_index",
"stack": [
{
"type": "num",
"value": "123"
}
]
}'
```
The result for this call is presented below. The stack in this case contains a single cell element in BoC format.
```text
{
"gas_used": 4049,
"exit_code": 0,
"stack": [
{
"type": "cell",
"value": "te6cckEBAQEAJAAAQ4AVoN3BhVDLKet4AYoVxOHz8WkaFncQfg/M79YWJEV4pxDg5fQi"
}
]
}
```
# Initialization (/blockchain-basics/tvm/initialization)
## Initialization of `cc`, `cp`, and gas limits [#initialization-of-cc-cp-and-gas-limits]
* The original `cc`, current continuation, is initialized using the cell slice created from the `code` section of the smart contract. If the account is frozen or uninitialized, the code must be provided in the `init` field of the incoming message.
* The `cp`, current TVM codepage, is set to the default value of 0.
* The gas limit values are initialized based on the results of the [credit phase](/blockchain-basics/primitives/phases).
## Registers initialization [#registers-initialization]
For more info about registers, take a look at [Registers](/blockchain-basics/tvm/registers)
* `c0`: `Quit` — extraordinary continuation which terminates TVM with exit code `0`.
* `c1`: `Quit` — extraordinary continuation which terminates TVM with exit code `1`. Both exit codes `0` and `1` are considered successful terminations of TVM.
* `c2`: `ExcQuit` — extraordinary continuation which terminates TVM with an exception. In this case, the exit code is an exception number.
* `c3`: root cell of code currently executing in TVM.
* `c4`: root cell of account data.
* `c5`: empty cell.
* `c7`: `Tuple[Tuple[0x076ef1ea, 0, 0, ...]]`.
## Stack [#stack]
The contents of the stack depend on the event that triggered the transaction:
* Internal message
* External message
* Tick-tock
* Split prepare
* Merge install
* [Get method (off-chain)](/blockchain-basics/tvm/get-method)
The top of the stack is always the *function selector*, an *integer* that identifies the event that caused the transaction.
The following function selectors are defined:
| ID | Name | Description |
| -- | ----------------- | -------------------------------------------------- |
| 0 | onInternalMessage | Received an internal message |
| -1 | onExternalMessage | Received an external message |
| -2 | onRunTickTock | Received a tick-tock event |
| -3 | onSplitPrepare | Received a split prepare event (unimplemented yet) |
| -4 | onSplitInstall | Received a split install event (unimplemented yet) |
Get methods can have arbitrary IDs and should not overlap with the ones listed above.
### External/internal message [#externalinternal-message]
| Index | Name | Type | Description |
| ----- | ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `s0` | Function selector | `Integer` | `-1` for external messages, `0` for internal messages. |
| `s1` | Message body | `Slice` | This is an arbitrary payload of a message, which can be used for text comments (when sending TONs from one wallet to another) or for smart contract commands. |
| `s2` | Message | `Cell` | Cell containing message metadata (sender, receiver, amount) as well as message body. |
| `s3` | Message value | `Integer` | Amount of received nanotons (`0` for externals). |
| `s4` | Contract balance | `Integer` | Current account balance in nanotons. |
### Tick‑tock [#ticktock]
| Index | Name | Type | Description |
| ----- | ----------------- | ------- | ------------------------------------------------------ |
| `s0` | Function selector | Integer | `-2` for tick-tock transactions. |
| `s1` | Tick or tock? | Integer | `0` for tick transactions, `-1` for tock transactions. |
| `s2` | Account address | Integer | 256-bit raw account address (without workchain). |
| `s3` | Contract | Integer | Current account balance in nanotons. |
### Split/merge events [#splitmerge-events]
These events are not implemented yet. Possible stack layout for split/merge events is described in [TON Blockchain](/blockchain-basics/whitepapers/tblkch#4-4-8-processing-split-prepare-transactions) whitepaper. However, it is subject to change.
# Instructions (/blockchain-basics/tvm/instructions)
{/* STATIC_START tvm_instructions */}
#### `00` NOP [#00-nop]
Does nothing.
**Category:** Stack Basic (stack\_basic)
```fift Fift
NOP
```
#### `0i` XCHG\_0I [#0i-xchg_0i]
Interchanges `s0` with `s[i]`, `1 <= i <= 15`.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s[i] XCHG0
```
**Aliases**:
* `SWAP`
Same as `s1 XCHG0`.
#### `10ij` XCHG\_IJ [#10ij-xchg_ij]
Interchanges `s[i]` with `s[j]`, `1 <= i < j <= 15`.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s[i] s[j] XCHG
```
#### `11ii` XCHG\_0I\_LONG [#11ii-xchg_0i_long]
Interchanges `s0` with `s[ii]`, `0 <= ii <= 255`.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s0 [ii] s() XCHG
```
#### `1i` XCHG\_1I [#1i-xchg_1i]
Interchanges `s1` with `s[i]`, `2 <= i <= 15`.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s1 s[i] XCHG
```
#### `2i` PUSH [#2i-push]
Pushes a copy of the old `s[i]` into the stack.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s[i] PUSH
```
**Aliases**:
* `DUP`
Same as `s0 PUSH`.
* `OVER`
Same as `s1 PUSH`.
#### `3i` POP [#3i-pop]
Pops the old `s0` value into the old `s[i]`.
**Category:** Stack Basic (stack\_basic)
```fift Fift
s[i] POP
```
**Aliases**:
* `DROP`
Same as `s0 POP`, discards the top-of-stack value.
* `NIP`
Same as `s1 POP`.
#### `4ijk` XCHG3 [#4ijk-xchg3]
Equivalent to `s2 s[i] XCHG` `s1 s[j] XCHG` `s[k] XCHG0`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k] XCHG3
```
#### `50ij` XCHG2 [#50ij-xchg2]
Equivalent to `s1 s[i] XCHG` `s[j] XCHG0`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] XCHG2
```
#### `51ij` XCPU [#51ij-xcpu]
Equivalent to `s[i] XCHG0` `s[j] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] XCPU
```
#### `52ij` PUXC [#52ij-puxc]
Equivalent to `s[i] PUSH` `SWAP` `s[j] XCHG0`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j-1] PUXC
```
#### `53ij` PUSH2 [#53ij-push2]
Equivalent to `s[i] PUSH` `s[j+1] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] PUSH2
```
#### `540ijk` XCHG3\_ALT [#540ijk-xchg3_alt]
Long form of `XCHG3`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k] XCHG3_l
```
#### `541ijk` XC2PU [#541ijk-xc2pu]
Equivalent to `s[i] s[j] XCHG2` `s[k] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k] XC2PU
```
#### `542ijk` XCPUXC [#542ijk-xcpuxc]
Equivalent to `s1 s[i] XCHG` `s[j] s[k-1] PUXC`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k-1] XCPUXC
```
#### `543ijk` XCPU2 [#543ijk-xcpu2]
Equivalent to `s[i] XCHG0` `s[j] s[k] PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k] XCPU2
```
#### `544ijk` PUXC2 [#544ijk-puxc2]
Equivalent to `s[i] PUSH` `s2 XCHG0` `s[j] s[k] XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j-1] s[k-1] PUXC2
```
#### `545ijk` PUXCPU [#545ijk-puxcpu]
Equivalent to `s[i] s[j-1] PUXC` `s[k] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j-1] s[k-1] PUXCPU
```
#### `546ijk` PU2XC [#546ijk-pu2xc]
Equivalent to `s[i] PUSH` `SWAP` `s[j] s[k-1] PUXC`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j-1] s[k-2] PU2XC
```
#### `547ijk` PUSH3 [#547ijk-push3]
Equivalent to `s[i] PUSH` `s[j+1] s[k+1] PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
s[i] s[j] s[k] PUSH3
```
#### `55ij` BLKSWAP [#55ij-blkswap]
Permutes two blocks `s[j+i+1] ... s[j+1]` and `s[j] ... s0`. `0 <= i,j <= 15` Equivalent to `[i+1] [j+1] REVERSE` `[j+1] 0 REVERSE` `[i+j+2] 0 REVERSE`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
[i+1] [j+1] BLKSWAP
```
**Aliases**:
* `ROT2`
Rotates the three topmost pairs of stack entries.
* `ROLL`
Rotates the top `i+1` stack entries. Equivalent to `1 [i+1] BLKSWAP`.
* `ROLLREV`
Rotates the top `i+1` stack entries in the other direction. Equivalent to `[i+1] 1 BLKSWAP`.
#### `56ii` PUSH\_LONG [#56ii-push_long]
Pushes a copy of the old `s[ii]` into the stack. `0 <= ii <= 255`
**Category:** Stack Complex (stack\_complex)
```fift Fift
[ii] s() PUSH
```
#### `57ii` POP\_LONG [#57ii-pop_long]
Pops the old `s0` value into the old `s[ii]`. `0 <= ii <= 255`
**Category:** Stack Complex (stack\_complex)
```fift Fift
[ii] s() POP
```
#### `58` ROT [#58-rot]
Equivalent to `1 2 BLKSWAP` or to `s2 s1 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
ROT
```
#### `59` ROTREV [#59-rotrev]
Equivalent to `2 1 BLKSWAP` or to `s2 s2 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
ROTREV
-ROT
```
#### `5A` SWAP2 [#5a-swap2]
Equivalent to `2 2 BLKSWAP` or to `s3 s2 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
SWAP2
2SWAP
```
#### `5B` DROP2 [#5b-drop2]
Equivalent to `DROP` `DROP`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
DROP2
2DROP
```
#### `5C` DUP2 [#5c-dup2]
Equivalent to `s1 s0 PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
DUP2
2DUP
```
#### `5D` OVER2 [#5d-over2]
Equivalent to `s3 s2 PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
OVER2
2OVER
```
#### `5Eij` REVERSE [#5eij-reverse]
Reverses the order of `s[j+i+1] ... s[j]`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
[i+2] [j] REVERSE
```
#### `5F0i` BLKDROP [#5f0i-blkdrop]
Equivalent to `DROP` performed `i` times.
**Category:** Stack Complex (stack\_complex)
```fift Fift
[i] BLKDROP
```
#### `5Fij` BLKPUSH [#5fij-blkpush]
Equivalent to `PUSH s(j)` performed `i` times. `1 <= i <= 15`, `0 <= j <= 15`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
[i] [j] BLKPUSH
```
#### `60` PICK [#60-pick]
Pops integer `i` from the stack, then performs `s[i] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
PICK
PUSHX
```
#### `61` ROLLX [#61-rollx]
Pops integer `i` from the stack, then performs `1 [i] BLKSWAP`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
ROLLX
```
#### `62` -ROLLX [#62--rollx]
Pops integer `i` from the stack, then performs `[i] 1 BLKSWAP`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
-ROLLX
ROLLREVX
```
#### `63` BLKSWX [#63-blkswx]
Pops integers `i`,`j` from the stack, then performs `[i] [j] BLKSWAP`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
BLKSWX
```
#### `64` REVX [#64-revx]
Pops integers `i`,`j` from the stack, then performs `[i] [j] REVERSE`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
REVX
```
#### `65` DROPX [#65-dropx]
Pops integer `i` from the stack, then performs `[i] BLKDROP`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
DROPX
```
#### `66` TUCK [#66-tuck]
Equivalent to `SWAP` `OVER` or to `s1 s1 XCPU`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
TUCK
```
#### `67` XCHGX [#67-xchgx]
Pops integer `i` from the stack, then performs `s[i] XCHG`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
XCHGX
```
#### `68` DEPTH [#68-depth]
Pushes the current depth of the stack.
**Category:** Stack Complex (stack\_complex)
```fift Fift
DEPTH
```
#### `69` CHKDEPTH [#69-chkdepth]
Pops integer `i` from the stack, then checks whether there are at least `i` elements, generating a stack underflow exception otherwise.
**Category:** Stack Complex (stack\_complex)
```fift Fift
CHKDEPTH
```
#### `6A` ONLYTOPX [#6a-onlytopx]
Pops integer `i` from the stack, then removes all but the top `i` elements.
**Category:** Stack Complex (stack\_complex)
```fift Fift
ONLYTOPX
```
#### `6B` ONLYX [#6b-onlyx]
Pops integer `i` from the stack, then leaves only the bottom `i` elements. Approximately equivalent to `DEPTH` `SWAP` `SUB` `DROPX`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
ONLYX
```
#### `6Cij` BLKDROP2 [#6cij-blkdrop2]
Drops `i` stack elements under the top `j` elements. `1 <= i <= 15`, `0 <= j <= 15` Equivalent to `[i+j] 0 REVERSE` `[i] BLKDROP` `[j] 0 REVERSE`.
**Category:** Stack Complex (stack\_complex)
```fift Fift
[i] [j] BLKDROP2
```
#### `6D` NULL [#6d-null]
Pushes the only value of type *Null*.
**Category:** Tuple (tuple)
```fift Fift
NULL
PUSHNULL
```
**Aliases**:
* `NEWDICT`
Returns a new empty dictionary. It is an alternative mnemonics for `PUSHNULL`.
#### `6E` ISNULL [#6e-isnull]
Checks whether `x` is a *Null*, and returns `-1` or `0` accordingly.
**Category:** Tuple (tuple)
```fift Fift
ISNULL
```
**Aliases**:
* `DICTEMPTY`
Checks whether dictionary `D` is empty, and returns `-1` or `0` accordingly. It is an alternative mnemonics for `ISNULL`.
#### `6F0n` TUPLE [#6f0n-tuple]
Creates a new *Tuple* `t=(x_1, ... ,x_n)` containing `n` values `x_1`,..., `x_n`. `0 <= n <= 15`
**Category:** Tuple (tuple)
```fift Fift
[n] TUPLE
```
**Aliases**:
* `NIL`
Pushes the only *Tuple* `t=()` of length zero.
* `SINGLE`
Creates a singleton `t:=(x)`, i.e., a *Tuple* of length one.
* `PAIR`
Creates pair `t:=(x,y)`.
* `TRIPLE`
Creates triple `t:=(x,y,z)`.
#### `6F1k` INDEX [#6f1k-index]
Returns the `k`-th element of a *Tuple* `t`. `0 <= k <= 15`.
**Category:** Tuple (tuple)
```fift Fift
[k] INDEX
```
**Aliases**:
* `FIRST`
Returns the first element of a *Tuple*.
* `SECOND`
Returns the second element of a *Tuple*.
* `THIRD`
Returns the third element of a *Tuple*.
#### `6F2n` UNTUPLE [#6f2n-untuple]
Unpacks a *Tuple* `t=(x_1,...,x_n)` of length equal to `0 <= n <= 15`. If `t` is not a *Tuple*, or if `|t| != n`, a type check exception is thrown.
**Category:** Tuple (tuple)
```fift Fift
[n] UNTUPLE
```
**Aliases**:
* `UNSINGLE`
Unpacks a singleton `t=(x)`.
* `UNPAIR`
Unpacks a pair `t=(x,y)`.
* `UNTRIPLE`
Unpacks a triple `t=(x,y,z)`.
#### `6F3k` UNPACKFIRST [#6f3k-unpackfirst]
Unpacks first `0 <= k <= 15` elements of a *Tuple* `t`. If `|t|
**Category:** Tuple (tuple)
```fift Fift
[k] UNPACKFIRST
```
**Aliases**:
* `CHKTUPLE`
Checks whether `t` is a *Tuple*. If not, throws a type check exception.
#### `6F4n` EXPLODE [#6f4n-explode]
Unpacks a *Tuple* `t=(x_1,...,x_m)` and returns its length `m`, but only if `m <= n <= 15`. Otherwise throws a type check exception.
**Category:** Tuple (tuple)
```fift Fift
[n] EXPLODE
```
#### `6F5k` SETINDEX [#6f5k-setindex]
Computes *Tuple* `t'` that differs from `t` only at position `t'_{k+1}`, which is set to `x`. `0 <= k <= 15` If `k >= |t|`, throws a range check exception.
**Category:** Tuple (tuple)
```fift Fift
[k] SETINDEX
```
**Aliases**:
* `SETFIRST`
Sets the first component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
* `SETSECOND`
Sets the second component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
* `SETTHIRD`
Sets the third component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
#### `6F6k` INDEXQ [#6f6k-indexq]
Returns the `k`-th element of a *Tuple* `t`, where `0 <= k <= 15`. In other words, returns `x_{k+1}` if `t=(x_1,...,x_n)`. If `k>=n`, or if `t` is *Null*, returns a *Null* instead of `x`.
**Category:** Tuple (tuple)
```fift Fift
[k] INDEXQ
```
**Aliases**:
* `FIRSTQ`
Returns the first element of a *Tuple*.
* `SECONDQ`
Returns the second element of a *Tuple*.
* `THIRDQ`
Returns the third element of a *Tuple*.
#### `6F7k` SETINDEXQ [#6f7k-setindexq]
Sets the `k`-th component of *Tuple* `t` to `x`, where `0 <= k < 16`, and returns the resulting *Tuple* `t'`. If `|t| <= k`, first extends the original *Tuple* to length `n'=k+1` by setting all new components to *Null*. If the original value of `t` is *Null*, treats it as an empty *Tuple*. If `t` is not *Null* or *Tuple*, throws an exception. If `x` is *Null* and either `|t| <= k` or `t` is *Null*, then always returns `t'=t` (and does not consume tuple creation gas).
**Category:** Tuple (tuple)
```fift Fift
[k] SETINDEXQ
```
**Aliases**:
* `SETFIRSTQ`
Sets the first component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
* `SETSECONDQ`
Sets the second component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
* `SETTHIRDQ`
Sets the third component of *Tuple* `t` to `x` and returns the resulting *Tuple* `t'`.
#### `6F80` TUPLEVAR [#6f80-tuplevar]
Creates a new *Tuple* `t` of length `n` similarly to `TUPLE`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
TUPLEVAR
```
#### `6F81` INDEXVAR [#6f81-indexvar]
Similar to `k INDEX`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
INDEXVAR
```
#### `6F82` UNTUPLEVAR [#6f82-untuplevar]
Similar to `n UNTUPLE`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
UNTUPLEVAR
```
#### `6F83` UNPACKFIRSTVAR [#6f83-unpackfirstvar]
Similar to `n UNPACKFIRST`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
UNPACKFIRSTVAR
```
#### `6F84` EXPLODEVAR [#6f84-explodevar]
Similar to `n EXPLODE`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
EXPLODEVAR
```
#### `6F85` SETINDEXVAR [#6f85-setindexvar]
Similar to `k SETINDEX`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
SETINDEXVAR
```
#### `6F86` INDEXVARQ [#6f86-indexvarq]
Similar to `n INDEXQ`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
INDEXVARQ
```
#### `6F87` SETINDEXVARQ [#6f87-setindexvarq]
Similar to `k SETINDEXQ`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift Fift
SETINDEXVARQ
```
#### `6F88` TLEN [#6f88-tlen]
Returns the length of a *Tuple*.
**Category:** Tuple (tuple)
```fift Fift
TLEN
```
#### `6F89` QTLEN [#6f89-qtlen]
Similar to `TLEN`, but returns `-1` if `t` is not a *Tuple*.
**Category:** Tuple (tuple)
```fift Fift
QTLEN
```
#### `6F8A` ISTUPLE [#6f8a-istuple]
Returns `-1` or `0` depending on whether `t` is a *Tuple*.
**Category:** Tuple (tuple)
```fift Fift
ISTUPLE
```
#### `6F8B` LAST [#6f8b-last]
Returns the last element of a non-empty *Tuple* `t`.
**Category:** Tuple (tuple)
```fift Fift
LAST
```
#### `6F8C` TPUSH [#6f8c-tpush]
Appends a value `x` to a *Tuple* `t=(x_1,...,x_n)`, but only if the resulting *Tuple* `t'=(x_1,...,x_n,x)` is of length at most 255. Otherwise throws a type check exception.
**Category:** Tuple (tuple)
```fift Fift
TPUSH
COMMA
```
#### `6F8D` TPOP [#6f8d-tpop]
Detaches the last element `x=x_n` from a non-empty *Tuple* `t=(x_1,...,x_n)`, and returns both the resulting *Tuple* `t'=(x_1,...,x_{n-1})` and the original last element `x`.
**Category:** Tuple (tuple)
```fift Fift
TPOP
```
#### `6FA0` NULLSWAPIF [#6fa0-nullswapif]
Pushes a *Null* under the topmost *Integer* `x`, but only if `x!=0`.
**Category:** Tuple (tuple)
```fift Fift
NULLSWAPIF
```
#### `6FA1` NULLSWAPIFNOT [#6fa1-nullswapifnot]
Pushes a *Null* under the topmost *Integer* `x`, but only if `x=0`. May be used for stack alignment after quiet primitives such as `PLDUXQ`.
**Category:** Tuple (tuple)
```fift Fift
NULLSWAPIFNOT
```
#### `6FA2` NULLROTRIF [#6fa2-nullrotrif]
Pushes a *Null* under the second stack entry from the top, but only if the topmost *Integer* `y` is non-zero.
**Category:** Tuple (tuple)
```fift Fift
NULLROTRIF
```
#### `6FA3` NULLROTRIFNOT [#6fa3-nullrotrifnot]
Pushes a *Null* under the second stack entry from the top, but only if the topmost *Integer* `y` is zero. May be used for stack alignment after quiet primitives such as `LDUXQ`.
**Category:** Tuple (tuple)
```fift Fift
NULLROTRIFNOT
```
#### `6FA4` NULLSWAPIF2 [#6fa4-nullswapif2]
Pushes two nulls under the topmost *Integer* `x`, but only if `x!=0`. Equivalent to `NULLSWAPIF` `NULLSWAPIF`.
**Category:** Tuple (tuple)
```fift Fift
NULLSWAPIF2
```
#### `6FA5` NULLSWAPIFNOT2 [#6fa5-nullswapifnot2]
Pushes two nulls under the topmost *Integer* `x`, but only if `x=0`. Equivalent to `NULLSWAPIFNOT` `NULLSWAPIFNOT`.
**Category:** Tuple (tuple)
```fift Fift
NULLSWAPIFNOT2
```
#### `6FA6` NULLROTRIF2 [#6fa6-nullrotrif2]
Pushes two nulls under the second stack entry from the top, but only if the topmost *Integer* `y` is non-zero. Equivalent to `NULLROTRIF` `NULLROTRIF`.
**Category:** Tuple (tuple)
```fift Fift
NULLROTRIF2
```
#### `6FA7` NULLROTRIFNOT2 [#6fa7-nullrotrifnot2]
Pushes two nulls under the second stack entry from the top, but only if the topmost *Integer* `y` is zero. Equivalent to `NULLROTRIFNOT` `NULLROTRIFNOT`.
**Category:** Tuple (tuple)
```fift Fift
NULLROTRIFNOT2
```
#### `6FBij` INDEX2 [#6fbij-index2]
Recovers `x=(t_{i+1})_{j+1}` for `0 <= i,j <= 3`. Equivalent to `[i] INDEX` `[j] INDEX`.
**Category:** Tuple (tuple)
```fift Fift
[i] [j] INDEX2
```
**Aliases**:
* `CADR`
Recovers `x=(t_2)_1`.
* `CDDR`
Recovers `x=(t_2)_2`.
#### `6FE_ijk` INDEX3 [#6fe_ijk-index3]
Recovers `x=t_{i+1}_{j+1}_{k+1}`. `0 <= i,j,k <= 3` Equivalent to `[i] [j] INDEX2` `[k] INDEX`.
**Category:** Tuple (tuple)
```fift Fift
[i] [j] [k] INDEX3
```
**Aliases**:
* `CADDR`
Recovers `x=t_2_2_1`.
* `CDDDR`
Recovers `x=t_2_2_2`.
#### `7i` PUSHINT\_4 [#7i-pushint_4]
Pushes integer `x` into the stack. `-5 <= x <= 10`. Here `i` equals four lower-order bits of `x` (`i=x mod 16`).
**Category:** Const Int (const\_int)
```fift Fift
[x] PUSHINT
[x] INT
```
**Aliases**:
* `ZERO`
* `ONE`
* `TWO`
* `TEN`
* `TRUE`
#### `80xx` PUSHINT\_8 [#80xx-pushint_8]
Pushes integer `xx`. `-128 <= xx <= 127`.
**Category:** Const Int (const\_int)
```fift Fift
[xx] PUSHINT
[xx] INT
```
#### `81xxxx` PUSHINT\_16 [#81xxxx-pushint_16]
Pushes integer `xxxx`. `-2^15 <= xx < 2^15`.
**Category:** Const Int (const\_int)
```fift Fift
[xxxx] PUSHINT
[xxxx] INT
```
#### `82lxxx` PUSHINT\_LONG [#82lxxx-pushint_long]
Pushes integer `xxx`. *Details:* 5-bit `0 <= l <= 30` determines the length `n=8l+19` of signed big-endian integer `xxx`. The total length of this instruction is `l+4` bytes or `n+13=8l+32` bits.
**Category:** Const Int (const\_int)
```fift Fift
[xxx] PUSHINT
[xxx] INT
```
#### `83xx` PUSHPOW2 [#83xx-pushpow2]
(Quietly) pushes `2^(xx+1)` for `0 <= xx <= 255`. `2^256` is a `NaN`.
**Category:** Const Int (const\_int)
```fift Fift
[xx+1] PUSHPOW2
```
#### `83FF` PUSHNAN [#83ff-pushnan]
Pushes a `NaN`.
**Category:** Const Int (const\_int)
```fift Fift
PUSHNAN
```
#### `84xx` PUSHPOW2DEC [#84xx-pushpow2dec]
Pushes `2^(xx+1)-1` for `0 <= xx <= 255`.
**Category:** Const Int (const\_int)
```fift Fift
[xx+1] PUSHPOW2DEC
```
#### `85xx` PUSHNEGPOW2 [#85xx-pushnegpow2]
Pushes `-2^(xx+1)` for `0 <= xx <= 255`.
**Category:** Const Int (const\_int)
```fift Fift
[xx+1] PUSHNEGPOW2
```
#### `88` PUSHREF [#88-pushref]
Pushes the reference `ref` into the stack. *Details:* Pushes the first reference of `cc.code` into the stack as a *Cell* (and removes this reference from the current continuation).
**Category:** Const Data (const\_data)
```fift Fift
[ref] PUSHREF
```
#### `89` PUSHREFSLICE [#89-pushrefslice]
Similar to `PUSHREF`, but converts the cell into a *Slice*.
**Category:** Const Data (const\_data)
```fift Fift
[ref] PUSHREFSLICE
```
#### `8A` PUSHREFCONT [#8a-pushrefcont]
Similar to `PUSHREFSLICE`, but makes a simple ordinary *Continuation* out of the cell.
**Category:** Const Data (const\_data)
```fift Fift
[ref] PUSHREFCONT
```
#### `8Bxsss` PUSHSLICE [#8bxsss-pushslice]
Pushes the slice `slice` into the stack. *Details:* Pushes the (prefix) subslice of `cc.code` consisting of its first `8x+4` bits and no references (i.e., essentially a bitstring), where `0 <= x <= 15`. A completion tag is assumed, meaning that all trailing zeroes and the last binary one (if present) are removed from this bitstring. If the original bitstring consists only of zeroes, an empty slice will be pushed.
**Category:** Const Data (const\_data)
```fift Fift
[slice] PUSHSLICE
[slice] SLICE
```
#### `8Crxxssss` PUSHSLICE\_REFS [#8crxxssss-pushslice_refs]
Pushes the slice `slice` into the stack. *Details:* Pushes the (prefix) subslice of `cc.code` consisting of its first `1 <= r+1 <= 4` references and up to first `8xx+1` bits of data, with `0 <= xx <= 31`. A completion tag is also assumed.
**Category:** Const Data (const\_data)
```fift Fift
[slice] PUSHSLICE
[slice] SLICE
```
#### `8Drxxsssss` PUSHSLICE\_LONG [#8drxxsssss-pushslice_long]
Pushes the slice `slice` into the stack. *Details:* Pushes the subslice of `cc.code` consisting of `0 <= r <= 4` references and up to `8xx+6` bits of data, with `0 <= xx <= 127`. A completion tag is assumed.
**Category:** Const Data (const\_data)
```fift Fift
[slice] PUSHSLICE
[slice] SLICE
```
#### `8F_rxxcccc` PUSHCONT [#8f_rxxcccc-pushcont]
Pushes a continuation made from `builder`. *Details:* Pushes the simple ordinary continuation `cccc` made from the first `0 <= r <= 3` references and the first `0 <= xx <= 127` bytes of `cc.code`.
**Category:** Const Data (const\_data)
```fift Fift
[builder] PUSHCONT
[builder] CONT
```
#### `9xccc` PUSHCONT\_SHORT [#9xccc-pushcont_short]
Pushes a continuation made from `builder`. *Details:* Pushes an `x`-byte continuation for `0 <= x <= 15`.
**Category:** Const Data (const\_data)
```fift Fift
[builder] PUSHCONT
[builder] CONT
```
#### `A0` ADD [#a0-add]
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
ADD
```
#### `A1` SUB [#a1-sub]
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
SUB
```
#### `A2` SUBR [#a2-subr]
Equivalent to `SWAP` `SUB`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
SUBR
```
#### `A3` NEGATE [#a3-negate]
Equivalent to `-1 MULCONST` or to `ZERO SUBR`. Notice that it triggers an integer overflow exception if `x=-2^256`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
NEGATE
```
#### `A4` INC [#a4-inc]
Equivalent to `1 ADDCONST`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
INC
```
#### `A5` DEC [#a5-dec]
Equivalent to `-1 ADDCONST`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
DEC
```
#### `A6cc` ADDCONST [#a6cc-addconst]
`-128 <= cc <= 127`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
[cc] ADDCONST
[cc] ADDINT
[-cc] SUBCONST
[-cc] SUBINT
```
#### `A7cc` MULCONST [#a7cc-mulconst]
`-128 <= cc <= 127`.
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
[cc] MULCONST
[cc] MULINT
```
#### `A8` MUL [#a8-mul]
**Category:** Arithm Basic (arithm\_basic)
```fift Fift
MUL
```
#### `A900` ADDDIVMOD [#a900-adddivmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDDIVMOD
```
#### `A901` ADDDIVMODR [#a901-adddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDDIVMODR
```
#### `A902` ADDDIVMODC [#a902-adddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDDIVMODC
```
#### `A904` DIV [#a904-div]
`q=floor(x/y)`, `r=x-y*q`
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIV
```
#### `A905` DIVR [#a905-divr]
`q'=round(x/y)`, `r'=x-y*q'`
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIVR
```
#### `A906` DIVC [#a906-divc]
`q''=ceil(x/y)`, `r''=x-y*q''`
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIVC
```
#### `A908` MOD [#a908-mod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MOD
```
#### `A909` MODR [#a909-modr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MODR
```
#### `A90A` MODC [#a90a-modc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MODC
```
#### `A90C` DIVMOD [#a90c-divmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIVMOD
```
#### `A90D` DIVMODR [#a90d-divmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIVMODR
```
#### `A90E` DIVMODC [#a90e-divmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
DIVMODC
```
#### `A920` ADDRSHIFTMOD\_VAR [#a920-addrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDRSHIFTMOD
```
#### `A921` ADDRSHIFTMODR [#a921-addrshiftmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDRSHIFTMODR
```
#### `A922` ADDRSHIFTMODC [#a922-addrshiftmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
ADDRSHIFTMODC
```
#### `A925` RSHIFTR\_VAR [#a925-rshiftr_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
RSHIFTR
```
#### `A926` RSHIFTC\_VAR [#a926-rshiftc_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
RSHIFTC
```
#### `A928` MODPOW2\_VAR [#a928-modpow2_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MODPOW2
```
#### `A929` MODPOW2R\_VAR [#a929-modpow2r_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MODPOW2R
```
#### `A92A` MODPOW2C\_VAR [#a92a-modpow2c_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MODPOW2C
```
#### `A92C` RSHIFTMOD\_VAR [#a92c-rshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
RSHIFTMOD
```
#### `A92D` RSHIFTMODR\_VAR [#a92d-rshiftmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
RSHIFTMODR
```
#### `A92E` RSHIFTMODC\_VAR [#a92e-rshiftmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
RSHIFTMODC
```
#### `A930tt` ADDRSHIFTMOD [#a930tt-addrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] ADDRSHIFT#MOD
```
#### `A931tt` ADDRSHIFTRMOD [#a931tt-addrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] ADDRSHIFTR#MOD
```
#### `A932tt` ADDRSHIFTCMOD [#a932tt-addrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] ADDRSHIFTC#MOD
```
#### `A935tt` RSHIFTR [#a935tt-rshiftr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] RSHIFTR#
```
#### `A936tt` RSHIFTC [#a936tt-rshiftc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] RSHIFTC#
```
#### `A938tt` MODPOW2 [#a938tt-modpow2]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MODPOW2#
```
#### `A939tt` MODPOW2R [#a939tt-modpow2r]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MODPOW2R#
```
#### `A93Att` MODPOW2C [#a93att-modpow2c]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MODPOW2C#
```
#### `A93Ctt` RSHIFTMOD [#a93ctt-rshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] RSHIFT#MOD
```
#### `A93Dtt` RSHIFTRMOD [#a93dtt-rshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] RSHIFTR#MOD
```
#### `A93Ett` RSHIFTCMOD [#a93ett-rshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] RSHIFTC#MOD
```
#### `A980` MULADDDIVMOD [#a980-muladddivmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDDIVMOD
```
#### `A981` MULADDDIVMODR [#a981-muladddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDDIVMODR
```
#### `A982` MULADDDIVMODC [#a982-muladddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDDIVMODC
```
#### `A984` MULDIV [#a984-muldiv]
`q=floor(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIV
```
#### `A985` MULDIVR [#a985-muldivr]
`q'=round(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIVR
```
#### `A986` MULDIVC [#a986-muldivc]
`q'=ceil(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIVC
```
#### `A988` MULMOD [#a988-mulmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMOD
```
#### `A989` MULMODR [#a989-mulmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMODR
```
#### `A98A` MULMODC [#a98a-mulmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMODC
```
#### `A98C` MULDIVMOD [#a98c-muldivmod]
`q=floor(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIVMOD
```
#### `A98D` MULDIVMODR [#a98d-muldivmodr]
`q=round(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIVMODR
```
#### `A98E` MULDIVMODC [#a98e-muldivmodc]
`q=ceil(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULDIVMODC
```
#### `A9A0` MULADDRSHIFTMOD\_VAR [#a9a0-muladdrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDRSHIFTMOD
```
#### `A9A1` MULADDRSHIFTRMOD\_VAR [#a9a1-muladdrshiftrmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDRSHIFTRMOD
```
#### `A9A2` MULADDRSHIFTCMOD\_VAR [#a9a2-muladdrshiftcmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULADDRSHIFTCMOD
```
#### `A9A4` MULRSHIFT\_VAR [#a9a4-mulrshift_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFT
```
#### `A9A5` MULRSHIFTR\_VAR [#a9a5-mulrshiftr_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTR
```
#### `A9A6` MULRSHIFTC\_VAR [#a9a6-mulrshiftc_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTC
```
#### `A9A8` MULMODPOW2\_VAR [#a9a8-mulmodpow2_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMODPOW2_VAR
```
#### `A9A9` MULMODPOW2R\_VAR [#a9a9-mulmodpow2r_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMODPOW2R_VAR
```
#### `A9AA` MULMODPOW2C\_VAR [#a9aa-mulmodpow2c_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULMODPOW2C_VAR
```
#### `A9AC` MULRSHIFTMOD\_VAR [#a9ac-mulrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTMOD_VAR
```
#### `A9AD` MULRSHIFTRMOD\_VAR [#a9ad-mulrshiftrmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTRMOD_VAR
```
#### `A9AE` MULRSHIFTCMOD\_VAR [#a9ae-mulrshiftcmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTCMOD_VAR
```
#### `A9B0tt` MULADDRSHIFTMOD [#a9b0tt-muladdrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULADDRSHIFT#MOD
```
#### `A9B1tt` MULADDRSHIFTRMOD [#a9b1tt-muladdrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULADDRSHIFTR#MOD
```
#### `A9B2tt` MULADDRSHIFTCMOD [#a9b2tt-muladdrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULADDRSHIFTC#MOD
```
#### `A9B4tt` MULRSHIFT [#a9b4tt-mulrshift]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULRSHIFT#
```
#### `A9B5tt` MULRSHIFTR [#a9b5tt-mulrshiftr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULRSHIFTR#
```
#### `A9B6tt` MULRSHIFTC [#a9b6tt-mulrshiftc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULRSHIFTC#
```
#### `A9B8tt` MULMODPOW2 [#a9b8tt-mulmodpow2]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULMODPOW2#
```
#### `A9B9tt` MULMODPOW2R [#a9b9tt-mulmodpow2r]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULMODPOW2R#
```
#### `A9BAtt` MULMODPOW2C [#a9batt-mulmodpow2c]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] MULMODPOW2C#
```
#### `A9BC` MULRSHIFTMOD [#a9bc-mulrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFT#MOD
```
#### `A9BD` MULRSHIFTRMOD [#a9bd-mulrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTR#MOD
```
#### `A9BE` MULRSHIFTCMOD [#a9be-mulrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
MULRSHIFTC#MOD
```
#### `A9C0` LSHIFTADDDIVMOD\_VAR [#a9c0-lshiftadddivmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTADDDIVMOD
```
#### `A9C1` LSHIFTADDDIVMODR\_VAR [#a9c1-lshiftadddivmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTADDDIVMODR
```
#### `A9C2` LSHIFTADDDIVMODC\_VAR [#a9c2-lshiftadddivmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTADDDIVMODC
```
#### `A9C4` LSHIFTDIV\_VAR [#a9c4-lshiftdiv_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIV
```
#### `A9C5` LSHIFTDIVR\_VAR [#a9c5-lshiftdivr_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIVR
```
#### `A9C6` LSHIFTDIVC\_VAR [#a9c6-lshiftdivc_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIVC
```
#### `A9C8` LSHIFTMOD\_VAR [#a9c8-lshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTMOD
```
#### `A9C9` LSHIFTMODR\_VAR [#a9c9-lshiftmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTMODR
```
#### `A9CA` LSHIFTMODC\_VAR [#a9ca-lshiftmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTMODC
```
#### `A9CC` LSHIFTDIVMOD\_VAR [#a9cc-lshiftdivmod_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIVMOD
```
#### `A9CD` LSHIFTDIVMODR\_VAR [#a9cd-lshiftdivmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIVMODR
```
#### `A9CE` LSHIFTDIVMODC\_VAR [#a9ce-lshiftdivmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift Fift
LSHIFTDIVMODC
```
#### `A9D0tt` LSHIFTADDDIVMOD [#a9d0tt-lshiftadddivmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#ADDDIVMOD
```
#### `A9D1tt` LSHIFTADDDIVMODR [#a9d1tt-lshiftadddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#ADDDIVMODR
```
#### `A9D2tt` LSHIFTADDDIVMODC [#a9d2tt-lshiftadddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#ADDDIVMODC
```
#### `A9D4tt` LSHIFTDIV [#a9d4tt-lshiftdiv]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIV
```
#### `A9D5tt` LSHIFTDIVR [#a9d5tt-lshiftdivr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIVR
```
#### `A9D6tt` LSHIFTDIVC [#a9d6tt-lshiftdivc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIVC
```
#### `A9D8tt` LSHIFTMOD [#a9d8tt-lshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#MOD
```
#### `A9D9tt` LSHIFTMODR [#a9d9tt-lshiftmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#MODR
```
#### `A9DAtt` LSHIFTMODC [#a9datt-lshiftmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#MODC
```
#### `A9DCtt` LSHIFTDIVMOD [#a9dctt-lshiftdivmod]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIVMOD
```
#### `A9DDtt` LSHIFTDIVMODR [#a9ddtt-lshiftdivmodr]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIVMODR
```
#### `A9DEtt` LSHIFTDIVMODC [#a9dett-lshiftdivmodc]
**Category:** Arithm Div (arithm\_div)
```fift Fift
[tt+1] LSHIFT#DIVMODC
```
#### `AAcc` LSHIFT [#aacc-lshift]
`0 <= cc <= 255`
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
[cc+1] LSHIFT#
```
#### `ABcc` RSHIFT [#abcc-rshift]
`0 <= cc <= 255`
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
[cc+1] RSHIFT#
```
#### `AC` LSHIFT\_VAR [#ac-lshift_var]
`0 <= y <= 1023`
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
LSHIFT
```
#### `AD` RSHIFT\_VAR [#ad-rshift_var]
`0 <= y <= 1023`
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
RSHIFT
```
#### `AE` POW2 [#ae-pow2]
`0 <= y <= 1023` Equivalent to `ONE` `SWAP` `LSHIFT`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
POW2
```
#### `B0` AND [#b0-and]
Bitwise and of two signed integers `x` and `y`, sign-extended to infinity.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
AND
```
#### `B1` OR [#b1-or]
Bitwise or of two integers.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
OR
```
#### `B2` XOR [#b2-xor]
Bitwise xor of two integers.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
XOR
```
#### `B3` NOT [#b3-not]
Bitwise not of an integer.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
NOT
```
#### `B4cc` FITS [#b4cc-fits]
Checks whether `x` is a `cc+1`-bit signed integer for `0 <= cc <= 255` (i.e., whether `-2^cc <= x < 2^cc`). If not, either triggers an integer overflow exception, or replaces `x` with a `NaN` (quiet version).
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
[cc+1] FITS
```
**Aliases**:
* `CHKBOOL`
Checks whether `x` is a ''boolean value'' (i.e., either 0 or -1).
#### `B5cc` UFITS [#b5cc-ufits]
Checks whether `x` is a `cc+1`-bit unsigned integer for `0 <= cc <= 255` (i.e., whether `0 <= x < 2^(cc+1)`).
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
[cc+1] UFITS
```
**Aliases**:
* `CHKBIT`
Checks whether `x` is a binary digit (i.e., zero or one).
#### `B600` FITSX [#b600-fitsx]
Checks whether `x` is a `c`-bit signed integer for `0 <= c <= 1023`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
FITSX
```
#### `B601` UFITSX [#b601-ufitsx]
Checks whether `x` is a `c`-bit unsigned integer for `0 <= c <= 1023`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
UFITSX
```
#### `B602` BITSIZE [#b602-bitsize]
Computes smallest `c >= 0` such that `x` fits into a `c`-bit signed integer (`-2^(c-1) <= c < 2^(c-1)`).
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
BITSIZE
```
#### `B603` UBITSIZE [#b603-ubitsize]
Computes smallest `c >= 0` such that `x` fits into a `c`-bit unsigned integer (`0 <= x < 2^c`), or throws a range check exception.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
UBITSIZE
```
#### `B608` MIN [#b608-min]
Computes the minimum of two integers `x` and `y`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
MIN
```
#### `B609` MAX [#b609-max]
Computes the maximum of two integers `x` and `y`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
MAX
```
#### `B60A` MINMAX [#b60a-minmax]
Sorts two integers. Quiet version of this operation returns two `NaN`s if any of the arguments are `NaN`s.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
MINMAX
INTSORT2
```
#### `B60B` ABS [#b60b-abs]
Computes the absolute value of an integer `x`.
**Category:** Arithm Logical (arithm\_logical)
```fift Fift
ABS
```
#### `B7A0` QADD [#b7a0-qadd]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADD
```
#### `B7A1` QSUB [#b7a1-qsub]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QSUB
```
#### `B7A2` QSUBR [#b7a2-qsubr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QSUBR
```
#### `B7A3` QNEGATE [#b7a3-qnegate]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QNEGATE
```
#### `B7A4` QINC [#b7a4-qinc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QINC
```
#### `B7A5` QDEC [#b7a5-qdec]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDEC
```
#### `B7A8` QMUL [#b7a8-qmul]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMUL
```
#### `B7A900` QADDDIVMOD [#b7a900-qadddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDDIVMOD
```
#### `B7A901` QADDDIVMODR [#b7a901-qadddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDDIVMODR
```
#### `B7A902` QADDDIVMODC [#b7a902-qadddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDDIVMODC
```
#### `B7A904` QDIV [#b7a904-qdiv]
Division returns `NaN` if `y=0`.
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIV
```
#### `B7A905` QDIVR [#b7a905-qdivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIVR
```
#### `B7A906` QDIVC [#b7a906-qdivc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIVC
```
#### `B7A908` QMOD [#b7a908-qmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMOD
```
#### `B7A909` QMODR [#b7a909-qmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMODR
```
#### `B7A90A` QMODC [#b7a90a-qmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMODC
```
#### `B7A90C` QDIVMOD [#b7a90c-qdivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIVMOD
```
#### `B7A90D` QDIVMODR [#b7a90d-qdivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIVMODR
```
#### `B7A90E` QDIVMODC [#b7a90e-qdivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QDIVMODC
```
#### `B7A920` QADDRSHIFTMOD [#b7a920-qaddrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDRSHIFTMOD
```
#### `B7A921` QADDRSHIFTMODR [#b7a921-qaddrshiftmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDRSHIFTMODR
```
#### `B7A922` QADDRSHIFTMODC [#b7a922-qaddrshiftmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QADDRSHIFTMODC
```
#### `B7A925` QRSHIFTR\_VAR [#b7a925-qrshiftr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFTR
```
#### `B7A926` QRSHIFTC\_VAR [#b7a926-qrshiftc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFTC
```
#### `B7A928` QMODPOW2\_VAR [#b7a928-qmodpow2_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMODPOW2
```
#### `B7A929` QMODPOW2R\_VAR [#b7a929-qmodpow2r_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMODPOW2R
```
#### `B7A92A` QMODPOW2C\_VAR [#b7a92a-qmodpow2c_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMODPOW2C
```
#### `B7A92C` QRSHIFTMOD\_VAR [#b7a92c-qrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFTMOD
```
#### `B7A92D` QRSHIFTMODR\_VAR [#b7a92d-qrshiftmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFTMODR
```
#### `B7A92E` QRSHIFTMODC\_VAR [#b7a92e-qrshiftmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFTMODC
```
#### `B7A930tt` QADDRSHIFTMOD [#b7a930tt-qaddrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QADDRSHIFT#MOD
```
#### `B7A931tt` QADDRSHIFTRMOD [#b7a931tt-qaddrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QADDRSHIFTR#MOD
```
#### `B7A932tt` QADDRSHIFTCMOD [#b7a932tt-qaddrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QADDRSHIFTC#MOD
```
#### `B7A935tt` QRSHIFTR [#b7a935tt-qrshiftr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QRSHIFTR#
```
#### `B7A936tt` QRSHIFTC [#b7a936tt-qrshiftc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QRSHIFTC#
```
#### `B7A938tt` QMODPOW2 [#b7a938tt-qmodpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMODPOW2#
```
#### `B7A939tt` QMODPOW2R [#b7a939tt-qmodpow2r]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMODPOW2R#
```
#### `B7A93Att` QMODPOW2C [#b7a93att-qmodpow2c]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMODPOW2C#
```
#### `B7A93Ctt` QRSHIFTMOD [#b7a93ctt-qrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QRSHIFT#MOD
```
#### `B7A93Dtt` QRSHIFTRMOD [#b7a93dtt-qrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QRSHIFTR#MOD
```
#### `B7A93Ett` QRSHIFTCMOD [#b7a93ett-qrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QRSHIFTC#MOD
```
#### `B7A980` QMULADDDIVMOD [#b7a980-qmuladddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDDIVMOD
```
#### `B7A981` QMULADDDIVMODR [#b7a981-qmuladddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDDIVMODR
```
#### `B7A982` QMULADDDIVMODC [#b7a982-qmuladddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDDIVMODC
```
#### `B7A984` QMULDIV [#b7a984-qmuldiv]
`q=floor(x*y/z)`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIV
```
#### `B7A985` QMULDIVR [#b7a985-qmuldivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIVR
```
#### `B7A986` QMULDIVC [#b7a986-qmuldivc]
`q'=ceil(x*y/z)`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIVC
```
#### `B7A988` QMULMOD [#b7a988-qmulmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMOD
```
#### `B7A989` QMULMODR [#b7a989-qmulmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMODR
```
#### `B7A98A` QMULMODC [#b7a98a-qmulmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMODC
```
#### `B7A98C` QMULDIVMOD [#b7a98c-qmuldivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIVMOD
```
#### `B7A98D` QMULDIVMODR [#b7a98d-qmuldivmodr]
`q=round(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIVMODR
```
#### `B7A98E` QMULDIVMODC [#b7a98e-qmuldivmodc]
`q=ceil(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULDIVMODC
```
#### `B7A9A0` QMULADDRSHIFTMOD\_VAR [#b7a9a0-qmuladdrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDRSHIFTMOD
```
#### `B7A9A1` QMULADDRSHIFTRMOD\_VAR [#b7a9a1-qmuladdrshiftrmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDRSHIFTRMOD
```
#### `B7A9A2` QMULADDRSHIFTCMOD\_VAR [#b7a9a2-qmuladdrshiftcmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULADDRSHIFTCMOD
```
#### `B7A9A4` QMULRSHIFT\_VAR [#b7a9a4-qmulrshift_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFT
```
#### `B7A9A5` QMULRSHIFTR\_VAR [#b7a9a5-qmulrshiftr_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTR
```
#### `B7A9A6` QMULRSHIFTC\_VAR [#b7a9a6-qmulrshiftc_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTC
```
#### `B7A9A8` QMULMODPOW2\_VAR [#b7a9a8-qmulmodpow2_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMODPOW2_VAR
```
#### `B7A9A9` QMULMODPOW2R\_VAR [#b7a9a9-qmulmodpow2r_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMODPOW2R_VAR
```
#### `B7A9AA` QMULMODPOW2C\_VAR [#b7a9aa-qmulmodpow2c_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULMODPOW2C_VAR
```
#### `B7A9AC` QMULRSHIFTMOD\_VAR [#b7a9ac-qmulrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTMOD_VAR
```
#### `B7A9AD` QMULRSHIFTRMOD\_VAR [#b7a9ad-qmulrshiftrmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTRMOD_VAR
```
#### `B7A9AE` QMULRSHIFTCMOD\_VAR [#b7a9ae-qmulrshiftcmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTCMOD_VAR
```
#### `B7A9B0tt` QMULADDRSHIFTMOD [#b7a9b0tt-qmuladdrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULADDRSHIFT#MOD
```
#### `B7A9B1tt` QMULADDRSHIFTRMOD [#b7a9b1tt-qmuladdrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULADDRSHIFTR#MOD
```
#### `B7A9B2tt` QMULADDRSHIFTCMOD [#b7a9b2tt-qmuladdrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULADDRSHIFTC#MOD
```
#### `B7A9B4tt` QMULRSHIFT [#b7a9b4tt-qmulrshift]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULRSHIFT#
```
#### `B7A9B5tt` QMULRSHIFTR [#b7a9b5tt-qmulrshiftr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULRSHIFTR#
```
#### `B7A9B6tt` QMULRSHIFTC [#b7a9b6tt-qmulrshiftc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULRSHIFTC#
```
#### `B7A9B8tt` QMULMODPOW2 [#b7a9b8tt-qmulmodpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULMODPOW2#
```
#### `B7A9B9tt` QMULMODPOW2R [#b7a9b9tt-qmulmodpow2r]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULMODPOW2R#
```
#### `B7A9BAtt` QMULMODPOW2C [#b7a9batt-qmulmodpow2c]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QMULMODPOW2C#
```
#### `B7A9BC` QMULRSHIFTMOD [#b7a9bc-qmulrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFT#MOD
```
#### `B7A9BD` QMULRSHIFTRMOD [#b7a9bd-qmulrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTR#MOD
```
#### `B7A9BE` QMULRSHIFTCMOD [#b7a9be-qmulrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QMULRSHIFTC#MOD
```
#### `B7A9C0` QLSHIFTADDDIVMOD\_VAR [#b7a9c0-qlshiftadddivmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTADDDIVMOD
```
#### `B7A9C1` QLSHIFTADDDIVMODR\_VAR [#b7a9c1-qlshiftadddivmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTADDDIVMODR
```
#### `B7A9C2` QLSHIFTADDDIVMODC\_VAR [#b7a9c2-qlshiftadddivmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTADDDIVMODC
```
#### `B7A9C4` QLSHIFTDIV\_VAR [#b7a9c4-qlshiftdiv_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIV
```
#### `B7A9C5` QLSHIFTDIVR\_VAR [#b7a9c5-qlshiftdivr_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIVR
```
#### `B7A9C6` QLSHIFTDIVC\_VAR [#b7a9c6-qlshiftdivc_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIVC
```
#### `B7A9C8` QLSHIFTMOD\_VAR [#b7a9c8-qlshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTMOD
```
#### `B7A9C9` QLSHIFTMODR\_VAR [#b7a9c9-qlshiftmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTMODR
```
#### `B7A9CA` QLSHIFTMODC\_VAR [#b7a9ca-qlshiftmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTMODC
```
#### `B7A9CC` QLSHIFTDIVMOD\_VAR [#b7a9cc-qlshiftdivmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIVMOD
```
#### `B7A9CD` QLSHIFTDIVMODR\_VAR [#b7a9cd-qlshiftdivmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIVMODR
```
#### `B7A9CE` QLSHIFTDIVMODC\_VAR [#b7a9ce-qlshiftdivmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFTDIVMODC
```
#### `B7A9D0tt` QLSHIFTADDDIVMOD [#b7a9d0tt-qlshiftadddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#ADDDIVMOD
```
#### `B7A9D1tt` QLSHIFTADDDIVMODR [#b7a9d1tt-qlshiftadddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#ADDDIVMODR
```
#### `B7A9D2tt` QLSHIFTADDDIVMODC [#b7a9d2tt-qlshiftadddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#ADDDIVMODC
```
#### `B7A9D4tt` QLSHIFTDIV [#b7a9d4tt-qlshiftdiv]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIV
```
#### `B7A9D5tt` QLSHIFTDIVR [#b7a9d5tt-qlshiftdivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIVR
```
#### `B7A9D6tt` QLSHIFTDIVC [#b7a9d6tt-qlshiftdivc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIVC
```
#### `B7A9D8tt` QLSHIFTMOD [#b7a9d8tt-qlshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#MOD
```
#### `B7A9D9tt` QLSHIFTMODR [#b7a9d9tt-qlshiftmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#MODR
```
#### `B7A9DAtt` QLSHIFTMODC [#b7a9datt-qlshiftmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#MODC
```
#### `B7A9DCtt` QLSHIFTDIVMOD [#b7a9dctt-qlshiftdivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIVMOD
```
#### `B7A9DDtt` QLSHIFTDIVMODR [#b7a9ddtt-qlshiftdivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIVMODR
```
#### `B7A9DEtt` QLSHIFTDIVMODC [#b7a9dett-qlshiftdivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[tt+1] QLSHIFT#DIVMODC
```
#### `B7AAcc` QLSHIFT [#b7aacc-qlshift]
`0 <= cc <= 255`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[cc+1] QLSHIFT#
```
#### `B7ABcc` QRSHIFT [#b7abcc-qrshift]
`0 <= cc <= 255`
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[cc+1] QRSHIFT#
```
#### `B7AC` QLSHIFT\_VAR [#b7ac-qlshift_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QLSHIFT
```
#### `B7AD` QRSHIFT\_VAR [#b7ad-qrshift_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QRSHIFT
```
#### `B7AE` QPOW2 [#b7ae-qpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QPOW2
```
#### `B7B0` QAND [#b7b0-qand]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QAND
```
#### `B7B1` QOR [#b7b1-qor]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QOR
```
#### `B7B2` QXOR [#b7b2-qxor]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QXOR
```
#### `B7B3` QNOT [#b7b3-qnot]
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QNOT
```
#### `B7B4cc` QFITS [#b7b4cc-qfits]
Replaces `x` with a `NaN` if x is not a `cc+1`-bit signed integer, leaves it intact otherwise.
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[cc+1] QFITS
```
#### `B7B5cc` QUFITS [#b7b5cc-qufits]
Replaces `x` with a `NaN` if x is not a `cc+1`-bit unsigned integer, leaves it intact otherwise.
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
[cc+1] QUFITS
```
#### `B7B600` QFITSX [#b7b600-qfitsx]
Replaces `x` with a `NaN` if x is not a c-bit signed integer, leaves it intact otherwise.
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QFITSX
```
#### `B7B601` QUFITSX [#b7b601-qufitsx]
Replaces `x` with a `NaN` if x is not a c-bit unsigned integer, leaves it intact otherwise.
**Category:** Arithm Quiet (arithm\_quiet)
```fift Fift
QUFITSX
```
#### `B8` SGN [#b8-sgn]
Computes the sign of an integer `x`: `-1` if `x<0`, `0` if `x=0`, `1` if `x>0`.
**Category:** Compare Int (compare\_int)
```fift Fift
SGN
```
#### `B9` LESS [#b9-less]
Returns `-1` if `x
**Category:** Compare Int (compare\_int)
```fift Fift
LESS
```
#### `BA` EQUAL [#ba-equal]
Returns `-1` if `x=y`, `0` otherwise.
**Category:** Compare Int (compare\_int)
```fift Fift
EQUAL
```
#### `BB` LEQ [#bb-leq]
**Category:** Compare Int (compare\_int)
```fift Fift
LEQ
```
#### `BC` GREATER [#bc-greater]
**Category:** Compare Int (compare\_int)
```fift Fift
GREATER
```
#### `BD` NEQ [#bd-neq]
Equivalent to `EQUAL` `NOT`.
**Category:** Compare Int (compare\_int)
```fift Fift
NEQ
```
#### `BE` GEQ [#be-geq]
Equivalent to `LESS` `NOT`.
**Category:** Compare Int (compare\_int)
```fift Fift
GEQ
```
#### `BF` CMP [#bf-cmp]
Computes the sign of `x-y`: `-1` if `xy`. No integer overflow can occur here unless `x` or `y` is a `NaN`.
**Category:** Compare Int (compare\_int)
```fift Fift
CMP
```
#### `C0yy` EQINT [#c0yy-eqint]
Returns `-1` if `x=yy`, `0` otherwise. `-2^7 <= yy < 2^7`.
**Category:** Compare Int (compare\_int)
```fift Fift
[yy] EQINT
```
**Aliases**:
* `ISZERO`
Checks whether an integer is zero. Corresponds to Forth's `0=`.
#### `C1yy` LESSINT [#c1yy-lessint]
Returns `-1` if `x `-2^7 <= yy < 2^7`.
**Category:** Compare Int (compare\_int)
```fift Fift
[yy] LESSINT
[yy-1] LEQINT
```
**Aliases**:
* `ISNEG`
Checks whether an integer is negative. Corresponds to Forth's `0<`.
* `ISNPOS`
Checks whether an integer is non-positive.
#### `C2yy` GTINT [#c2yy-gtint]
Returns `-1` if `x>yy`, `0` otherwise. `-2^7 <= yy < 2^7`.
**Category:** Compare Int (compare\_int)
```fift Fift
[yy] GTINT
[yy+1] GEQINT
```
**Aliases**:
* `ISPOS`
Checks whether an integer is positive. Corresponds to Forth's `0>`.
* `ISNNEG`
Checks whether an integer is non-negative.
#### `C3yy` NEQINT [#c3yy-neqint]
Returns `-1` if `x!=yy`, `0` otherwise. `-2^7 <= yy < 2^7`.
**Category:** Compare Int (compare\_int)
```fift Fift
[yy] NEQINT
```
#### `C4` ISNAN [#c4-isnan]
Checks whether `x` is a `NaN`.
**Category:** Compare Int (compare\_int)
```fift Fift
ISNAN
```
#### `C5` CHKNAN [#c5-chknan]
Throws an arithmetic overflow exception if `x` is a `NaN`.
**Category:** Compare Int (compare\_int)
```fift Fift
CHKNAN
```
#### `C700` SEMPTY [#c700-sempty]
Checks whether a *Slice* `s` is empty (i.e., contains no bits of data and no cell references).
**Category:** Compare Other (compare\_other)
```fift Fift
SEMPTY
```
#### `C701` SDEMPTY [#c701-sdempty]
Checks whether *Slice* `s` has no bits of data.
**Category:** Compare Other (compare\_other)
```fift Fift
SDEMPTY
```
#### `C702` SREMPTY [#c702-srempty]
Checks whether *Slice* `s` has no references.
**Category:** Compare Other (compare\_other)
```fift Fift
SREMPTY
```
#### `C703` SDFIRST [#c703-sdfirst]
Checks whether the first bit of *Slice* `s` is a one.
**Category:** Compare Other (compare\_other)
```fift Fift
SDFIRST
```
#### `C704` SDLEXCMP [#c704-sdlexcmp]
Compares the data of `s` lexicographically with the data of `s'`, returning `-1`, 0, or 1 depending on the result.
**Category:** Compare Other (compare\_other)
```fift Fift
SDLEXCMP
```
#### `C705` SDEQ [#c705-sdeq]
Checks whether the data parts of `s` and `s'` coincide, equivalent to `SDLEXCMP` `ISZERO`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDEQ
```
#### `C708` SDPFX [#c708-sdpfx]
Checks whether `s` is a prefix of `s'`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDPFX
```
#### `C709` SDPFXREV [#c709-sdpfxrev]
Checks whether `s'` is a prefix of `s`, equivalent to `SWAP` `SDPFX`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDPFXREV
```
#### `C70A` SDPPFX [#c70a-sdppfx]
Checks whether `s` is a proper prefix of `s'` (i.e., a prefix distinct from `s'`).
**Category:** Compare Other (compare\_other)
```fift Fift
SDPPFX
```
#### `C70B` SDPPFXREV [#c70b-sdppfxrev]
Checks whether `s'` is a proper prefix of `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDPPFXREV
```
#### `C70C` SDSFX [#c70c-sdsfx]
Checks whether `s` is a suffix of `s'`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDSFX
```
#### `C70D` SDSFXREV [#c70d-sdsfxrev]
Checks whether `s'` is a suffix of `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDSFXREV
```
#### `C70E` SDPSFX [#c70e-sdpsfx]
Checks whether `s` is a proper suffix of `s'`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDPSFX
```
#### `C70F` SDPSFXREV [#c70f-sdpsfxrev]
Checks whether `s'` is a proper suffix of `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDPSFXREV
```
#### `C710` SDCNTLEAD0 [#c710-sdcntlead0]
Returns the number of leading zeroes in `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDCNTLEAD0
```
#### `C711` SDCNTLEAD1 [#c711-sdcntlead1]
Returns the number of leading ones in `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDCNTLEAD1
```
#### `C712` SDCNTTRAIL0 [#c712-sdcnttrail0]
Returns the number of trailing zeroes in `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDCNTTRAIL0
```
#### `C713` SDCNTTRAIL1 [#c713-sdcnttrail1]
Returns the number of trailing ones in `s`.
**Category:** Compare Other (compare\_other)
```fift Fift
SDCNTTRAIL1
```
#### `C8` NEWC [#c8-newc]
Creates a new empty *Builder*.
**Category:** Cell Build (cell\_build)
```fift Fift
NEWC
```
#### `C9` ENDC [#c9-endc]
Converts a *Builder* into an ordinary *Cell*.
**Category:** Cell Build (cell\_build)
```fift Fift
ENDC
```
#### `CAcc` STI [#cacc-sti]
Stores a signed `cc+1`-bit integer `x` into *Builder* `b` for `0 <= cc <= 255`, throws a range check exception if `x` does not fit into `cc+1` bits.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STI
```
#### `CBcc` STU [#cbcc-stu]
Stores an unsigned `cc+1`-bit integer `x` into *Builder* `b`. In all other respects it is similar to `STI`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STU
```
#### `CC` STREF [#cc-stref]
Stores a reference to *Cell* `c` into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STREF
```
#### `CD` STBREFR [#cd-stbrefr]
Equivalent to `ENDC` `SWAP` `STREF`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBREFR
ENDCST
```
#### `CE` STSLICE [#ce-stslice]
Stores *Slice* `s` into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSLICE
```
**Aliases**:
* `STDICTS`
Stores a *Slice*-represented dictionary `s` into *Builder* `b`. It is actually a synonym for `STSLICE`.
#### `CF00` STIX [#cf00-stix]
Stores a signed `l`-bit integer `x` into `b` for `0 <= l <= 257`.
**Category:** Cell Build (cell\_build)
```fift Fift
STIX
```
#### `CF01` STUX [#cf01-stux]
Stores an unsigned `l`-bit integer `x` into `b` for `0 <= l <= 256`.
**Category:** Cell Build (cell\_build)
```fift Fift
STUX
```
#### `CF02` STIXR [#cf02-stixr]
Similar to `STIX`, but with arguments in a different order.
**Category:** Cell Build (cell\_build)
```fift Fift
STIXR
```
#### `CF03` STUXR [#cf03-stuxr]
Similar to `STUX`, but with arguments in a different order.
**Category:** Cell Build (cell\_build)
```fift Fift
STUXR
```
#### `CF04` STIXQ [#cf04-stixq]
A quiet version of `STIX`. If there is no space in `b`, sets `b'=b` and `f=-1`. If `x` does not fit into `l` bits, sets `b'=b` and `f=1`. If the operation succeeds, `b'` is the new *Builder* and `f=0`. However, `0 <= l <= 257`, with a range check exception if this is not so.
**Category:** Cell Build (cell\_build)
```fift Fift
STIXQ
```
#### `CF05` STUXQ [#cf05-stuxq]
A quiet version of `STUX`.
**Category:** Cell Build (cell\_build)
```fift Fift
STUXQ
```
#### `CF06` STIXRQ [#cf06-stixrq]
A quiet version of `STIXR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STIXRQ
```
#### `CF07` STUXRQ [#cf07-stuxrq]
A quiet version of `STUXR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STUXRQ
```
#### `CF08cc` STI\_ALT [#cf08cc-sti_alt]
A longer version of `[cc+1] STI`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STI_l
```
#### `CF09cc` STU\_ALT [#cf09cc-stu_alt]
A longer version of `[cc+1] STU`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STU_l
```
#### `CF0Acc` STIR [#cf0acc-stir]
Equivalent to `SWAP` `[cc+1] STI`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STIR
```
#### `CF0Bcc` STUR [#cf0bcc-stur]
Equivalent to `SWAP` `[cc+1] STU`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STUR
```
#### `CF0Ccc` STIQ [#cf0ccc-stiq]
A quiet version of `STI`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STIQ
```
#### `CF0Dcc` STUQ [#cf0dcc-stuq]
A quiet version of `STU`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STUQ
```
#### `CF0Ecc` STIRQ [#cf0ecc-stirq]
A quiet version of `STIR`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STIRQ
```
#### `CF0Fcc` STURQ [#cf0fcc-sturq]
A quiet version of `STUR`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] STURQ
```
#### `CF10` STREF\_ALT [#cf10-stref_alt]
A longer version of `STREF`.
**Category:** Cell Build (cell\_build)
```fift Fift
STREF_l
```
#### `CF11` STBREF [#cf11-stbref]
Equivalent to `SWAP` `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBREF
```
#### `CF12` STSLICE\_ALT [#cf12-stslice_alt]
A longer version of `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSLICE_l
```
#### `CF13` STB [#cf13-stb]
Appends all data from *Builder* `b'` to *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STB
```
#### `CF14` STREFR [#cf14-strefr]
Equivalent to `SWAP` `STREF`.
**Category:** Cell Build (cell\_build)
```fift Fift
STREFR
```
#### `CF15` STBREFR\_ALT [#cf15-stbrefr_alt]
A longer encoding of `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBREFR_l
```
#### `CF16` STSLICER [#cf16-stslicer]
Equivalent to `SWAP` `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSLICER
```
#### `CF17` STBR [#cf17-stbr]
Concatenates two builders. Equivalent to `SWAP` `STB`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBR
BCONCAT
```
#### `CF18` STREFQ [#cf18-strefq]
Quiet version of `STREF`.
**Category:** Cell Build (cell\_build)
```fift Fift
STREFQ
```
#### `CF19` STBREFQ [#cf19-stbrefq]
Quiet version of `STBREF`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBREFQ
```
#### `CF1A` STSLICEQ [#cf1a-stsliceq]
Quiet version of `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSLICEQ
```
#### `CF1B` STBQ [#cf1b-stbq]
Quiet version of `STB`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBQ
```
#### `CF1C` STREFRQ [#cf1c-strefrq]
Quiet version of `STREFR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STREFRQ
```
#### `CF1D` STBREFRQ [#cf1d-stbrefrq]
Quiet version of `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBREFRQ
```
#### `CF1E` STSLICERQ [#cf1e-stslicerq]
Quiet version of `STSLICER`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSLICERQ
```
#### `CF1F` STBRQ [#cf1f-stbrq]
Quiet version of `STBR`.
**Category:** Cell Build (cell\_build)
```fift Fift
STBRQ
BCONCATQ
```
#### `CF20` STREFCONST [#cf20-strefconst]
Equivalent to `PUSHREF` `STREFR`.
**Category:** Cell Build (cell\_build)
```fift Fift
[ref] STREFCONST
```
#### `CF21` STREF2CONST [#cf21-stref2const]
Equivalent to `STREFCONST` `STREFCONST`.
**Category:** Cell Build (cell\_build)
```fift Fift
[ref] [ref] STREF2CONST
```
#### `CF23` ENDXC [#cf23-endxc]
If `x!=0`, creates a *special* or *exotic* cell from *Builder* `b`. The type of the exotic cell must be stored in the first 8 bits of `b`. If `x=0`, it is equivalent to `ENDC`. Otherwise some validity checks on the data and references of `b` are performed before creating the exotic cell.
**Category:** Cell Build (cell\_build)
```fift Fift
ENDXC
```
#### `CF28` STILE4 [#cf28-stile4]
Stores a little-endian signed 32-bit integer.
**Category:** Cell Build (cell\_build)
```fift Fift
STILE4
```
#### `CF29` STULE4 [#cf29-stule4]
Stores a little-endian unsigned 32-bit integer.
**Category:** Cell Build (cell\_build)
```fift Fift
STULE4
```
#### `CF2A` STILE8 [#cf2a-stile8]
Stores a little-endian signed 64-bit integer.
**Category:** Cell Build (cell\_build)
```fift Fift
STILE8
```
#### `CF2B` STULE8 [#cf2b-stule8]
Stores a little-endian unsigned 64-bit integer.
**Category:** Cell Build (cell\_build)
```fift Fift
STULE8
```
#### `CF30` BDEPTH [#cf30-bdepth]
Returns the depth of *Builder* `b`. If no cell references are stored in `b`, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BDEPTH
```
#### `CF31` BBITS [#cf31-bbits]
Returns the number of data bits already stored in *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BBITS
```
#### `CF32` BREFS [#cf32-brefs]
Returns the number of cell references already stored in `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BREFS
```
#### `CF33` BBITREFS [#cf33-bbitrefs]
Returns the numbers of both data bits and cell references in `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BBITREFS
```
#### `CF35` BREMBITS [#cf35-brembits]
Returns the number of data bits that can still be stored in `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BREMBITS
```
#### `CF36` BREMREFS [#cf36-bremrefs]
Returns the number of references that can still be stored in `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BREMREFS
```
#### `CF37` BREMBITREFS [#cf37-brembitrefs]
Returns the numbers of both data bits and references that can still be stored in `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
BREMBITREFS
```
#### `CF38cc` BCHKBITS [#cf38cc-bchkbits]
Checks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] BCHKBITS#
```
#### `CF39` BCHKBITS\_VAR [#cf39-bchkbits_var]
Checks whether `x` bits can be stored into `b`, `0 <= x <= 1023`. If there is no space for `x` more bits in `b`, or if `x` is not within the range `0...1023`, throws an exception.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKBITS
```
#### `CF3A` BCHKREFS [#cf3a-bchkrefs]
Checks whether `y` references can be stored into `b`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKREFS
```
#### `CF3B` BCHKBITREFS [#cf3b-bchkbitrefs]
Checks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKBITREFS
```
#### `CF3Ccc` BCHKBITSQ [#cf3ccc-bchkbitsq]
Checks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`.
**Category:** Cell Build (cell\_build)
```fift Fift
[cc+1] BCHKBITSQ#
```
#### `CF3D` BCHKBITSQ\_VAR [#cf3d-bchkbitsq_var]
Checks whether `x` bits can be stored into `b`, `0 <= x <= 1023`.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKBITSQ
```
#### `CF3E` BCHKREFSQ [#cf3e-bchkrefsq]
Checks whether `y` references can be stored into `b`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKREFSQ
```
#### `CF3F` BCHKBITREFSQ [#cf3f-bchkbitrefsq]
Checks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift Fift
BCHKBITREFSQ
```
#### `CF40` STZEROES [#cf40-stzeroes]
Stores `n` binary zeroes into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STZEROES
```
#### `CF41` STONES [#cf41-stones]
Stores `n` binary ones into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STONES
```
#### `CF42` STSAME [#cf42-stsame]
Stores `n` binary `x`es (`0 <= x <= 1`) into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift Fift
STSAME
```
#### `CF50` BTOS [#cf50-btos]
Same as `ENDC CTOS`, but without gas cost for cell creation and loading.
**Category:** Cell Build (cell\_build)
```fift Fift
BTOS
```
#### `CFC_xysss` STSLICECONST [#cfc_xysss-stsliceconst]
Stores a constant subslice `sss`. *Details:* `sss` consists of `0 <= x <= 3` references and up to `8y+2` data bits, with `0 <= y <= 7`. Completion bit is assumed. Note that the assembler can replace `STSLICECONST` with `PUSHSLICE` `STSLICER` if the slice is too big.
**Category:** Cell Build (cell\_build)
```fift Fift
[slice] STSLICECONST
```
**Aliases**:
* `STZERO`
Stores one binary zero.
* `STONE`
Stores one binary one.
#### `D0` CTOS [#d0-ctos]
Converts a *Cell* into a *Slice*. Notice that `c` must be either an ordinary cell, or an exotic cell which is automatically *loaded* to yield an ordinary cell `c'`, converted into a *Slice* afterwards.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CTOS
```
#### `D1` ENDS [#d1-ends]
Removes a *Slice* `s` from the stack, and throws an exception if it is not empty.
**Category:** Cell Parse (cell\_parse)
```fift Fift
ENDS
```
#### `D2cc` LDI [#d2cc-ldi]
Loads (i.e., parses) a signed `cc+1`-bit integer `x` from *Slice* `s`, and returns the remainder of `s` as `s'`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDI
```
#### `D3cc` LDU [#d3cc-ldu]
Loads an unsigned `cc+1`-bit integer `x` from *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDU
```
#### `D4` LDREF [#d4-ldref]
Loads a cell reference `c` from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDREF
```
#### `D5` LDREFRTOS [#d5-ldrefrtos]
Equivalent to `LDREF` `SWAP` `CTOS`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDREFRTOS
```
#### `D6cc` LDSLICE [#d6cc-ldslice]
Cuts the next `cc+1` bits of `s` into a separate *Slice* `s''`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDSLICE
```
#### `D700` LDIX [#d700-ldix]
Loads a signed `l`-bit (`0 <= l <= 257`) integer `x` from *Slice* `s`, and returns the remainder of `s` as `s'`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDIX
```
#### `D701` LDUX [#d701-ldux]
Loads an unsigned `l`-bit integer `x` from (the first `l` bits of) `s`, with `0 <= l <= 256`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDUX
```
#### `D702` PLDIX [#d702-pldix]
Preloads a signed `l`-bit integer from *Slice* `s`, for `0 <= l <= 257`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDIX
```
#### `D703` PLDUX [#d703-pldux]
Preloads an unsigned `l`-bit integer from `s`, for `0 <= l <= 256`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDUX
```
#### `D704` LDIXQ [#d704-ldixq]
Quiet version of `LDIX`: loads a signed `l`-bit integer from `s` similarly to `LDIX`, but returns a success flag, equal to `-1` on success or to `0` on failure (if `s` does not have `l` bits), instead of throwing a cell underflow exception.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDIXQ
```
#### `D705` LDUXQ [#d705-lduxq]
Quiet version of `LDUX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDUXQ
```
#### `D706` PLDIXQ [#d706-pldixq]
Quiet version of `PLDIX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDIXQ
```
#### `D707` PLDUXQ [#d707-plduxq]
Quiet version of `PLDUX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDUXQ
```
#### `D708cc` LDI\_ALT [#d708cc-ldi_alt]
A longer encoding for `LDI`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDI_l
```
#### `D709cc` LDU\_ALT [#d709cc-ldu_alt]
A longer encoding for `LDU`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDU_l
```
#### `D70Acc` PLDI [#d70acc-pldi]
Preloads a signed `cc+1`-bit integer from *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDI
```
#### `D70Bcc` PLDU [#d70bcc-pldu]
Preloads an unsigned `cc+1`-bit integer from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDU
```
#### `D70Ccc` LDIQ [#d70ccc-ldiq]
A quiet version of `LDI`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDIQ
```
#### `D70Dcc` LDUQ [#d70dcc-lduq]
A quiet version of `LDU`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDUQ
```
#### `D70Ecc` PLDIQ [#d70ecc-pldiq]
A quiet version of `PLDI`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDIQ
```
#### `D70Fcc` PLDUQ [#d70fcc-plduq]
A quiet version of `PLDU`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDUQ
```
#### `D714_c` PLDUZ [#d714_c-plduz]
Preloads the first `32(c+1)` bits of *Slice* `s` into an unsigned integer `x`, for `0 <= c <= 7`. If `s` is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with `IFBITJMP` and similar instructions.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[32(c+1)] PLDUZ
```
#### `D718` LDSLICEX [#d718-ldslicex]
Loads the first `0 <= l <= 1023` bits from *Slice* `s` into a separate *Slice* `s''`, returning the remainder of `s` as `s'`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDSLICEX
```
#### `D719` PLDSLICEX [#d719-pldslicex]
Returns the first `0 <= l <= 1023` bits of `s` as `s''`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDSLICEX
```
#### `D71A` LDSLICEXQ [#d71a-ldslicexq]
A quiet version of `LDSLICEX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDSLICEXQ
```
#### `D71B` PLDSLICEXQ [#d71b-pldslicexq]
A quiet version of `LDSLICEXQ`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDSLICEXQ
```
#### `D71Ccc` LDSLICE\_ALT [#d71ccc-ldslice_alt]
A longer encoding for `LDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDSLICE_l
```
#### `D71Dcc` PLDSLICE [#d71dcc-pldslice]
Returns the first `0 < cc+1 <= 256` bits of `s` as `s''`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDSLICE
```
#### `D71Ecc` LDSLICEQ [#d71ecc-ldsliceq]
A quiet version of `LDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] LDSLICEQ
```
#### `D71Fcc` PLDSLICEQ [#d71fcc-pldsliceq]
A quiet version of `PLDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[cc+1] PLDSLICEQ
```
#### `D720` SDCUTFIRST [#d720-sdcutfirst]
Returns the first `0 <= l <= 1023` bits of `s`. It is equivalent to `PLDSLICEX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDCUTFIRST
```
#### `D721` SDSKIPFIRST [#d721-sdskipfirst]
Returns all but the first `0 <= l <= 1023` bits of `s`. It is equivalent to `LDSLICEX` `NIP`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDSKIPFIRST
```
#### `D722` SDCUTLAST [#d722-sdcutlast]
Returns the last `0 <= l <= 1023` bits of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDCUTLAST
```
#### `D723` SDSKIPLAST [#d723-sdskiplast]
Returns all but the last `0 <= l <= 1023` bits of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDSKIPLAST
```
#### `D724` SDSUBSTR [#d724-sdsubstr]
Returns `0 <= l' <= 1023` bits of `s` starting from offset `0 <= l <= 1023`, thus extracting a bit substring out of the data of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDSUBSTR
```
#### `D726` SDBEGINSX [#d726-sdbeginsx]
Checks whether `s` begins with (the data bits of) `s'`, and removes `s'` from `s` on success. On failure throws a cell deserialization exception. Primitive `SDPFXREV` can be considered a quiet version of `SDBEGINSX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDBEGINSX
```
#### `D727` SDBEGINSXQ [#d727-sdbeginsxq]
A quiet version of `SDBEGINSX`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDBEGINSXQ
```
#### `D72A_xsss` SDBEGINS [#d72a_xsss-sdbegins]
Checks whether `s` begins with constant bitstring `sss` of length `8x+3` (with continuation bit assumed), where `0 <= x <= 127`, and removes `sss` from `s` on success.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[slice] SDBEGINS
```
#### `D72E_xsss` SDBEGINSQ [#d72e_xsss-sdbeginsq]
A quiet version of `SDBEGINS`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[slice] SDBEGINSQ
```
#### `D730` SCUTFIRST [#d730-scutfirst]
Returns the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCUTFIRST
```
#### `D731` SSKIPFIRST [#d731-sskipfirst]
Returns all but the first `l` bits of `s` and `r` references of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SSKIPFIRST
```
#### `D732` SCUTLAST [#d732-scutlast]
Returns the last `0 <= l <= 1023` data bits and last `0 <= r <= 4` references of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCUTLAST
```
#### `D733` SSKIPLAST [#d733-sskiplast]
Returns all but the last `l` bits of `s` and `r` references of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SSKIPLAST
```
#### `D734` SUBSLICE [#d734-subslice]
Returns `0 <= l' <= 1023` bits and `0 <= r' <= 4` references from *Slice* `s`, after skipping the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SUBSLICE
```
#### `D736` SPLIT [#d736-split]
Splits the first `0 <= l <= 1023` data bits and first `0 <= r <= 4` references from `s` into `s'`, returning the remainder of `s` as `s''`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SPLIT
```
#### `D737` SPLITQ [#d737-splitq]
A quiet version of `SPLIT`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SPLITQ
```
#### `D739` XCTOS [#d739-xctos]
Transforms an ordinary or exotic cell into a *Slice*, as if it were an ordinary cell. A flag is returned indicating whether `c` is exotic. If that be the case, its type can later be deserialized from the first eight bits of `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
XCTOS
```
#### `D73A` XLOAD [#d73a-xload]
Loads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, throws an exception.
**Category:** Cell Parse (cell\_parse)
```fift Fift
XLOAD
```
#### `D73B` XLOADQ [#d73b-xloadq]
Loads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, returns 0.
**Category:** Cell Parse (cell\_parse)
```fift Fift
XLOADQ
```
#### `D741` SCHKBITS [#d741-schkbits]
Checks whether there are at least `l` data bits in *Slice* `s`. If this is not the case, throws a cell deserialisation (i.e., cell underflow) exception.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKBITS
```
#### `D742` SCHKREFS [#d742-schkrefs]
Checks whether there are at least `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKREFS
```
#### `D743` SCHKBITREFS [#d743-schkbitrefs]
Checks whether there are at least `l` data bits and `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKBITREFS
```
#### `D745` SCHKBITSQ [#d745-schkbitsq]
Checks whether there are at least `l` data bits in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKBITSQ
```
#### `D746` SCHKREFSQ [#d746-schkrefsq]
Checks whether there are at least `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKREFSQ
```
#### `D747` SCHKBITREFSQ [#d747-schkbitrefsq]
Checks whether there are at least `l` data bits and `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SCHKBITREFSQ
```
#### `D748` PLDREFVAR [#d748-pldrefvar]
Returns the `n`-th cell reference of *Slice* `s` for `0 <= n <= 3`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDREFVAR
```
#### `D749` SBITS [#d749-sbits]
Returns the number of data bits in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SBITS
```
#### `D74A` SREFS [#d74a-srefs]
Returns the number of references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SREFS
```
#### `D74B` SBITREFS [#d74b-sbitrefs]
Returns both the number of data bits and the number of references in `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SBITREFS
```
#### `D74E_n` PLDREFIDX [#d74e_n-pldrefidx]
Returns the `n`-th cell reference of *Slice* `s`, where `0 <= n <= 3`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[n] PLDREFIDX
```
**Aliases**:
* `PLDREF`
Preloads the first cell reference of a *Slice*.
#### `D750` LDILE4 [#d750-ldile4]
Loads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDILE4
```
#### `D751` LDULE4 [#d751-ldule4]
Loads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDULE4
```
#### `D752` LDILE8 [#d752-ldile8]
Loads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDILE8
```
#### `D753` LDULE8 [#d753-ldule8]
Loads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDULE8
```
#### `D754` PLDILE4 [#d754-pldile4]
Preloads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDILE4
```
#### `D755` PLDULE4 [#d755-pldule4]
Preloads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDULE4
```
#### `D756` PLDILE8 [#d756-pldile8]
Preloads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDILE8
```
#### `D757` PLDULE8 [#d757-pldule8]
Preloads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDULE8
```
#### `D758` LDILE4Q [#d758-ldile4q]
Quietly loads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDILE4Q
```
#### `D759` LDULE4Q [#d759-ldule4q]
Quietly loads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDULE4Q
```
#### `D75A` LDILE8Q [#d75a-ldile8q]
Quietly loads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDILE8Q
```
#### `D75B` LDULE8Q [#d75b-ldule8q]
Quietly loads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDULE8Q
```
#### `D75C` PLDILE4Q [#d75c-pldile4q]
Quietly preloads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDILE4Q
```
#### `D75D` PLDULE4Q [#d75d-pldule4q]
Quietly preloads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDULE4Q
```
#### `D75E` PLDILE8Q [#d75e-pldile8q]
Quietly preloads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDILE8Q
```
#### `D75F` PLDULE8Q [#d75f-pldule8q]
Quietly preloads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift Fift
PLDULE8Q
```
#### `D760` LDZEROES [#d760-ldzeroes]
Returns the count `n` of leading zero bits in `s`, and removes these bits from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDZEROES
```
#### `D761` LDONES [#d761-ldones]
Returns the count `n` of leading one bits in `s`, and removes these bits from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDONES
```
#### `D762` LDSAME [#d762-ldsame]
Returns the count `n` of leading bits equal to `0 <= x <= 1` in `s`, and removes these bits from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
LDSAME
```
#### `D764` SDEPTH [#d764-sdepth]
Returns the depth of *Slice* `s`. If `s` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `s`.
**Category:** Cell Parse (cell\_parse)
```fift Fift
SDEPTH
```
#### `D765` CDEPTH [#d765-cdepth]
Returns the depth of *Cell* `c`. If `c` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `c`. If `c` is a *Null* instead of a *Cell*, returns zero.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CDEPTH
```
#### `D766` CLEVEL [#d766-clevel]
Returns level of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CLEVEL
```
#### `D767` CLEVELMASK [#d767-clevelmask]
Returns level mask of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CLEVELMASK
```
#### `D76A_` CHASHI [#d76a_-chashi]
Returns `i`th hash of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[i] CHASHI
```
#### `D76E_` CDEPTHI [#d76e_-cdepthi]
Returns `i`th depth of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
[i] CDEPTHI
```
#### `D770` CHASHIX [#d770-chashix]
Returns `i`th hash of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CHASHIX
```
#### `D771` CDEPTHIX [#d771-cdepthix]
Returns `i`th depth of the cell.
**Category:** Cell Parse (cell\_parse)
```fift Fift
CDEPTHIX
```
#### `D8` EXECUTE [#d8-execute]
*Calls*, or *executes*, continuation `c`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
EXECUTE
CALLX
```
#### `D9` JMPX [#d9-jmpx]
*Jumps*, or transfers control, to continuation `c`. The remainder of the previous current continuation `cc` is discarded.
**Category:** Cont Basic (cont\_basic)
```fift Fift
JMPX
```
#### `DApr` CALLXARGS [#dapr-callxargs]
*Calls* continuation `c` with `p` parameters and expecting `r` return values `0 <= p <= 15`, `0 <= r <= 15`
**Category:** Cont Basic (cont\_basic)
```fift Fift
[p] [r] CALLXARGS
```
#### `DB0p` CALLXARGS\_VAR [#db0p-callxargs_var]
*Calls* continuation `c` with `0 <= p <= 15` parameters, expecting an arbitrary number of return values.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[p] -1 CALLXARGS
```
#### `DB1p` JMPXARGS [#db1p-jmpxargs]
*Jumps* to continuation `c`, passing only the top `0 <= p <= 15` values from the current stack to it (the remainder of the current stack is discarded).
**Category:** Cont Basic (cont\_basic)
```fift Fift
[p] JMPXARGS
```
#### `DB2r` RETARGS [#db2r-retargs]
*Returns* to `c0`, with `0 <= r <= 15` return values taken from the current stack.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[r] RETARGS
```
#### `DB30` RET [#db30-ret]
*Returns* to the continuation at `c0`. The remainder of the current continuation `cc` is discarded. Approximately equivalent to `c0 PUSHCTR` `JMPX`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
RET
RETTRUE
```
#### `DB31` RETALT [#db31-retalt]
*Returns* to the continuation at `c1`. Approximately equivalent to `c1 PUSHCTR` `JMPX`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
RETALT
RETFALSE
```
#### `DB32` BRANCH [#db32-branch]
Performs `RETTRUE` if integer `f!=0`, or `RETFALSE` if `f=0`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
BRANCH
RETBOOL
```
#### `DB34` CALLCC [#db34-callcc]
*Call with current continuation*, transfers control to `c`, pushing the old value of `cc` into `c`'s stack (instead of discarding it or writing it into new `c0`).
**Category:** Cont Basic (cont\_basic)
```fift Fift
CALLCC
```
#### `DB35` JMPXDATA [#db35-jmpxdata]
Similar to `CALLCC`, but the remainder of the current continuation (the old value of `cc`) is converted into a *Slice* before pushing it into the stack of `c`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
JMPXDATA
```
#### `DB36pr` CALLCCARGS [#db36pr-callccargs]
Similar to `CALLXARGS`, but pushes the old value of `cc` (along with the top `0 <= p <= 15` values from the original stack) into the stack of newly-invoked continuation `c`, setting `cc.nargs` to `-1 <= r <= 14`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[p] [r] CALLCCARGS
```
#### `DB38` CALLXVARARGS [#db38-callxvarargs]
Similar to `CALLXARGS`, but takes `-1 <= p,r <= 254` from the stack. The next three operations also take `p` and `r` from the stack, both in the range `-1...254`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
CALLXVARARGS
```
#### `DB39` RETVARARGS [#db39-retvarargs]
Similar to `RETARGS`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
RETVARARGS
```
#### `DB3A` JMPXVARARGS [#db3a-jmpxvarargs]
Similar to `JMPXARGS`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
JMPXVARARGS
```
#### `DB3B` CALLCCVARARGS [#db3b-callccvarargs]
Similar to `CALLCCARGS`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
CALLCCVARARGS
```
#### `DB3C` CALLREF [#db3c-callref]
Equivalent to `PUSHREFCONT` `CALLX`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[ref] CALLREF
```
#### `DB3D` JMPREF [#db3d-jmpref]
Equivalent to `PUSHREFCONT` `JMPX`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[ref] JMPREF
```
#### `DB3E` JMPREFDATA [#db3e-jmprefdata]
Equivalent to `PUSHREFCONT` `JMPXDATA`.
**Category:** Cont Basic (cont\_basic)
```fift Fift
[ref] JMPREFDATA
```
#### `DB3F` RETDATA [#db3f-retdata]
Equivalent to `c0 PUSHCTR` `JMPXDATA`. In this way, the remainder of the current continuation is converted into a *Slice* and returned to the caller.
**Category:** Cont Basic (cont\_basic)
```fift Fift
RETDATA
```
#### `DB4fff` RUNVM [#db4fff-runvm]
Runs child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags. Flags operate similarly to `RUNVMX` in Fift: - `+1`: sets `c3` to code. - `+2`: pushes an implicit `0` before executing the code. - `+4`: takes persistent data `c4` from the stack and returns its final value. - `+8`: takes the gas limit `g_l` from the stack and returns the consumed gas `g_c`. - `+16`: takes `c7` (smart contract context) from the stack. - `+32`: returns the final value of `c5` (actions). - `+64`: pops the hard gas limit `g_m` enabled by `ACCEPT` from the stack. - `+128`: enables "isolated gas consumption", meaning the child VM maintains a separate set of visited cells and a `chksgn` counter. - `+256`: pops an integer `r` and ensures exactly `r` values are returned from the top of the stack: - If `RUNVM` call succeeds and `r` is set, it returns `r` elements. If `r` is not set, it returns all available elements. - If `RUNVM` is successful but lacks elements on the stack, meaning the stack depth is less than `r`, it is treated as an exception in the child VM. The `exit_code` is set to `-3`, and `exit_arg` is set to `0`, so `0` is returned as the only stack element. - If `RUNVM` fails with an exception, only one element is returned, `exit_arg`, which should not be confused with `exit_code`. - In the case of running out of gas, `exit_code` is set to `-14`, and `exit_arg` contains the amount of gas. Gas cost: - 66 gas; - 1 gas for each stack element passed to the child VM (the first 32 elements are free); - 1 gas for each stack element returned from the child VM (the first 32 elements are free).
**Category:** Cont Basic (cont\_basic)
```fift Fift
flags RUNVM
```
#### `DB50` RUNVMX [#db50-runvmx]
Runs child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags. Flags operate similarly to `RUNVMX` in Fift: - `+1`: sets `c3` to code. - `+2`: pushes an implicit `0` before executing the code. - `+4`: takes persistent data `c4` from the stack and returns its final value. - `+8`: takes the gas limit `g_l` from the stack and returns the consumed gas `g_c`. - `+16`: takes `c7` (smart contract context) from the stack. - `+32`: returns the final value of `c5` (actions). - `+64`: pops the hard gas limit `g_m` enabled by `ACCEPT` from the stack. - `+128`: enables "isolated gas consumption", meaning the child VM maintains a separate set of visited cells and a `chksgn` counter. - `+256`: pops an integer `r` and ensures exactly `r` values are returned from the top of the stack: - If `RUNVM` call succeeds and `r` is set, it returns `r` elements. If `r` is not set, it returns all available elements. - If `RUNVM` is successful but lacks elements on the stack, meaning the stack depth is less than `r`, it is treated as an exception in the child VM. The `exit_code` is set to `-3`, and `exit_arg` is set to `0`, so `0` is returned as the only stack element. - If `RUNVM` fails with an exception, only one element is returned, `exit_arg`, which should not be confused with `exit_code`. - In the case of running out of gas, `exit_code` is set to `-14`, and `exit_arg` contains the amount of gas. Gas cost: - 66 gas; - 1 gas for each stack element passed to the child VM (the first 32 elements are free); - 1 gas for each stack element returned from the child VM (the first 32 elements are free).
**Category:** Cont Basic (cont\_basic)
```fift Fift
RUNVMX
```
#### `DC` IFRET [#dc-ifret]
Performs a `RET`, but only if integer `f` is non-zero. If `f` is a `NaN`, throws an integer overflow exception.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFRET
IFNOT:
```
#### `DD` IFNOTRET [#dd-ifnotret]
Performs a `RET`, but only if integer `f` is zero.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFNOTRET
IF:
```
#### `DE` IF [#de-if]
Performs `EXECUTE` for `c` (i.e., *executes* `c`), but only if integer `f` is non-zero. Otherwise simply discards both values.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IF
```
#### `DF` IFNOT [#df-ifnot]
Executes continuation `c`, but only if integer `f` is zero. Otherwise simply discards both values.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFNOT
```
#### `E0` IFJMP [#e0-ifjmp]
Jumps to `c` (similarly to `JMPX`), but only if `f` is non-zero.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFJMP
```
#### `E1` IFNOTJMP [#e1-ifnotjmp]
Jumps to `c` (similarly to `JMPX`), but only if `f` is zero.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFNOTJMP
```
#### `E2` IFELSE [#e2-ifelse]
If integer `f` is non-zero, executes `c`, otherwise executes `c'`. Equivalent to `CONDSELCHK` `EXECUTE`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFELSE
```
#### `E300` IFREF [#e300-ifref]
Equivalent to `PUSHREFCONT` `IF`, with the optimization that the cell reference is not actually loaded into a *Slice* and then converted into an ordinary *Continuation* if `f=0`. Gas consumption of this primitive depends on whether `f=0` and whether the reference was loaded before. Similar remarks apply other primitives that accept a continuation as a reference.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFREF
```
#### `E301` IFNOTREF [#e301-ifnotref]
Equivalent to `PUSHREFCONT` `IFNOT`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFNOTREF
```
#### `E302` IFJMPREF [#e302-ifjmpref]
Equivalent to `PUSHREFCONT` `IFJMP`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFJMPREF
```
#### `E303` IFNOTJMPREF [#e303-ifnotjmpref]
Equivalent to `PUSHREFCONT` `IFNOTJMP`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFNOTJMPREF
```
#### `E304` CONDSEL [#e304-condsel]
If integer `f` is non-zero, returns `x`, otherwise returns `y`. Notice that no type checks are performed on `x` and `y`; as such, it is more like a conditional stack operation. Roughly equivalent to `ROT` `ISZERO` `INC` `ROLLX` `NIP`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
CONDSEL
```
#### `E305` CONDSELCHK [#e305-condselchk]
Same as `CONDSEL`, but first checks whether `x` and `y` have the same type.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
CONDSELCHK
```
#### `E308` IFRETALT [#e308-ifretalt]
Performs `RETALT` if integer `f!=0`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFRETALT
```
#### `E309` IFNOTRETALT [#e309-ifnotretalt]
Performs `RETALT` if integer `f=0`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
IFNOTRETALT
```
#### `E30D` IFREFELSE [#e30d-ifrefelse]
Equivalent to `PUSHREFCONT` `SWAP` `IFELSE`, with the optimization that the cell reference is not actually loaded into a *Slice* and then converted into an ordinary *Continuation* if `f=0`. Similar remarks apply to the next two primitives: cells are converted into continuations only when necessary.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFREFELSE
```
#### `E30E` IFELSEREF [#e30e-ifelseref]
Equivalent to `PUSHREFCONT` `IFELSE`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] IFELSEREF
```
#### `E30F` IFREFELSEREF [#e30f-ifrefelseref]
Equivalent to `PUSHREFCONT` `PUSHREFCONT` `IFELSE`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] [ref] IFREFELSEREF
```
#### `E39_n` IFBITJMP [#e39_n-ifbitjmp]
Checks whether bit `0 <= n <= 31` is set in integer `x`, and if so, performs `JMPX` to continuation `c`. Value `x` is left in the stack.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[n] IFBITJMP
```
#### `E3B_n` IFNBITJMP [#e3b_n-ifnbitjmp]
Jumps to `c` if bit `0 <= n <= 31` is not set in integer `x`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[n] IFNBITJMP
```
#### `E3D_n` IFBITJMPREF [#e3d_n-ifbitjmpref]
Performs a `JMPREF` if bit `0 <= n <= 31` is set in integer `x`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] [n] IFBITJMPREF
```
#### `E3F_n` IFNBITJMPREF [#e3f_n-ifnbitjmpref]
Performs a `JMPREF` if bit `0 <= n <= 31` is not set in integer `x`.
**Category:** Cont Conditional (cont\_conditional)
```fift Fift
[ref] [n] IFNBITJMPREF
```
#### `E4` REPEAT [#e4-repeat]
Executes continuation `c` `n` times, if integer `n` is non-negative. If `n>=2^31` or `n<-2^31`, generates a range check exception. Notice that a `RET` inside the code of `c` works as a `continue`, not as a `break`. One should use either alternative (experimental) loops or alternative `RETALT` (along with a `SETEXITALT` before the loop) to `break` out of a loop.
**Category:** Cont Loops (cont\_loops)
```fift Fift
REPEAT
```
#### `E5` REPEATEND [#e5-repeatend]
Similar to `REPEAT`, but it is applied to the current continuation `cc`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
REPEATEND
REPEAT:
```
#### `E6` UNTIL [#e6-until]
Executes continuation `c`, then pops an integer `x` from the resulting stack. If `x` is zero, performs another iteration of this loop. The actual implementation of this primitive involves an extraordinary continuation `ec_until` with its arguments set to the body of the loop (continuation `c`) and the original current continuation `cc`. This extraordinary continuation is then saved into the savelist of `c` as `c.c0` and the modified `c` is then executed. The other loop primitives are implemented similarly with the aid of suitable extraordinary continuations.
**Category:** Cont Loops (cont\_loops)
```fift Fift
UNTIL
```
#### `E7` UNTILEND [#e7-untilend]
Similar to `UNTIL`, but executes the current continuation `cc` in a loop. When the loop exit condition is satisfied, performs a `RET`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
UNTILEND
UNTIL:
```
#### `E8` WHILE [#e8-while]
Executes `c'` and pops an integer `x` from the resulting stack. If `x` is zero, exists the loop and transfers control to the original `cc`. If `x` is non-zero, executes `c`, and then begins a new iteration.
**Category:** Cont Loops (cont\_loops)
```fift Fift
WHILE
```
#### `E9` WHILEEND [#e9-whileend]
Similar to `WHILE`, but uses the current continuation `cc` as the loop body.
**Category:** Cont Loops (cont\_loops)
```fift Fift
WHILEEND
```
#### `EA` AGAIN [#ea-again]
Similar to `REPEAT`, but executes `c` infinitely many times. A `RET` only begins a new iteration of the infinite loop, which can be exited only by an exception, or a `RETALT` (or an explicit `JMPX`).
**Category:** Cont Loops (cont\_loops)
```fift Fift
AGAIN
```
#### `EB` AGAINEND [#eb-againend]
Similar to `AGAIN`, but performed with respect to the current continuation `cc`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
AGAINEND
AGAIN:
```
#### `E314` REPEATBRK [#e314-repeatbrk]
Similar to `REPEAT`, but also sets `c1` to the original `cc` after saving the old value of `c1` into the savelist of the original `cc`. In this way `RETALT` could be used to break out of the loop body.
**Category:** Cont Loops (cont\_loops)
```fift Fift
REPEATBRK
```
#### `E315` REPEATENDBRK [#e315-repeatendbrk]
Similar to `REPEATEND`, but also sets `c1` to the original `c0` after saving the old value of `c1` into the savelist of the original `c0`. Equivalent to `SAMEALTSAVE` `REPEATEND`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
REPEATENDBRK
```
#### `E316` UNTILBRK [#e316-untilbrk]
Similar to `UNTIL`, but also modifies `c1` in the same way as `REPEATBRK`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
UNTILBRK
```
#### `E317` UNTILENDBRK [#e317-untilendbrk]
Equivalent to `SAMEALTSAVE` `UNTILEND`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
UNTILENDBRK
UNTILBRK:
```
#### `E318` WHILEBRK [#e318-whilebrk]
Similar to `WHILE`, but also modifies `c1` in the same way as `REPEATBRK`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
WHILEBRK
```
#### `E319` WHILEENDBRK [#e319-whileendbrk]
Equivalent to `SAMEALTSAVE` `WHILEEND`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
WHILEENDBRK
```
#### `E31A` AGAINBRK [#e31a-againbrk]
Similar to `AGAIN`, but also modifies `c1` in the same way as `REPEATBRK`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
AGAINBRK
```
#### `E31B` AGAINENDBRK [#e31b-againendbrk]
Equivalent to `SAMEALTSAVE` `AGAINEND`.
**Category:** Cont Loops (cont\_loops)
```fift Fift
AGAINENDBRK
AGAINBRK:
```
#### `ECrn` SETCONTARGS\_N [#ecrn-setcontargs_n]
Pushes `0 <= r <= 15` values `x_1...x_r` into the stack of (a copy of) the continuation `c`, starting with `x_1`. When `n` is 15 (-1 in Fift notation), does nothing with `c.nargs`. For `0 <= n <= 14`, sets `c.nargs` to the final size of the stack of `c'` plus `n`. In other words, transforms `c` into a *closure* or a *partially applied function*, with `0 <= n <= 14` arguments missing.
**Category:** Cont Stack (cont\_stack)
```fift Fift
[r] [n] SETCONTARGS
```
**Aliases**:
* `SETNUMARGS`
Sets `c.nargs` to `n` plus the current depth of `c`'s stack, where `0 <= n <= 14`. If `c.nargs` is already set to a non-negative value, does nothing.
* `SETCONTARGS`
Pushes `0 <= r <= 15` values `x_1...x_r` into the stack of (a copy of) the continuation `c`, starting with `x_1`. If the final depth of `c`'s stack turns out to be greater than `c.nargs`, a stack overflow exception is generated.
#### `ED0p` RETURNARGS [#ed0p-returnargs]
Leaves only the top `0 <= p <= 15` values in the current stack (somewhat similarly to `ONLYTOPX`), with all the unused bottom values not discarded, but saved into continuation `c0` in the same way as `SETCONTARGS` does.
**Category:** Cont Stack (cont\_stack)
```fift Fift
[p] RETURNARGS
```
#### `ED10` RETURNVARARGS [#ed10-returnvarargs]
Similar to `RETURNARGS`, but with Integer `0 <= p <= 255` taken from the stack.
**Category:** Cont Stack (cont\_stack)
```fift Fift
RETURNVARARGS
```
#### `ED11` SETCONTVARARGS [#ed11-setcontvarargs]
Similar to `SETCONTARGS`, but with `0 <= r <= 255` and `-1 <= n <= 255` taken from the stack.
**Category:** Cont Stack (cont\_stack)
```fift Fift
SETCONTVARARGS
```
#### `ED12` SETNUMVARARGS [#ed12-setnumvarargs]
`-1 <= n <= 255` If `n=-1`, this operation does nothing (`c'=c`). Otherwise its action is similar to `[n] SETNUMARGS`, but with `n` taken from the stack.
**Category:** Cont Stack (cont\_stack)
```fift Fift
SETNUMVARARGS
```
#### `ED1E` BLESS [#ed1e-bless]
Transforms a *Slice* `s` into a simple ordinary continuation `c`, with `c.code=s` and an empty stack and savelist.
**Category:** Cont Create (cont\_create)
```fift Fift
BLESS
```
#### `ED1F` BLESSVARARGS [#ed1f-blessvarargs]
Equivalent to `ROT` `BLESS` `ROTREV` `SETCONTVARARGS`.
**Category:** Cont Create (cont\_create)
```fift Fift
BLESSVARARGS
```
#### `EErn` BLESSARGS [#eern-blessargs]
`0 <= r <= 15`, `-1 <= n <= 14` Equivalent to `BLESS` `[r] [n] SETCONTARGS`. The value of `n` is represented inside the instruction by the 4-bit integer `n mod 16`.
**Category:** Cont Create (cont\_create)
```fift Fift
[r] [n] BLESSARGS
```
**Aliases**:
* `BLESSNUMARGS`
Also transforms a *Slice* `s` into a *Continuation* `c`, but sets `c.nargs` to `0 <= n <= 14`.
#### `ED4i` PUSHCTR [#ed4i-pushctr]
Pushes the current value of control register `c(i)`. If the control register is not supported in the current codepage, or if it does not have a value, an exception is triggered.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] PUSHCTR
c[i] PUSH
```
**Aliases**:
* `PUSHROOT`
Pushes the ''global data root'' cell reference, thus enabling access to persistent smart-contract data.
#### `ED5i` POPCTR [#ed5i-popctr]
Pops a value `x` from the stack and stores it into control register `c(i)`, if supported in the current codepage. Notice that if a control register accepts only values of a specific type, a type-checking exception may occur.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] POPCTR
c[i] POP
```
**Aliases**:
* `POPROOT`
Sets the ''global data root'' cell reference, thus allowing modification of persistent smart-contract data.
#### `ED6i` SETCONTCTR [#ed6i-setcontctr]
Stores `x` into the savelist of continuation `c` as `c(i)`, and returns the resulting continuation `c'`. Almost all operations with continuations may be expressed in terms of `SETCONTCTR`, `POPCTR`, and `PUSHCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SETCONT
c[i] SETCONTCTR
```
#### `ED7i` SETRETCTR [#ed7i-setretctr]
Equivalent to `c0 PUSHCTR` `c[i] SETCONTCTR` `c0 POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SETRETCTR
```
#### `ED8i` SETALTCTR [#ed8i-setaltctr]
Equivalent to `c1 PUSHCTR` `c[i] SETCONTCTR` `c1 POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SETALTCTR
```
#### `ED9i` POPSAVE [#ed9i-popsave]
Similar to `c[i] POPCTR`, but also saves the old value of `c[i]` into continuation `c0`. Equivalent (up to exceptions) to `c[i] SAVECTR` `c[i] POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] POPSAVE
c[i] POPCTRSAVE
```
#### `EDAi` SAVE [#edai-save]
Saves the current value of `c(i)` into the savelist of continuation `c0`. If an entry for `c[i]` is already present in the savelist of `c0`, nothing is done. Equivalent to `c[i] PUSHCTR` `c[i] SETRETCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SAVE
c[i] SAVECTR
```
#### `EDBi` SAVEALT [#edbi-savealt]
Similar to `c[i] SAVE`, but saves the current value of `c[i]` into the savelist of `c1`, not `c0`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SAVEALT
c[i] SAVEALTCTR
```
#### `EDCi` SAVEBOTH [#edci-saveboth]
Equivalent to `c[i] SAVE` `c[i] SAVEALT`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
c[i] SAVEBOTH
c[i] SAVEBOTHCTR
```
#### `EDE0` PUSHCTRX [#ede0-pushctrx]
Similar to `c[i] PUSHCTR`, but with `i`, `0 <= i <= 255`, taken from the stack. Notice that this primitive is one of the few ''exotic'' primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of `x` depends on `i`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
PUSHCTRX
```
#### `EDE1` POPCTRX [#ede1-popctrx]
Similar to `c[i] POPCTR`, but with `0 <= i <= 255` from the stack.
**Category:** Cont Registers (cont\_registers)
```fift Fift
POPCTRX
```
#### `EDE2` SETCONTCTRX [#ede2-setcontctrx]
Similar to `c[i] SETCONTCTR`, but with `0 <= i <= 255` from the stack.
**Category:** Cont Registers (cont\_registers)
```fift Fift
SETCONTCTRX
```
#### `EDE3mm` SETCONTCTRMANY [#ede3mm-setcontctrmany]
Takes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`).
**Category:** Cont Registers (cont\_registers)
```fift Fift
SETCONTCTRMANY
SETCONTMANY
```
#### `EDE4` SETCONTCTRMANYX [#ede4-setcontctrmanyx]
Takes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`).
**Category:** Cont Registers (cont\_registers)
```fift Fift
SETCONTCTRMANYX
SETCONTMANYX
```
#### `EDF0` COMPOS [#edf0-compos]
Computes the composition `compose0(c, c')`, which has the meaning of ''perform `c`, and, if successful, perform `c'`'' (if `c` is a boolean circuit) or simply ''perform `c`, then `c'`''. Equivalent to `SWAP` `c0 SETCONT`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
COMPOS
BOOLAND
```
#### `EDF1` COMPOSALT [#edf1-composalt]
Computes the alternative composition `compose1(c, c')`, which has the meaning of ''perform `c`, and, if not successful, perform `c'`'' (if `c` is a boolean circuit). Equivalent to `SWAP` `c1 SETCONT`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
COMPOSALT
BOOLOR
```
#### `EDF2` COMPOSBOTH [#edf2-composboth]
Computes composition `compose1(compose0(c, c'), c')`, which has the meaning of ''compute boolean circuit `c`, then compute `c'`, regardless of the result of `c`''.
**Category:** Cont Registers (cont\_registers)
```fift Fift
COMPOSBOTH
```
#### `EDF3` ATEXIT [#edf3-atexit]
Sets `c0` to `compose0(c, c0)`. In other words, `c` will be executed before exiting current subroutine.
**Category:** Cont Registers (cont\_registers)
```fift Fift
ATEXIT
```
#### `EDF4` ATEXITALT [#edf4-atexitalt]
Sets `c1` to `compose1(c, c1)`. In other words, `c` will be executed before exiting current subroutine by its alternative return path.
**Category:** Cont Registers (cont\_registers)
```fift Fift
ATEXITALT
```
#### `EDF5` SETEXITALT [#edf5-setexitalt]
Sets `c1` to `compose1(compose0(c, c0), c1)`, In this way, a subsequent `RETALT` will first execute `c`, then transfer control to the original `c0`. This can be used, for instance, to exit from nested loops.
**Category:** Cont Registers (cont\_registers)
```fift Fift
SETEXITALT
```
#### `EDF6` THENRET [#edf6-thenret]
Computes `compose0(c, c0)`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
THENRET
```
#### `EDF7` THENRETALT [#edf7-thenretalt]
Computes `compose0(c, c1)`
**Category:** Cont Registers (cont\_registers)
```fift Fift
THENRETALT
```
#### `EDF8` INVERT [#edf8-invert]
Interchanges `c0` and `c1`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
INVERT
```
#### `EDF9` BOOLEVAL [#edf9-booleval]
Performs `cc:=compose1(compose0(c, compose0(-1 PUSHINT, cc)), compose0(0 PUSHINT, cc))`. If `c` represents a boolean circuit, the net effect is to evaluate it and push either `-1` or `0` into the stack before continuing.
**Category:** Cont Registers (cont\_registers)
```fift Fift
BOOLEVAL
```
#### `EDFA` SAMEALT [#edfa-samealt]
Sets `c1` to `c0`. Equivalent to `c0 PUSHCTR` `c1 POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
SAMEALT
```
#### `EDFB` SAMEALTSAVE [#edfb-samealtsave]
Sets `c1` to `c0`, but first saves the old value of `c1` into the savelist of `c0`. Equivalent to `c1 SAVE` `SAMEALT`.
**Category:** Cont Registers (cont\_registers)
```fift Fift
SAMEALTSAVE
```
#### `F0nn` CALLDICT [#f0nn-calldict]
Calls the continuation in `c3`, pushing integer `0 <= nn <= 255` into its stack as an argument. Approximately equivalent to `[nn] PUSHINT` `c3 PUSHCTR` `EXECUTE`.
**Category:** Cont Dict (cont\_dict)
```fift Fift
[nn] CALL
[nn] CALLDICT
```
#### `F12_n` CALLDICT\_LONG [#f12_n-calldict_long]
For `0 <= n < 2^14`, an encoding of `[n] CALL` for larger values of `n`.
**Category:** Cont Dict (cont\_dict)
```fift Fift
[n] CALL
[n] CALLDICT
```
#### `F16_n` JMPDICT [#f16_n-jmpdict]
Jumps to the continuation in `c3`, pushing integer `0 <= n < 2^14` as its argument. Approximately equivalent to `n PUSHINT` `c3 PUSHCTR` `JMPX`.
**Category:** Cont Dict (cont\_dict)
```fift Fift
[n] JMP
```
#### `F1A_n` PREPAREDICT [#f1a_n-preparedict]
Equivalent to `n PUSHINT` `c3 PUSHCTR`, for `0 <= n < 2^14`. In this way, `[n] CALL` is approximately equivalent to `[n] PREPARE` `EXECUTE`, and `[n] JMP` is approximately equivalent to `[n] PREPARE` `JMPX`. One might use, for instance, `CALLXARGS` or `CALLCC` instead of `EXECUTE` here.
**Category:** Cont Dict (cont\_dict)
```fift Fift
[n] PREPARE
[n] PREPAREDICT
```
#### `F22_n` THROW\_SHORT [#f22_n-throw_short]
Throws exception `0 <= n <= 63` with parameter zero. In other words, it transfers control to the continuation in `c2`, pushing `0` and `n` into its stack, and discarding the old stack altogether.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROW
```
#### `F26_n` THROWIF\_SHORT [#f26_n-throwif_short]
Throws exception `0 <= n <= 63` with parameter zero only if integer `f!=0`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWIF
```
#### `F2A_n` THROWIFNOT\_SHORT [#f2a_n-throwifnot_short]
Throws exception `0 <= n <= 63` with parameter zero only if integer `f=0`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWIFNOT
```
#### `F2C4_n` THROW [#f2c4_n-throw]
For `0 <= n < 2^11`, an encoding of `[n] THROW` for larger values of `n`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROW
```
#### `F2CC_n` THROWARG [#f2cc_n-throwarg]
Throws exception `0 <= n < 2^11` with parameter `x`, by copying `x` and `n` into the stack of `c2` and transferring control to `c2`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWARG
```
#### `F2D4_n` THROWIF [#f2d4_n-throwif]
For `0 <= n < 2^11`, an encoding of `[n] THROWIF` for larger values of `n`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWIF
```
#### `F2DC_n` THROWARGIF [#f2dc_n-throwargif]
Throws exception `0 <= nn < 2^11` with parameter `x` only if integer `f!=0`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWARGIF
```
#### `F2E4_n` THROWIFNOT [#f2e4_n-throwifnot]
For `0 <= n < 2^11`, an encoding of `[n] THROWIFNOT` for larger values of `n`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWIFNOT
```
#### `F2EC_n` THROWARGIFNOT [#f2ec_n-throwargifnot]
Throws exception `0 <= n < 2^11` with parameter `x` only if integer `f=0`.
**Category:** Exceptions (exceptions)
```fift Fift
[n] THROWARGIFNOT
```
#### `F2F0` THROWANY [#f2f0-throwany]
Throws exception `0 <= n < 2^16` with parameter zero. Approximately equivalent to `ZERO` `SWAP` `THROWARGANY`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWANY
```
#### `F2F1` THROWARGANY [#f2f1-throwargany]
Throws exception `0 <= n < 2^16` with parameter `x`, transferring control to the continuation in `c2`. Approximately equivalent to `c2 PUSHCTR` `2 JMPXARGS`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWARGANY
```
#### `F2F2` THROWANYIF [#f2f2-throwanyif]
Throws exception `0 <= n < 2^16` with parameter zero only if `f!=0`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWANYIF
```
#### `F2F3` THROWARGANYIF [#f2f3-throwarganyif]
Throws exception `0 <= n<2^16` with parameter `x` only if `f!=0`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWARGANYIF
```
#### `F2F4` THROWANYIFNOT [#f2f4-throwanyifnot]
Throws exception `0 <= n<2^16` with parameter zero only if `f=0`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWANYIFNOT
```
#### `F2F5` THROWARGANYIFNOT [#f2f5-throwarganyifnot]
Throws exception `0 <= n<2^16` with parameter `x` only if `f=0`.
**Category:** Exceptions (exceptions)
```fift Fift
THROWARGANYIFNOT
```
#### `F2FF` TRY [#f2ff-try]
Sets `c2` to `c'`, first saving the old value of `c2` both into the savelist of `c'` and into the savelist of the current continuation, which is stored into `c.c0` and `c'.c0`. Then runs `c` similarly to `EXECUTE`. If `c` does not throw any exceptions, the original value of `c2` is automatically restored on return from `c`. If an exception occurs, the execution is transferred to `c'`, but the original value of `c2` is restored in the process, so that `c'` can re-throw the exception by `THROWANY` if it cannot handle it by itself.
**Category:** Exceptions (exceptions)
```fift Fift
TRY
```
#### `F3pr` TRYARGS [#f3pr-tryargs]
Similar to `TRY`, but with `[p] [r] CALLXARGS` internally used instead of `EXECUTE`. In this way, all but the top `0 <= p <= 15` stack elements will be saved into current continuation's stack, and then restored upon return from either `c` or `c'`, with the top `0 <= r <= 15` values of the resulting stack of `c` or `c'` copied as return values.
**Category:** Exceptions (exceptions)
```fift Fift
[p] [r] TRYARGS
```
#### `F400` STDICT [#f400-stdict]
Stores dictionary `D` into *Builder* `b`, returning the resulting *Builder* `b'`. In other words, if `D` is a cell, performs `STONE` and `STREF`; if `D` is *Null*, performs `NIP` and `STZERO`; otherwise throws a type checking exception.
**Category:** Dict Serial (dict\_serial)
```fift Fift
STDICT
STOPTREF
```
#### `F401` SKIPDICT [#f401-skipdict]
Equivalent to `LDDICT` `NIP`.
**Category:** Dict Serial (dict\_serial)
```fift Fift
SKIPDICT
SKIPOPTREF
```
#### `F402` LDDICTS [#f402-lddicts]
Loads (parses) a (*Slice*-represented) dictionary `s'` from *Slice* `s`, and returns the remainder of `s` as `s''`. This is a ''split function'' for all `HashmapE(n,X)` dictionary types.
**Category:** Dict Serial (dict\_serial)
```fift Fift
LDDICTS
```
#### `F403` PLDDICTS [#f403-plddicts]
Preloads a (*Slice*-represented) dictionary `s'` from *Slice* `s`. Approximately equivalent to `LDDICTS` `DROP`.
**Category:** Dict Serial (dict\_serial)
```fift Fift
PLDDICTS
```
#### `F404` LDDICT [#f404-lddict]
Loads (parses) a dictionary `D` from *Slice* `s`, and returns the remainder of `s` as `s'`. May be applied to dictionaries or to values of arbitrary `(^Y)?` types.
**Category:** Dict Serial (dict\_serial)
```fift Fift
LDDICT
LDOPTREF
```
#### `F405` PLDDICT [#f405-plddict]
Preloads a dictionary `D` from *Slice* `s`. Approximately equivalent to `LDDICT` `DROP`.
**Category:** Dict Serial (dict\_serial)
```fift Fift
PLDDICT
PLDOPTREF
```
#### `F406` LDDICTQ [#f406-lddictq]
A quiet version of `LDDICT`.
**Category:** Dict Serial (dict\_serial)
```fift Fift
LDDICTQ
```
#### `F407` PLDDICTQ [#f407-plddictq]
A quiet version of `PLDDICT`.
**Category:** Dict Serial (dict\_serial)
```fift Fift
PLDDICTQ
```
#### `F40A` DICTGET [#f40a-dictget]
Looks up key `k` (represented by a *Slice*, the first `0 <= n <= 1023` data bits of which are used as a key) in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys. On success, returns the value found as a *Slice* `x`.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTGET
```
#### `F40B` DICTGETREF [#f40b-dictgetref]
Similar to `DICTGET`, but with a `LDREF` `ENDS` applied to `x` on success. This operation is useful for dictionaries of type `HashmapE(n,^Y)`.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTGETREF
```
#### `F40C` DICTIGET [#f40c-dictiget]
Similar to `DICTGET`, but with a signed (big-endian) `n`-bit *Integer* `i` as a key. If `i` does not fit into `n` bits, returns `0`. If `i` is a `NaN`, throws an integer overflow exception.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTIGET
```
#### `F40D` DICTIGETREF [#f40d-dictigetref]
Combines `DICTIGET` with `DICTGETREF`: it uses signed `n`-bit *Integer* `i` as a key and returns a *Cell* instead of a *Slice* on success.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTIGETREF
```
#### `F40E` DICTUGET [#f40e-dictuget]
Similar to `DICTIGET`, but with *unsigned* (big-endian) `n`-bit *Integer* `i` used as a key.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTUGET
```
#### `F40F` DICTUGETREF [#f40f-dictugetref]
Similar to `DICTIGETREF`, but with an unsigned `n`-bit *Integer* key `i`.
**Category:** Dict Get (dict\_get)
```fift Fift
DICTUGETREF
```
#### `F412` DICTSET [#f412-dictset]
Sets the value associated with `n`-bit key `k` (represented by a *Slice* as in `DICTGET`) in dictionary `D` (also represented by a *Slice*) to value `x` (again a *Slice*), and returns the resulting dictionary as `D'`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTSET
```
#### `F413` DICTSETREF [#f413-dictsetref]
Similar to `DICTSET`, but with the value set to a reference to *Cell* `c`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTSETREF
```
#### `F414` DICTISET [#f414-dictiset]
Similar to `DICTSET`, but with the key represented by a (big-endian) signed `n`-bit integer `i`. If `i` does not fit into `n` bits, a range check exception is generated.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTISET
```
#### `F415` DICTISETREF [#f415-dictisetref]
Similar to `DICTSETREF`, but with the key a signed `n`-bit integer as in `DICTISET`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTISETREF
```
#### `F416` DICTUSET [#f416-dictuset]
Similar to `DICTISET`, but with `i` an *unsigned* `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUSET
```
#### `F417` DICTUSETREF [#f417-dictusetref]
Similar to `DICTISETREF`, but with `i` unsigned.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUSETREF
```
#### `F41A` DICTSETGET [#f41a-dictsetget]
Combines `DICTSET` with `DICTGET`: it sets the value corresponding to key `k` to `x`, but also returns the old value `y` associated with the key in question, if present.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTSETGET
```
#### `F41B` DICTSETGETREF [#f41b-dictsetgetref]
Combines `DICTSETREF` with `DICTGETREF` similarly to `DICTSETGET`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTSETGETREF
```
#### `F41C` DICTISETGET [#f41c-dictisetget]
`DICTISETGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTISETGET
```
#### `F41D` DICTISETGETREF [#f41d-dictisetgetref]
`DICTISETGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTISETGETREF
```
#### `F41E` DICTUSETGET [#f41e-dictusetget]
`DICTISETGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUSETGET
```
#### `F41F` DICTUSETGETREF [#f41f-dictusetgetref]
`DICTISETGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUSETGETREF
```
#### `F422` DICTREPLACE [#f422-dictreplace]
A *Replace* operation, which is similar to `DICTSET`, but sets the value of key `k` in dictionary `D` to `x` only if the key `k` was already present in `D`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTREPLACE
```
#### `F423` DICTREPLACEREF [#f423-dictreplaceref]
A *Replace* counterpart of `DICTSETREF`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTREPLACEREF
```
#### `F424` DICTIREPLACE [#f424-dictireplace]
`DICTREPLACE`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIREPLACE
```
#### `F425` DICTIREPLACEREF [#f425-dictireplaceref]
`DICTREPLACEREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIREPLACEREF
```
#### `F426` DICTUREPLACE [#f426-dictureplace]
`DICTREPLACE`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUREPLACE
```
#### `F427` DICTUREPLACEREF [#f427-dictureplaceref]
`DICTREPLACEREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUREPLACEREF
```
#### `F42A` DICTREPLACEGET [#f42a-dictreplaceget]
A *Replace* counterpart of `DICTSETGET`: on success, also returns the old value associated with the key in question.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTREPLACEGET
```
#### `F42B` DICTREPLACEGETREF [#f42b-dictreplacegetref]
A *Replace* counterpart of `DICTSETGETREF`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTREPLACEGETREF
```
#### `F42C` DICTIREPLACEGET [#f42c-dictireplaceget]
`DICTREPLACEGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIREPLACEGET
```
#### `F42D` DICTIREPLACEGETREF [#f42d-dictireplacegetref]
`DICTREPLACEGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIREPLACEGETREF
```
#### `F42E` DICTUREPLACEGET [#f42e-dictureplaceget]
`DICTREPLACEGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUREPLACEGET
```
#### `F42F` DICTUREPLACEGETREF [#f42f-dictureplacegetref]
`DICTREPLACEGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUREPLACEGETREF
```
#### `F432` DICTADD [#f432-dictadd]
An *Add* counterpart of `DICTSET`: sets the value associated with key `k` in dictionary `D` to `x`, but only if it is not already present in `D`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTADD
```
#### `F433` DICTADDREF [#f433-dictaddref]
An *Add* counterpart of `DICTSETREF`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTADDREF
```
#### `F434` DICTIADD [#f434-dictiadd]
`DICTADD`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIADD
```
#### `F435` DICTIADDREF [#f435-dictiaddref]
`DICTADDREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIADDREF
```
#### `F436` DICTUADD [#f436-dictuadd]
`DICTADD`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUADD
```
#### `F437` DICTUADDREF [#f437-dictuaddref]
`DICTADDREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUADDREF
```
#### `F43A` DICTADDGET [#f43a-dictaddget]
An *Add* counterpart of `DICTSETGET`: sets the value associated with key `k` in dictionary `D` to `x`, but only if key `k` is not already present in `D`. Otherwise, just returns the old value `y` without changing the dictionary.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTADDGET
```
#### `F43B` DICTADDGETREF [#f43b-dictaddgetref]
An *Add* counterpart of `DICTSETGETREF`.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTADDGETREF
```
#### `F43C` DICTIADDGET [#f43c-dictiaddget]
`DICTADDGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIADDGET
```
#### `F43D` DICTIADDGETREF [#f43d-dictiaddgetref]
`DICTADDGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTIADDGETREF
```
#### `F43E` DICTUADDGET [#f43e-dictuaddget]
`DICTADDGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUADDGET
```
#### `F43F` DICTUADDGETREF [#f43f-dictuaddgetref]
`DICTADDGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift Fift
DICTUADDGETREF
```
#### `F441` DICTSETB [#f441-dictsetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTSETB
```
#### `F442` DICTISETB [#f442-dictisetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTISETB
```
#### `F443` DICTUSETB [#f443-dictusetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUSETB
```
#### `F445` DICTSETGETB [#f445-dictsetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTSETGETB
```
#### `F446` DICTISETGETB [#f446-dictisetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTISETGETB
```
#### `F447` DICTUSETGETB [#f447-dictusetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUSETGETB
```
#### `F449` DICTREPLACEB [#f449-dictreplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTREPLACEB
```
#### `F44A` DICTIREPLACEB [#f44a-dictireplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTIREPLACEB
```
#### `F44B` DICTUREPLACEB [#f44b-dictureplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUREPLACEB
```
#### `F44D` DICTREPLACEGETB [#f44d-dictreplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTREPLACEGETB
```
#### `F44E` DICTIREPLACEGETB [#f44e-dictireplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTIREPLACEGETB
```
#### `F44F` DICTUREPLACEGETB [#f44f-dictureplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUREPLACEGETB
```
#### `F451` DICTADDB [#f451-dictaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTADDB
```
#### `F452` DICTIADDB [#f452-dictiaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTIADDB
```
#### `F453` DICTUADDB [#f453-dictuaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUADDB
```
#### `F455` DICTADDGETB [#f455-dictaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTADDGETB
```
#### `F456` DICTIADDGETB [#f456-dictiaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTIADDGETB
```
#### `F457` DICTUADDGETB [#f457-dictuaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift Fift
DICTUADDGETB
```
#### `F459` DICTDEL [#f459-dictdel]
Deletes `n`-bit key, represented by a *Slice* `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'` and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTDEL
```
#### `F45A` DICTIDEL [#f45a-dictidel]
A version of `DICTDEL` with the key represented by a signed `n`-bit *Integer* `i`. If `i` does not fit into `n` bits, simply returns `D` `0` (''key not found, dictionary unmodified'').
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTIDEL
```
#### `F45B` DICTUDEL [#f45b-dictudel]
Similar to `DICTIDEL`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTUDEL
```
#### `F462` DICTDELGET [#f462-dictdelget]
Deletes `n`-bit key, represented by a *Slice* `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'`, the original value `x` associated with the key `k` (represented by a *Slice*), and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTDELGET
```
#### `F463` DICTDELGETREF [#f463-dictdelgetref]
Similar to `DICTDELGET`, but with `LDREF` `ENDS` applied to `x` on success, so that the value returned `c` is a *Cell*.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTDELGETREF
```
#### `F464` DICTIDELGET [#f464-dictidelget]
`DICTDELGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTIDELGET
```
#### `F465` DICTIDELGETREF [#f465-dictidelgetref]
`DICTDELGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTIDELGETREF
```
#### `F466` DICTUDELGET [#f466-dictudelget]
`DICTDELGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTUDELGET
```
#### `F467` DICTUDELGETREF [#f467-dictudelgetref]
`DICTDELGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift Fift
DICTUDELGETREF
```
#### `F469` DICTGETOPTREF [#f469-dictgetoptref]
A variant of `DICTGETREF` that returns *Null* instead of the value `c^?` if the key `k` is absent from dictionary `D`.
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTGETOPTREF
```
#### `F46A` DICTIGETOPTREF [#f46a-dictigetoptref]
`DICTGETOPTREF`, but with `i` a signed `n`-bit integer. If the key `i` is out of range, also returns *Null*.
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTIGETOPTREF
```
#### `F46B` DICTUGETOPTREF [#f46b-dictugetoptref]
`DICTGETOPTREF`, but with `i` an unsigned `n`-bit integer. If the key `i` is out of range, also returns *Null*.
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTUGETOPTREF
```
#### `F46D` DICTSETGETOPTREF [#f46d-dictsetgetoptref]
A variant of both `DICTGETOPTREF` and `DICTSETGETREF` that sets the value corresponding to key `k` in dictionary `D` to `c^?` (if `c^?` is *Null*, then the key is deleted instead), and returns the old value `~c^?` (if the key `k` was absent before, returns *Null* instead).
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTSETGETOPTREF
```
#### `F46E` DICTISETGETOPTREF [#f46e-dictisetgetoptref]
Similar to primitive `DICTSETGETOPTREF`, but using signed `n`-bit *Integer* `i` as a key. If `i` does not fit into `n` bits, throws a range checking exception.
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTISETGETOPTREF
```
#### `F46F` DICTUSETGETOPTREF [#f46f-dictusetgetoptref]
Similar to primitive `DICTSETGETOPTREF`, but using unsigned `n`-bit *Integer* `i` as a key.
**Category:** Dict Mayberef (dict\_mayberef)
```fift Fift
DICTUSETGETOPTREF
```
#### `F470` PFXDICTSET [#f470-pfxdictset]
**Category:** Dict Prefix (dict\_prefix)
```fift Fift
PFXDICTSET
```
#### `F471` PFXDICTREPLACE [#f471-pfxdictreplace]
**Category:** Dict Prefix (dict\_prefix)
```fift Fift
PFXDICTREPLACE
```
#### `F472` PFXDICTADD [#f472-pfxdictadd]
**Category:** Dict Prefix (dict\_prefix)
```fift Fift
PFXDICTADD
```
#### `F473` PFXDICTDEL [#f473-pfxdictdel]
**Category:** Dict Prefix (dict\_prefix)
```fift Fift
PFXDICTDEL
```
#### `F474` DICTGETNEXT [#f474-dictgetnext]
Computes the minimal key `k'` in dictionary `D` that is lexicographically greater than `k`, and returns `k'` (represented by a *Slice*) along with associated value `x'` (also represented by a *Slice*).
**Category:** Dict Next (dict\_next)
```fift Fift
DICTGETNEXT
```
#### `F475` DICTGETNEXTEQ [#f475-dictgetnexteq]
Similar to `DICTGETNEXT`, but computes the minimal key `k'` that is lexicographically greater than or equal to `k`.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTGETNEXTEQ
```
#### `F476` DICTGETPREV [#f476-dictgetprev]
Similar to `DICTGETNEXT`, but computes the maximal key `k'` lexicographically smaller than `k`.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTGETPREV
```
#### `F477` DICTGETPREVEQ [#f477-dictgetpreveq]
Similar to `DICTGETPREV`, but computes the maximal key `k'` lexicographically smaller than or equal to `k`.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTGETPREVEQ
```
#### `F478` DICTIGETNEXT [#f478-dictigetnext]
Similar to `DICTGETNEXT`, but interprets all keys in dictionary `D` as big-endian signed `n`-bit integers, and computes the minimal key `i'` that is larger than *Integer* `i` (which does not necessarily fit into `n` bits).
**Category:** Dict Next (dict\_next)
```fift Fift
DICTIGETNEXT
```
#### `F479` DICTIGETNEXTEQ [#f479-dictigetnexteq]
Similar to `DICTGETNEXTEQ`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTIGETNEXTEQ
```
#### `F47A` DICTIGETPREV [#f47a-dictigetprev]
Similar to `DICTGETPREV`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTIGETPREV
```
#### `F47B` DICTIGETPREVEQ [#f47b-dictigetpreveq]
Similar to `DICTGETPREVEQ`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTIGETPREVEQ
```
#### `F47C` DICTUGETNEXT [#f47c-dictugetnext]
Similar to `DICTGETNEXT`, but interprets all keys in dictionary `D` as big-endian unsigned `n`-bit integers, and computes the minimal key `i'` that is larger than *Integer* `i` (which does not necessarily fit into `n` bits, and is not necessarily non-negative).
**Category:** Dict Next (dict\_next)
```fift Fift
DICTUGETNEXT
```
#### `F47D` DICTUGETNEXTEQ [#f47d-dictugetnexteq]
Similar to `DICTGETNEXTEQ`, but interprets keys as unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTUGETNEXTEQ
```
#### `F47E` DICTUGETPREV [#f47e-dictugetprev]
Similar to `DICTGETPREV`, but interprets keys as unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTUGETPREV
```
#### `F47F` DICTUGETPREVEQ [#f47f-dictugetpreveq]
Similar to `DICTGETPREVEQ`, but interprets keys a unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift Fift
DICTUGETPREVEQ
```
#### `F482` DICTMIN [#f482-dictmin]
Computes the minimal key `k` (represented by a *Slice* with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTMIN
```
#### `F483` DICTMINREF [#f483-dictminref]
Similar to `DICTMIN`, but returns the only reference in the value as a *Cell* `c`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTMINREF
```
#### `F484` DICTIMIN [#f484-dictimin]
Similar to `DICTMIN`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTMIN` and `DICTUMIN`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIMIN
```
#### `F485` DICTIMINREF [#f485-dictiminref]
Similar to `DICTIMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIMINREF
```
#### `F486` DICTUMIN [#f486-dictumin]
Similar to `DICTMIN`, but returns the key as an unsigned `n`-bit *Integer* `i`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUMIN
```
#### `F487` DICTUMINREF [#f487-dictuminref]
Similar to `DICTUMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUMINREF
```
#### `F48A` DICTMAX [#f48a-dictmax]
Computes the maximal key `k` (represented by a *Slice* with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTMAX
```
#### `F48B` DICTMAXREF [#f48b-dictmaxref]
Similar to `DICTMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTMAXREF
```
#### `F48C` DICTIMAX [#f48c-dictimax]
Similar to `DICTMAX`, but computes the maximal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTMAX` and `DICTUMAX`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIMAX
```
#### `F48D` DICTIMAXREF [#f48d-dictimaxref]
Similar to `DICTIMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIMAXREF
```
#### `F48E` DICTUMAX [#f48e-dictumax]
Similar to `DICTMAX`, but returns the key as an unsigned `n`-bit *Integer* `i`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUMAX
```
#### `F48F` DICTUMAXREF [#f48f-dictumaxref]
Similar to `DICTUMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUMAXREF
```
#### `F492` DICTREMMIN [#f492-dictremmin]
Computes the minimal key `k` (represented by a *Slice* with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTREMMIN
```
#### `F493` DICTREMMINREF [#f493-dictremminref]
Similar to `DICTREMMIN`, but returns the only reference in the value as a *Cell* `c`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTREMMINREF
```
#### `F494` DICTIREMMIN [#f494-dictiremmin]
Similar to `DICTREMMIN`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTREMMIN` and `DICTUREMMIN`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIREMMIN
```
#### `F495` DICTIREMMINREF [#f495-dictiremminref]
Similar to `DICTIREMMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIREMMINREF
```
#### `F496` DICTUREMMIN [#f496-dicturemmin]
Similar to `DICTREMMIN`, but returns the key as an unsigned `n`-bit *Integer* `i`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUREMMIN
```
#### `F497` DICTUREMMINREF [#f497-dicturemminref]
Similar to `DICTUREMMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUREMMINREF
```
#### `F49A` DICTREMMAX [#f49a-dictremmax]
Computes the maximal key `k` (represented by a *Slice* with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTREMMAX
```
#### `F49B` DICTREMMAXREF [#f49b-dictremmaxref]
Similar to `DICTREMMAX`, but returns the only reference in the value as a *Cell* `c`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTREMMAXREF
```
#### `F49C` DICTIREMMAX [#f49c-dictiremmax]
Similar to `DICTREMMAX`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTREMMAX` and `DICTUREMMAX`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIREMMAX
```
#### `F49D` DICTIREMMAXREF [#f49d-dictiremmaxref]
Similar to `DICTIREMMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTIREMMAXREF
```
#### `F49E` DICTUREMMAX [#f49e-dicturemmax]
Similar to `DICTREMMAX`, but returns the key as an unsigned `n`-bit *Integer* `i`.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUREMMAX
```
#### `F49F` DICTUREMMAXREF [#f49f-dicturemmaxref]
Similar to `DICTUREMMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift Fift
DICTUREMMAXREF
```
#### `F4A0` DICTIGETJMP [#f4a0-dictigetjmp]
Similar to `DICTIGET`, but with `x` `BLESS`ed into a continuation with a subsequent `JMPX` to it on success. On failure, does nothing. This is useful for implementing `switch`/`case` constructions.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTIGETJMP
```
#### `F4A1` DICTUGETJMP [#f4a1-dictugetjmp]
Similar to `DICTIGETJMP`, but performs `DICTUGET` instead of `DICTIGET`.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTUGETJMP
```
#### `F4A2` DICTIGETEXEC [#f4a2-dictigetexec]
Similar to `DICTIGETJMP`, but with `EXECUTE` instead of `JMPX`.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTIGETEXEC
```
#### `F4A3` DICTUGETEXEC [#f4a3-dictugetexec]
Similar to `DICTUGETJMP`, but with `EXECUTE` instead of `JMPX`.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTUGETEXEC
```
#### `F4A6_n` DICTPUSHCONST [#f4a6_n-dictpushconst]
Pushes a non-empty constant dictionary `D` (as a `Cell^?`) along with its key length `0 <= n <= 1023`, stored as a part of the instruction. The dictionary itself is created from the first of remaining references of the current continuation. In this way, the complete `DICTPUSHCONST` instruction can be obtained by first serializing `xF4A4_`, then the non-empty dictionary itself (one `1` bit and a cell reference), and then the unsigned 10-bit integer `n` (as if by a `STU 10` instruction). An empty dictionary can be pushed by a `NEWDICT` primitive instead.
**Category:** Dict Special (dict\_special)
```fift Fift
[ref] [n] DICTPUSHCONST
```
#### `F4A8` PFXDICTGETQ [#f4a8-pfxdictgetq]
Looks up the unique prefix of *Slice* `s` present in the prefix code dictionary represented by `Cell^?` `D` and `0 <= n <= 1023`. If found, the prefix of `s` is returned as `s'`, and the corresponding value (also a *Slice*) as `x`. The remainder of `s` is returned as a *Slice* `s''`. If no prefix of `s` is a key in prefix code dictionary `D`, returns the unchanged `s` and a zero flag to indicate failure.
**Category:** Dict Special (dict\_special)
```fift Fift
PFXDICTGETQ
```
#### `F4A9` PFXDICTGET [#f4a9-pfxdictget]
Similar to `PFXDICTGET`, but throws a cell deserialization failure exception on failure.
**Category:** Dict Special (dict\_special)
```fift Fift
PFXDICTGET
```
#### `F4AA` PFXDICTGETJMP [#f4aa-pfxdictgetjmp]
Similar to `PFXDICTGETQ`, but on success `BLESS`es the value `x` into a *Continuation* and transfers control to it as if by a `JMPX`. On failure, returns `s` unchanged and continues execution.
**Category:** Dict Special (dict\_special)
```fift Fift
PFXDICTGETJMP
```
#### `F4AB` PFXDICTGETEXEC [#f4ab-pfxdictgetexec]
Similar to `PFXDICTGETJMP`, but `EXEC`utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception.
**Category:** Dict Special (dict\_special)
```fift Fift
PFXDICTGETEXEC
```
#### `F4AE_n` PFXDICTCONSTGETJMP [#f4ae_n-pfxdictconstgetjmp]
Combines `[n] DICTPUSHCONST` for `0 <= n <= 1023` with `PFXDICTGETJMP`.
**Category:** Dict Special (dict\_special)
```fift Fift
[ref] [n] PFXDICTCONSTGETJMP
[ref] [n] PFXDICTSWITCH
```
#### `F4BC` DICTIGETJMPZ [#f4bc-dictigetjmpz]
A variant of `DICTIGETJMP` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTIGETJMPZ
```
#### `F4BD` DICTUGETJMPZ [#f4bd-dictugetjmpz]
A variant of `DICTUGETJMP` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTUGETJMPZ
```
#### `F4BE` DICTIGETEXECZ [#f4be-dictigetexecz]
A variant of `DICTIGETEXEC` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTIGETEXECZ
```
#### `F4BF` DICTUGETEXECZ [#f4bf-dictugetexecz]
A variant of `DICTUGETEXEC` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift Fift
DICTUGETEXECZ
```
#### `F4B1` SUBDICTGET [#f4b1-subdictget]
Constructs a subdictionary consisting of all keys beginning with prefix `k` (represented by a *Slice*, the first `0 <= l <= n <= 1023` data bits of which are used as a key) of length `l` in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys. On success, returns the new subdictionary of the same type `HashmapE(n,X)` as a *Slice* `D'`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTGET
```
#### `F4B2` SUBDICTIGET [#f4b2-subdictiget]
Variant of `SUBDICTGET` with the prefix represented by a signed big-endian `l`-bit *Integer* `x`, where necessarily `l <= 257`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTIGET
```
#### `F4B3` SUBDICTUGET [#f4b3-subdictuget]
Variant of `SUBDICTGET` with the prefix represented by an unsigned big-endian `l`-bit *Integer* `x`, where necessarily `l <= 256`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTUGET
```
#### `F4B5` SUBDICTRPGET [#f4b5-subdictrpget]
Similar to `SUBDICTGET`, but removes the common prefix `k` from all keys of the new dictionary `D'`, which becomes of type `HashmapE(n-l,X)`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTRPGET
```
#### `F4B6` SUBDICTIRPGET [#f4b6-subdictirpget]
Variant of `SUBDICTRPGET` with the prefix represented by a signed big-endian `l`-bit *Integer* `x`, where necessarily `l <= 257`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTIRPGET
```
#### `F4B7` SUBDICTURPGET [#f4b7-subdicturpget]
Variant of `SUBDICTRPGET` with the prefix represented by an unsigned big-endian `l`-bit *Integer* `x`, where necessarily `l <= 256`.
**Category:** Dict Sub (dict\_sub)
```fift Fift
SUBDICTURPGET
```
#### `F800` ACCEPT [#f800-accept]
Sets current gas limit `g_l` to its maximal allowed value `g_m`, and resets the gas credit `g_c` to zero, decreasing the value of `g_r` by `g_c` in the process. In other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves.
**Category:** App Gas (app\_gas)
```fift Fift
ACCEPT
```
#### `F801` SETGASLIMIT [#f801-setgaslimit]
Sets current gas limit `g_l` to the minimum of `g` and `g_m`, and resets the gas credit `g_c` to zero. If the gas consumed so far (including the present instruction) exceeds the resulting value of `g_l`, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that `SETGASLIMIT` with an argument `g >= 2^63-1` is equivalent to `ACCEPT`.
**Category:** App Gas (app\_gas)
```fift Fift
SETGASLIMIT
```
#### `F807` GASCONSUMED [#f807-gasconsumed]
Returns gas consumed by VM so far (including this instruction).
**Category:** App Gas (app\_gas)
```fift Fift
GASCONSUMED
```
#### `F80F` COMMIT [#f80f-commit]
Commits the current state of registers `c4` (''persistent data'') and `c5` (''actions'') so that the current execution is considered ''successful'' with the saved values even if an exception is thrown later.
**Category:** App Gas (app\_gas)
```fift Fift
COMMIT
```
#### `F810` RANDU256 [#f810-randu256]
Generates a new pseudo-random unsigned 256-bit *Integer* `x`. The algorithm is as follows: if `r` is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its `sha512(r)` is computed; the first 32 bytes of this hash are stored as the new value `r'` of the random seed, and the remaining 32 bytes are returned as the next random value `x`.
**Category:** App Rnd (app\_rnd)
```fift Fift
RANDU256
```
#### `F811` RAND [#f811-rand]
Generates a new pseudo-random integer `z` in the range `0...y-1` (or `y...-1`, if `y<0`). More precisely, an unsigned random value `x` is generated as in `RAND256U`; then `z:=floor(x*y/2^256)` is computed. Equivalent to `RANDU256` `256 MULRSHIFT`.
**Category:** App Rnd (app\_rnd)
```fift Fift
RAND
```
#### `F814` SETRAND [#f814-setrand]
Sets the random seed to unsigned 256-bit *Integer* `x`.
**Category:** App Rnd (app\_rnd)
```fift Fift
SETRAND
```
#### `F815` ADDRAND [#f815-addrand]
Mixes unsigned 256-bit *Integer* `x` into the random seed `r` by setting the random seed to `Sha` of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed `r`, and the second with the big-endian representation of `x`.
**Category:** App Rnd (app\_rnd)
```fift Fift
ADDRAND
RANDOMIZE
```
#### `F82i` GETPARAM [#f82i-getparam]
Returns the `i`-th parameter from the *Tuple* provided at `c7` for `0 <= i <= 15`. Equivalent to `c7 PUSHCTR` `FIRST` `[i] INDEX`. If one of these internal operations fails, throws an appropriate type checking or range checking exception.
**Category:** App Config (app\_config)
```fift Fift
[i] GETPARAM
```
**Aliases**:
* `NOW`
Returns the current Unix time as an *Integer*. If it is impossible to recover the requested value starting from `c7`, throws a type checking or range checking exception as appropriate. Equivalent to `3 GETPARAM`.
* `BLOCKLT`
Returns the starting logical time of the current block. Equivalent to `4 GETPARAM`.
* `LTIME`
Returns the logical time of the current transaction. Equivalent to `5 GETPARAM`.
* `RANDSEED`
Returns the current random seed as an unsigned 256-bit *Integer*. Equivalent to `6 GETPARAM`.
* `BALANCE`
Returns the remaining balance of the smart contract as a *Tuple* consisting of an *Integer* (the remaining Gram balance in nanograms) and a *Maybe Cell* (a dictionary with 32-bit keys representing the balance of ''extra currencies''). Equivalent to `7 GETPARAM`. Note that `RAW` primitives such as `SENDRAWMSG` do not update this field.
* `MYADDR`
Returns the internal address of the current smart contract as a *Slice* with a `MsgAddressInt`. If necessary, it can be parsed further using primitives such as `PARSEMSGADDR` or `REWRITESTDADDR`. Equivalent to `8 GETPARAM`.
* `CONFIGROOT`
Returns the *Maybe Cell* `D` with the current global configuration dictionary. Equivalent to `9 GETPARAM `.
* `MYCODE`
Retrieves code of smart-contract from c7. Equivalent to `10 GETPARAM `.
* `INCOMINGVALUE`
Retrieves value of incoming message from c7. Equivalent to `11 GETPARAM `.
* `STORAGEFEES`
Retrieves value of storage phase fees from c7. Equivalent to `12 GETPARAM `.
* `PREVBLOCKSINFOTUPLE`
Retrives PrevBlocksInfo: `[last_mc_blocks, prev_key_block]` from c7. Equivalent to `13 GETPARAM `.
* `UNPACKEDCONFIGTUPLE`
Retrives tuple that contains some config parameters as cell slices. If the parameter is absent from the config, the value is null. Values: \* **0**: `StoragePrices` from `ConfigParam 18`. Not the whole dict, but only the one StoragePrices entry (one which corresponds to the current time). \* **1**: `ConfigParam 19` (global id). \* **2**: `ConfigParam 20` (mc gas prices). \* **3**: `ConfigParam 21` (gas prices). \* **4**: `ConfigParam 24` (mc fwd fees). \* **5**: `ConfigParam 25` (fwd fees). \* **6**: `ConfigParam 43` (size limits).
* `DUEPAYMENT`
Retrives current debt for storage fee (nanotons).
#### `F830` CONFIGDICT [#f830-configdict]
Returns the global configuration dictionary along with its key length (32). Equivalent to `CONFIGROOT` `32 PUSHINT`.
**Category:** App Config (app\_config)
```fift Fift
CONFIGDICT
```
#### `F832` CONFIGPARAM [#f832-configparam]
Returns the value of the global configuration parameter with integer index `i` as a *Cell* `c`, and a flag to indicate success. Equivalent to `CONFIGDICT` `DICTIGETREF`.
**Category:** App Config (app\_config)
```fift Fift
CONFIGPARAM
```
#### `F833` CONFIGOPTPARAM [#f833-configoptparam]
Returns the value of the global configuration parameter with integer index `i` as a *Maybe Cell* `c^?`. Equivalent to `CONFIGDICT` `DICTIGETOPTREF`.
**Category:** App Config (app\_config)
```fift Fift
CONFIGOPTPARAM
```
#### `F83400` PREVMCBLOCKS [#f83400-prevmcblocks]
Retrives `last_mc_blocks` part of PrevBlocksInfo from c7 (parameter 13).
**Category:** App Config (app\_config)
```fift Fift
PREVMCBLOCKS
```
#### `F83401` PREVKEYBLOCK [#f83401-prevkeyblock]
Retrives `prev_key_block` part of PrevBlocksInfo from c7 (parameter 13).
**Category:** App Config (app\_config)
```fift Fift
PREVKEYBLOCK
```
#### `F83402` PREVMCBLOCKS\_100 [#f83402-prevmcblocks_100]
Retrives `last_mc_blocks_divisible_by_100` part of PrevBlocksInfo from c7 (parameter 13).
**Category:** App Config (app\_config)
```fift Fift
PREVMCBLOCKS_100
```
#### `F835` GLOBALID [#f835-globalid]
Retrieves `global_id` from 19 network config.
**Category:** App Config (app\_config)
```fift Fift
GLOBALID
```
#### `F836` GETGASFEE [#f836-getgasfee]
Calculates gas fee
**Category:** App Config (app\_config)
```fift Fift
GETGASFEE
```
#### `F837` GETSTORAGEFEE [#f837-getstoragefee]
Calculates storage fees (only current StoragePrices entry is used).
**Category:** App Config (app\_config)
```fift Fift
GETSTORAGEFEE
```
#### `F838` GETFORWARDFEE [#f838-getforwardfee]
Calculates forward fee.
**Category:** App Config (app\_config)
```fift Fift
GETFORWARDFEE
```
#### `F839` GETPRECOMPILEDGAS [#f839-getprecompiledgas]
Returns gas usage for the current contract if it is precompiled, `null` otherwise.
**Category:** App Config (app\_config)
```fift Fift
GETPRECOMPILEDGAS
```
#### `F83A` GETORIGINALFWDFEE [#f83a-getoriginalfwdfee]
Calculate `(fwd_fee * 2^16) / (2^16 - first_frac)`. Can be used to get the original `fwd_fee` of the message.
**Category:** App Config (app\_config)
```fift Fift
GETORIGINALFWDFEE
```
#### `F83B` GETGASFEESIMPLE [#f83b-getgasfeesimple]
Same as `GETGASFEE`, but without flat price (just `(gas_used * price) / 2^16)`.
**Category:** App Config (app\_config)
```fift Fift
GETGASFEESIMPLE
```
#### `F83C` GETFORWARDFEESIMPLE [#f83c-getforwardfeesimple]
Same as `GETFORWARDFEE`, but without lump price (just (`bits*bit_price + cells*cell_price) / 2^16`).
**Category:** App Config (app\_config)
```fift Fift
GETFORWARDFEESIMPLE
```
#### `F840` GETGLOBVAR [#f840-getglobvar]
Returns the `k`-th global variable for `0 <= k < 255`. Equivalent to `c7 PUSHCTR` `SWAP` `INDEXVARQ`.
**Category:** App Global (app\_global)
```fift Fift
GETGLOBVAR
```
#### `F85_k` GETGLOB [#f85_k-getglob]
Returns the `k`-th global variable for `1 <= k <= 31`. Equivalent to `c7 PUSHCTR` `[k] INDEXQ`.
**Category:** App Global (app\_global)
```fift Fift
[k] GETGLOB
```
#### `F860` SETGLOBVAR [#f860-setglobvar]
Assigns `x` to the `k`-th global variable for `0 <= k < 255`. Equivalent to `c7 PUSHCTR` `ROTREV` `SETINDEXVARQ` `c7 POPCTR`.
**Category:** App Global (app\_global)
```fift Fift
SETGLOBVAR
```
#### `F87_k` SETGLOB [#f87_k-setglob]
Assigns `x` to the `k`-th global variable for `1 <= k <= 31`. Equivalent to `c7 PUSHCTR` `SWAP` `k SETINDEXQ` `c7 POPCTR`.
**Category:** App Global (app\_global)
```fift Fift
[k] SETGLOB
```
#### `F880` GETEXTRABALANCE [#f880-getextrabalance]
Takes id of the extra currency (integer in range `0..2^32-1`), returns the amount of this extra currency on the account balance. The first `5` executions of `GETEXTRABALANCE` consume at most `26 + 200` gas each. The subsequent executions incur the full gas cost of `26` (normal instruction cost) plus gas for loading cells (up to `3300` if the dictionary has maximum depth).
**Category:** App Global (app\_global)
```fift Fift
GETEXTRABALANCE
```
#### `F881ii` GETPARAMLONG [#f881ii-getparamlong]
Returns the `i`-th parameter from the *Tuple* provided at `c7` for `0 <= i <= 255`. Equivalent to `c7 PUSHCTR` `FIRST` `[i] INDEX`. If one of these internal operations fails, throws an appropriate type checking or range checking exception.
**Category:** App Config (app\_config)
```fift Fift
[i] GETPARAMLONG
```
#### `F89i` INMSGPARAM [#f89i-inmsgparam]
Equivalent to `INMSGPARAMS` `i INDEX`
**Category:** App Config (app\_config)
```fift Fift
[i] INMSGPARAM
```
**Aliases**:
* `INMSG_BOUNCE`
Retrives `bounce` flag of incoming message.
* `INMSG_BOUNCED`
Retrives `bounced` flag of incoming message.
* `INMSG_SRC`
Retrives `src` flag of incoming message.
* `INMSG_FWDFEE`
Retrives `fwd_fee` field of incoming message.
* `INMSG_LT`
Retrives `lt` field of incoming message.
* `INMSG_UTIME`
Retrives `utime` field of incoming message.
* `INMSG_ORIGVALUE`
Retrives original value of the message. This is sometimes different from the value in `INCOMINGVALUE` and TVM stack because of storage fees.
* `INMSG_VALUE`
Retrives value of the message after deducting storage fees. This is same as in `INCOMINGVALUE` and TVM stack.
* `INMSG_VALUEEXTRA`
Same as in `INCOMINGVALUE`.
* `INMSG_STATEINIT`
Retrieves `init` field of the incoming message.
#### `F900` HASHCU [#f900-hashcu]
Computes the representation hash of a *Cell* `c` and returns it as a 256-bit unsigned integer `x`. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHCU
```
#### `F901` HASHSU [#f901-hashsu]
Computes the hash of a *Slice* `s` and returns it as a 256-bit unsigned integer `x`. The result is the same as if an ordinary cell containing only data and references from `s` had been created and its hash computed by `HASHCU`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHSU
```
#### `F902` SHA256U [#f902-sha256u]
Computes `Sha` of the data bits of *Slice* `s`. If the bit length of `s` is not divisible by eight, throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`.
**Category:** App Crypto (app\_crypto)
```fift Fift
SHA256U
```
#### `F90400` HASHEXT\_SHA256 [#f90400-hashext_sha256]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXT_SHA256
```
#### `F90401` HASHEXT\_SHA512 [#f90401-hashext_sha512]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXT_SHA512
```
#### `F90402` HASHEXT\_BLAKE2B [#f90402-hashext_blake2b]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXT_BLAKE2B
```
#### `F90403` HASHEXT\_KECCAK256 [#f90403-hashext_keccak256]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXT_KECCAK256
```
#### `F90404` HASHEXT\_KECCAK512 [#f90404-hashext_keccak512]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXT_KECCAK512
```
#### `F90500` HASHEXTR\_SHA256 [#f90500-hashextr_sha256]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTR_SHA256
```
#### `F90501` HASHEXTR\_SHA512 [#f90501-hashextr_sha512]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTR_SHA512
```
#### `F90502` HASHEXTR\_BLAKE2B [#f90502-hashextr_blake2b]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTR_BLAKE2B
```
#### `F90503` HASHEXTR\_KECCAK256 [#f90503-hashextr_keccak256]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTR_KECCAK256
```
#### `F90504` HASHEXTR\_KECCAK512 [#f90504-hashextr_keccak512]
Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTR_KECCAK512
```
#### `F90600` HASHEXTA\_SHA256 [#f90600-hashexta_sha256]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTA_SHA256
```
#### `F90601` HASHEXTA\_SHA512 [#f90601-hashexta_sha512]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTA_SHA512
```
#### `F90602` HASHEXTA\_BLAKE2B [#f90602-hashexta_blake2b]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTA_BLAKE2B
```
#### `F90603` HASHEXTA\_KECCAK256 [#f90603-hashexta_keccak256]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTA_KECCAK256
```
#### `F90604` HASHEXTA\_KECCAK512 [#f90604-hashexta_keccak512]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTA_KECCAK512
```
#### `F90700` HASHEXTAR\_SHA256 [#f90700-hashextar_sha256]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTAR_SHA256
```
#### `F90701` HASHEXTAR\_SHA512 [#f90701-hashextar_sha512]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTAR_SHA512
```
#### `F90702` HASHEXTAR\_BLAKE2B [#f90702-hashextar_blake2b]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTAR_BLAKE2B
```
#### `F90703` HASHEXTAR\_KECCAK256 [#f90703-hashextar_keccak256]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTAR_KECCAK256
```
#### `F90704` HASHEXTAR\_KECCAK512 [#f90704-hashextar_keccak512]
Calculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHEXTAR_KECCAK512
```
#### `F910` CHKSIGNU [#f910-chksignu]
Checks the Ed25519-signature `s` of a hash `h` (a 256-bit unsigned integer, usually computed as the hash of some data) using public key `k` (also represented by a 256-bit unsigned integer). The signature `s` must be a *Slice* containing at least 512 data bits; only the first 512 bits are used. The result is `-1` if the signature is valid, `0` otherwise. Notice that `CHKSIGNU` is equivalent to `ROT` `NEWC` `256 STU` `ENDC` `ROTREV` `CHKSIGNS`, i.e., to `CHKSIGNS` with the first argument `d` set to 256-bit *Slice* containing `h`. Therefore, if `h` is computed as the hash of some data, these data are hashed *twice*, the second hashing occurring inside `CHKSIGNS`.
**Category:** App Crypto (app\_crypto)
```fift Fift
CHKSIGNU
```
#### `F911` CHKSIGNS [#f911-chksigns]
Checks whether `s` is a valid Ed25519-signature of the data portion of *Slice* `d` using public key `k`, similarly to `CHKSIGNU`. If the bit length of *Slice* `d` is not divisible by eight, throws a cell underflow exception. The verification of Ed25519 signatures is the standard one, with `Sha` used to reduce `d` to the 256-bit number that is actually signed.
**Category:** App Crypto (app\_crypto)
```fift Fift
CHKSIGNS
```
#### `F912` ECRECOVER [#f912-ecrecover]
Recovers the public key from a secp256k1 signature, identical to Bitcoin/Ethereum operations. Takes a 32-byte hash as `uint256 hash` and a 65-byte signature as `uint8 v`, `uint256 r`, and `uint256 s`. In TON, the `v` value is strictly 0 or 1; no extra flags or extended values are supported. If the public key cannot be recovered, the instruction returns `0`. On success, it returns the recovered 65-byte public key as `uint8 h`, `uint256 x1`, and `uint256 x2`, followed by `-1`.
**Category:** App Crypto (app\_crypto)
```fift Fift
ECRECOVER
```
#### `F913` SECP256K1\_XONLY\_PUBKEY\_TWEAK\_ADD [#f913-secp256k1_xonly_pubkey_tweak_add]
performs [`secp256k1_xonly_pubkey_tweak_add`](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_extrakeys.h#L120). `key` and `tweak` are 256-bit unsigned integers. 65-byte public key is returned as `uint8 f`, `uint256 x, y` (as in `ECRECOVER`).
**Category:** App Crypto (app\_crypto)
```fift Fift
SECP256K1_XONLY_PUBKEY_TWEAK_ADD
```
#### `F914` P256\_CHKSIGNU [#f914-p256_chksignu]
Checks seck256r1-signature `sig` of a number `h` (a 256-bit unsigned integer, usually computed as the hash of some data) and public key `k`. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of [SECG SEC 1](https://www.secg.org/sec1-v2.pdf)). Signature `sig` is a 64-byte slice (two 256-bit unsigned integers `r` and `s`).
**Category:** App Crypto (app\_crypto)
```fift Fift
P256_CHKSIGNU
```
#### `F915` P256\_CHKSIGNS [#f915-p256_chksigns]
Checks seck256r1-signature `sig` of data portion of slice `d` and public key `k`. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of [SECG SEC 1](https://www.secg.org/sec1-v2.pdf)). Signature `sig` is a 64-byte slice (two 256-bit unsigned integers `r` and `s`).
**Category:** App Crypto (app\_crypto)
```fift Fift
P256_CHKSIGNS
```
#### `F916` HASHBU [#f916-hashbu]
Same as `ENDC HASHCU`, but without gas cost for cell creation.
**Category:** App Crypto (app\_crypto)
```fift Fift
HASHBU
```
#### `F920` RIST255\_FROMHASH [#f920-rist255_fromhash]
Deterministically generates a valid point `x` from a 512-bit hash (given as two 256-bit integers).
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_FROMHASH
```
#### `F921` RIST255\_VALIDATE [#f921-rist255_validate]
Checks that integer `x` is a valid representation of some curve point. Throws range\_chk on error.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_VALIDATE
```
#### `F922` RIST255\_ADD [#f922-rist255_add]
Addition of two points on a curve.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_ADD
```
#### `F923` RIST255\_SUB [#f923-rist255_sub]
Subtraction of two points on curve.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_SUB
```
#### `F924` RIST255\_MUL [#f924-rist255_mul]
Multiplies point `x` by a scalar `n`. Any `n` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_MUL
```
#### `F925` RIST255\_MULBASE [#f925-rist255_mulbase]
Multiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_MULBASE
```
#### `F926` RIST255\_PUSHL [#f926-rist255_pushl]
Pushes integer l=2^252+27742317777372353535851937790883648493, which is the order of the group.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_PUSHL
```
#### `B7F921` RIST255\_QVALIDATE [#b7f921-rist255_qvalidate]
Checks that integer `x` is a valid representation of some curve point. Returns -1 on success and 0 on failure.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_QVALIDATE
```
#### `B7F922` RIST255\_QADD [#b7f922-rist255_qadd]
Addition of two points on a curve. Returns -1 on success and 0 on failure.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_QADD
```
#### `B7F923` RIST255\_QSUB [#b7f923-rist255_qsub]
Subtraction of two points on curve. Returns -1 on success and 0 on failure.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_QSUB
```
#### `B7F924` RIST255\_QMUL [#b7f924-rist255_qmul]
Multiplies point `x` by a scalar `n`. Any `n` is valid, including negative. Returns -1 on success and 0 on failure.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_QMUL
```
#### `B7F925` RIST255\_QMULBASE [#b7f925-rist255_qmulbase]
Multiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
RIST255_QMULBASE
```
#### `F93000` BLS\_VERIFY [#f93000-bls_verify]
Checks BLS signature, return true on success, false otherwise.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_VERIFY
```
#### `F93001` BLS\_AGGREGATE [#f93001-bls_aggregate]
Aggregates signatures. `n>0`. Throw exception if `n=0` or if some `sig_i` is not a valid signature.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_AGGREGATE
```
#### `F93002` BLS\_FASTAGGREGATEVERIFY [#f93002-bls_fastaggregateverify]
Checks aggregated BLS signature for keys `pk_1...pk_n` and message `msg`. Return true on success, false otherwise. Return false if `n=0`.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_FASTAGGREGATEVERIFY
```
#### `F93003` BLS\_AGGREGATEVERIFY [#f93003-bls_aggregateverify]
Checks aggregated BLS signature for key-message pairs `pk_1 msg_1...pk_n msg_n`. Return true on success, false otherwise. Return false if `n=0`.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_AGGREGATEVERIFY
```
#### `F93010` BLS\_G1\_ADD [#f93010-bls_g1_add]
Addition on G1.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_ADD
```
#### `F93011` BLS\_G1\_SUB [#f93011-bls_g1_sub]
Subtraction on G1.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_SUB
```
#### `F93012` BLS\_G1\_NEG [#f93012-bls_g1_neg]
Negation on G1.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_NEG
```
#### `F93013` BLS\_G1\_MUL [#f93013-bls_g1_mul]
Multiplies G1 point `x` by scalar `s`. Any `s` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_MUL
```
#### `F93014` BLS\_G1\_MULTIEXP [#f93014-bls_g1_multiexp]
Calculates `x_1*s_1+...+x_n*s_n` for G1 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_MULTIEXP
```
#### `F93015` BLS\_G1\_ZERO [#f93015-bls_g1_zero]
Pushes zero point in G1.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_ZERO
```
#### `F93016` BLS\_MAP\_TO\_G1 [#f93016-bls_map_to_g1]
Converts FP element `f` to a G1 point.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_MAP_TO_G1
```
#### `F93017` BLS\_G1\_INGROUP [#f93017-bls_g1_ingroup]
Checks that slice `x` represents a valid element of G1.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_INGROUP
```
#### `F93018` BLS\_G1\_ISZERO [#f93018-bls_g1_iszero]
Checks that G1 point `x` is equal to zero.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G1_ISZERO
```
#### `F93020` BLS\_G2\_ADD [#f93020-bls_g2_add]
Addition on G2.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_ADD
```
#### `F93021` BLS\_G2\_SUB [#f93021-bls_g2_sub]
Subtraction on G2.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_SUB
```
#### `F93022` BLS\_G2\_NEG [#f93022-bls_g2_neg]
Negation on G2.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_NEG
```
#### `F93023` BLS\_G2\_MUL [#f93023-bls_g2_mul]
Multiplies G2 point `x` by scalar `s`. Any `s` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_MUL
```
#### `F93024` BLS\_G2\_MULTIEXP [#f93024-bls_g2_multiexp]
Calculates `x_1*s_1+...+x_n*s_n` for G2 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_MULTIEXP
```
#### `F93025` BLS\_G2\_ZERO [#f93025-bls_g2_zero]
Pushes zero point in G2.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_ZERO
```
#### `F93026` BLS\_MAP\_TO\_G2 [#f93026-bls_map_to_g2]
Converts FP2 element `f` to a G2 point.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_MAP_TO_G2
```
#### `F93027` BLS\_G2\_INGROUP [#f93027-bls_g2_ingroup]
Checks that slice `x` represents a valid element of G2.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_INGROUP
```
#### `F93028` BLS\_G2\_ISZERO [#f93028-bls_g2_iszero]
Checks that G2 point `x` is equal to zero.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_G2_ISZERO
```
#### `F93030` BLS\_PAIRING [#f93030-bls_pairing]
Given G1 points `x_i` and G2 points `y_i`, calculates and multiply pairings of `x_i,y_i`. Returns true if the result is the multiplicative identity in FP12, false otherwise. Returns false if `n=0`.
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_PAIRING
```
#### `F93031` BLS\_PUSHR [#f93031-bls_pushr]
Pushes the order of G1 and G2 (approx. `2^255`).
**Category:** App Crypto (app\_crypto)
```fift Fift
BLS_PUSHR
```
#### `F940` CDATASIZEQ [#f940-cdatasizeq]
Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z` in the dag rooted at *Cell* `c`, effectively returning the total storage used by this dag taking into account the identification of equal cells. The values of `x`, `y`, and `z` are computed by a depth-first traversal of this dag, with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells `x` cannot exceed non-negative *Integer* `n`; otherwise the computation is aborted before visiting the `(n+1)`-st cell and a zero is returned to indicate failure. If `c` is *Null*, returns `x=y=z=0`.
**Category:** App Misc (app\_misc)
```fift Fift
CDATASIZEQ
```
#### `F941` CDATASIZE [#f941-cdatasize]
A non-quiet version of `CDATASIZEQ` that throws a cell overflow exception (8) on failure.
**Category:** App Misc (app\_misc)
```fift Fift
CDATASIZE
```
#### `F942` SDATASIZEQ [#f942-sdatasizeq]
Similar to `CDATASIZEQ`, but accepting a *Slice* `s` instead of a *Cell*. The returned value of `x` does not take into account the cell that contains the slice `s` itself; however, the data bits and the cell references of `s` are accounted for in `y` and `z`.
**Category:** App Misc (app\_misc)
```fift Fift
SDATASIZEQ
```
#### `F943` SDATASIZE [#f943-sdatasize]
A non-quiet version of `SDATASIZEQ` that throws a cell overflow exception (8) on failure.
**Category:** App Misc (app\_misc)
```fift Fift
SDATASIZE
```
#### `FA00` LDGRAMS [#fa00-ldgrams]
Loads (deserializes) a `Gram` or `VarUInteger 16` amount from *Slice* `s`, and returns the amount as *Integer* `x` along with the remainder `s'` of `s`. The expected serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, followed by an `8l`-bit unsigned big-endian representation of `x`. The net effect is approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDUX`.
**Category:** App Currency (app\_currency)
```fift Fift
LDGRAMS
LDVARUINT16
```
#### `FA01` LDVARINT16 [#fa01-ldvarint16]
Similar to `LDVARUINT16`, but loads a *signed* *Integer* `x`. Approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDIX`.
**Category:** App Currency (app\_currency)
```fift Fift
LDVARINT16
```
#### `FA02` STGRAMS [#fa02-stgrams]
Stores (serializes) an *Integer* `x` in the range `0...2^120-1` into *Builder* `b`, and returns the resulting *Builder* `b'`. The serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, which is the smallest integer `l>=0`, such that `x<2^(8l)`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown.
**Category:** App Currency (app\_currency)
```fift Fift
STGRAMS
STVARUINT16
```
#### `FA03` STVARINT16 [#fa03-stvarint16]
Similar to `STVARUINT16`, but serializes a *signed* *Integer* `x` in the range `-2^119...2^119-1`.
**Category:** App Currency (app\_currency)
```fift Fift
STVARINT16
```
#### `FA04` LDVARUINT32 [#fa04-ldvaruint32]
Loads (deserializes) a `VarUInteger 32` amount from *Slice* `s`, and returns the amount as *Integer* `x` along with the remainder `s'` of `s`. The expected serialization of `x` consists of a 5-bit unsigned big-endian integer `l`, followed by an `8l`-bit unsigned big-endian representation of `x`. The net effect is approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDUX`.
**Category:** App Currency (app\_currency)
```fift Fift
LDVARUINT32
```
#### `FA05` LDVARINT32 [#fa05-ldvarint32]
Similar to `LDVARUINT32`, but loads a *signed* *Integer* `x`. Approximately equivalent to `5 LDU` `SWAP` `3 LSHIFT#` `LDIX`.
**Category:** App Currency (app\_currency)
```fift Fift
LDVARINT32
```
#### `FA06` STVARUINT32 [#fa06-stvaruint32]
Stores (serializes) an *Integer* `x` in the range `0...2^248-1` into *Builder* `b`, and returns the resulting *Builder* `b'`. The serialization of `x` consists of a 5-bit unsigned big-endian integer `l`, which is the smallest integer `l>=0`, such that `x<2^(8l)`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown.
**Category:** App Currency (app\_currency)
```fift Fift
STVARUINT32
```
#### `FA07` STVARINT32 [#fa07-stvarint32]
Similar to `STVARUINT32`, but serializes a *signed* *Integer* `x` in the range `-2^247...2^247-1`.
**Category:** App Currency (app\_currency)
```fift Fift
STVARINT32
```
#### `FA40` LDMSGADDR [#fa40-ldmsgaddr]
Loads from *Slice* `s` the only prefix that is a valid `MsgAddress`, and returns both this prefix `s'` and the remainder `s''` of `s` as slices.
**Category:** App Addr (app\_addr)
```fift Fift
LDMSGADDR
```
#### `FA41` LDMSGADDRQ [#fa41-ldmsgaddrq]
A quiet version of `LDMSGADDR`: on success, pushes an extra `-1`; on failure, pushes the original `s` and a zero.
**Category:** App Addr (app\_addr)
```fift Fift
LDMSGADDRQ
```
#### `FA42` PARSEMSGADDR [#fa42-parsemsgaddr]
Decomposes *Slice* `s` containing a valid `MsgAddress` into a *Tuple* `t` with separate fields of this `MsgAddress`. If `s` is not a valid `MsgAddress`, a cell deserialization exception is thrown.
**Category:** App Addr (app\_addr)
```fift Fift
PARSEMSGADDR
```
#### `FA43` PARSEMSGADDRQ [#fa43-parsemsgaddrq]
A quiet version of `PARSEMSGADDR`: returns a zero on error instead of throwing an exception.
**Category:** App Addr (app\_addr)
```fift Fift
PARSEMSGADDRQ
```
#### `FA44` REWRITESTDADDR [#fa44-rewritestdaddr]
Parses *Slice* `s` containing a valid `MsgAddressInt` (usually a `msg_addr_std`), applies rewriting from the `anycast` (if present) to the same-length prefix of the address, and returns both the workchain `x` and the 256-bit address `y` as integers. If the address is not 256-bit, or if `s` is not a valid serialization of `MsgAddressInt`, throws a cell deserialization exception.
**Category:** App Addr (app\_addr)
```fift Fift
REWRITESTDADDR
```
#### `FA45` REWRITESTDADDRQ [#fa45-rewritestdaddrq]
A quiet version of primitive `REWRITESTDADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
REWRITESTDADDRQ
```
#### `FA46` REWRITEVARADDR [#fa46-rewritevaraddr]
`msg_addr_var` not allowed since TVM v10, so it behaves like `REWRITESTDADDR`, but returns account id in `Slice`, not `Integer`: parses address `s` into workchain `x` and account id `s`.
**Category:** App Addr (app\_addr)
```fift Fift
REWRITEVARADDR
```
#### `FA47` REWRITEVARADDRQ [#fa47-rewritevaraddrq]
A quiet version of primitive `REWRITEVARADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
REWRITEVARADDRQ
```
#### `FA48` LDSTDADDR [#fa48-ldstdaddr]
Loads `addr_std$10`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).
**Category:** App Addr (app\_addr)
```fift Fift
LDSTDADDR
```
#### `FA49` LDSTDADDRQ [#fa49-ldstdaddrq]
A quiet version of primitive `LDSTDADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
LDSTDADDRQ
```
#### `FA50` LDOPTSTDADDR [#fa50-ldoptstdaddr]
Loads `addr_std$10` or `addr_none$00`, if address is `addr_none$00` pushes a Null, if address is not `addr_std` or `addr_none`, throws an error 9 (`cannot load a MsgAddressInt`).
**Category:** App Addr (app\_addr)
```fift Fift
LDOPTSTDADDR
```
#### `FA51` LDOPTSTDADDRQ [#fa51-ldoptstdaddrq]
A quiet version of primitive `LDOPTSTDADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
LDOPTSTDADDRQ
```
#### `FA52` STSTDADDR [#fa52-ststdaddr]
Stores `addr_std$10`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).
**Category:** App Addr (app\_addr)
```fift Fift
STSTDADDR
```
#### `FA53` STSTDADDRQ [#fa53-ststdaddrq]
A quiet version of primitive `STSTDADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
STSTDADDRQ
```
#### `FA54` STOPTSTDADDR [#fa54-stoptstdaddr]
stores `addr_std$10` or Null. Null is stored as `addr_none$00`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).
**Category:** App Addr (app\_addr)
```fift Fift
STOPTSTDADDR
```
#### `FA55` STOPTSTDADDRQ [#fa55-stoptstdaddrq]
A quiet version of primitive `STOPTSTDADDR`.
**Category:** App Addr (app\_addr)
```fift Fift
STOPTSTDADDRQ
```
#### `FB00` SENDRAWMSG [#fb00-sendrawmsg]
Sends a raw message contained in *Cell `c`*, which should contain a correctly serialized object `Message X`, with the only exception that the source address is allowed to have dummy value `addr_none` (to be automatically replaced with the current smart-contract address), and `ihr_fee`, `fwd_fee`, `created_lt` and `created_at` fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter `x` contains the flags. Currently `x=0` is used for ordinary messages; `x=128` is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); `x=64` is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); `x'=x+1` means that the sender wants to pay transfer fees separately; `x'=x+2` means that any errors arising while processing this message during the action phase should be ignored. Finally, `x'=x+32` means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with `+128`.
**Category:** App Actions (app\_actions)
```fift Fift
SENDRAWMSG
```
#### `FB02` RAWRESERVE [#fb02-rawreserve]
Creates an output action which would reserve exactly `x` nanograms (if `y=0`), at most `x` nanograms (if `y=2`), or all but `x` nanograms (if `y=1` or `y=3`), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying `x` nanograms (or `b-x` nanograms, where `b` is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit `+2` in `y` means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit `+8` in `y` means `x:=-x` before performing any further actions. Bit `+4` in `y` means that `x` is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently `x` must be a non-negative integer, and `y` must be in the range `0...15`.
**Category:** App Actions (app\_actions)
```fift Fift
RAWRESERVE
```
#### `FB03` RAWRESERVEX [#fb03-rawreservex]
Similar to `RAWRESERVE`, but also accepts a dictionary `D` (represented by a *Cell* or *Null*) with extra currencies. In this way currencies other than Grams can be reserved.
**Category:** App Actions (app\_actions)
```fift Fift
RAWRESERVEX
```
#### `FB04` SETCODE [#fb04-setcode]
Creates an output action that would change this smart contract code to that given by *Cell* `c`. Notice that this change will take effect only after the successful termination of the current run of the smart contract.
**Category:** App Actions (app\_actions)
```fift Fift
SETCODE
```
#### `FB06` SETLIBCODE [#fb06-setlibcode]
Creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in *Cell* `c`. If `x=0`, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If `x=1`, the library is added as a private library, and if `x=2`, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to `x`. Values of `x` other than `0...2` are invalid.
**Category:** App Actions (app\_actions)
```fift Fift
SETLIBCODE
```
#### `FB07` CHANGELIB [#fb07-changelib]
Creates an output action similarly to `SETLIBCODE`, but instead of the library code accepts its hash as an unsigned 256-bit integer `h`. If `x!=0` and the library with hash `h` is absent from the library collection of this smart contract, this output action will fail.
**Category:** App Actions (app\_actions)
```fift Fift
CHANGELIB
```
#### `FB08` SENDMSG [#fb08-sendmsg]
Creates an output action and returns a fee for creating a message. Mode has the same effect as in the case of `SENDRAWMSG`. Additionally `+1024` means - do not create an action, only estimate fee. Other modes affect the fee calculation as follows: `+64` substitutes the entire balance of the incoming message as an outcoming value (slightly inaccurate, gas expenses that cannot be estimated before the computation is completed are not taken into account), `+128` substitutes the value of the entire balance of the contract before the start of the computation phase (slightly inaccurate, since gas expenses that cannot be estimated before the completion of the computation phase are not taken into account).
**Category:** App Actions (app\_actions)
```fift Fift
SENDMSG
```
#### `FEij` DEBUG [#feij-debug]
**Category:** Debug (debug)
```fift Fift
{i*16+j} DEBUG
```
**Aliases**:
* `DUMPSTK`
Dumps the stack (at most the top 255 values) and shows the total stack depth. Does nothing on production versions of TVM.
* `STRDUMP`
Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.
* `DUMP`
Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.
#### `FEFnssss` DEBUGSTR [#fefnssss-debugstr]
`0 <= n < 16`. Length of `ssss` is `n+1` bytes. `{string}` is a [string literal](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-29-string-literals). `DEBUGSTR`: `ssss` is the given string. `DEBUGSTRI`: `ssss` is one-byte integer `0 <= x <= 255` followed by the given string.
**Category:** Debug (debug)
```fift Fift
{string} DEBUGSTR
{string} {x} DEBUGSTRI
```
#### `FFnn` SETCP [#ffnn-setcp]
Selects TVM codepage `0 <= nn < 240`. If the codepage is not supported, throws an invalid opcode exception.
**Category:** Codepage (codepage)
```fift Fift
[nn] SETCP
```
**Aliases**:
* `SETCP0`
Selects TVM (test) codepage zero as described in this document.
#### `FFFz` SETCP\_SPECIAL [#fffz-setcp_special]
Selects TVM codepage `z-16` for `1 <= z <= 15`. Negative codepages `-13...-1` are reserved for restricted versions of TVM needed to validate runs of TVM in other codepages. Negative codepage `-14` is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM.
**Category:** Codepage (codepage)
```fift Fift
[z-16] SETCP
```
#### `FFF0` SETCPX [#fff0-setcpx]
Selects codepage `c` with `-2^15 <= c < 2^15` passed in the top of the stack.
**Category:** Codepage (codepage)
```fift Fift
SETCPX
```
{/* STATIC_END tvm_instructions */}
# TVM overview (/blockchain-basics/tvm/overview)
TON Virtual Machine (TVM) is a [stack-based](https://en.wikipedia.org/wiki/Stack_machine) virtual machine which executes smart contracts on TON blockchain.
TVM is invoked when a message is sent to an account that has deployed contract code, when a get method is called on an account, and in some [more rare cases](/blockchain-basics/tvm/initialization#stack).
Executing code on same inputs and prior state deterministically produces same outputs, so that validators can agree on whether code was executed correctly.
Every instruction consumes [gas](/blockchain-basics/tvm/gas). Gas exhaustion stops execution. This limit is imposed so that expensive computations (i.e. infinite loops) cannot be used to exhaust validators' computation resources, causing [denial of service](https://en.wikipedia.org/wiki/Denial-of-service_attack).
## Data model [#data-model]
* TVM has no [random-access memory](https://en.wikipedia.org/wiki/Random-access_memory). Instead it uses a stack of values as a scratchpad.
* There are no memory addresses. Most instructions either store their parameters directly in the code, or take them from the top of the stack.
* All values are [immutable](https://en.wikipedia.org/wiki/Immutable_object).
Most of the data is stored as immutable tree of [cells](/blockchain-basics/primitives/serialization/cells).
* Reading and writing of cells is done with [slices and builders](/blockchain-basics/tvm/builders-and-slices).
* There are no function addresses or function pointers. Code is executed from bitcode inside [continuations](/blockchain-basics/tvm/continuations).
## TVM state [#tvm-state]
On incoming messages or get method call, a new instance of TVM is started, with a new state. Derivation of the initial state from the message is described in [its own article](/blockchain-basics/tvm/initialization).
The total state of TVM consists of the following components:
* **Stack**. A regular [stack data structure](https://en.wikipedia.org/wiki/Stack_\(abstract_data_type\)). The vast majority of instructions `pop()` operands from the top and `push()` results back.
* [**Control registers**](/blockchain-basics/tvm/registers). A small fixed set of special registers, denoted as `c0`, `c1`, ..., `c5`, and `c7` (`c6` does not exist).
* [**Gas counter**](/blockchain-basics/tvm/gas). Tracks remaining computation budget. Each instruction decrements gas. When counter hits zero/negative value, an exception is raised, and the run aborts.
* **Current continuation (`cc`)**. A special register that stores a list of the next instructions to execute. Similar to the instruction pointer in traditional architectures.
* **Current codepage (`cp`)**. Determines how to decode the next instruction in `cc`. Different codepages may implement different instruction sets, allowing for adding new features to TVM without affecting old smart contracts. Currently, only codepage `0` (`cp0`) is implemented. Smart contract runs [`SETCP0`](/blockchain-basics/tvm/instructions#ff-setcp) instruction to explicitly use codepage `0`.
## TVM data types [#tvm-data-types]
Values on the stack and inside of registers are of one of the following seven types:
| Type | Description |
| ------------ | --------------------------------------------------------------------------------------------------------------------------- |
| Integer | 257-bit signed integer. Has the special `NaN` value representing arithmetic faults. |
| Cell | Node of a tree with bit string on it (\<= 1023 bits), and up to 4 arrows (refs). |
| Slice | Read cursor over a Cell. |
| Builder | Write cursor to construct a new Cell. |
| Tuple | List of 0..255 elements of any of seven types. Types of elements can be distinct. |
| Continuation | Executable Slice with TVM bitcode. [Continuations](https://en.wikipedia.org/wiki/Continuation) are callable like functions. |
| Null | Empty value. |
## Example of a smart contract: counter [#example-of-a-smart-contract-counter]
Here is a sample contract, written in [Fift](/blockchain-basics/languages/fift/overview). It implements the following logic:
* If an event is not an internal message, stop execution.
* Read 32-bit number (`msg_counter`) from internal message's body.
* Check that it is equal to the 32-bit number stored in `c4` (persistent account storage).
* Increment it.
* Save it back to `c4`.
When an account with this code gets an internal message, TVM stack [is initialized](/blockchain-basics/tvm/initialization#stack) with these values:
1. `s0` (top of the stack), function selector, is `0`. For other events, e.g., external messages or get method calls, selector will be non-zero.
2. `s1`, message body. The example contract expects exactly 32 bits here.
3. Three more values `s2`, `s3`, `s4` [are pushed](/blockchain-basics/tvm/initialization#external%2Finternal-message) by TVM onto a stack. They won't be used in the example. After execution finishes, they'll still be on the stack, and will be silently ignored.
In `Current stack` comments, we represent stack at that moment of execution, keeping its top to the right (e.g., `s2 s1 s0`, where `s0` is the top of the stack).
```fift Fift
<{
// Current stack: msg_body selector
// Use codepage 0. Picks the only available instruction set.
SETCP0
// This instruction does not affect the stack.
// Current stack: msg_body selector
// Consume `selector` from the top of the stack.
// Stop execution if `selector != 0`,
// i.e. "is not an internal message".
IFRET
// Continue execution if we received an internal message.
// Current stack: msg_body
// Load (LD) unsigned (U) 32-bit integer from a slice.
// This instruction pops (consumes) a slice from the stack,
// pushes an integer, and then pushes a new slice with
// 32 bits cut from it
32 LDU
// Current stack: msg_counter msg_body'
// msg_body' is a slice whose read cursor was moved by 32 bits
// when we loaded a 32-bit integer.
// For example, if we had slice x{00000001} on the stack and
// then invoked 32 LDU, there will be integer `1` and `x{}`
// (empty slice) on the stack
// Assert the END of a slice (S).
// These instructions consume a slice and check that it is
// empty (no more data to read), otherwise it throws an
// exception, because there was more data than we expected.
ENDS
// Current stack: msg_counter
// Push c4 (persistent storage) on the stack.
// `storage` is a cell
c4 PUSH
// Current stack: msg_counter storage
// Convert Cell to a Slice, i.e. make it readable
CTOS
// Current stack: msg_counter storage_slice
// Read 32-bit unsigned integer from `storage_slice`
32 LDU
// Current stack: msg_counter storage_counter storage_slice'
// Assert there is no more data in the storage
ENDS
// Current stack: msg_counter storage_counter
// Duplicate s0 (top of stack) under two top values
TUCK
// Current stack: storage_counter msg_counter storage_counter
// Check counters are equal
EQUAL
// Current stack: storage_counter msg_counter==storage_counter?
// Throw an exception with code 33 if it is not equal
33 THROWIFNOT
// Current stack: storage_counter
// Increase counter
INC
// Current stack: storage_counter+1
// Create an empty Builder
NEWC
// Current stack: storage_counter+1 builder
// Store (ST) unsigned (U) 32-bit integer `storage_counter+1` to a builder
32 STU
// Current stack: builder'
// Finalize Builder to a Cell
ENDC
// Current stack: new_storage
// Save `new_storage` to c4 (persistent storage)
c4 POP
// Current stack: (no values)
}>
```
# Registers (/blockchain-basics/tvm/registers)
TVM registers hold special values, such as contract storage, list of output actions, or exception handler
Only `c4` (new state) and `c5` (final actions) represent durable effects of a successful on‑chain run. Everything else is transient.
## `c0` — return continuation [#c0--return-continuation]
**Type**: `Continuation`
**Initial value**: `Quit` — extraordinary continuation which terminates TVM with exit code `0`.
When [`RET`](/blockchain-basics/tvm/instructions#db30-ret) is called or the current continuation remains no instructions (*implicit ret*), `c0` is invoked. Call-like instructions use it to store the current continuation in order to return to it after executing the inner function.
## `c1` — alternative return continuation [#c1--alternative-return-continuation]
**Type**: Continuation
**Initial value**: `Quit` — extraordinary continuation which terminates TVM with exit code `1`. Both exit codes `0` and `1` are considered successful terminations of TVM.
Same as `c0`, but invoked only in special control flow instructions, such as [`RETALT`](/blockchain-basics/tvm/instructions#db31-retalt), [`IFRETALT`](/blockchain-basics/tvm/instructions#e308-ifretalt), and others.
## `c2` — exception handler [#c2--exception-handler]
**Type**: Continuation
**Initial value**: `ExcQuit` — extraordinary continuation which terminates TVM with an exception. In this case, the exit code is an exception number.
Invoked implicitly on any exception that occurs during TVM execution. Can be invoked explicitly by [`THROW`](/blockchain-basics/tvm/instructions#f2c4_-throw)-like instructions. To set a custom exception handler, use [TRY](/blockchain-basics/tvm/instructions#f2ff-try).
## `c3` — function selector [#c3--function-selector]
**Type**: Continuation
**Initial value**: Root cell of code currently executing in TVM.
Invoked by [`CALLDICT`](/blockchain-basics/tvm/instructions#f0-calldict) instruction with a function ID (integer) passed on the stack. The function selector should jump to a function with that ID.
Fift-ASM assembler constructs following function selector ([`Asm.fif`:1624](https://github.com/ton-blockchain/ton/blob/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/fift/lib/Asm.fif#L1624)):
```fift Fift
SETCP0
<{
// a dictionary which maps 19-bit function id (integer) => function code (slice)
}> DICTPUSHCONST
DICTIGETJMPZ // get a function with given id from dictionary and execute it
11 THROWARG // if no function found, throw with exit code 11 and function id as additional argument
```
## `c4` — persistent account storage [#c4--persistent-account-storage]
**Type**: Cell
**Initial value**: Root cell of account data.
This register helps to store some information between smart contract invocations. When the transaction succeeds, the final value of `c4` is saved as new account data.
## `c5` — outbound actions accumulator [#c5--outbound-actions-accumulator]
**Type**: Cell
**Initial value**: Empty cell.
List of actions to perform in the action phase after TVM execution: send a message, reserve funds, update code, and install libraries.
`c5` has an `OutList` structure:
```tlb title="TL-B"
out_list_empty$_ = OutList 0;
out_list$_ {n:#} prev:^(OutList n) action:OutAction = OutList (n + 1);
action_send_msg#0ec3c86d mode:(## 8) out_msg:^(MessageRelaxed Any) = OutAction;
action_set_code#ad4de08e new_code:^Cell = OutAction;
action_reserve_currency#36e6b809 mode:(## 8) currency:CurrencyCollection = OutAction;
libref_hash$0 lib_hash:bits256 = LibRef;
libref_ref$1 library:^Cell = LibRef;
action_change_library#26fa1dd4 mode:(## 7) libref:LibRef = OutAction;
```
The previous action is always the first reference of the next one. If action itself has a reference, it is stored as the second reference in the list. At the beginning of the list, an empty cell is stored as the first reference of the first action.
## `c7` — environment information and global variables [#c7--environment-information-and-global-variables]
**Type**: Tuple
**Initial value**: `Tuple[Tuple[0x076ef1ea, 0, 0, ...]]`.
The zero element of the `c7` tuple is an environment information (which itself is also a tuple). The remaining 255 slots are used for global variables. [`[i] SETGLOB`](/tvm/instructions#f87_-setglob) modifies `c7`, inserting an element with index `i`, [`[i] GETGLOB`](/tvm/instructions#f85_-getglob) reads `i`-th element from `c7`.
### Structure of environment information tuple [#structure-of-environment-information-tuple]
\#
Instruction
Field
Type
Description
0
\-
0x076ef1ea
integer
tag of the
SmartContractInfo
TL-B structure
1
\-
actions count
integer
increments when new action is pushed to
`c5`
.
2
\-
messages sent
integer
increments when new
`action_send_msg`
is pushed to
`c5`
3
NOW
unix time
integer
current time (timestamp of block collation)
4
BLOCKLT
current block LT (logical time)
integer
5
LTIME
current transaction LT
integer
6
RANDSEED
random seed
integer
`sha256(block_rand_seed . account_address)`
7
BALANCE
smart contract balance
tuple
tuple of integer (TON balance) and cell or
`null`
(extra currencies dictionary)
8
MYADDR
smart contract address
slice
9
CONFIGROOT
global blockchain configuration
cell or
`null`
(dictionary)
10
MYCODE
smart contract code
cell
11
INCOMINGVALUE
value of incoming message
tuple
tuple of integer (TON value) and cell or
`null`
(extra currencies dictionary)
12
STORAGEFEES
fees collected during storage phase
integer
13
PREVBLOCKSINFOTUPLE, PREVMCBLOCKS_100
last 16 masterchain blocks, last keyblock, and last 16 masterchain blocks with seqno divisible by 100
tuple
tuple has following `PrevBlocksInfo` structure:
```tlb
[ wc:Integer
shard:Integer
seqno:Integer
root_hash:Integer
file_hash:Integer ]
= BlockId;
[ last_mc_blocks:BlockId[]
prev_key_block:BlockId
last_mc_blocks_divisible_by_100:BlockId[] ]
= PrevBlocksInfo;
```
14
UNPACKEDCONFIGTUPLE
unpacked config values
tuple
* 0: `StoragePrices` from the `ConfigParam 18` — not the whole dictionary, but only the one `StoragePrices` entry which corresponds to the current time
* 1: `ConfigParam 19`, global ID
* 2: `ConfigParam 20`, masterchain gas prices
* 3: `ConfigParam 21`, non-masterchain gas prices
* 4: `ConfigParam 24`, masterchain forward fees
* 5: `ConfigParam 25`, non-masterchain forward fees
* 6: `ConfigParam 43`, size limits
15
DUEPAYMENT
current debt for storage fee in nanotons
integer
16
GETPRECOMPILEDGAS
gas usage for the current contract if it is precompiled,
null
otherwise
integer or
`null`
see
`ConfigParam 45`
17
INMSGPARAMS
inbound message parameters
tuple
* 0: `bounce: boolean` — can bounce
* 1: `bounced: boolean` — did bounce
* 2: `src_addr: slice` — sender
* 3: `fwd_fee: int`
* 4: `created_lt: int`
* 5: `created_at: int`
* 6: `orig_value: int` — this is sometimes different from the value in `INCOMINGVALUE` and TVM stack because of storage fees
* 7: `value: int` — same as in `INCOMINGVALUE` and on the initial TVM stack
* 8: `value_extra: cell or null` — same as in `INCOMINGVALUE`
* 9: `state_init: cell or null`
For external messages, tick-tock transactions and get methods: `bounce`, `bounced`, `fwd_fee`, `created_lt`, `created_at`, `orig_value`, `value` are 0, `value_extra` is null. For tick-tock transactions and get methods, `src_addr` is `addr_none`.
# Blockchain nodes overview (/blockchain-basics/nodes/overview)
A full node is a software that stores the whole blockchain state locally, opposite to lite-clients, which request small pieces of data from liteservers when needed. It does not solve any problem itself, but provides a base for other services requiring a full blockchain state (validator, liteserver, etc). Usually, full nodes keep only the latest part of the blockchain state, which is vital for ensuring client applications' network stability and operation. Full nodes *prune* the state of the TON blockchain they keep. This means the full node automatically removes earlier blocks that become unnecessary for the network to manage its data volume effectively. To allow client applications to look for blocks and transactions and send new transactions into the TON blockchain, full nodes are equipped with the liteserver functionality.
## Full node modes [#full-node-modes]
| Role | What it does | When to use it |
| ------------------ | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Liteserver | Stores the latest shards, tracks the masterchain, and serves data to lite-clients. | Required for custom infrastructure, analytics, or to back your own APIs. |
| Archive liteserver | Stores all blockchain data, including old blocks and states. | Required for explorers and other services working with historical data. |
| Validator | Signs blocks, participates in elections, and earns rewards. | Needed to run validation with your stake or to operate a nominator pool service. |
| Collator | Produces blocks for validators. | Needed to reduce load on your validators by setting up block creation on a separate machine. |
| Nominator pool | Accepts funds from stakers and runs a validator with their stake. | Needed when you want to securely accept stakes from multiple parties and share rewards between them. |
| Single nominator | Secure way to run a validator without depositing all funds to a hot wallet. | Generally, you should use it each time you want to run a new validator. |
| Liquid staking | Same as nominator pool, but exchanges stakers' funds for a synthetic token to be used in DeFi. | Needed to run a liquid staking protocol. |
## Do you need your own node? [#do-you-need-your-own-node]
* **Run your own full node** when you need guaranteed uptime or to serve high-volume workloads without third-party rate limits. Validators and staking services need to install a node and activate validator mode.
* **Rely on public endpoints** when building prototypes or light integrations. Community liteservers and APIs such as [TON Center](/applications/api/toncenter/introduction) or other [RPC providers](/applications/api/overview) already expose the blockchain for read access and transaction submission.
## Pick your target environment [#pick-your-target-environment]
| If you need | Run |
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Validator or nominator capacity | [Setting up a node using MyTonCtrl](/blockchain-basics/nodes/cpp/setup-mytonctrl) with the validator, nominator pool, or single nominator workflows; the wrapper automates validator wallets, overlays, elections, and upgrades. |
| Liteserver APIs | [Setting up a node using MyTonCtrl](/blockchain-basics/nodes/cpp/setup-mytonctrl) with liteserver option (and archive mode if needed) to expose API for applications. |
| An isolated development network | [Setting up a local blockchain using MyLocalTon](/blockchain-basics/nodes/cpp/setup-mylocalton) to spin up a local shard, explorer, and APIs for rapid iterations with no mainnet impact. |
| Kubernetes-native production operations | [Use Rust node chart workflows](/blockchain-basics/nodes/rust/quick-start) and references. |
## Rust node overview [#rust-node-overview]
TON Rust node is an alternative implementation of a TON full node written in Rust. It is protocol-compatible with TON and follows an operational model designed for containerized environments rather than single-instance deployments.
Rust node operational focus:
* container-based architecture;
* Kubernetes-native deployment model;
* deterministic, version-pinned builds with automated release validation;
* node lifecycle management within a cluster environment;
* integration with external key management systems such as [HashiCorp Vault](https://www.hashicorp.com/en/products/vault).
Rust node is designed for:
* node providers operating multiple full nodes, liteservers, or validators;
* staking operators managing one or many validators as cluster resources;
* operators running node infrastructure that requires external key management integration and structured operational processes.
This model targets predictable scaling: infrastructure growth is handled through standardized deployment patterns, centralized control, and safer upgrade workflows.
### Advantages [#advantages]
* Multi-node deployment and centralized management: a new node can be launched in minutes, excluding sync time, using standardized Helm workflows.
* Fully tested container delivery: release images are version-pinned and validated by more than 10 automated test suites before publication.
* Built-in observability: Rust node exposes Prometheus metrics across 8 subsystems and serves `/healthz` and `/readyz` from the same metrics HTTP server.
* Grafana-ready workflow: a bundled dashboard and documented Prometheus/Grafana integration are provided for Kubernetes deployments.
* Key isolation: validator wallet and ADNL keys are designed for Vault-backed workflows instead of direct in-node private key storage.
### Rust node resource recommendations [#rust-node-resource-recommendations]
Recommended Kubernetes requests and limits are:
| Role | CPU request | CPU limit | Memory request | Memory limit |
| ---------------------- | ----------- | --------- | -------------- | ------------ |
| Full node / liteserver | 8 | 16 | 32GiB | 64GiB |
| Validator | 16 | 32 | 64GiB | 128GiB |
The node can run on fewer resources, but these values provide headroom for load spikes such as elections, heavy traffic, and catch-up after restarts.
Source: [TON Rust Node resource recommendations](https://github.com/RSquad/ton-rust-node/blob/e8bd0451b326099146a90a913beedaebd952fa56/helm/ton-rust-node/docs/resources.md).
## Full node [#full-node]
**The full node** is a basic node type within the TON blockchain. It serves as the backbone of the TON blockchain by keeping its block history — in other words, its *current state*.
Compared to **archive nodes**, full nodes keep only the latest part of the blockchain state, which is vital for ensuring client applications' network stability and operation. Full nodes *prune* the state of the TON blockchain they keep. This means the full node automatically removes earlier blocks that become unnecessary for the network to manage its data volume effectively.
To allow client applications to look for blocks and transactions and send new transactions into the TON blockchain, full nodes are equipped with the liteserver functionality.
## Archive node [#archive-node]
The archive node is a full node that keeps the entire block history of the TON blockchain. These nodes act as the decentralized point of truth to ensure consistency of the whole blockchain history. They are a backend for blockchain explorers and other applications relying on deep transaction history.
Archive nodes do not prune the blockchain state, elevating system requirements, especially in storage. According to the latest estimations, while full and validator nodes require about 1 TB of disk space, archive nodes need about 12 TB to store the complete block history.
## Validator node [#validator-node]
**Validator nodes** or **validators** are the TON network participants who propose new blocks and verify transactions according to the TON's *proof-of-stake* mechanism. In this way, validators contribute to the overall blockchain security.
Validators get rewards in TON for successful participation in the validation process.
To be entitled to propose and validate blocks, other participants elect validators based on the amount of TON they hold — in other words, their *stake*. The more TON a validator stakes, the higher its chances of being elected, validating blocks for the network, and earning rewards. As a rule, validator operators motivate other TON holders to stake with them to get passive income from the resulting rewards. In this way, validators ensure network stability and security and contribute to its growth.
## Interacting with TON nodes [#interacting-with-ton-nodes]
TON nodes can run in **liteserver mode**, which allows external applications to interact with the TON blockchain. In this mode, the nodes process client requests, enabling clients to access blockchain data, send transactions, and retrieve information about blocks and transactions.
Full and archive nodes typically enable liteserver mode because they store blockchain history and handle external requests. In contrast, validator nodes do not need it, as they focus on efficiently validating new blocks without additional workload from external queries. Use MyTonCtrl to [enable liteserver mode in a full or archive C++ node](/blockchain-basics/nodes/cpp/setup-mytonctrl#liteserver-quickstart).
Liteserver mode, or *liteserver* for short, uses the Abstract Datagram Network Layer (ADNL) protocol. Direct connections require either a client called *lite-client* downloaded from the [latest TON release](https://github.com/ton-blockchain/ton/releases/latest), or a library that understands ADNL. In the [SDK table](/applications/sdks), such libraries have a mark in the ADNL column.
To connect from a webpage or otherwise interact with TON nodes over HTTP, an HTTP-to-ADNL frontend is required. [TON Center](/applications/api/toncenter/introduction) is an official HTTP API provider, and its API endpoints can be used directly or [self-hosted](/applications/api/overview). In the [SDK table](/applications/sdks), libraries that use these endpoints or other HTTP providers have a mark in the HTTP column.
# TMA create CLI (/ecosystem/tma/create-mini-app)
`@telegram-apps/create-mini-app` is a CLI tool designed to scaffold your new
mini application on the Telegram Mini Apps platform. It generates a project with pre-configured libraries and template files,
allowing you to customize the content based on your specific requirements.
## Usage [#usage]
To run the tool, use one of the following scripts depending on your package manager.
```bash npm icon="package"
npx @telegram-apps/telegram-apps-tools@latest
```
## Creating a new application [#creating-a-new-application]
The above command executes a script that guides you through the creation of
your application by sequentially prompting for the following information:
### Project directory name [#project-directory-name]
* **Prompt**: Enter the name of the folder where the project files will be located.
* **Default**: mini-app
The script will create a subfolder with the specified name in the current directory.
### Preferred technologies [#preferred-technologies]
#### TMA SDKs [#tma-sdks]
* **`tma.js`** [`@telegram-apps/sdk`](https://www.npmjs.com/package/@telegram-apps/sdk) – A TypeScript library for seamless communication with Telegram Mini Apps functionality.
* **Telegram SDK** [`@twa-dev/sdk`](https://www.npmjs.com/package/@twa-dev/sdk) – This package allows you to work with the SDK as an npm package.
#### Frameworks [#frameworks]
* **React.js** [template](https://github.com/Telegram-Mini-Apps/reactjs-template)
* **Next.js** [template](https://github.com/Telegram-Mini-Apps/nextjs-template)
* **Solid.js** [template](https://github.com/Telegram-Mini-Apps/solidjs-js-template)
* **Vue.js** [template](https://github.com/Telegram-Mini-Apps/vuejs-template)
### Git remote repository URL [#git-remote-repository-url]
Enter the git remote repository URL. This value will be used to connect the created project with your
remote git repository. It should be either an HTTPS link or an SSH connection string.
## Build configuration [#build-configuration]
Projects created with `create-mini-app` are configured to use the [Vite](https://vite.dev/) bundler. The project includes a `vite.config.js` file,
which you can customize to adjust the build settings according to your needs.
# TMA: Telegram Mini Apps overview (/ecosystem/tma/overview)
Telegram Mini Apps (TMAs) are web applications that run within the Telegram messenger. They are built using web technologies — HTML, CSS, and JavaScript.
Your browser does not support the \ tag.
Mini Apps run within Telegram and are instantly accessible — without the need for installation or redirects.
## TMA developer tools [#tma-developer-tools]
* [TMA create CLI](/ecosystem/tma/create-mini-app)
* [Telegram UI Kit](/ecosystem/tma/telegram-ui/overview)
* [Analytics](/ecosystem/tma/analytics/analytics)
# Documentation style guide (/overview/contribute/style-guide)
This guide covers the basics: how to structure pages, write examples, and keep docs consistent and safe.
## Write for the reader [#write-for-the-reader]
* Default audience: experienced software developers new to blockchain. Explain TON-specific concepts. Do not re-teach general programming. This keeps pages focused.
* Be answer‑first. Start with what the reader will achieve, what they need, and the steps. This shortens the time to success.
* Lead with a working example. Show a copy‑pasteable snippet early and the expected output. This shows it works.
* Use a neutral, precise tone. Write in the present tense, active voice, and second person (“Run the node”). This makes actions clear.
* Avoid marketing or hype (“blazingly fast”, “seamless”, “revolutionary”) and vague praise. Prefer measurable facts or omit the claim.
* Keep it scannable. Use short sections and paragraphs, clear headings, lists, and tables. Most readers skim to find the next action.
* Aim for one main idea per sentence. Split long, multi‑clause sentences or turn them into lists.
* Use bold only for a few scan‑worthy words in a paragraph, not full sentences or tokens. If a skimming reader loses nothing when the bold is removed, drop it.
* Use italics for new or defined terms and subtle emphasis; use bold for words a skimming reader should find quickly.
* Draft in plain text first. During editing, add minimal emphasis and remove any styling that does not change meaning.
## Page types [#page-types]
* Step-by-step guides — for beginners; handhold from zero to first success on one happy path; explain from scratch, define terms, and link out for depth.
* How-tos — a focused recipe for a specific outcome; assume concepts known and show only what’s needed.
* Explanation — concepts, architecture, and trade‑offs; clarify why and when, with minimal examples.
* Reference — exact, complete facts (APIs, CLI, types, errors); stable anchors and minimal prose.
* Don’t mix types on the same page.
## Where pages go [#where-pages-go]
* Keep the flow linear; follow the `docs.json` sidebar.
* In each topic group, order pages: Explanation → How‑to → Reference.
* Canonical specs — `reference/`. Link to it; don’t duplicate tables or parameters.
## Structure pages for success [#structure-pages-for-success]
* Start with Objective and Prerequisites so readers know they’re in the right place. Use Prerequisites for things the reader must have or have done; use an Audience note for skills or knowledge.
* Make each step a single action; use sub‑bullets for options.
* Include Verify and Troubleshoot so readers can confirm success and fix common errors.
* End with Next steps / See also only if essential (1–3 links). Prefer a linear path that needs no extra navigation.
## Examples that run [#examples-that-run]
* Make commands copy‑pasteable. Do not include shell prompts like `$` or `>`. Prompts break commands when pasted.
* Separate command and output. Use two fenced blocks. Mixing them causes copy errors.
* Use `` placeholders in commands and prose and define each on first use (for example, ``). In code, use `UPPER_SNAKE` if `< >` clashes with syntax. One clear convention prevents hard‑coded values from slipping in.
* Tag code fences with a language (`bash`, `json`, `rust`, and so on). This enables correct highlighting and tooling.
* Prefer end‑to‑end examples on testnet by default. Safe defaults encourage trying the steps.
* Label partial snippets as Not runnable and link to a complete example.
* Do not hard‑wrap long commands. Use soft wrap in the UI or safe continuation if the shell supports it. Hard wraps break execution.
* For UI buttons, menu items, and key names, wrap the label in `… ` instead of quotes or bold. This keeps controls easy to spot and consistent with the main style guide.
Good
```bash
ton-node start --ledger --network testnet
```
Expected output
```text
Node started. Workchain: 0 Shard: -1 Status: running
```
Define placeholders
`` — local ledger directory.
`` — HTTPS endpoint of your TON RPC provider.
## Safety warnings [#safety-warnings]
Add a Caution or Warning when a step moves funds, changes fees or withdrawals, exposes or stores private keys or mnemonics, modifies validator or network settings, or performs chain‑affecting operations such as resharding, pruning, halting, or replay. These actions can cause irreversible loss or outages.
On long guides with many risky commands, combine a clear page‑level warning at the top (covering risk, scope, rollback where feasible, and environment) with short local notes next to each critical step. Local notes can be brief if they point back to the main warning.
Pattern
> Warning — funds at risk
> Running the next command on mainnet transfers funds irreversibly.
> Safer first (testnet):
>
> ```bash
> jetton transfer --to --amount --network testnet
> ```
>
> If you must use mainnet: no rollback; on‑chain transfers are final.
Default to testnet in task pages. Make destructive flags opt‑in and document mitigations.
## Necessary disclaimers [#necessary-disclaimers]
Add a Caution or Warning when a page or step:
* Moves funds or changes fee/withdrawal behavior.
* Exposes, stores, or transmits private keys or mnemonics.
* Modifies validator configuration, networking, or other consensus‑affecting parameters.
* Performs chain‑affecting operations (for example, resharding, pruning, halting, replay).
* Uses destructive flags or commands that delete, rewrite, or lock state (for example, `--purge`, `--force`).
* Runs on mainnet, where actions are irreversible; label the environment and give the safer testnet first.
Make sure the guide as a whole clearly covers the risk, scope, rollback or mitigation (where feasible), and the environment label (testnet vs mainnet). For a single hazardous step, put these points directly in its callout. On long risky guides, put a big safety callout at the top and keep step‑level notes short, pointing back to that summary.
## Titles and headings [#titles-and-headings]
* Use sentence case. Keep headings concise and unique.
* Use imperatives for tasks (“Deploy a validator”); nouns for concepts (“Validator architecture”). Titles should signal action vs. explanation.
* Don’t style headings, except when an identifier needs code font.
* Use clear section labels such as Verify, Troubleshoot, and See also.
## Link to details, don’t duplicate [#link-to-details-dont-duplicate]
* On first useful mention, link flags, parameters, error codes, and data types to their reference anchors.
* Do not paste reference tables into guides. Link instead. Duplicated tables go stale.
* Use descriptive link text that names the destination, not generic labels like “click here”, “here”, or “this page”, and avoid mechanics-focused link labels like “click” or “go to”.
* Link core TON terms to the Glossary on first useful mention unless you define them on the page.
* Internal links **MUST** be root‑absolute (start with `/`). Deep‑link to the exact section or anchor that contains the needed fact (not the page top). **MUST NOT** use relative segments like `./` or `../` in any Markdown/MDX link. (Why: content moves frequently; root‑absolute links survive reorganizations.)
## Images [#images]
* Use the `` component for all images. Markdown image syntax `` and raw ` ` are not allowed.
* Store images under `resources/images/` and reference them with root‑absolute paths, for example ` `. **MUST NOT** use relative `src` such as `./` or `../`.
* Provide meaningful, non‑empty `alt` text (never `alt=""`); add `darkSrc` when the dark theme needs different contrast. Keep sizes/aspect ratios consistent across a page.
* SVGs: if you omit `darkSrc`, colors are auto‑inverted in dark mode; add `darkSrc` if inversion isn’t correct.
## Terminology and names [#terminology-and-names]
* Use the project term bank for canonical spellings, casing, and preferred terms. One vocabulary prevents drift.
Examples: TON, jetton, smart contract, BoC (bag of cells), accountchain, shardchain, workchain, masterchain, basechain.
* Prefer allowlist and denylist over whitelist and blacklist. These are clearer and inclusive.
* Use mainnet and testnet as common nouns. Use TON Mainnet and TON Testnet for the proper names. This distinguishes the generic type from the named network.
## Files, front matter, labels [#files-front-matter-labels]
* Filenames use `kebab-case.md` or `kebab-case.mdx` (for example, `validator-setup.mdx`). This is readable and consistent across platforms.
* Optional front matter can declare `doc_type`, `audience`, and `status` (experimental or deprecated). If deprecated, add an Important callout with the replacement and timeline.
* Keep sidebar labels short (2–4 words) and mirror in‑page headings.
## Accessibility [#accessibility]
* Use plain English; avoid idioms and culture-specific references.
* Use American English spelling (e.g., color, analyze).
* Write descriptive headings and link text.
* Tables should have headers and units (for example, “Latency (ms)”) and keep cells brief.
* Provide text alternatives for complex figures when possible.
* Avoid emojis. Only use them where they follow a common convention (for example, `✅ Supported`, `❌ Not supported`) and always pair them with text.
## Secrets and environments [#secrets-and-environments]
* Never include real keys, mnemonics, or tokens. Use placeholders or clearly invalid test values. This prevents accidental leaks.
* Prefer environment variables or keystores over inlining secrets.
* Call out commands that can delete, rewrite, or lock state.
* Label the environment when it matters (testnet vs mainnet).
# AgentKit: @ton/mcp (/overview/ai/mcp)
The [`@ton/mcp` server][mcp-repo] enables AI agents to operate TON wallets and perform common blockchain operations through the [Model Context Protocol (MCP)][mcp-spec] or CLI using [agent skills][skills-spec]. It handles private keys and signing internally, so agents interact only with high-level intents and confirmation flows. The server is built on top of [WalletKit](/applications/walletkit/overview).
The latest alpha release is available on [npm][mcp-npm]. Run it locally with:
```bash
npx -y @ton/mcp@alpha
```
To set it up, follow the [quick start guide](#quick-start).
`@ton/mcp` is currently in alpha . It is safe for use in mainnet, but APIs, behaviors, and [underlying wallet contracts][wallets] may change between releases. Pin a specific version for production use and check the [changelog][changelog] before upgrading.
For all official TON MCP servers, their setup, and related skills, refer to the [TON MCP portal](https://mcp.ton.org/).
## Features [#features]
* Balance queries: check Toncoin and jetton (token) balances, view transaction history
* Transfers: send Toncoin, jettons, and NFTs
* Assets: list, inspect, and manage popular jettons and NFTs
* Swaps: get quotes for token swaps through DEX aggregators
* DNS: resolve TON DNS domains and perform reverse lookups
* Agentic wallets: create, import, and manage self-custody [agentic wallets][wallets]
* Multiple transports: standard I/O (default), multi-session HTTP server, and serverless (AWS Lambda, Vercel, or custom integrations)
## Quick start [#quick-start]
There are two ways to set up `@ton/mcp`:
Skills give an agent instructions on how to launch and use `@ton/mcp` on its own. No manual MCP client configuration is required. This approach works best with agents that support the [skills specification][skills-spec].
Run the following command to install the skills for `@ton/mcp`:
```bash
npx skills add ton-connect/kit/packages/mcp
```
After installation, agents can launch and manage `@ton/mcp` on their own. No further configuration is needed. The server starts in [agentic wallets mode](#agentic-wallets-mode) by default.
Register `@ton/mcp` as a server in Claude Desktop, Cursor, Windsurf, or another MCP client. Use this approach when the agent does not support skills or when finer control over server configuration is needed.
Add the following block to the MCP client configuration file:
```json
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@ton/mcp@alpha"]
}
}
}
```
The server starts in [agentic wallets mode](#agentic-wallets-mode) by default. For [single-wallet mode](#single-wallet-mode), add `MNEMONIC` or `PRIVATE_KEY` to the `env` object.
See [environment variables](#environment-variables) for the full list of configuration options.
To start using `@ton/mcp` in agentic wallets mode:
To create a first agentic wallet, ask the agent to "create an agentic wallet" and follow the instructions.
The process goes as follows:
1. The agent generates private keys for a new wallet and suggests [opening the dashboard](https://agents.ton.org/).
2. On the dashboard, the user should connect their regular mainnet or testnet TON wallet: it will be the owner of an agentic wallet.
3. Agentic wallet gets deployed from the dashboard.
4. User provides the address of the deployed agentic wallet to the agent.
5. Agent imports the wallet and can then sign transactions using its operator key.
The user can revoke access or withdraw funds at any time from the dashboard.
An agentic wallet is a TON contract. There are three ways to fund it:
1. During creation: use the "Initial TON deposit" field on the deployment page.
2. From the dashboard: use the Fund button to transfer Toncoin, jettons, or NFTs.
3. Directly: use a wallet app like Tonkeeper to transfer assets to the agentic wallet address directly.
To check the balance, ask the agent: "What is my agent balance?"
Once setup is complete, ask agent to perform desired actions. For example:
* `Send 1 TON to UQB.._WALLET_ADDRESS` - sign and send a transfer from the agentic wallet.
* `Swap 5 TON for USDT` - get a quote and execute a swap.
* `Resolve the contract address of this DNS domain: DOMAIN_NAME.ton` - obtain the wallet address of the domain owner.
* `Show my NFTs` - query all NFTs owned by the wallet.
* `Check my balance` - current Toncoin and jetton balances. Do not use this data for any calculations, as it becomes outdated quickly.
* `Get my last transactions` - list of several latest events initiated by the wallet.
* `Import agentic wallet` - reinstate a wallet previously managed by another agent.
Web dashboard allows to see all agentic wallets in one place. Monitor transactions, fund and withdraw assets, grant and revoke accesses, rotate operator keys without redeploying the wallets.
## Runtime modes [#runtime-modes]
`@ton/mcp` supports two runtime modes:
* [Agentic wallets mode](#agentic-wallets-mode) (default) - operates with self-custody wallets for autonomous AI agents.
* [Single-wallet mode](#single-wallet-mode) (optional) - operates with a single in-memory wallet.
### Agentic wallets mode [#agentic-wallets-mode]
[Agentic wallets][wallets] are self-custody wallets designed for autonomous agents. The user retains the owner key, and the agent holds a separate operator key. This split-key design gives agents access to transfers, swaps, and other on-chain operations without exposing the root credentials.
Agentic wallets mode is the **default**. When neither `MNEMONIC` nor `PRIVATE_KEY` is set, the server loads wallets from a local config registry at `~/.config/ton/config.json` or the path in `TON_CONFIG_PATH`.
In this mode the server provides additional tools for multi-wallet management, agentic wallet onboarding, operator key rotation, and wallet import. Wallet-scoped tools accept an optional selector parameter: wallet ID, name, or address. When omitted, the current active wallet is used.
```bash
# Start in agentic wallets mode (default)
npx @ton/mcp@alpha
# Start with a custom config path
TON_CONFIG_PATH=/path/to/config.json npx @ton/mcp@alpha
```
### Single-wallet mode [#single-wallet-mode]
Single-wallet mode starts the server with one in-memory wallet derived from a mnemonic or private key. This mode is useful for one-off tasks or for operating a single known wallet.
Set `MNEMONIC` or `PRIVATE_KEY` as an environment variable to activate this mode:
```bash
# First, securely set either a MNEMONIC=" ... "
# or a PRIVATE_KEY=""
# Then, launch the server
npx @ton/mcp@alpha
```
`MNEMONIC` and `PRIVATE_KEY` grant full control of the wallet. Store these values in environment variables or a secrets manager. Do not commit them to Git or other source control systems. Do not pass them inline in shell commands.
The default TON wallet version in the single-wallet mode is [`v5r1`][wallets-comparison]. Override it with `WALLET_VERSION`:
```bash
# First, securely set either a MNEMONIC or a PRIVATE_KEY
# Then, use a diffent wallet version
WALLET_VERSION=v4r2 npx @ton/mcp@alpha
```
## Transport modes [#transport-modes]
The `@ton/mcp` server supports two transport modes:
* [Standard I/O](#standard-i%2Fo) (stdio, default)
* [HTTP](#http), which can also be run [serverless](#serverless)
### Standard I/O [#standard-io]
Standard IO is the default transport. The server reads MCP requests from stdin and writes responses to stdout. Most MCP clients, including Claude Desktop and Cursor, can use this transport. They spawn the server process and interact over standard streams.
```bash
npx @ton/mcp@alpha
```
### HTTP [#http]
HTTP mode starts a multi-session HTTP server. Each MCP client session gets its own server transport, so multiple clients can initialize and reconnect independently.
```bash
# Start on the default port (3000)
npx @ton/mcp@alpha --http
# Start on a custom port
npx @ton/mcp@alpha --http 8080
# Start on a custom host and port
npx @ton/mcp@alpha --http 8080 --host 127.0.0.1
```
The MCP endpoint is available at `http://:/mcp`. Point the MCP client to this URL to connect.
#### Serverless [#serverless]
The package exports a `@ton/mcp/serverless` entry point for deployment as a serverless function on AWS Lambda, Vercel, Cloudflare Workers, and similar platforms. In serverless mode, credentials are passed via request headers rather than environment variables.
Serverless headers carry wallet credentials in every request. Use HTTPS in production to prevent credential interception. Restrict access to the serverless endpoint with authentication or network-level controls.
Serverless mode operates in [single-wallet mode](#single-wallet-mode) only and always uses the [`v5r1` TON wallet version][wallets-comparison]. It does not use the wallet registry, nor does it expose wallet management or onboarding tools.
| Header | Description |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `MNEMONIC` | Space-separated 24-word mnemonic phrase. |
| `PRIVATE_KEY` | Hex-encoded 32-byte or 64-byte private key (paired with the public key). Takes priority over `MNEMONIC`. |
| `NETWORK` | Either `mainnet` (default) or `testnet`. |
| `TONCENTER_API_KEY` | Optional API key for higher rate limits. |
```typescript title="AWS Lambda"
import { createServerlessHandler } from '@ton/mcp/serverless';
export const handler = createServerlessHandler();
```
```typescript title="Vercel"
import { createServerlessHandler } from '@ton/mcp/serverless';
export default createServerlessHandler();
```
```typescript title="Custom integration"
import { createServerlessHandler } from '@ton/mcp/serverless';
const handle = createServerlessHandler();
const response = await handle({
method: 'POST',
url: '/mcp',
headers: {
'MNEMONIC': ' ... ',
'NETWORK': 'mainnet',
},
body: {},
});
```
## Available tools [#available-tools]
### Common tools [#common-tools]
All transfer tools move real funds. The agent confirms every transfer with the user before executing. After sending, the default flow polls `get_transaction_status` until the transaction completes or fails.
* Wallet management:
* `get_wallet` - returns the current wallet address and network: `mainnet` or `testnet`.
* Balances and history:
* `get_balance` - returns the Toncoin balance of the current wallet.
* `get_balance_by_address` - returns the Toncoin balance for any address.
* `get_jetton_balance` - returns the balance of a specific jetton in the current wallet.
* `get_jettons` - lists all jettons held by the current wallet with balances and metadata.
* `get_jettons_by_address` - lists all jettons held by any address with balances and metadata. Supports pagination.
* `get_jetton_info` - returns metadata for a jetton minter (master) contract: name, symbol, decimals, image, URI.
* `get_known_jettons` - returns a built-in list of popular jettons on TON with addresses and metadata.
* `get_transactions` - returns recent transaction history: Toncoin transfers, jetton transfers, swaps.
* `get_transaction_status` - returns the status (pending, completed, or failed) and trace details for a transaction by its normalized hash.
* Transfers:
* `send_ton` - sends Toncoin to an address. Amounts are in human-readable format. For example, `"1.5"` for 1.5 Toncoin. Returns a `normalizedHash`.
* `send_jetton` - sends jettons to an address. Amounts are in human-readable format. Returns a `normalizedHash`.
* `send_nft` - transfers an NFT to another address. Returns a `normalizedHash`.
* `send_raw_transaction` - sends a raw transaction with full control over messages. Amounts are in nanoToncoin. Supports multiple messages. Returns a `normalizedHash`.
* Swaps:
* `get_swap_quote` - returns a quote for a token swap. The response includes transaction parameters ready for `send_raw_transaction`. Use `"TON"` for native Toncoin or a jetton minter (master) contract address.
* NFTs:
* `get_nfts` - lists NFTs in the current wallet with metadata, collection info, and attributes. Supports pagination.
* `get_nfts_by_address` - lists NFTs held by any address. Supports pagination.
* `get_nft` - returns detailed information about a specific NFT by its item contract address.
* DNS:
* `resolve_dns` - resolves a TON DNS domain to a wallet address.
* `back_resolve_dns` - reverse-resolves a wallet address to its associated DNS domain when one exists.
### Agentic tools [#agentic-tools]
* Wallet management:
* `list_wallets` - lists all wallets in the local config registry.
* `get_current_wallet` - returns the active wallet from the local config registry.
* `set_active_wallet` - switches the active wallet in the local config registry by its ID, name, or address.
* `remove_wallet` - soft-deletes a wallet from the local config registry. The wallet remains in the config file but is hidden from MCP lookups.
* Agentic wallet management:
* `agentic_validate_wallet` - validates an agentic wallet address against the expected network and collection.
* `agentic_list_wallets_by_owner` - lists agentic wallets owned by a given main wallet address.
* `agentic_import_wallet` - imports existing agentic wallet into the local registry. If no matching pending draft exists, the wallet is read-only until `agentic_rotate_operator_key` completes.
* `agentic_rotate_operator_key` - starts operator key rotation: generates a replacement key, persists a pending draft, and returns a dashboard URL for the on-chain change.
* `agentic_get_pending_operator_key_rotation` - returns one pending operator key rotation by ID.
* `agentic_complete_rotate_operator_key` - completes a key rotation after the on-chain transaction confirms and updates the stored operator key locally.
* `agentic_cancel_rotate_operator_key` - cancels a pending key rotation and discards the replacement key.
* Agentic wallet onboarding:
* `agentic_start_root_wallet_setup` - starts first-time root agent setup: generates operator keys, persists a pending draft, and returns a dashboard URL.
* `agentic_list_pending_root_wallet_setups` - lists pending root agent onboarding drafts and their callback status.
* `agentic_get_root_wallet_setup` - returns one pending onboarding draft by setup ID.
* `agentic_complete_root_wallet_setup` - completes onboarding from a callback payload or a manually supplied wallet address, then imports the wallet and makes it active.
* `agentic_cancel_root_wallet_setup` - cancels a pending onboarding draft and removes its state.
## Environment variables [#environment-variables]
### Common [#common]
TON network and default env override target for `TONCENTER_API_KEY`. Use `mainnet` for production and `testnet` for development and testing.
Defaults to `mainnet`.
API key for [TON Center](/applications/api/toncenter/introduction). Raises the default rate limit from 1 request per second to the limit of the selected plan. Without a key, the server uses a built-in shared key suitable for low-volume development and experiments.
For production workloads, [obtain a dedicated key](/applications/api/toncenter/get-api-key).
Optional public base URL for agentic onboarding callbacks
Host for the local callback server in stdio mode. Defaults to `127.0.0.1`.
Port for the local callback server in stdio mode. Defaults to a random free port.
### Agentic wallets [#agentic-wallets]
Config path for agentic wallets mode. Defaults to `~/.config/ton/config.json`.
### Single-wallet [#single-wallet]
Space-separated 24-word mnemonic phrase for the single-wallet mode.
Alternative to `PRIVATE_KEY`.
Hex-encoded private key for the single-wallet mode. Can be given either 32-byte standalone or 64-byte when paired with the public key.
Alternative to `MNEMONIC`. Takes priority over it.
TON wallet version to use in the single-wallet mode: [`v5r1`, `v4r2`][wallets-comparison], or [`agentic`][wallets].
Defaults to `v5r1`.
Address of the agentic wallet in the single-wallet mode. Required for `WALLET_VERSION` set to `agentic`, unless derived from initial params.
Optional index of the agentic wallet NFT contract.
Defaults to none.
Agentic collection address override for single-wallet mode.
Defaults to `EQByQ19qvWxW7VibSbGEgZiYMqilHY5y1a_eeSL2VaXhfy07` on the mainnet.
## Library usage [#library-usage]
The package also exports a programmatic API for building custom MCP servers:
```typescript
import { createTonWalletMCP } from '@ton/mcp';
import {
Signer,
WalletV5R1Adapter,
TonWalletKit,
MemoryStorageAdapter,
Network,
} from '@ton/walletkit';
// Mnemonic as a single string of 24 words:
// " ... "
const MNEMONIC = process.env.MNEMONIC!;
// Initialize WalletKit
const network = Network.mainnet();
const kit = new TonWalletKit({
networks: { [network.chainId]: {} },
storage: new MemoryStorageAdapter(),
});
await kit.waitForReady();
// Create a wallet from a mnemonic
const signer = await Signer.fromMnemonic(MNEMONIC.split(' '), { type: 'ton' });
const walletAdapter = await WalletV5R1Adapter.create(signer, {
client: kit.getApiClient(network),
network,
});
const wallet = await kit.addWallet(walletAdapter);
// Create the MCP server object
const server = await createTonWalletMCP({ wallet });
```
Agentic wallets mode:
```typescript
import { createTonWalletMCP } from '@ton/mcp';
// A key for higher RPS limits
const TONCENTER_API_KEY = process.env.TONCENTER_API_KEY!;
// Create the MCP server object
const server = await createTonWalletMCP({
networks: {
mainnet: { apiKey: TONCENTER_API_KEY },
},
});
```
## See also [#see-also]
* [Agentic wallets][wallets]
* [`@ton/mcp` on GitHub][mcp-repo]
[mcp-repo]: https://github.com/ton-connect/kit/tree/main/packages/mcp
[mcp-npm]: https://www.npmjs.com/package/@ton/mcp?activeTab=versions
[mcp-spec]: https://modelcontextprotocol.io/
[skills-spec]: https://agentskills.io/specification
[wallets]: /ecosystem/ai/wallets
[wallets-comparison]: /standard/wallets/comparison#comparison-table
[changelog]: https://github.com/ton-connect/kit/blob/main/packages/mcp/CHANGELOG.md
# Overview of AI in TON (/overview/ai/overview)
There are AI products utilizing TON Blockchain, such as agents and wallet tooling. Additionally, TON documentation is AI-friendly, and enables all kinds of AI workflows.
## AI ecosystem [#ai-ecosystem]
### `@ton/mcp` [#tonmcp]
The main official entry point is [`@ton/mcp`](/overview/ai/mcp), a TON MCP server for agents. It exposes tools for balance checks, asset queries, transfers, TON DNS resolution, swaps, and [agentic wallet](/overview/ai/wallets) management. Use [`@ton/mcp`](/overview/ai/mcp) when an agent needs to operate on TON through MCP or through a skills-based setup.
For the catalog of official TON MCP servers, setup guides, and related skills, see the [TON MCP portal](https://mcp.ton.org/).
### Agentic wallets [#agentic-wallets]
[Agentic wallet contracts](/overview/ai/wallets) provide self-custody wallets for autonomous AI agents operating on TON. They are used by `@ton/mcp` in its default agentic wallets mode.
### Community [#community]
The [AI Dev Wall on Telegram](https://t.me/ai_dev_wall) is a builder channel for TON AI tooling and project updates. This channel primarily features third-party, community resources.
## Documentation [#documentation]
TON documentation exposes several AI-facing surfaces:
* The in-site assistant can answer questions over the docs and cite relevant pages. Assistant can be invoked by a shortcut Ctrl+K (or Cmd+K on macOS), a query in the floating input field at the bottom of each page, from any selection on the page, or via a button on each code block to explain its contents.
* MCP server allows reading and querying documentation pages via MCP clients: `https://docs.ton.org/mcp`. Unlike [`@ton/mcp`](/overview/ai/mcp), it does not provide agents with tools to act on TON, only the documentation content.
* The contextual menu can copy page content, open a page in external AI tools, or connect to the documentation MCP.
* The [`llms.txt`](https://docs.ton.org/llms.txt) file provides a machine-readable index of documentation pages.
* Raw Markdown is available through `.md` page routes. This is useful when a tool needs the page content without the site UI. For example, to obtain raw contents of this page, query `https://docs.ton.org/ecosystem/ai/overview.md`.
# Agentic wallet contracts (/overview/ai/wallets)
Agentic wallets are self-custody wallets designed for autonomous AI agents on TON.
Agentic wallet contracts have not been audited. Use testnet for experiments.
## Split-key architecture [#split-key-architecture]
Each agentic wallet is a smart contract deployed as [Soulbound Token (SBT)](/blockchain-basics/standard/tokens/nft/comparison#sbt) within a shared NFT collection. Internally, each agentic wallet retains full [wallet v5](/blockchain-basics/standard/wallets/comparison#comparison-table) functionality. It stores the user's address (owner), the agent's (operator) public key, and a nonce to protect against replay attacks.
The deployment process goes as follows:
1. The agent creates a pair of keys (public and private), keeping the private key in the local config registry.
2. User deploys an agentic wallet from their regular TON wallet by providing the operator's public key and wallet address (owner address).
3. The contract checks that the sender's address matches the stored owner's address. If it doesn't match, the wallet will be deployed in an uninitialized state and will not appear in explorers, preventing the creation of unwanted wallets without the user's consent.
4. If deployment is successful, the agent receives the address of the new wallet.
With a private operator key and a new wallet address, the agent can sign and send transactions from that wallet. Alas, the user can withdraw funds, rotate the operator key, or deactivate the agent at any time by setting the operator key to zero.
This split-key design gives agents access to transfers, swaps, and other on-chain operations without exposing the user's root credentials or violating the user's ownership and control.
## Funding [#funding]
Transactions initiated by the agent (operator) must be signed with the operator key. Because the operator key is separate from the user's key (owner's key), the agent never controls the owner's main wallet. However, an agent with an active operator key has complete control of the balance and assets held in its own agentic wallet.
Only fund agentic wallets with amounts and assets that they are allowed to risk.
## Dashboard [#dashboard]
The [agentic wallets dashboard](https://agents.ton.org/) is a web interface for managing agentic wallets. It supports:
* Wallet creation - deploy a new agentic wallet, assign an operator key, and fund it with Toncoin.
* Real-time monitoring - observe agent transactions as they happen.
* Key rotation - rotate operator keys without redeploying the wallet contract.
* Revocation - revoke agent access by removing the operator key.
* Funding and withdrawal - deposit or withdraw Toncoin, jettons, and NFTs.
Connect an existing TON wallet to access the dashboard.
## Get started [#get-started]
The recommended way to create and use agentic wallets is through [`@ton/mcp`](/overview/ai/mcp). The [`@ton/mcp` quick start](/overview/ai/mcp#quick-start) guide covers the full setup flow and gives common usage examples.
## FAQ [#faq]
The owner key is never shared with agents. The agent has its own operator key that can only be used to spend from its own agentic wallet, and any balance in that wallet is fully under the agent's control. All operations are performed on-chain with no intermediaries.
The agent can only spend what was deposited into its wallet. The owner's main wallet is completely separate.
However, if the agent behaves incorrectly or performs expensive transactions, it can spend the entire wallet balance before the owner reacts.
The risk is capped to the deposited amount. Only deposit funds that are acceptable to lose.
Not yet. This is a developer preview. The contracts are open source and [available on GitHub](https://github.com/the-ton-tech/agentic-wallet-contract), but a formal audit has not been completed.
There is no limit. Each agent has its own wallet and balance. All agents are managed from a single dashboard.
Select Revoke , then confirm the transaction. The operator is deactivated, and remaining funds can be withdrawn.
# Analytics and data providers (/overview/infrastructure/analytics)
Developers often need to run analytical queries on top of on-chain data — for example, to track historical changes and aggregate data from multiple accounts.
Since blockchains are not designed for analytical workloads, you need to build an indexing pipeline and run off-chain analytical queries.
Creating such pipelines from scratch can be resource-consuming, so we recommend using one of the tools mentioned on this page.
## Dune analytics [#dune-analytics]
[Dune analytics](https://dune.com/) is one of the leading platforms for running analytical queries and building dashboards. It comes with 100+ blockchain integrations, and TON is among them. Basically, one needs to be familiar with SQL language to write queries, but the [Dune AI](https://docs.dune.com/learning/how-tos/dune-ai-prompt-engineering) prompt engine allows users to start working with data even without SQL knowledge.
### Raw and decoded tables [#raw-and-decoded-tables]
Dune analytics consumes data from the public [TON Data Lake](#public-data-lake) (see below) and comes with a variety of raw and decoded tables.
The [raw tables](https://dune.com/queries?category=canonical\&namespace=ton) include:
* [Blocks](https://docs.dune.com/data-catalog/ton/blocks)
* [Transactions](https://docs.dune.com/data-catalog/ton/transactions)
* [Messages](https://docs.dune.com/data-catalog/ton/messages) — includes raw body and `StateInit` data.
* [Balances history](https://docs.dune.com/data-catalog/ton/balances_history) — allows you to get a precise point-in-time balance for any account.
* [Jetton events](https://docs.dune.com/data-catalog/ton/jetton_events) — comes with transfers, burns, and mints.
Since mints are not covered by the [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) standard, it is not possible to reconstruct balances based solely on jetton events, so the balance history should be used.
Apart from raw tables, there are decoded tables that allow you to work with high-level structures in a unified manner:
* [NFT events](https://dune.com/queries?category=canonical\&namespace=ton\&id=ton.nft_events) — comprehensive source of NFT-related data, including
sales, transfers, and mints.
* [DEX trades](https://docs.dune.com/data-catalog/ton/dex_trades) — includes a unified data model for DEX trades. The full list of
supported DEXs is available [here](https://github.com/ton-studio/ton-etl/blob/main/datalake/README.md#dex-trades).
* [DEX pools](https://docs.dune.com/data-catalog/ton/dex_pools) — comes with the full history of DEX pool balances and TVL estimations.
Finally, two tables with off-chain metadata are available:
* [Jetton metadata](https://docs.dune.com/data-catalog/ton/jetton_metadata)
* [NFT metadata](https://dune.com/queries?category=canonical\&namespace=ton\&id=ton.nft_metadata).
### Bespoke data marts [#bespoke-data-marts]
Dune analytics allows projects to build bespoke data marts for each protocol — it is widely used for EVMs with the help of ABIs.
#### Decoding raw data [#decoding-raw-data]
Since TON handles complex [data structures](/blockchain-basics/primitives/serialization/cells) and doesn't have ABIs, a [special decoding framework](https://github.com/duneanalytics/spellbook/blob/main/dbt_subprojects/daily_spellbook/macros/project/ton/README.md) was created. It works on top of the [Spellbook](https://github.com/duneanalytics/spellbook) — a powerful tool for building custom tables with [`dbt`](https://github.com/dbt-labs/dbt-core) and Jinja macros. It helps decode important information from raw protocol message payloads.
The following protocols are decoded using this framework and serve as examples:
* [EVAA](https://dune.com/queries?category=abstraction\&namespace=evaa) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/evaa/ton))
* [Affluent](https://dune.com/queries?category=abstraction\&namespace=affluent) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/affluent/ton))
* [StormTrade](https://dune.com/queries?category=abstraction\&namespace=stormtrade) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/stormtrade/ton))
* [TON DNS](https://dune.com/queries?category=abstraction\&namespace=dns_ton) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/ton/dns))
#### Custom views [#custom-views]
In addition to decoding raw data, the Spellbook allows building custom materialized views. Some of them are widely used and maintained to be up to date:
* [ton.prices\_daily](https://dune.com/queries?category=abstraction\&namespace=ton\&id=ton.prices_daily) — prices calculated based on all other tables. The prices include jettons traded on DEXs, LP tokens for DEXs, perpetuals, tsUSDe, and other core assets. It is recommended to use this table if you need to build an estimation of assets denominated in TON or USD.
* [ton.accounts](https://dune.com/queries?category=abstraction\&namespace=ton\&id=ton.accounts) — materialized view with information about all accounts. It comes with the latest TON balance, interface (if any), funding information, and other fields.
* [ton.latest\_balances](https://dune.com/queries?category=abstraction\&namespace=ton\&id=ton.latest_balances) — helper table to get the latest balances for TON and Jettons.
All tables mentioned above are updated daily.
### Getting started with Dune [#getting-started-with-dune]
If you're just starting to explore TON data on Dune, we recommend checking these articles first:
For inspiration to build your own dashboards, check out these examples:
## Public Data Lake [#public-data-lake]
Dune integration runs on the public data lake from the [TON-ETL](https://github.com/re-doubt/ton-etl/blob/main/datalake/README.md) project.
[TON-ETL](https://github.com/re-doubt/ton-etl/blob/main/datalake/README.md) is built on top of [TON Center](https://github.com/toncenter) indexer and allows extraction of data from TON Node into data formats suitable for MPP (Massively Parallel Processing) engines: Presto, Apache Spark, etc.
You can deploy it on your own infrastructure or use publicly available data from the S3 bucket: `s3://aws-public-blockchain/v1.1/ton/`. This dataset is part of the [AWS Public Blockchain Data](https://registry.opendata.aws/aws-public-blockchain/) project and is optimized for use within the AWS big data stack.
Examples of AWS Athena and AWS Bedrock integration can be found in this [article](https://repost.aws/articles/AR3ABC81yvTPW2ktfHiHPWIA/new-dataset-added-to-the-aws-public-blockchain-data-ton-the-open-network).
The TON-ETL extracts raw data and performs decoding to create a unified view of high-level on-chain activity. The most important part is decoding DEX activity.
The decoding implementation must solve the following tasks:
* Decoding of swap events. The code must check the authenticity of the swap. For example, you cannot rely on the opcode alone since anyone can generate messages with your opcode.
* Extracting all swap-related fields: tokens sold and bought, amounts, query IDs, trader, router (if any), and pool.
* Fetching pool reserves and LP token supply, if applicable.
To add support for a new DEX and decode its activity, you need to prepare a relevant PR on GitHub [to TON-ETL's repo](https://github.com/ton-studio/ton-etl). Use those past PRs as a reference: [BidAsk](https://github.com/ton-studio/ton-etl/pull/186), [CoffeeSwap](https://github.com/ton-studio/ton-etl/pull/171/files), [MemesLab](https://github.com/ton-studio/ton-etl/pull/144).
## Real-time streams [#real-time-streams]
In addition to bulk data export, TON-ETL provides real-time data streaming via Kafka. A [public endpoint](https://github.com/ton-studio/ton-etl/blob/main/datalake/README.md#near-real-time--data-streaming-via-pulic-kafka-topics) is available free of charge for non-profit projects.
For projects that don't meet the non-profit criteria or require an in-house solution, you can deploy the infrastructure yourself by:
1. Running your own [TON node](/blockchain-basics/nodes/overview)
2. Launching [ton-etl](https://github.com/re-doubt/ton-etl/blob/main/README.md)
3. Setting up [ton-index-worker](https://github.com/ton-studio/ton-index-worker)
## TON Labels [#ton-labels]
While data availability and integrations are essential, building insightful dashboards requires enriching data with address labels.
The [TON Labels](https://github.com/ton-studio/ton-labels) project simplifies this process by providing a comprehensive taxonomy of addresses in TON Ecosystem. It covers active addresses across various categories, including centralized exchanges (CEXs), decentralized applications (dApps), and DeFi protocols.
You can access the latest labels either directly from [the build branch](https://github.com/ton-studio/ton-labels/blob/build/assets.json) or through Dune analytics using the [`dune.ton_foundation.dataset_labels`](https://dune.com/queries?category=uploaded_data\&id=dune.ton_foundation.dataset_labels) table.
## Other platforms [#other-platforms]
* [Chainbase](https://docs.chainbase.com/catalog/Ton/Overview) offers a set of raw and decoded tables with TON data. It allows you to run SQL queries and fetch results via API.
* [TON Console](https://docs.tonconsole.com/tonconsole/analytics) provides analysts with Analytics Service.
* [TokenTerminal](https://tokenterminal.com/explorer/projects/the-open-network) comes with high-level metrics across TON Ecosystem.
* [Artemis](https://app.artemisanalytics.com/project/ton?from=projects) contains key metrics for TON and allows you to build customized charts.
* [Spice harvester](https://github.com/txsociety/spice-harvester) supports high-load transaction monitoring and asset tracking on TON through a self-hosted API with access to invoice states and metadata.
# Bridges (/overview/infrastructure/bridges)
In the TON ecosystem, bridges allow users to transfer assets and data between TON and other major blockchains like Ethereum, BNB Chain, and Polygon.
In this article, we will explore cross-chain bridges on TON.
## What are Cross-Chain Bridges? [#what-are-cross-chain-bridges]
Cross-chain bridges are protocols that allow users to transfer cryptocurrencies, tokens, and sometimes arbitrary data from one blockchain to another. They act as connectors between otherwise isolated blockchain networks, enabling a multi-chain ecosystem where assets can move freely across different platforms.
Bridges typically work by locking assets on the source blockchain and minting equivalent wrapped tokens on the destination blockchain. When users want to move assets back, the wrapped tokens are burned on the destination chain, and the original assets are unlocked on the source chain.
### Types of Cross-Chain Bridges [#types-of-cross-chain-bridges]
#### 1. Trustless vs. Custodial Bridges [#1-trustless-vs-custodial-bridges]
Trustless Bridges:
* Use smart contracts and cryptographic proofs for validation
* No single point of failure
* Decentralized verification mechanisms
Centralized Bridges:
* Rely on trusted entities or multi-signature wallets
* Single point of failure risk
* Generally, they are easier to implement
#### 2. Asset Transfer Methods [#2-asset-transfer-methods]
Lock-and-Mint Bridges:
* Lock original assets on the source chain
* Mint wrapped tokens on the destination chain
* Most common bridge type
Burn-and-Mint Bridges:
* Burn tokens on the source chain
* Mint new tokens on the destination chain
* Used for native multi-chain tokens
## Bridges on TON [#bridges-on-ton]
The TON blockchain has a bridge ecosystem that connects it to major EVM-compatible networks. There are several kinds of bridge providers on TON.
### Legacy: Official TON Bridges [#legacy-official-ton-bridges]
During the early development of TON ecosystem (2021-2023) there were a few official TON bridges, supported at the protocol level. Now, they are considered legacy and not recommended for usage since they can be deprecated at any moment.
TON blockchain supports several official bridges configured at the protocol level:
#### Outbound Bridges (Config parameters 71-73) [#outbound-bridges-config-parameters-71-73]
These bridges wrap TON into other networks:
* **ETH-TON Bridge** ([Config Parameter 71](/blockchain-basics/primitives/config#param-71-73%3A-outbound-bridges))
* **BNB-TON Bridge** ([Config Parameter 72](/blockchain-basics/primitives/config#param-71-73%3A-outbound-bridges))
* **Polygon-TON Bridge** ([Config Parameter 73](/blockchain-basics/primitives/config#param-71-73%3A-outbound-bridges))
#### Inbound Bridges (Config parameters 79, 81-82) [#inbound-bridges-config-parameters-79-81-82]
These bridges wrap tokens from other networks into TON:
* **ETH-TON Bridge** ([Config Parameter 79](/blockchain-basics/primitives/config#param-79%2C-81-and-82%3A-inbound-bridges))
* **BNB-TON Bridge** ([Config Parameter 81](/blockchain-basics/primitives/config#param-79%2C-81-and-82%3A-inbound-bridges))
* **Polygon-TON Bridge** ([Config Parameter 82](/blockchain-basics/primitives/config#param-79%2C-81-and-82%3A-inbound-bridges))
You can read more about these bridge configuration parameters on the [TON Config page](/blockchain-basics/primitives/config).
### Third-Party Bridge Ecosystem [#third-party-bridge-ecosystem]
The TON ecosystem features multiple bridge providers offering different features and supported networks. You can read more about them in [TON Bridges page](https://ton.org/en/bridges).
You can see existing bridges statistics on [TON Foundation Bridge Dashboard](https://dune.com/ton_foundation/bridges).
# Network status (/overview/infrastructure/status)
This page lists websites that show if specific parts of TON blockchain are working normally.
| | |
| ---------------------------------------------------------------- | ------------------------------------------------------------- |
| [https://tonstat.us/](https://tonstat.us/) | HTTP and ADNL server availability and performance. |
| [https://status.toncenter.com/](https://status.toncenter.com/) | Low-level metrics, such as latencies, rates, and loads. |
| [https://validators.ton.org/](https://validators.ton.org/) | Official validation dashboard. |
| [https://tonscan.com/validation](https://tonscan.com/validation) | Pretty validation dashboard. |
| [https://t.me/tonstatus](https://t.me/tonstatus) | Notifications and requests for action for mainnet validators. |
| [https://t.me/testnetstatus](https://t.me/testnetstatus) | Notifications and requests for action for testnet validators. |
| [https://t.me/validators](https://t.me/validators) | Bot for validator owners to track their status. |
# Coming from Ethereum (/overview/learn-more/from-ethereum)
Learn how to develop and build on TON coming from the Ethereum (EVM) ecosystem.
## Execution model [#execution-model]
### Asynchronous blockchain [#asynchronous-blockchain]
A fundamental aspect of TON development is the asynchronous execution model. Messages sent by one contract take time to arrive at another, so the resulting transactions for processing incoming messages occur after the current transaction terminates.
Compared to Ethereum, where multiple messages and state changes on different contracts can be processed within the same atomic transaction, a TON transaction represents a state change only for one account and only for a processing of a single message. Even though in both blockchains a signed included-in-block unit is called a "transaction", one transaction on Ethereum usually corresponds to several transactions on TON, that are processed over a span of several blocks.
| Action description | Ethereum | TON |
| :--------------------------------------------------------------------------------------------- | -------------------------------------- | -------------------------------- |
| Single message processing with state change on one contract | Message call or "internal transaction" | Transaction |
| Number of state changes and messages on different accounts produced from initial contract call | Transaction | Chain of transactions or "trace" |
Consider a practical example: liquidity withdrawal on a DEX.
* On Ethereum, it appears as a single atomic transaction with multiple contract calls inside it. This transaction has a single hash and is included in one block.
* The same operation on TON consists of a sequence of more than 10 transactions. Each arrow on this image represents a distinct finalized transaction, with its own hash, inclusion block, and all the other properties:
Executing a large transaction on Ethereum or any other EVM-based blockchain comes with certain limitations: [call depth](https://ethereum.org/developers/docs/evm/#evm-instructions) of 1,024 nested calls and the [block gas limit](https://ethereum.org/developers/docs/blocks/#block-size). With TON's asynchronous execution model, a trace — a chain of transactions — can have any length, as long as there are enough fees to continue it. For example, the [trace](https://tonviewer.com/transaction/e887503f7dac857be80487e3ed0774db962379d1c153e6df7b9b5313c657ab94) resulting from this message consisted of more than 1.5 million transactions, lasting more than 4,000 blocks until completion.
### On-chain get methods [#on-chain-get-methods]
Another difference is in the [get methods](/blockchain-basics/tvm/get-method). Both Ethereum and TON support them, allowing data to be retrieved from contracts without paying fees. However, in TON, get methods cannot be called on-chain: a contract cannot synchronously retrieve data from another contract during a transaction. This is a consequence of TON's asynchronous model: by the moment transaction that called a get method would start its execution, data might already change.
### Account model [#account-model]
In Ethereum, there are two types of accounts: externally owned accounts (EOA), and contract accounts. EOAs are human-controlled entities, each represented by a private-public key pair. They sign transactions and each has its own balance; the community often refers to them as "wallets".
In TON, there is no such separation. Every valid address represents an on-chain [account](/blockchain-basics/primitives/addresses/overview), each with its own state and balance, that could be changed through transactions. This means that "wallets" in TON are smart contracts that operate under the same rules as any other contract on the blockchain.
The [TON wallet](/blockchain-basics/standard/wallets/comparison) smart contract works as a proxy: handles an external message, checks message is sent by the wallet's owner using regular [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography), and sends an internal message somewhere further in the network.
### Limited contract storage [#limited-contract-storage]
In Ethereum, it's possible to store any amount of data in a single contract. Unbounded maps and arrays are considered standard practice. TON sets a limit to the amount of data a contract can store. This means that ERC-20-like fungible tokens cannot be implemented in the same way as in an EVM chain, using a single map within a single contract.
[The limit](/blockchain-basics/primitives/config) for contract storage is 65,536 unique cells contract storage, where a cell [stores up to](/blockchain-basics/primitives/serialization/cells) 1,023 bits. Messages are constrained by two size limits: 8,192 cells or 221 bits among them, whichever is smaller.
Every map that is expected to grow beyond 1,000 values is dangerous. In the TVM map, key access is asymptotically logarithmic, meaning that gas consumption continuously increases to find keys as the map grows.
Instead, [sharding](/blockchain-basics/contract-dev/techniques/contract-sharding) should be used.
## Ecosystem [#ecosystem]
### Tooling [#tooling]
The recommended programming language for smart contract development in TON is [Tolk](/blockchain-basics/tolk/overview). Other established languages also exist and are still used, albeit in legacy status.
For off-chain software, TypeScript is the most adopted language in TON. Most of the tooling, bindings and [SDKs](/applications/sdks) are implemented in TypeScript.
| Use case | Ethereum tool | TON counterparts |
| :------------------------------------ | --------------------- | --------------------------------------------------------------------------------------------------------------- |
| Blockchain interaction | Ethers, Web3.js, Viem | [`@ton/ton`](https://www.npmjs.com/package/@ton/ton), [Asset-sdk](https://github.com/ton-community/assets-sdk) |
| Wallet connection protocol | WalletConnect, Wagmi | [TON Connect](https://github.com/ton-connect) |
| Dev environment framework / scripting | Hardhat, Truffle | [Acton](https://github.com/ton-blockchain/acton), [Blueprint](https://github.com/ton-org/blueprint) |
| Simulation engine | Revm & Reth | [Emulator within Acton](https://github.com/ton-blockchain/acton), [Sandbox](https://github.com/ton-org/sandbox) |
For low-level manipulation of TON-specific data structures, there is [`@ton/core`](https://www.npmjs.com/package/@ton/core). Another library with wrappers for most important contracts and HTTP APIs is [`@ton/ton`](https://www.npmjs.com/package/@ton/ton).
### Services [#services]
Web3 developers often rely on specific products and services for on-chain development.
The following table showcases some use cases that existing TON services support.
| Use case | Ethereum service | TON service |
| --------------------------------------- | ---------------- | -------------------------------------------------------------------- |
| User-friendly explorer | Etherscan | [Tonviewer](https://tonviewer.com/), [Tonscan](https://tonscan.org/) |
| Open-source dev explorer | Blockscout | [TON Explorer](https://explorer.toncoin.org/) |
| Debugger | Remix Debugger | [TxTracer](https://txtracer.ton.org/) |
| IDE | Remix IDE | [Web IDE](https://ide.ton.org/) |
| Asm playground and compilation explorer | EVM.Codes | [TxTracer](https://txtracer.ton.org/) |
### Standards [#standards]
The table maps Ethereum standards and proposals, including ERC and EIP, to their TON counterparts, referred to as TEP.
Due to significant differences in execution models, most of the standards in TON differ significantly in semantics and general approach compared to their Ethereum analogs.
| Description | Ethereum standard | TON Standard (TEP) |
| --------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------ |
| Fungible token standard | ERC-20 | [Jettons (TEP-0074)](/blockchain-basics/standard/tokens/jettons/overview) |
| Non-fungible token standard | ERC-721 | [NFT standard (TEP-0062)](/blockchain-basics/standard/tokens/nft/overview) |
| Token metadata | ERC-4955 (Not exactly, but close match) | [Token Data Standard (TEP-0064)](/blockchain-basics/standard/tokens/metadata) |
| NFT royalty standard | EIP-2981 | [NFT Royalty Standard (TEP-0066)](/blockchain-basics/standard/tokens/nft/comparison) |
| DNS-like registry | ENS (EIP-137) | [DNS Standard (TEP-0081)](/blockchain-basics/primitives/web3/overview) |
| Soulbound / account-bound token concept | EIP-4973 | [SBT Standard (TEP-0085)](/blockchain-basics/standard/tokens/nft/comparison#sbt) |
| Wallet connection protocol | WalletConnect / EIP-1193 | [TonConnect (TEP-0115)](/applications/ton-connect/overview) |
# Glossary (/overview/learn-more/glossary)
## A [#a]
### Airdrop [#airdrop]
a free distribution of tokens among specific participants.
### Altcoin [#altcoin]
all cryptocurrencies, except Bitcoin, are called altcoins.
### Application Programming Interface (API) [#application-programming-interface-api]
a mechanism that allows two programs to interact with each other through a series of protocols.
### Annual Percentage Yield (APY) [#annual-percentage-yield-apy]
a calculated yearly interest rate for a given asset.
***
## B [#b]
### Bearish [#bearish]
the term “bearish” is used when the price of an asset has declined due to investors selling. (The term is often used to describe the overall market sentiment.)
### Binance [#binance]
a major cryptocurrency exchange. [Website](https://www.binance.com/).
### Bitcoin (BTC) [#bitcoin-btc]
the preeminent cryptocurrency and the first decentralized network with open-source code, which laid the groundwork for the proliferation of blockchain technology. [**Wikipedia**](https://en.wikipedia.org/wiki/Bitcoin).
### Blockchain [#blockchain]
a distributed ledger of data in the form of a chain of blocks recording transaction information for every event on the network.
### Bag of Cells (BoC) [#bag-of-cells-boc]
serialization format for cells. Commonly used in code. [Article](/blockchain-basics/primitives/serialization/boc).
### Bot [#bot]
a program written for two ecosystems to interact with each other — e.g., The Open Network and the Telegram messenger. On Telegram, bots are accounts in the messenger operated by software.
### Bridge [#bridge]
a program connecting various blockchains to transfer tokens and data from one network to another. [Article](/overview/infrastructure/oracles/overview).
### Bullish [#bullish]
the term “bullish” is used to describe an asset whose value is appreciating. (“Bullish” is the opposite of “bearish” — i.e., when the market's overall value is increasing.)
### Burning [#burning]
the act of permanently removing tokens from circulating and total supply.
***
## C [#c]
### Centralized exchange (CEX) [#centralized-exchange-cex]
a centralized cryptocurrency exchange to trade tokens.
### CoinMarketCap (CMC) [#coinmarketcap-cmc]
a crypto information aggregator that closely follows changes in token prices and market capitalization. [Website](https://coinmarketcap.com/).
### Coinbase [#coinbase]
a major cryptocurrency exchange based in the United States. [Website](https://www.coinbase.com/).
### Cryptobot [#cryptobot]
a peer-to-peer (P2P) bot service for buying, trading, and selling Toncoin and other cryptocurrencies.
### Custodial [#custodial]
a type of crypto wallet where a third party stores cryptocurrencies, and not their true owner.
***
## D [#d]
### Decentralized application (dApp) [#decentralized-application-dapp]
applications run on-chain and rely on smart contracts for computation, storage, and communication.
### Dollar-cost averaging (DCA) [#dollar-cost-averaging-dca]
an investment strategy whereby investors buy a fixed amount at regular intervals regardless of price to reduce timing risk.
### Decentralization [#decentralization]
one of the main tenets behind TON and other blockchains. Without decentralization, Web3 would be impossible to achieve; therefore, every element of the TON ecosystem revolves around maximizing decentralization.
### DeFi [#defi]
the decentralized analog to traditional finance; it includes accessible financial services and applications based on smart contracts.
### Decentralized exchange (DEX) [#decentralized-exchange-dex]
an exchange where users can trade cryptocurrencies without any intermediaries. The online entity needed to guarantee safe transactions is the blockchain itself.
### Diamond hands [#diamond-hands]
a colloquial term describing an investor who has no intention of selling their assets regardless of the state of the market — even if there's a crash or the market is bearish.
### Domain Name System (DNS) [#domain-name-system-dns]
a technology that translates human-readable domain names (e.g. ton.org) to machine-readable IP addresses (e.g. 192.0.2.44).
### Dolphin [#dolphin]
an investor who has relatively small capital but has an influence on the community.
### Donate [#donate]
a bot service on Telegram through which people can donate money, and content creators can monetize their channels and services in Toncoin.
### Dump [#dump]
rapidly selling a cryptocurrency or asset, often causing a price decline.
### Durov [#durov]
Pavel Durov, a Russian entrepreneur who is famous for having founded the VK social network and Telegram messenger.
Nikolai Durov is Pavel's brother, who helped develop VK, Telegram, and TON.
### Do Your Own Research (DYOR) [#do-your-own-research-dyor]
the process by which you do research on a project, company or cryptocurrency before deciding to invest.
***
## E [#e]
### Ethereum Virtual Machine (EVM) [#ethereum-virtual-machine-evm]
a machine behaving like a decentralized computer, it computes the state of the Ethereum blockchain after each new block and executes smart contracts.
### Exchange [#exchange]
a place for trading and using other market instruments.
***
## F [#f]
### Farming [#farming]
lending your crypto assets to receive rewards.
### Fiat [#fiat]
regular money issued by central banks or financial authorities.
### Fear of missing out (FOMO) [#fear-of-missing-out-fomo]
a psychological state that consumes some investors when the idea of losing potential gains from an opportunity is present. It usually appears during a bull market and when traders don't do their due diligence analyzing a particular project.
### Fungible tokens [#fungible-tokens]
cryptocurrencies that carry the same value as any other token of the same kind at any given moment.
### FUD [#fud]
“fear, uncertainty, and doubt,” market sentiments based on many factors.
### Full node [#full-node]
a computer on blockchain that synchronizes and copies the entire blockchain.
### FunC [#func]
the smart contract language on TON.
***
## G [#g]
### Gas [#gas]
the fee paid for transactions on the blockchain.
### GitHub [#github]
a platform for hosting code and collaborating via Git repositories.
***
## H [#h]
### Hackathon [#hackathon]
a collaborative event where programmers and builders develop software projects.
### Hash [#hash]
a fixed-size digest computed from data using a hashing algorithm.
### Hash rate [#hash-rate]
the indication of how much computational power is being used on a network for crypto mining.
### Hold [#hold]
saving — i.e., not selling — an asset or assets from your portfolio.
***
## I [#i]
### Initial Coin Offering (ICO) [#initial-coin-offering-ico]
a method for crypto projects to attract capital in the early stages.
### Initial Decentralized exchange Offering (IDO) [#initial-decentralized-exchange-offering-ido]
a method of attracting capital when launching a cryptocurrency or token on a decentralized exchange.
### Inflation [#inflation]
the process when the value of a currency — e.g., U.S. dollar or the euro — decreases. Toncoin has predictable issuance and a low inflation rate.
***
## K [#k]
### Know Your Customer (KYC) [#know-your-customer-kyc]
the process by which a user verifies their identity when creating an account for a crypto service.
***
## L [#l]
### Launchpad [#launchpad]
a platform for crypto startups that brings investors and projects together.
### Liquidity pool [#liquidity-pool]
grouping together crypto assets and freezing them in a smart contract. Liquidity pools are used for decentralized trading, loans, and other endeavors.
***
## M [#m]
### Mainnet [#mainnet]
the main network of a blockchain.
### Market capitalization (market cap) [#market-capitalization-market-cap]
the total market value of a cryptocurrency's circulating supply.
### Masterchain [#masterchain]
the main chain that references shard and workchain blocks; a shard block is finalized once a Masterchain block references it.
### Metaverse [#metaverse]
a digital universe similar to a video game where users create avatars and interact with the digital representations of other people or users.
### Moon [#moon]
a crypto term that describes a crypto asset's vertical trajectory on a price chart — i.e., it quickly gains value.
***
## N [#n]
### "Not financial advice" (NFA) [#not-financial-advice-nfa]
acronym used as a disclaimer to avoid liability or responsibility when investors discuss cryptocurrencies or projects with other people.
### Non-fungible token (NFT) [#non-fungible-token-nft]
a unique digital token on a blockchain that cannot be duplicated or minted more than once.
### Nominator [#nominator]
those who provide financial resources to validators so the latter can confirm blocks on TON blockchain.
### Non-custodial [#non-custodial]
a kind of crypto wallet that gives full control over assets to the owner/user.
***
## O [#o]
### Off-ramp [#off-ramp]
ways to convert cryptocurrencies into fiat money.
### On-ramp [#on-ramp]
ways to convert (buy) cryptocurrency by spending fiat money.
### Onion routing [#onion-routing]
a technology similar to Tor that allows anonymous interactions on a network. All messages are encrypted in various layers akin to an onion. TON Proxy applies such a technique.
***
## P [#p]
### Paper hands [#paper-hands]
an investor who's inclined to panic-sell — an inexperienced investor.
### Proof-of-stake [#proof-of-stake]
a consensus mechanism to process transactions in new blocks on the blockchain.
### Proof-of-work [#proof-of-work]
a consensus algorithm where one party proves to another that a specific amount of computational work was spent. By expending a little energy, a party can verify this.
### Proxy [#proxy]
a service on a computer network that allows clients to establish indirect network connections with other network services.
### Pump [#pump]
artificially inflating the price of a cryptocurrency or asset.
### Peer-to-peer (P2P) [#peer-to-peer-p2p]
transactions among users without the help of a third party or intermediary.
***
## R [#r]
### Roadmap [#roadmap]
a project's strategic plan that displays when its products, services, updates, etc. will be released.
### Return on investment (ROI) [#return-on-investment-roi]
the profits made from investments.
***
## S [#s]
### Soulbound token (SBT) [#soulbound-token-sbt]
an NFT that can never be transferred because it contains information about its owner and their accomplishments.
### Scalability [#scalability]
the ability of a blockchain network to process complex transactions as well as a large number of them.
### Securities and Exchange Commission (SEC) [#securities-and-exchange-commission-sec]
a financial regulator in the United States. [Website](https://www.sec.gov/).
### Shard [#shard]
a mechanism that helps a blockchain network to scale by breaking into smaller blockchains to relieve network congestion — something which TON blockchain does.
### Smart contract [#smart-contract]
self-executing code that oversees and enables operations with the help of mathematical algorithms and without human intervention.
### Spot trading [#spot-trading]
trading a financial asset for money.
### Stablecoin [#stablecoin]
a cryptocurrency that aims to maintain a stable value (often pegged to a fiat currency).
### Staking [#staking]
a way for users to earn a passive income by storing coins or tokens in a proof-of-stake algorithm, which, in turn, ensures the blockchain runs smoothly. For this, they earn rewards as an incentive.
### Swap [#swap]
the exchange of two financial assets — e.g., Toncoin for USDT.
***
## T [#t]
### TON Enhancement Proposals (TEPs) [#ton-enhancement-proposals-teps]
a [standard set](https://github.com/ton-blockchain/TEPs) of ways to interact with various parts of the TON ecosystem.
### TON Pay [#ton-pay]
a payment integration for TON that provides APIs, UI components, and webhooks for creating and tracking transfers.
### Testnet [#testnet]
a network for testing projects or services before launching on the mainnet.
### Ticker [#ticker]
the short form of a cryptocurrency, asset, or token on exchanges, trading services, or other DeFi solutions — e.g. TON for Toncoin.
### The Merge [#the-merge]
the transition process of Ethereum switching from proof-of-work to proof-of-stake.
### Token [#token]
a form of digital asset; it can have multiple functions.
### Tokenomics [#tokenomics]
the economic plan and distribution strategy of a cryptocurrency (or token).
### To the moon [#to-the-moon]
a colloquial phrase used when people create FOMO. It refers to hopefuls wanting the value of a cryptocurrency rapidly gaining a lot of value — hence its trajectory to the moon.
### Toncoin [#toncoin]
the native cryptocurrency of the TON ecosystem, which is used to develop services and pay for fees and services. It can be bought, sold, and traded.
### Trading [#trading]
buying and selling cryptocurrencies with the goal of making a profit.
### Total Value Locked (TVL) [#total-value-locked-tvl]
the total value of assets currently locked (e.g. staked) in a specific protocol.
### TON Virtual Machine (TVM) [#ton-virtual-machine-tvm]
a machine that behaves like a decentralized computer; it computes the state of the TON blockchain after each new block and executes smart contracts.
***
## V [#v]
### Validator [#validator]
those who verify new blocks on TON blockchain.
***
## W [#w]
### “We're all gonna make it” (WAGMI) [#were-all-gonna-make-it-wagmi]
a sentence often used in the crypto community to express the aspirations of becoming rich one day by investing in cryptocurrencies.
### Wallet [#wallet]
an application that manages private keys and assets for sending, receiving, and storing cryptocurrencies. A Telegram bot (e.g., @wallet) also provides wallet functions within the TON ecosystem.
### Web3 [#web3]
a new generation of the internet based on blockchain technology that includes decentralization and tokenomics.
### Whale [#whale]
an investor who owns a large number of cryptocurrencies and tokens.
### White paper [#white-paper]
the main document of a project written by its developers. It explains the technology and the project's goals.
### Watchlist [#watchlist]
a customizable list of cryptocurrencies whose price action an investor wishes to follow.
### Workchain [#workchain]
secondary chains that connect to the masterchain. They can contain a massive number of different connected chains that have their own consensus rules. They can also contain address and transaction information and virtual machines for smart contracts. Additionally, they can be compatible with the masterchain and interact with one another.
***
## Y [#y]
### Yield farming [#yield-farming]
lending or placing cryptocurrencies or tokens in a smart contract to earn rewards in the form of transaction fees.
# Other resources (/overview/learn-more/more-tutorials)
This page collects additional learning resources beyond this documentation. You'll find a mix of official content not hosted in this documentation and community-created materials to help you continue your journey.
Whether you prefer structured courses, in-depth articles, video tutorials, or real code examples, there is something here to match your learning style and current skill level.
## Courses [#courses]
### Blockchain basics with TON [#blockchain-basics-with-ton]
Deprecated
This course introduces blockchain basics, focusing on practical skills in the TON ecosystem. You will understand how blockchain functions and its diverse applications.
This course is for junior developers, people new to crypto, non-technical IT professionals, and anyone curious about blockchains.
* [English](https://stepik.org/course/201294/promo)
* [Chinese](https://stepik.org/course/200976/promo)
* [Russian](https://stepik.org/course/202221/promo)
### TON & Telegram Blockchain development [#ton--telegram-blockchain-development]
Deprecated
The course is aimed at developers and IT specialists interested in gaining practical knowledge about the technologies and concepts of the TON Blockchain, such as FunC, dApps, decentralization, smart contracts, contract testing, as well as the creation of Mini Apps within Telegram.
* [English](https://stepik.org/course/176754/promo)
* [Chinese](https://stepik.org/course/201638/promo)
* [Russian](https://stepik.org/course/201855/promo)
## Articles [#articles]
Introductory:
* [How a Blockchain Can Help You on a Deserted Island](https://talkol.medium.com/why-decentralized-consensus-blockchain-is-good-for-business-5ff263468210)
Beginner-friendly:
* [What is Blockchain? What is a Smart Contract? What is Gas?](https://blog.ton.org/what_is_blockchain)
### "Hello World" guide series [#hello-world-guide-series]
A step-by-step tutorial series that starts with creating a new TON wallet and ends with a working, test-covered, and deployed smart contract, along with a Telegram Mini App frontend for it.
* [Part 1: Working with your first TON wallet](https://helloworld.tonstudio.io/01-wallet/)
* [Part 2: Writing your first smart contract](https://helloworld.tonstudio.io/02-contract/)
* [Part 3: Building your first web client](https://helloworld.tonstudio.io/03-client/)
* [Part 4: Testing your first smart contract](https://helloworld.tonstudio.io/04-testing/)
## Videos [#videos]
Introductory:
* [Crypto Networks and Why They Matter](https://www.youtube.com/watch?v=2wxtiNgXBaU)
### Playlists [#playlists]
Beginner-friendly:
* [TON Development with Tact](https://www.youtube.com/watch?v=Vf3Fx7qgL6k\&list=PLQ5rEj25H3U2P5qp7nsgVtNGYxEojnnez)
{/* NOTE: ## Podcasts */}
## Interactive learning [#interactive-learning]
### Code playgrounds [#code-playgrounds]
* [TxTracer](https://txtracer.ton.org/) - Trace and analyze TON Blockchain transactions with tools to visualize execution, inspect and debug smart contracts with a code editor and user-friendly interface.
* [Assembly Playground](https://txtracer.ton.org/play/) - Experiment with TVM assembly code directly in your browser. Write, test, and debug assembly instructions with real-time execution.
* [Code Explorer](https://txtracer.ton.org/code-explorer/) - Compile FunC or Tolk code to assembly and explore the generated bytecode to understand how your smart contracts work under the hood.
* [TVM Instruction table](https://txtracer.ton.org/spec/) - Browse the TVM instruction reference with detailed descriptions, opcodes, stack effects, and control flow information for every instruction.
* [Sandbox](https://txtracer.ton.org/sandbox/) - Inspect transactions produced by your local tests using the `@ton/sandbox` package. Visualize messages, transaction info, VM logs and exit codes with an interactive UI.
{/* NOTE: ### Tours */}
### Challenges and exercises [#challenges-and-exercises]
* [Hack the TON](https://www.hacktheton.com/en) - TON-based wargame inspired by The Ethernaut, played in the TON Virtual Machine. Each level is a smart contract that needs to be hacked. Our goal is to help you to learn how to develop safe TON smart contracts and build a thriving community around this craft.
## Smart contract examples [#smart-contract-examples]
Examples of smart contracts on TON include wallets, electors (which manage validator elections on TON), multi-signature wallets, and many more. They can serve as an excellent reference for those studying on real projects.
* [Tolk benchmark contracts](https://github.com/ton-blockchain/tolk-bench) - Tolk vs. FunC gas benchmarks and, simultaneously, reference Tolk contracts.
## Join the community [#join-the-community]
* [All TON communities](https://ton.org/en/community)
* [Telegram Dev chats](https://t.me/addlist/1r5Vcb8eljk5Yzcy)
# Get your TON Center API key (/applications/api/toncenter/get-api-key)
To interact with TON Center's API at higher rate limits, you'll need to generate an API key via the official [Telegram bot](https://t.me/toncenter).
## Open the TON Center bot [#open-the-ton-center-bot]
Open the [`@toncenter`](https://t.me/toncenter) bot in Telegram. Click **Start** to begin the setup.
## Open the API keys manager [#open-the-api-keys-manager]
Once the bot greets you, press **Manage API Keys**.
## Choose a subscription plan [#choose-a-subscription-plan]
Click **Manage** to open your current subscription details. The default API subscription is the free one.
You'll see different tiers available:
* **Free** – 10 requests/sec, 1 token per network
* **Plus** – 25 requests/sec, 3 tokens per network (2.5 TON/month)
* **Advanced** – 100 requests/sec, 10 tokens per network (25 TON/month)
* **Enterprise** – Tailored rate limits, priority support
## (optional) Upgrade your plan [#optional-upgrade-your-plan]
To upgrade:
* Select your desired plan in the bot interface and click **Purchase Subscription**.
* You'll be shown payment instructions like the following:
* Send the **exact amount** of TON to the address provided.
* Your subscription will upgrade automatically once the transaction is confirmed.
## Create your API key [#create-your-api-key]
After subscribing (or staying on Free), click **Create API Key** to generate your key.
Once created, your token will appear in the list and can be used in all authenticated requests.
## Get help [#get-help]
* General help: [`@toncenter_help_bot`](https://t.me/toncenter_help_bot)
* Support for enterprise and custom plans: [`@toncenter_support`](https://t.me/toncenter_support)
# Introduction (/applications/api/toncenter/introduction)
TON Center HTTP APIs: read blockchain data, query smart contracts, send transactions.
Direct liteserver for balances, sending transactions, contract queries.
Indexed database for traces, Jettons, NFTs, and historical queries.
Low-latency updates on subscriptions through SSE or WebSockets.
# Rate limits (/applications/api/toncenter/rate-limit)
To ensure stability and fair access, TON Center applies rate limits to all API requests.\
If an application exceeds these limits, the API returns a `429` response.
Increase limits by [requesting an API key](/applications/api/toncenter/get-api-key) and selecting a higher subscription plan. Without any API key, the default rate limit is 1 request per second.
## Default limits [#default-limits]
| Plan | Tokens per network | Requests per second | Notes |
| ---------- | ------------------ | ------------------- | ---------------------------------------------------------------------------------------------------------- |
| Free | 1 | 10 | Shared liteservers suitable for low-volume testing and small projects. |
| Plus | 3 | 25 | Private liteservers that reduce contention compared to shared access. |
| Advanced | 10 | 100 | Private infrastructure with capacity for higher request rates. |
| Enterprise | Custom | Custom | Custom throughput and support. Contact [`@toncenter_support`](https://t.me/toncenter_support) for details. |
Rate limits apply to all API keys in total separately for every TON network, including mainnet and testnet. For example, the Plus plan users can create three API keys for the mainnet. The total limit for these three keys will be 25 requests per second.
Each token represents an individual API key used to authenticate requests. Plans differ by how many tokens can be generated per network (mainnet and testnet). For example, the Free plan allows 1 key per network, while higher plans provide multiple keys for separate apps or environments.
## Rate limit exceeded [#rate-limit-exceeded]
When requests are sent faster than the allowed rate limit, the TON Center API temporarily blocks new ones. A JSON response indicates the rate limit is exceeded:
```json
{
"ok": false,
"result": "Ratelimit exceed",
"code": 429
}
```
When this occurs:
* Stop sending new requests and wait a few seconds before retrying.
* Implement exponential backoff to avoid repeated rate-limit violations.
## Troubleshooting [#troubleshooting]
If a paid plan is active but the rate remains 1 RPS:
* Check that the API key is included correctly in the requests. Requests without a valid API key are limited to 1 RPS, even if a subscription is active.
* Verify the correct key is used for the intended environment (mainnet or testnet). Each network requires its own key.
Wait up to 10 minutes after upgrading the plan or changing the API key.
Subscription and key updates can take several minutes to propagate across TON Center’s rate-limiting system.
# API authentication (/applications/api/toncenter/v2-authentication)
## Overview [#overview]
The API v2 accepts an API key for all methods, including the JSON-RPC endpoint. Requests without an API key are limited to one request per second. To make more than one request per second, please include an API key.
The key can be sent either in an HTTP header or as a query parameter. Only one of these is needed per request.
To obtain an API key, see the [TON Center API key guide](/applications/api/toncenter/get-api-key).
| Method | Location | Name |
| ------- | -------- | ----------- |
| API key | Header | `X-API-Key` |
| API key | Query | `api_key` |
Never expose the API key in client-side code or public repositories. Store keys in a secrets manager or environment variables, rotate them periodically, and generate a new key immediately if one is compromised.
## Public hosts [#public-hosts]
| Network | Host |
| ------- | -------------------------------------- |
| Testnet | `https://testnet.toncenter.com/api/v2` |
| Mainnet | `https://toncenter.com/api/v2` |
## REST endpoint authentication [#rest-endpoint-authentication]
### Header authentication [#header-authentication]
Send the API key in the `X-API-Key` header:
```bash
curl "https://testnet.toncenter.com/api/v2/getMasterchainInfo" \
-H "X-API-Key: "
```
### Query parameter authentication [#query-parameter-authentication]
Pass the key as a query parameter named `api_key`:
```bash
curl "https://testnet.toncenter.com/api/v2/getMasterchainInfo?api_key="
```
Both forms are equivalent.
## JSON-RPC endpoint authentication [#json-rpc-endpoint-authentication]
**Endpoint:** `POST /api/v2/jsonRPC`
The same API key rules apply. Example using header authentication:
```bash
curl "https://testnet.toncenter.com/api/v2/jsonRPC" \
-H "Content-Type: application/json" \
-H "X-API-Key: " \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMasterchainInfo",
"params": {}
}'
```
Or using the query parameter:
```bash
curl "https://testnet.toncenter.com/api/v2/jsonRPC?api_key=" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMasterchainInfo",
"params": {}
}'
```
## API key error codes [#api-key-error-codes]
| Status | Error | Meaning |
| -----: | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `401` | `API key does not exist` | The provided key is invalid. Check for typos or generate a new key. |
| `403` | `Network not allowed` | The key was issued for a different network (e.g., testnet key on mainnet). Use a key matching the target network. |
| `429` | `Ratelimit exceeded` | Too many requests. Back off and retry, or use an API key for higher limits. |
# API error codes (/applications/api/toncenter/v2-errors)
All TON Center API v2 methods use a standard set of HTTP status codes to indicate the result of a request.
| Status code | Description |
| --------------------------- | ------------------------------------------------------------------------------------------- |
| `404 Not Found` | The requested resource does not exist in storage. |
| `405 Method Not Allowed` | The endpoint was called with an unsupported HTTP method. Use GET or POST. |
| `409 Conflict` | The resource was found but does not match the expected type for this method. |
| `422 Unprocessable Content` | The request parameters failed validation (e.g., missing, malformed, or conflicting values). |
| `429 Too Many Requests` | Too many requests. Back off and retry. |
| `500 Internal Server Error` | An internal error occurred. Retry or contact support if it persists. |
| `504 Gateway Timeout` | The liteserver did not respond in time. Retry the request. |
| `542 Server Error` | A liteserver error or an unsupported TVM stack type was encountered. |
For method-specific error messages and troubleshooting details, refer to the documentation for the relevant endpoint.
# Tonlib type identifiers (/applications/api/toncenter/v2-tonlib-types)
Every object returned by API v2 includes a `@type` field that identifies the object's structure. These values originate from two sources:
1. Tonlib types such as `raw.fullAccountState` and `tvm.cell` come from the [tonlib TL schema](https://github.com/ton-blockchain/ton/blob/a31025f39ed0dae5f6799280133624dc3a23cefb/tl/generate/scheme/tonlib_api.tl), the type definition language used by the C++ library powering this API.
2. Extended types, which are prefixed with `ext.`, are added by TON Center to provide parsed representations with additional decoded fields that are not available in the base tonlib schema.
The `@type` field acts as a **discriminator**: when a response can return different object shapes, the `@type` value indicates which fields to expect. This pattern is useful for type-safe deserialization in statically typed languages.
```json
{
"@type": "raw.fullAccountState",
"balance": "1000000000",
"code": "te6cc...",
"data": "te6cc...",
"last_transaction_id": {
"@type": "internal.transactionId",
"lt": "12345678",
"hash": "abc..."
}
}
```
## TL primitive types [#tl-primitive-types]
The TL schema maps to JSON types as follows:
| TL type | JSON type | Notes |
| :---------- | :-------- | :------------------------------------------------------------- |
| `int32` | number | 32-bit signed integer |
| `int53` | number | 53-bit signed integer; safe for JavaScript `Number` |
| `int64` | string | 64-bit signed integer as decimal string; exceeds JS safe range |
| `int256` | string | 256-bit integer as decimal or hex string |
| `bytes` | string | Binary data, base64-encoded |
| `string` | string | UTF-8 text |
| `Bool` | boolean | `true` or `false` |
| `vector` | array | Ordered list of elements of type `T` |
## Account state [#account-state]
When querying account information, the `account_state` field uses `@type` to indicate which kind of contract is deployed. The TL schema defines these as variants of `AccountState`:
```tl
raw.accountState code:bytes data:bytes frozen_hash:bytes = AccountState;
wallet.v3.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.v4.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.highload.v1.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.highload.v2.accountState wallet_id:int64 = AccountState;
dns.accountState wallet_id:int64 = AccountState;
rwallet.accountState wallet_id:int64 seqno:int32 unlocked_balance:int64 config:rwallet.config = AccountState;
pchan.accountState config:pchan.config state:pchan.State description:string = AccountState;
uninited.accountState frozen_hash:bytes = AccountState;
```
| `@type` value | API schema | TL fields |
| :-------------------------------- | :----------------------------- | :------------------------------------------------- |
| `raw.accountState` | `AccountStateRaw` | `code`, `data`, `frozen_hash` |
| `wallet.v3.accountState` | `AccountStateWalletV3` | `wallet_id`, `seqno` |
| `wallet.v4.accountState` | `AccountStateWalletV4` | `wallet_id`, `seqno` |
| `wallet.highload.v1.accountState` | `AccountStateWalletHighloadV1` | `wallet_id`, `seqno` |
| `wallet.highload.v2.accountState` | `AccountStateWalletHighloadV2` | `wallet_id` |
| `dns.accountState` | `AccountStateDns` | `wallet_id` |
| `rwallet.accountState` | `AccountStateRWallet` | `wallet_id`, `seqno`, `unlocked_balance`, `config` |
| `pchan.accountState` | `AccountStatePChan` | `config`, `state`, `description` |
| `uninited.accountState` | `AccountStateUninited` | `frozen_hash` |
## Account information [#account-information]
Full account queries return one of these top-level types:
```tl
raw.fullAccountState balance:int64 extra_currencies:vector code:bytes data:bytes
last_transaction_id:internal.transactionId block_id:ton.blockIdExt frozen_hash:bytes sync_utime:int53
= raw.FullAccountState;
fullAccountState address:accountAddress balance:int64 extra_currencies:vector
last_transaction_id:internal.transactionId block_id:ton.blockIdExt sync_utime:int53
account_state:AccountState revision:int32
= FullAccountState;
```
| `@type` value | API schema | Description |
| :------------------------------- | :--------------------------- | :------------------------------------------------------------------- |
| `raw.fullAccountState` | `AddressInformation` | Raw state with balance, code, data, and frozen hash. |
| `fullAccountState` | `ExtendedAddressInformation` | Parsed state with identified contract type. |
| `ext.accounts.walletInformation` | `WalletInformation` | Wallet-specific: `type`, `seqno`, `wallet_id`; TON Center extension. |
## Address types [#address-types]
```tl
accountAddress account_address:string = AccountAddress;
```
| `@type` value | API schema | TL fields |
| :--------------- | :--------------- | :---------------- |
| `accountAddress` | `AccountAddress` | `account_address` |
| `addr_std` | `SmcAddr` | `workchain`, `id` |
## Block identifiers [#block-identifiers]
```tl
ton.blockIdExt workchain:int32 shard:int64 seqno:int32 root_hash:bytes file_hash:bytes = ton.BlockIdExt;
```
| `@type` value | API schema | TL fields |
| :--------------- | :-------------- | :------------------------------------------------------ |
| `ton.blockIdExt` | `TonBlockIdExt` | `workchain`, `shard`, `seqno`, `root_hash`, `file_hash` |
## Block data [#block-data]
These types are returned by block query endpoints. The TL definitions:
```tl
blocks.masterchainInfo last:ton.BlockIdExt state_root_hash:bytes init:ton.BlockIdExt = blocks.MasterchainInfo;
blocks.shards shards:vector = blocks.Shards;
blocks.header id:ton.blockIdExt global_id:int32 version:int32 flags:# after_merge:Bool after_split:Bool
before_split:Bool want_merge:Bool want_split:Bool validator_list_hash_short:int32 catchain_seqno:int32
min_ref_mc_seqno:int32 is_key_block:Bool prev_key_block_seqno:int32 start_lt:int64 end_lt:int64
gen_utime:int53 vert_seqno:# prev_blocks:vector = blocks.Header;
blocks.transactions id:ton.blockIdExt req_count:int32 incomplete:Bool
transactions:vector = blocks.Transactions;
blocks.transactionsExt id:ton.blockIdExt req_count:int32 incomplete:Bool
transactions:vector = blocks.TransactionsExt;
blocks.blockSignatures id:ton.blockIdExt signatures:(vector blocks.signature) = blocks.BlockSignatures;
blocks.shardBlockProof from:ton.blockIdExt mc_id:ton.blockIdExt
links:(vector blocks.shardBlockLink) mc_proof:(vector blocks.blockLinkBack) = blocks.ShardBlockProof;
blocks.outMsgQueueSizes shards:(vector blocks.outMsgQueueSize)
ext_msg_queue_size_limit:int32 = blocks.OutMsgQueueSizes;
```
| `@type` value | API schema | Description |
| :-------------------------- | :--------------------------- | :-------------------------------------------- |
| `blocks.masterchainInfo` | `MasterchainInfo` | Latest and genesis block references. |
| `blocks.shards` | `Shards` | Active shard block identifiers. |
| `blocks.header` | `BlockHeader` | Block metadata, merge or split flags, timing. |
| `blocks.transactions` | `BlockTransactions` | Short transaction IDs within a block. |
| `blocks.transactionsExt` | `BlockTransactionsExt` | Full transactions within a block. |
| `blocks.shortTxId` | `ShortTxId` | Compact reference: account, lt, hash. |
| `blocks.blockSignatures` | `MasterchainBlockSignatures` | Validator signatures for a block. |
| `blocks.signature` | `BlockSignature` | Single validator signature. |
| `blocks.shardBlockProof` | `ShardBlockProof` | Merkle proof chain to masterchain. |
| `blocks.shardBlockLink` | `ShardBlockLink` | Single link in a proof chain. |
| `blocks.blockLinkBack` | `BlockLinkBack` | Backward proof link between blocks. |
| `blocks.outMsgQueueSize` | `OutMsgQueueSize` | Per-shard queue size. |
| `blocks.outMsgQueueSizes` | `OutMsgQueueSizes` | Queue sizes across all shards. |
| `ext.blocks.consensusBlock` | `ConsensusBlock` | Latest finalized block; TON Center extension. |
## Transactions and messages [#transactions-and-messages]
```tl
raw.transaction address:accountAddress utime:int53 data:bytes transaction_id:internal.transactionId
fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message
out_msgs:vector = raw.Transaction;
raw.transactions transactions:vector
previous_transaction_id:internal.transactionId = raw.Transactions;
raw.message hash:bytes source:accountAddress destination:accountAddress value:int64
extra_currencies:vector fwd_fee:int64 ihr_fee:int64 created_lt:int64
body_hash:bytes msg_data:msg.Data = raw.Message;
raw.extMessageInfo hash:bytes hash_norm:bytes = raw.ExtMessageInfo;
internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
```
| `@type` value | API schema | Description |
| :----------------------- | :---------------------- | :-------------------------------------------------------- |
| `raw.transaction` | `TransactionStd` | Raw transaction with messages and fees. |
| `raw.transactions` | `TransactionsStd` | Paginated transaction list with cursor. |
| `raw.message` | `MessageStd` | Raw message with sender, recipient, value. |
| `raw.extMessageInfo` | `ExtMessageInfo` | External message hash after broadcast. |
| `internal.transactionId` | `InternalTransactionId` | Transaction reference: lt + hash. |
| `ext.transaction` | `Transaction` | Transaction with decoded comments; TON Center extension. |
| `ext.message` | `Message` | Message with decoded text comments; TON Center extension. |
### Message body types [#message-body-types]
The `msg_data` field on messages uses `@type` to indicate how to interpret the body:
```tl
msg.dataRaw body:bytes init_state:bytes = msg.Data;
msg.dataText text:bytes = msg.Data;
msg.dataDecryptedText text:bytes = msg.Data;
msg.dataEncryptedText text:bytes = msg.Data;
```
| `@type` value | API schema | Description |
| :---------------------- | :--------------------- | :---------------------------------------- |
| `msg.dataRaw` | `MsgDataRaw` | Raw binary body + optional init state. |
| `msg.dataText` | `MsgDataText` | Plain text comment; base64-encoded UTF-8. |
| `msg.dataEncryptedText` | `MsgDataEncryptedText` | Encrypted message body. |
| `msg.dataDecryptedText` | `MsgDataDecryptedText` | Decrypted message body. |
## TVM types [#tvm-types]
Used as input and output for smart contract get methods: `runGetMethod`, `runGetMethodStd`.
### Stack entries [#stack-entries]
Each stack entry wraps a value with a type tag:
```tl
tvm.stackEntryNumber number:tvm.Number = tvm.StackEntry;
tvm.stackEntryCell cell:tvm.cell = tvm.StackEntry;
tvm.stackEntrySlice slice:tvm.slice = tvm.StackEntry;
tvm.stackEntryTuple tuple:tvm.Tuple = tvm.StackEntry;
tvm.stackEntryList list:tvm.List = tvm.StackEntry;
tvm.stackEntryUnsupported = tvm.StackEntry;
```
| `@type` value | API schema | Value field |
| :-------------------------- | :------------------------- | :------------------------------------------------ |
| `tvm.stackEntryNumber` | `TvmStackEntryNumber` | `number` (decimal string via `tvm.numberDecimal`) |
| `tvm.stackEntryCell` | `TvmStackEntryCell` | `cell` (base64 BoC via `tvm.cell`) |
| `tvm.stackEntrySlice` | `TvmStackEntrySlice` | `slice` (base64 BoC via `tvm.slice`) |
| `tvm.stackEntryTuple` | `TvmStackEntryTuple` | `tuple` (nested stack entries) |
| `tvm.stackEntryList` | `TvmStackEntryList` | `list` (nested stack entries) |
| `tvm.stackEntryUnsupported` | `TvmStackEntryUnsupported` | No value (type not representable) |
### Value types [#value-types]
```tl
tvm.cell bytes:bytes = tvm.Cell;
tvm.slice bytes:bytes = tvm.Slice;
tvm.numberDecimal number:string = tvm.Number;
tvm.tuple elements:vector = tvm.Tuple;
tvm.list elements:vector = tvm.List;
```
| `@type` value | API schema | TL fields |
| :------------------ | :----------------- | :------------------------- |
| `tvm.cell` | `TvmCell` | `bytes` (base64 BoC) |
| `tvm.slice` | `TvmSlice` | `bytes` (base64 BoC) |
| `tvm.numberDecimal` | `TvmNumberDecimal` | `number` (decimal string) |
| `tvm.tuple` | `TvmTuple` | `elements` (stack entries) |
| `tvm.list` | `TvmList` | `elements` (stack entries) |
### Get method result [#get-method-result]
```tl
smc.runResult gas_used:int53 stack:vector exit_code:int32 = smc.RunResult;
```
| `@type` value | API schema | TL fields |
| :-------------- | :---------------------- | :------------------------------- |
| `smc.runResult` | `RunGetMethodResult` | `gas_used`, `stack`, `exit_code` |
| `smc.runResult` | `RunGetMethodStdResult` | Same fields, typed stack entries |
## Fees [#fees]
```tl
fees in_fwd_fee:int53 storage_fee:int53 gas_fee:int53 fwd_fee:int53 = Fees;
query.fees source_fees:fees destination_fees:vector = query.Fees;
```
| `@type` value | API schema | TL fields |
| :------------ | :---------- | :------------------------------------------------ |
| `fees` | `Fees` | `in_fwd_fee`, `storage_fee`, `gas_fee`, `fwd_fee` |
| `query.fees` | `QueryFees` | `source_fees`, `destination_fees` |
## Configuration [#configuration]
```tl
configInfo config:tvm.cell = ConfigInfo;
```
| `@type` value | API schema | TL fields |
| :------------ | :----------- | :-------------------------------- |
| `configInfo` | `ConfigInfo` | `config` TVM cell with parameters |
## Libraries [#libraries]
```tl
smc.libraryEntry hash:int256 data:bytes = smc.LibraryEntry;
smc.libraryResult result:(vector smc.libraryEntry) = smc.LibraryResult;
```
| `@type` value | API schema | TL fields |
| :------------------ | :-------------- | :----------------- |
| `smc.libraryEntry` | `LibraryEntry` | `hash`, `data` |
| `smc.libraryResult` | `LibraryResult` | `result` (entries) |
## Token types (TON Center extensions) [#token-types-ton-center-extensions]
These types are not in the base tonlib TL schema. They are added by TON Center to provide parsed Jetton and NFT data via the `getTokenData` endpoint.
| `@type` value | API schema | Description |
| :----------------------------- | :------------------ | :----------------------------------------------- |
| `ext.tokens.jettonMasterData` | `JettonMasterData` | Jetton master: total supply, admin, metadata. |
| `ext.tokens.jettonWalletData` | `JettonWalletData` | Jetton wallet: balance, owner, master reference. |
| `ext.tokens.nftCollectionData` | `NftCollectionData` | NFT collection: item count, owner, metadata. |
| `ext.tokens.nftItemData` | `NftItemData` | NFT item: index, owner, collection reference. |
## DNS record types [#dns-record-types]
DNS entries use `@type` to indicate the record type stored at a domain:
```tl
dns.entryDataNextResolver resolver:AccountAddress = dns.EntryData;
dns.entryDataSmcAddress smc_address:AccountAddress = dns.EntryData;
dns.entryDataAdnlAddress adnl_address:AdnlAddress = dns.EntryData;
dns.entryDataStorageAddress bag_id:int256 = dns.EntryData;
```
| `@type` value | API schema | TL fields |
| :----------------------------- | :------------------------ | :---------------------- |
| `dns.entryDataNextResolver` | `DnsRecordNextResolver` | `resolver` (address) |
| `dns.entryDataSmcAddress` | `DnsRecordSmcAddress` | `smc_address` (address) |
| `dns.entryDataAdnlAddress ` | `DnsRecordAdnlAddress` | `adnl_address` |
| `dns.entryDataStorageAddress ` | `DnsRecordStorageAddress` | `bag_id` (int256) |
## Payment channel types [#payment-channel-types]
```tl
pchan.config alice_public_key:string alice_address:accountAddress bob_public_key:string
bob_address:accountAddress init_timeout:int32 close_timeout:int32 channel_id:int64 = pchan.Config;
pchan.stateInit signed_A:Bool signed_B:Bool min_A:int64 min_B:int64
expire_at:int53 A:int64 B:int64 = pchan.State;
pchan.stateClose signed_A:Bool signed_B:Bool min_A:int64 min_B:int64
expire_at:int53 A:int64 B:int64 = pchan.State;
pchan.statePayout A:int64 B:int64 = pchan.State;
```
| `@type` value | API schema | Description |
| :------------------ | :----------------- | :----------------------------- |
| `pchan.config` | `PChanConfig` | Channel parties, timeouts, ID |
| `pchan.stateInit` | `PChanStateInit` | Initialization phase (signing) |
| `pchan.stateClose` | `PChanStateClose` | Closing phase (signing) |
| `pchan.statePayout` | `PChanStatePayout` | Payout phase (final balances) |
## Restricted wallet types [#restricted-wallet-types]
```tl
rwallet.limit seconds:int32 value:int64 = rwallet.Limit;
rwallet.config start_at:int53 limits:vector = rwallet.Config;
```
| `@type` value | API schema | TL fields |
| :--------------- | :-------------- | :------------------- |
| `rwallet.config` | `RWalletConfig` | `start_at`, `limits` |
| `rwallet.limit` | `RWalletLimit` | `seconds`, `value` |
## Utility types [#utility-types]
TON Center extensions.
| `@type` value | API schema | Description |
| :--------------------------------- | :--------------------------- | :------------------------------ |
| `ext.utils.detectedAddress` | `DetectAddress` | Address in all encoding formats |
| `ext.utils.detectedAddressVariant` | `DetectAddressBase64Variant` | Base64 and URL-safe base64 pair |
| `ext.utils.detectedHash` | `DetectHash` | Hash in hex, base64, URL-safe |
| `extraCurrency` | `ExtraCurrencyBalance` | Non-TON currency ID and balance |
| `ok` | `ResultOk` | Success with no return data |
## Reference [#reference]
For background on the TL-B format used across the TON ecosystem, see the [TL-B overview](/blockchain-basics/languages/tl-b/overview).
Types prefixed with `ext.` are TON Center extensions not present in the upstream TL schema.
# API authentication (/applications/api/toncenter/v3-authentication)
## Overview [#overview]
The API v3 accepts an API key for all methods. Requests without an API key are limited to one request per second. To make more than one request per second, please include an API key.
The key can be sent either in an HTTP header or as a query parameter. Only one of these is needed per request.
To obtain an API key, see the [TON Center API key guide](/applications/api/toncenter/get-api-key).
| Method | Location | Name |
| ------- | -------- | ----------- |
| API key | Header | `X-API-Key` |
| API key | Query | `api_key` |
Never expose the API key in client-side code or public repositories. Store keys in a secrets manager or environment variables, rotate them periodically, and generate a new key immediately if one is compromised.
## Public hosts [#public-hosts]
| Network | Host |
| ------- | -------------------------------------- |
| Testnet | `https://testnet.toncenter.com/api/v3` |
| Mainnet | `https://toncenter.com/api/v3` |
## REST endpoint authentication [#rest-endpoint-authentication]
### Header authentication [#header-authentication]
Send the API key in the `X-API-Key` header:
```bash
curl "https://testnet.toncenter.com/api/v3/masterchainInfo" \
-H "X-API-Key: "
```
### Query parameter authentication [#query-parameter-authentication]
Pass the key as a query parameter named `api_key`:
```bash
curl "https://testnet.toncenter.com/api/v3/masterchainInfo?api_key="
```
Both forms are equivalent.
## API key error codes [#api-key-error-codes]
| Status | Error | Meaning |
| -----: | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `401` | `API key does not exist` | The provided key is invalid. Check for typos or generate a new key. |
| `403` | `Network not allowed` | The key was issued for a different network (e.g., testnet key on mainnet). Use a key matching the target network. |
| `429` | `Ratelimit exceeded` | Too many requests. Back off and retry, or use an API key for higher limits. |
# API error codes (/applications/api/toncenter/v3-errors)
All TON Center API v3 methods use a standard set of HTTP status codes to indicate the result of a request.
| Status code | Description |
| --------------------------- | ---------------------------------------------------------------------------------- |
| `401 Unauthorized` | A required parameter was not included in the request. |
| `404 Not Found` | The requested resource does not exist in storage. |
| `409 Conflict` | The resource was found but does not match the expected type for this method. |
| `422 Unprocessable Content` | The request parameters failed validation (e.g., conflicting or malformed filters). |
| `500 Internal Server Error` | An internal error occurred. Retry or contact support if it persists. |
For method-specific error messages and troubleshooting details, refer to the documentation for the relevant endpoint.
# Pagination (/applications/api/toncenter/v3-pagination)
The v3 API uses offset-based pagination. Each paginated endpoint accepts `limit` and `offset` parameters. `limit` controls how many results to return per request, and `offset` skips a number of rows from the beginning of the result set. To retrieve the next page, increment `offset` by the value of `limit`.
The following endpoints support pagination:
| Endpoint | Default limit | Max limit | Sortable |
| ------------------------------------------------------------------------------------------------------------------------ | :-----------: | :-------: | :------: |
| [`transactions`](/applications/api/toncenter/v3/blockchain-data/get-transactions) | 10 | 1000 | Yes |
| [`actions`](/applications/api/toncenter/v3/actions-and-traces/get-actions) | 10 | 1000 | Yes |
| [`blocks`](/applications/api/toncenter/v3/blockchain-data/get-blocks) | 10 | 1000 | Yes |
| [`messages`](/applications/api/toncenter/v3/blockchain-data/get-messages) | 10 | 1000 | Yes |
| [`traces`](/applications/api/toncenter/v3/actions-and-traces/get-traces) | 10 | 1000 | Yes |
| [`jetton/burns`](/applications/api/toncenter/v3/jettons/get-jetton-burns) | 10 | 1000 | Yes |
| [`jetton/transfers`](/applications/api/toncenter/v3/jettons/get-jetton-transfers) | 10 | 1000 | Yes |
| [`jetton/wallets`](/applications/api/toncenter/v3/jettons/get-jetton-wallets) | 10 | 1000 | Yes |
| [`nft/items`](/applications/api/toncenter/v3/nfts/get-nft-items) | 10 | 1000 | Yes |
| [`nft/transfers`](/applications/api/toncenter/v3/nfts/get-nft-transfers) | 10 | 1000 | Yes |
| [`multisig/orders`](/applications/api/toncenter/v3/multisig/get-multisig-orders) | 10 | 1000 | Yes |
| [`multisig/wallets`](/applications/api/toncenter/v3/multisig/get-multisig-wallets) | 10 | 1000 | Yes |
| [`transactionsByMasterchainBlock`](/applications/api/toncenter/v3/blockchain-data/get-transactions-by-masterchain-block) | 10 | 1000 | Yes |
| [`jetton/masters`](/applications/api/toncenter/v3/jettons/get-jetton-masters) | 10 | 1000 | No |
| [`nft/collections`](/applications/api/toncenter/v3/nfts/get-nft-collections) | 10 | 1000 | No |
| [`dns/records`](/applications/api/toncenter/v3/dns/get-dns-records) | 100 | 1000 | No |
| [`masterchainBlockShards`](/applications/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state-1) | 10 | 1000 | No |
| [`topAccountsByBalance`](/applications/api/toncenter/v3/stats/get-top-accounts-by-balance) | 10 | 1024 | No |
| [`transactionsByMessage`](/applications/api/toncenter/v3/blockchain-data/get-transactions-by-message) | 10 | 1000 | No |
| [`vesting`](/applications/api/toncenter/v3/vesting/get-vesting-contracts) | 10 | 1000 | No |
All other v3 endpoints return single objects or fixed results and do not support pagination.
## Parameters [#parameters]
These parameters are shared across all paginated endpoints.
| Parameter | Type | Description |
| --------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `limit` | integer | Maximum number of rows to return. Defaults vary by endpoint; see table above. |
| `offset` | integer | Number of rows to skip from the beginning of the result set. Default is `0`. |
| `sort` | string | Sort order: `desc` (default, newest first) or `asc` (oldest first). Available only on sortable endpoints. |
## Pagination example [#pagination-example]
This example uses the `transactions` endpoint, but the same `limit` and `offset` pattern applies to all paginated endpoints.
Send a request with `account` and `limit`. `offset` defaults to `0` for the first page.
```bash
curl "https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3"
```
Response (abbreviated):
```json
{
"transactions": [
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "KkpVTX9RwiZcug8KQuOFUF8+eNoxuHVuIFpGQqufCWU=",
"lt": "67064337000004",
"now": 1771410670
},
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "b5fhFby+j8gg936W+XEsAEhboQW0zPcOHOHgyqXkTwI=",
"lt": "67011337000003",
"now": 1771286044
},
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "lT/wWTiJIdEF8A2Rox9CRdQRzlUgnIDGeUfEHQ8jGZQ=",
"lt": "66986300000006",
"now": 1771226782
}
],
"address_book": { ... }
}
```
Three transactions returned, sorted by logical time in descending order (newest first).
Set `offset=3` to skip the first 3 results and get the next batch.
```bash
curl "https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3&offset=3"
```
Response (abbreviated):
```json
{
"transactions": [
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "07QaeBRRA62+RJPgetgSraYLH5i9G5QhC2dUvKAsAiI=",
"lt": "66927779000007",
"now": 1771088713
},
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "8d7sSor1NqbGNdX1JEGl1d4rX3lb7CeC3DZjhe7V7z4=",
"lt": "66927779000003",
"now": 1771088713
},
{
"account": "0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7",
"hash": "szM1I5/MU1uJGgeScS7uxNF6V/FsLkokCpul88ZEau8=",
"lt": "66926353000007",
"now": 1771085323
}
],
"address_book": { ... }
}
```
No overlap with the previous page. Offset pagination does not produce duplicates.
Continue incrementing `offset` by the `limit` value on each request (`offset=6`, `offset=9`, ...). When the response returns fewer transactions than the `limit`, all results have been retrieved.
```javascript
const address = "EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2";
async function main() {
let allTransactions = [];
let offset = 0;
const limit = 3;
let page = 0;
while (true) {
page++;
const params = new URLSearchParams({
account: address,
limit: String(limit),
offset: String(offset),
});
const res = await fetch(
`https://toncenter.com/api/v3/transactions?${params}`
);
const data = await res.json();
const transactions = data.transactions || [];
console.log(`\n--- Page ${page} (offset=${offset}) ---`);
for (const tx of transactions) {
console.log(` lt: ${tx.lt} hash: ${tx.hash}`);
}
allTransactions.push(...transactions);
if (transactions.length < limit) break;
offset += limit;
}
console.log(`\nTotal transactions: ${allTransactions.length}`);
}
main();
```
Output:
```bash
--- Page 1 (offset=0) ---
lt: 67064337000004 hash: KkpVTX9RwiZcug8KQuOFUF8+eNoxuHVuIFpGQqufCWU=
lt: 67011337000003 hash: b5fhFby+j8gg936W+XEsAEhboQW0zPcOHOHgyqXkTwI=
lt: 66986300000006 hash: lT/wWTiJIdEF8A2Rox9CRdQRzlUgnIDGeUfEHQ8jGZQ=
--- Page 2 (offset=3) ---
lt: 66927779000007 hash: 07QaeBRRA62+RJPgetgSraYLH5i9G5QhC2dUvKAsAiI=
lt: 66927779000003 hash: 8d7sSor1NqbGNdX1JEGl1d4rX3lb7CeC3DZjhe7V7z4=
lt: 66926353000007 hash: szM1I5/MU1uJGgeScS7uxNF6V/FsLkokCpul88ZEau8=
--- Page 3 (offset=6) ---
Total transactions: 6
```
## Sorting options [#sorting-options]
Sortable endpoints accept a `sort` parameter with two values:
* `desc` (default): newest results first, sorted by logical time (or UTC timestamp for `blocks`).
* `asc`: oldest results first.
```bash
curl "https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3&sort=asc"
```
Response (abbreviated):
```json
{
"transactions": [
{
"hash": "3ziyP0yvGklMTNWWXDplmlBcPH0P7MJtusoVthNu8e0=",
"lt": "39547833000003",
"now": 1690204554
},
{
"hash": "lYXDtLL53JkKa35vP05gbwTyd6Lq4335TwlZeUebxZ8=",
"lt": "39547876000003",
"now": 1690204686
},
{
"hash": "DSz0P/wmE0EkdfaxFl2R36Eie+Lw4paLa1sAHHUliJA=",
"lt": "39548648000003",
"now": 1690207175
}
],
"address_book": { ... }
}
```
With `sort=asc`, the earliest transactions are returned first, starting from 2023-07 for this account.
The `jetton/wallets` endpoint sorts results by balance instead of logical time. When balances change between requests, using `limit` and `offset` can skip or repeat wallets because the sort order changes between pages.
# Use basic getter hooks (/applications/appkit/get-started/basic-getter-hooks)
Read the connected wallet's state from React using AppKit's getter hooks. They re-render when the underlying state changes and do not themselves start wallet actions — transactions and signatures use mutation hooks such as `useTransferTon`, `useSignText`, and `useSendTransaction`.
## Before you begin [#before-you-begin]
You need the React providers in place. See [Installation → Wrap the application](/applications/appkit/get-started/installation/react-app#wrap-the-application).
## Three return shapes [#three-return-shapes]
Getter hooks come in three return shapes. Which shape a hook uses depends on where the data lives.
**Tuple with setter** — for state AppKit stores reactively and that the app can change. The first element is the value (or `null` if not yet set), the second is the setter.
```tsx
const [wallet, setWalletId] = useSelectedWallet();
const [network, setDefaultNetwork] = useDefaultNetwork();
```
The hooks that return tuples: `useSelectedWallet`, `useDefaultNetwork`.
**Direct value** — for store-derived state that is read-only from React. Returns the value itself, no wrapper.
```tsx
const address = useAddress(); // string | undefined
const network = useNetwork(); // Network | undefined
const networks = useNetworks(); // Network[]
const connectors = useConnectors(); // Connector[]
const wallets = useConnectedWallets(); // WalletInterface[]
const connector = useConnectorById('tonconnect'); // Connector | undefined
const appKit = useAppKit(); // AppKit
```
These hooks use `useSyncExternalStore` under the hood and re-render when the underlying state changes.
**TanStack Query result** — for chain data fetched through an API client. Returns `{ data, isLoading, isError, error, refetch }` and accepts a `query` field for `refetchInterval`, `enabled`, `staleTime`, and the rest of the TanStack Query options.
```tsx
const { data: balance, isLoading } = useBalance();
const { data: jettons } = useJettons({ query: { refetchInterval: 20000 } });
```
The hooks that return query results: `useBalance`, `useJettons`, `useNfts`, `useTransactionStatus`, `useJettonInfo`, `useJettonBalanceByAddress`, `useJettonWalletAddress`, `useBlockNumber`, `useNft`, and the `*ByAddress` variants.
## Provider data is not chain finality [#provider-data-is-not-chain-finality]
A getter hook reflects a snapshot of provider data, not the chain itself. The user's wallet may report state that differs from what the configured `apiClient` returns — usually because the indexer is a few blocks behind the wallet, sometimes because the two read different networks. For live updates without manual refetch, mount the matching `useWatch*` hook (covered on [Stream live updates](/applications/appkit/get-started/streaming)).
## Tips [#tips]
Treat hook data as the latest read, not as a settlement check. Verify chain effects with `getTransactionStatus` or a backend before crediting value, and re-check after any reconnect.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) that uses `useBalance`, `useJettons`, and `useNfts` to render wallet state — [try it live](https://appkit-minter.vercel.app/).
## What to do next [#what-to-do-next]
* Move on to [Send transactions](/applications/appkit/get-started/sending-transactions) — at that point you'll have a working app.
* For a full walkthrough of reading TON, jetton, and NFT data, see [Read balances](/applications/appkit/howto/read-balances).
* Look up the full hook surface in the [`@ton/appkit-react` reference](/applications/appkit/reference/appkit-react).
# Add wallet connectors (/applications/appkit/get-started/connectors)
Wire up a connector so AppKit can talk to a wallet. A connector is the transport that carries requests to the wallet and responses back — it does not sign, and is not itself a wallet. Signing always happens inside the user's wallet application. AppKit cares about the connector's `id`, `type`, `metadata`, and the methods it exposes (`connectWallet`, `disconnectWallet`, `getConnectedWallets`, `destroy`). The protocol underneath is hidden.
## Before you begin [#before-you-begin]
Install AppKit first. See [Prepare your project](/applications/appkit/get-started/installation/installation).
## Create the AppKit instance [#create-the-appkit-instance]
The `AppKit` constructor takes a `connectors` array of connector factories such as `createTonConnectConnector`. A single `AppKit` instance can hold more than one connector, and the user picks at connect time. The example below registers a single TON Connect connector — enough to start wiring up the connect button.
```ts
// appkit.ts
import { AppKit, createTonConnectConnector } from '@ton/appkit';
export const appKit = new AppKit({
connectors: [
createTonConnectConnector({
tonConnectOptions: {
manifestUrl: 'https://example.com/tonconnect-manifest.json',
},
}),
],
});
```
## Render a connect button [#render-a-connect-button]
Drop ` ` somewhere in the tree to open the wallet picker. The button assumes the React providers are already mounted — see [Installation → Wrap the application](/applications/appkit/get-started/installation/react-app#wrap-the-application).
For most apps, this drop-in component is the right starting point. ` ` from `@ton/appkit-react` owns the connect modal, the session lifecycle (open, restore on reload, expire), and the connected-address display. When the UI needs a tailored wallet list, use `useConnectors` and `useConnect` directly. That pattern is documented in [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet).
```tsx
import { TonConnectButton } from '@ton/appkit-react';
export function Header() {
return ;
}
```
## Tips [#tips]
Do not assume every connector supports every flow. Check capability before sending a request and treat user rejection as a normal outcome on every action. Connector errors and chain errors are different failure classes and need different recovery paths.
## What to do next [#what-to-do-next]
* Continue to [Add networks](/applications/appkit/get-started/networks) to configure mainnet alongside testnet and pick an API client.
* For the custom-selector pattern, vanilla JS connect, and error handling, see [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet).
# Get started with AppKit (/applications/appkit/get-started/get-started)
Follow this section end-to-end to take a fresh project from zero to a working AppKit app. Each page is one concrete action.
The first four pages get the baseline running — install the packages, register a connector, read wallet and chain state, and send a transaction. From that point the app is functional. The remaining pages are improvements that layer on live updates, DeFi flows, and ready-made UI.
## Step by step [#step-by-step]
| Step | What you do |
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| [Prepare your project](/applications/appkit/get-started/installation/installation) | Scaffold a project if you have none, install AppKit, and add the Buffer polyfill. |
| [Add wallet connectors](/applications/appkit/get-started/connectors) | Create the AppKit instance and drop in ` `. |
| [Add networks](/applications/appkit/get-started/networks) | Configure mainnet alongside testnet and pick an API client. |
| [Use basic getter hooks](/applications/appkit/get-started/basic-getter-hooks) | Read wallet, address, balance, jetton, NFT, network, and transaction state. |
| [Send transactions](/applications/appkit/get-started/sending-transactions) | Send Toncoin, jettons, NFTs, or prepared transactions. |
| [Stream live updates](/applications/appkit/get-started/streaming) | Subscribe to balance, jetton, and transaction changes in real time. |
| [Add DeFi providers](/applications/appkit/get-started/providers) | Plug in swap and staking providers when the app needs DeFi flows. |
| [Use UI widgets](/applications/appkit/get-started/using-ui-widgets) | Drop in ` `, ` `, and other prebuilt flows. |
## What to do next [#what-to-do-next]
* See task-level walkthroughs in [How to](/applications/appkit/howto/howto).
* Look up the full surface in [AppKit reference](/applications/appkit/reference/reference).
# Add networks (/applications/appkit/get-started/networks)
Declare every chain the app can read. A network in AppKit is the chain context AppKit uses to read data and to compare wallet state against the app's expected chain — each network is identified by a `Network` value with a `chainId` and carries an `apiClient` that reads chain state for that chain.
A single `AppKit` instance can hold more than one network. The user picks at connect time, and a flow can move between networks without rebuilding the instance.
## Before you begin [#before-you-begin]
Install AppKit first. See [Prepare your project](/applications/appkit/get-started/installation/installation).
## Basic configuration [#basic-configuration]
By default, AppKit constructs a mainnet-only `ApiClientToncenter` with no API key when `networks` is omitted. That is enough to start exploring AppKit, but production traffic will hit TON Center's public rate limits — apps that ship to users should supply their own key.
Pass an `apiClient` entry on the network with a `key` to lift the limits. AppKit has preset URLs for mainnet (`https://toncenter.com`) and testnet (`https://testnet.toncenter.com`), so `url` can be omitted for those. For other networks, specify `url` explicitly.
```ts
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: {
key: 'your-key',
},
},
},
});
```
## Use TonAPI instead [#use-tonapi-instead]
Besides TON Center, AppKit ships `ApiClientTonApi` for TonAPI and compatible deployments. The inline `{ url, key }` shape is TON Center-only. To use TonAPI, pass a constructed instance into `apiClient`.
```ts
import { AppKit, ApiClientTonApi, Network } from '@ton/appkit';
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: new ApiClientTonApi({
network: Network.mainnet(),
apiKey: 'your-key',
}),
},
},
});
```
## What to do next [#what-to-do-next]
* Continue to [Use basic getter hooks](/applications/appkit/get-started/basic-getter-hooks) to read the connected wallet's state from the configured networks.
* For multiple networks, custom chains, the default network, and mismatch handling, see [Networks](/applications/appkit/howto/networks).
# Add DeFi providers (/applications/appkit/get-started/providers)
Plug in a swap or staking provider when the app needs DeFi flows. Each provider sits on the AppKit instance and supplies data: prices, quotes, and the transactions that the user will sign. The wallet still signs; the provider only prepares.
A provider is not a wallet and not a connector. AppKit treats whatever it returns as external input — useful for showing prices, balances, and quotes, but never as proof of settlement.
## Before you begin [#before-you-begin]
You need AppKit packages installed and an `AppKit` instance created. See [Prepare your project](/applications/appkit/get-started/installation/installation) and [Add wallet connectors](/applications/appkit/get-started/connectors).
## Add a swap provider [#add-a-swap-provider]
Swap providers ship as separate entrypoints under `@ton/appkit/swap/*` so the bundler only includes the protocols you actually use. Construct an instance and pass it in the `providers` array on the `AppKit` constructor; AppKit registers it with the swap manager and the swap hooks (`useSwapQuote`, `useBuildSwapTransaction`) start returning quotes from that protocol.
```ts
// appkit.ts
import { AppKit } from '@ton/appkit';
import { DeDustSwapProvider } from '@ton/appkit/swap/dedust';
export const appKit = new AppKit({
// networks, connectors...
providers: [
new DeDustSwapProvider(),
],
});
```
Omniston requires its own SDK package — install it before registering the provider:
```bash
npm i @ston-fi/omniston-sdk
```
## Add a staking provider [#add-a-staking-provider]
Use `createTonstakersProvider({})` from `@ton/appkit/staking/tonstakers` the same way:
```ts
import { AppKit } from '@ton/appkit';
import { createTonstakersProvider } from '@ton/appkit/staking/tonstakers';
export const appKit = new AppKit({
// networks, connectors...
providers: [
createTonstakersProvider({}),
],
});
```
The staking hooks (`useStakingQuote`, `useBuildStakeTransaction`) start returning data from the registered provider.
## Tips [#tips]
Provider responses are external data. Validate critical outcomes server side before changing product state — wallet acceptance is not settlement, and a swap quote is not a price guarantee.
## What to do next [#what-to-do-next]
* Continue to [Use UI widgets](/applications/appkit/get-started/using-ui-widgets) to render full swap and staking UIs with one component each.
* For task-level walkthroughs, see [Swaps](/applications/appkit/howto/swaps) and [Staking](/applications/appkit/howto/staking).
* See [Providers](/applications/appkit/howto/providers) for the full provider model — including the streaming and API client roles not covered here.
# Send transactions (/applications/appkit/get-started/sending-transactions)
Assemble a `TransactionRequest`, ask the connected wallet to sign and broadcast it, and wait for the chain to settle the result. AppKit ships three layers over this flow: UI components that wrap the full mutation lifecycle, mutation hooks that expose the same lifecycle without UI, and core actions that just make the wallet call.
Reaching this page means you have a working app: install, connect, read, send. The pages after this one — streaming, DeFi providers, and UI widgets — layer on improvements rather than baseline functionality.
The lifecycle has clear ownership boundaries. *Your code* assembles the request — recipient, amount, payload, validity window. *The wallet* reviews the request, presents it to the user, and signs it. *The chain* receives the signed message, orders it, and either includes or rejects it. *The streaming provider* observes the result and reports back. `onSuccess` firing on a component or hook means the wallet accepted the request, not that the chain accepted the transaction; settlement is observed separately on [Streaming](/applications/appkit/get-started/streaming).
## Send Toncoin in one component [#send-toncoin-in-one-component]
` ` owns the whole lifecycle for a Toncoin transfer. It builds the request from `recipientAddress`, `amount` (decimal TON), and an optional `comment`; calls the wallet; and surfaces pending, error, and success state through a render-prop child. When you need to send something other than a plain Toncoin transfer — an NFT, a multi-message bundle, a swap-built transaction — use ` ` with a `request` callback that returns a `TransactionRequest` you assembled yourself.
```tsx
import { SendTonButton } from '@ton/appkit-react';
{({ isLoading, onSubmit, disabled, text }) => (
{isLoading ? 'Sending…' : text}
)}
```
The component exposes `{ isLoading, onSubmit, disabled, text }` to the render-prop child.
## Pick the right call [#pick-the-right-call]
The three layers trade off control against work done for you. Components own the full lifecycle and ship a default render-prop UI hook, so you write the least code; mutation hooks give you the lifecycle without UI, so you build the button yourself; core actions give you neither — just a function that drives the wallet — and are the right pick from vanilla code or when you need to compose multiple transactions in one user action. Pick by how much of the lifecycle you want AppKit to own.
| Goal | Component | Hook | Core action |
| ----------------------------------- | ---------------------- | -------------------- | ----------------- |
| Send Toncoin | ` ` | `useTransferTon` | `transferTon` |
| Send a jetton | ` ` | `useTransferJetton` | `transferJetton` |
| Send an NFT | ` ` + builder | `useTransferNft` | `transferNft` |
| Send a prepared transaction request | ` ` | `useSendTransaction` | `sendTransaction` |
## Tips [#tips]
Wallet acceptance is not settlement. Always pair a send with [Stream live updates](/applications/appkit/get-started/streaming) or `getTransactionStatus`, and verify the final outcome on a backend before delivering paid goods.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) of TON, jetton, and NFT transfers built with these mutations — [try it live](https://appkit-minter.vercel.app/).
## What to do next [#what-to-do-next]
You now have the baseline working app. From here, layer on improvements:
* [Stream live updates](/applications/appkit/get-started/streaming) to react to chain changes without polling.
* [Add DeFi providers](/applications/appkit/get-started/providers) when the app needs swaps or staking.
* [Use UI widgets](/applications/appkit/get-started/using-ui-widgets) to drop in ready-made flows.
For task-level walkthroughs, see [Send Toncoin](/applications/appkit/howto/send-toncoin), [Send jettons](/applications/appkit/howto/send-jettons), and [NFTs](/applications/appkit/howto/nfts).
# Stream live updates (/applications/appkit/get-started/streaming)
Subscribe to balance, jetton, and transaction updates pushed by a streaming provider so the UI reflects chain changes without polling. Use it whenever you would otherwise refetch on a timer.
Treat the stream as a fast cache, not as proof of settlement. The underlying transport is a long-lived connection; it can disconnect and reconnect while the chain advances, and after reconnect updates resume from the provider's current view, which may skip in-flight transitions.
## Before you begin [#before-you-begin]
A streaming provider has to be registered on the AppKit instance before any watcher will fire. The default `ApiClient` does not stream — you register a streaming provider separately on `appKit.streamingManager`. See [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered) for the registration pattern, and use `hasStreamingProvider(appKit, network)` from `@ton/appkit` as the runtime check before subscribing.
## Mount global watchers [#mount-global-watchers]
Mount the `useWatch*` hooks once at a high level — the router, the app shell, or a layout component — so the underlying cache stays current for every consumer below. Calling a hook with no arguments simply keeps the cache warm. Pass an `onChange` callback for one-shot side effects (toast, log, navigate). A [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) calls `useWatchBalance()`, `useWatchJettons()`, and `useWatchTransactions({ onChange })` from its router for exactly this reason. [Try it live](https://appkit-minter.vercel.app/).
Call the `useWatch*` hooks once high in the tree. They keep the cache fresh; pass `onChange` when you want to react to each update.
```tsx
import { useWatchBalance, useWatchTransactions } from '@ton/appkit-react';
export function GlobalWatchers() {
useWatchBalance();
useWatchTransactions({
onChange: (update) => {
if (update.status === 'finalized') {
console.log('settled', update.traceHash);
}
},
});
return null;
}
```
`update.status` is `'pending' | 'confirmed' | 'finalized' | 'invalidated'`. Treat anything before `'finalized'` as not yet settled.
Each status names a different stage and carries a different meaning. `pending` means the streaming provider has seen the request but not its inclusion in a block. `confirmed` means a block contains the transaction but it is not irreversible. `finalized` means the chain considers the transaction permanent. `invalidated` means the provider has rolled the transaction back or rejected it; treat it the same as a failed send. UI hints are appropriate at every stage; product-state changes (delivering value, settling an order) are appropriate only at `finalized`.
## Tips [#tips]
A stream is a hint, not proof. Verify the final state on a backend before delivering value or settling an order, and re-check after every reconnect — the stream may have missed transitions while disconnected.
## What to do next [#what-to-do-next]
* Continue to [Add DeFi providers](/applications/appkit/get-started/providers) when the app needs swap or staking flows.
* For task-level patterns that combine sends with settlement tracking, see [Streaming](/applications/appkit/howto/streaming) in How to.
# Use UI widgets (/applications/appkit/get-started/using-ui-widgets)
Drop in ready-made React components when an AppKit flow needs to ship fast. This page shows the three component shapes and when to pick each one.
## Before you begin [#before-you-begin]
Install the React packages, mount `AppKitProvider`, and import the default stylesheet. See [Install AppKit in a React app](/applications/appkit/get-started/installation/react-app).
## Pick a widget level [#pick-a-widget-level]
AppKit UI widgets come in three levels:
| Level | Use when |
| ---------------------- | ------------------------------------------------------------------------------------ |
| Default component | The app needs a ready-made flow with the package stylesheet. |
| Render-prop component | The app needs AppKit to own the state machine, but the layout must be custom. |
| Hooks and core actions | The flow no longer matches one widget, or state must be shared across a larger page. |
Default components such as ` ` and ` ` cover the full user flow. Render-prop components keep the same behavior while letting the app render custom markup. Hooks and core actions are the lowest level and fit flows that need fully custom product logic.
## Start with a ready-made component [#start-with-a-ready-made-component]
` ` is the smallest example. It opens the TON Connect modal, restores the session, and renders the selected wallet address.
```tsx
import { TonConnectButton } from '@ton/appkit-react';
export function Header() {
return ;
}
```
## Move to a custom send flow [#move-to-a-custom-send-flow]
` ` keeps the AppKit transaction flow while exposing render props for custom UI.
```tsx
import { SendTonButton } from '@ton/appkit-react';
{({ isLoading, onSubmit, disabled, text }) => (
{isLoading ? 'Sending…' : text}
)}
;
```
## Tips [#tips]
Pick the widget level by control needs. Use a ready-made component for the smallest integration, render props for custom layout, and hooks or core actions when the flow needs more control than one widget can provide.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) that integrates ` ` and ` ` — [try it live](https://appkit-minter.vercel.app/).
## What to do next [#what-to-do-next]
* For a component-by-component walkthrough (Send, NFT, Swap, Staking, transaction progress), see [Use UI widgets](/applications/appkit/howto/use-ui-widgets).
* For task-level recipes, switch to [How to](/applications/appkit/howto/howto).
# AppKit (/applications/appkit/howto/appkit)
TON Connect's **AppKit** is an open-source SDK that integrates web2 and web3 applications with TON. It enables wallet connection, authorization, balance tracking, asset transfers, and data signing.
The framework-independent core lives in `@ton/appkit`. React bindings live in `@ton/appkit-react` and wrap the same actions with hooks.
AppKit prepares requests, tracks application state, and connects your interface to wallets and providers. Wallets still sign transactions and data. Your backend still verifies orders, signatures, and business rules.
## Features [#features]
* **TON Connect**: integrates with the standard wallet infrastructure for TON.
* **Wallet management**: access connected wallets from registered connectors.
* **Asset support**: work with Toncoin, jettons (USDT and others), and NFTs.
* **React**: hooks and ready-made UI components for common flows.
* **DeFi**: swaps, staking, on-ramp, and gasless transfers through registered providers.
## What it owns [#what-it-owns]
A single `AppKit` instance holds configured **networks** (mainnet, testnet, and the API client used to read each), registered **connectors** that route signing requests to wallets, **connected wallets** with one wallet marked as selected, and **managers** for swap, staking, and streaming flows. Anything that reads or changes wallet state should go through this instance.
## Configuration notes [#configuration-notes]
Create the `AppKit` instance once with an `AppKitConfig`. All fields are optional; pass only the configuration your app needs. See [Get started → Add wallet connectors](/applications/appkit/get-started/connectors) for the constructor walkthrough.
If `networks` is omitted entirely, AppKit constructs a **mainnet-only** `ApiClientToncenter` with no API key. Fine for quick prototyping; expect rate limits on real workloads. Testnet apps must declare `networks` explicitly.
## Lifecycle [#lifecycle]
```text
new AppKit(config) → connect → connector:connected → wallets:updated → (auto-select) wallets:selection-changed
```
## Action shapes [#action-shapes]
AppKit exposes its capabilities as standalone functions instead of instance methods. Every action takes the `AppKit` instance as its first argument, which keeps the API easy to test and tree-shake.
```ts
import { getSelectedWallet, transferTon } from '@ton/appkit';
const wallet = getSelectedWallet(appKit);
if (wallet) {
await transferTon(appKit, { recipientAddress: 'EQ...', amount: '1.25' });
}
```
Actions use three patterns. **Queries** read state synchronously or with a one-shot async call (`getSelectedWallet`, `getBalance`). **Watchers** subscribe to changes and return an unsubscribe function (`watchSelectedWallet`, `watchBalance`). **Mutations** trigger side effects and return a promise (`connect`, `transferTon`, `sendTransaction`).
Read actions that target the selected wallet (`getBalance`, `getJettons`, `getNfts`, …) return **`null`** when no wallet is selected. Mutation and signing actions (`transferTon`, `sendTransaction`, `signText`, …) **throw** `Error('Wallet not connected')` in the same case. Check for a selected wallet — or be ready for the throw — before calling a mutation.
## React integration [#react-integration]
`@ton/appkit-react` provides hooks for the main AppKit actions and watchers. Mount `AppKitProvider` once at the root inside a TanStack `QueryClientProvider`, then call hooks anywhere below it. See [Installation → Wrap the application](/applications/appkit/get-started/installation/react-app#wrap-the-application) for the full mount.
Most async data hooks return TanStack Query results such as `{ data, isLoading, error, refetch }`, and mutation hooks return `{ mutate, mutateAsync, isPending, error }`. Watch hooks such as `useWatchBalance` return `void` and keep the related query cache fresh while mounted. Wallet state hooks read AppKit's local store directly: `useSelectedWallet()` returns `[wallet, setWalletId]`, while `useConnectedWallets()` and `useConnectors()` return arrays.
## Tips [#tips]
* Create one AppKit instance for one app runtime. Do not share an instance across windows or processes.
* Pass the instance to actions directly, or provide it to React with `AppKitProvider`. Do not call actions before the instance is constructed.
* Connector `id`s are singletons. Registering a second connector with the same `id` calls `destroy()` on the old one before installing the new.
* Swap and staking provider `providerId`s are singletons too, but only the registry entry is replaced — the previous provider is not torn down. Hold the reference if you need to dispose of it yourself.
* Do not call signing or transfer mutations without first checking that a wallet is selected.
## Related pages [#related-pages]
* [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet)
* [Providers](/applications/appkit/howto/providers)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
* [Sign data](/applications/appkit/howto/sign-data)
# Connect to a wallet (/applications/appkit/howto/connect-to-a-wallet)
Open a wallet session, restore it across reloads, and disconnect cleanly.
## How it works [#how-it-works]
A wallet is the signing application that owns the keys. A connector is the transport AppKit uses to open the wallet flow, restore sessions, list connected wallets, and route signing requests. A connector is not a wallet and does not sign — signing always happens inside the user's wallet application.
AppKit can track multiple connected wallets, but one wallet is selected for actions such as transfers and data signing. A selected wallet can change after disconnects, network changes, or session restore, so read it from AppKit state instead of storing it as long-lived application state. The same wallet on a different network has a different wallet id, and AppKit treats those as separate wallet objects.
## Before you begin [#before-you-begin]
You need an `AppKit` instance with at least one connector and the React providers mounted. See [Add wallet connectors](/applications/appkit/get-started/connectors) for the instance and [Installation → Wrap the application](/applications/appkit/get-started/installation/react-app#wrap-the-application) for the provider setup.
## Drop-in button [#drop-in-button]
` ` from `@ton/appkit-react` opens the TON Connect modal, manages the session, and renders the connected address. This is the recommended path for most apps.
```tsx
import { TonConnectButton } from '@ton/appkit-react';
export function Header() {
return ;
}
```
## Custom connector picker [#custom-connector-picker]
When the app needs a tailored UI, render the connector list directly. `useConnectors()` returns an array of registered connectors, and `useConnect()` accepts a `connectorId`.
```tsx
import { useConnect, useConnectors, useDisconnect, useSelectedWallet } from '@ton/appkit-react';
export function ConnectPanel() {
const connectors = useConnectors();
const [wallet] = useSelectedWallet();
const connect = useConnect();
const disconnect = useDisconnect();
if (wallet) {
return (
disconnect.mutate({ connectorId: wallet.connectorId })}>
Disconnect {wallet.getAddress()}
);
}
return connectors.map((connector) => (
connect.mutate({ connectorId: connector.id })}>
Connect {connector.metadata.name}
));
}
```
If the `connectorId` passed to `connect` is not registered, the action throws `Connector with id "" not found`. Confirm registration with `getConnectors` (or `useConnectors` in React) before calling `connect`.
## Read the connected wallet [#read-the-connected-wallet]
`useSelectedWallet` returns the wallet used by the next action. The wallet exposes `getAddress()` and `getNetwork()`.
```tsx
import { useSelectedWallet } from '@ton/appkit-react';
const [wallet] = useSelectedWallet();
const address = wallet?.getAddress();
const network = wallet?.getNetwork();
```
For just the address string, `useAddress` is the convenience hook:
```tsx
import { useAddress } from '@ton/appkit-react';
const address = useAddress(); // string | undefined
```
## Register a connector after construction [#register-a-connector-after-construction]
If connector configuration is not available at construction time, register it with `addConnector`. Use this for user-scoped manifest URLs, feature flags, or dynamic wallet sets. `addConnector` accepts a `Connector` instance or a factory and returns an unregister function.
```ts
import { addConnector, createTonConnectConnector } from '@ton/appkit';
import { appKit } from './appkit';
const unregister = addConnector(
appKit,
createTonConnectConnector({
tonConnectOptions: { manifestUrl: 'https://example.com/tonconnect-manifest.json' },
}),
);
// Later, to remove and destroy the connector:
unregister();
```
Connector ids are singletons. Registering a second connector with the same id calls `destroy()` on the previous one before installing the new.
## Connect from vanilla JS [#connect-from-vanilla-js]
```ts
import { connect, disconnect, getConnectors } from '@ton/appkit';
import { appKit } from './appkit';
const [connector] = getConnectors(appKit);
await connect(appKit, { connectorId: connector.id });
// Later:
await disconnect(appKit, { connectorId: connector.id });
```
`connector.connectWallet()` and `connector.disconnectWallet()` are the lower-level equivalents when direct connector access is preferred.
## Wallet and Connector interfaces [#wallet-and-connector-interfaces]
Every connected wallet exposes the same minimum surface: a reference to the connector that produced it, four identity readers, and two wallet-approved operations that are routed through the connector.
```ts
interface WalletInterface {
/** Connector that created this wallet */
readonly connectorId: string;
// Identity
getAddress(): UserFriendlyAddress;
getPublicKey(): Hex;
getNetwork(): Network;
getWalletId(): string;
// Actions requiring wallet signature
sendTransaction(request: TransactionRequest): Promise;
signData(payload: SignDataRequest): Promise;
}
```
Connectors implement a small interface that AppKit treats as opaque transport — the protocol underneath is hidden.
```ts
interface Connector {
readonly id: string;
readonly type: string;
readonly metadata: ConnectorMetadata;
destroy(): void;
connectWallet(network?: Network): Promise;
disconnectWallet(): Promise;
getConnectedWallets(): WalletInterface[];
}
```
The bundled `createTonConnectConnector` covers most apps. It wraps `@tonconnect/ui`, restores prior sessions when the connector is first read, and syncs TON Connect with AppKit's default network.
## Errors and recovery [#errors-and-recovery]
Wrap every action in try/catch and convert errors with `getErrorMessage` from `@ton/appkit`.
| Error | Recovery |
| ----------------- | -------------------------------------------------- |
| User rejected | Keep state unchanged and allow retry. |
| Missing connector | Check the AppKit configuration. |
| Expired session | Disconnect and request a new connection. |
| Wrong network | Prompt the user to switch network in their wallet. |
## Tips [#tips]
* Do not call mutations or signing actions while `getSelectedWallet` is `null` — the action will throw.
* Do not assume every connector supports every flow. Catch rejections from the wallet and surface a recovery option.
* Do not store `selectedWalletId` as long-lived application state. The selected wallet can change after disconnects, network changes, or session restores.
* In application code, use public actions or React hooks instead of calling connector methods directly, so AppKit's event flow stays consistent. Connector methods are still the public surface for custom connector implementations.
## Related pages [#related-pages]
* [AppKit](/applications/appkit/howto/appkit)
* [`@ton/appkit-react` reference](/applications/appkit/reference/appkit-react)
* [Use UI widgets](/applications/appkit/howto/use-ui-widgets)
# Gasless (/applications/appkit/howto/gasless)
Gasless in AppKit lets the selected wallet sign a transaction while a relayer broadcasts it and charges fees in an accepted jetton instead of TON.
## Relayer model [#relayer-model]
Gasless does not remove the wallet step. The selected wallet still reviews and signs the message set, and the relayer only takes over after the wallet signature exists.
The `GaslessManager` coordinates a gasless provider. The provider describes which gas jettons it accepts, how it estimates fees, and which message shapes it is willing to relay.
## Fee and signature flow [#fee-and-signature-flow]
The flow begins by reading relayer configuration, then estimating the fee for the chosen gas jetton. The estimate gives the app two things to present together: the fee charged by the relayer and the message set the wallet must sign.
After signing, the app sends the signed payload to the relayer. The relayer broadcasts the transaction on behalf of the wallet and charges its fee according to its own rules.
```ts
import { estimateGasless, getGaslessConfig, sendGaslessTransaction } from '@ton/appkit';
const config = await getGaslessConfig(appKit, { network });
const gasJetton = config.gasJettons[0];
const estimate = await estimateGasless(appKit, {
network,
gasJetton,
messages,
});
const response = await sendGaslessTransaction(appKit, {
estimate,
});
```
Show the chosen gas jetton and estimated fee before opening the wallet. The wallet signs the message set; the relayer handles broadcast after that signature exists.
## Failure boundaries [#failure-boundaries]
Gasless introduces a relayer failure class in addition to wallet and chain failures. The wallet can reject signing, the relayer can reject the signed request, and the chain can still reject or fail the broadcast transaction.
Those outcomes need different recovery paths. A relayer rejection may require a different gas jetton or payload, while a chain failure requires normal transaction-status handling.
## Tips [#tips]
* Show the fee in the chosen gas jetton before opening the wallet.
* Treat relayer rejection and chain rejection as different outcomes.
* Verify the final on-chain result after the relayer accepts the signed request.
## Related pages [#related-pages]
* [Providers](/applications/appkit/howto/providers)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
* [How to](/applications/appkit/howto/howto)
# How to (/applications/appkit/howto/howto)
How-to guides explain how AppKit features work, then show the code path for using them in an app.
Start with [Get started](/applications/appkit/get-started/get-started) for installation and the smallest setup. Use these guides when you need both the model behind a feature and the practical code that drives it.
## Core setup [#core-setup]
| Guide | What it covers |
| --------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [AppKit](/applications/appkit/howto/appkit) | Runtime state, configuration, lifecycle, and React provider setup. |
| [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet) | Wallet and connector model, connect UI, selected wallet, and errors. |
| [Providers](/applications/appkit/howto/providers) | API clients, streaming providers, swap providers, and staking setup. |
| [Networks](/applications/appkit/howto/networks) | Mainnet, testnet, default network, API clients, and mismatch checks. |
## Wallet data and assets [#wallet-data-and-assets]
| Guide | What it covers |
| --------------------------------------------------------- | -------------------------------------------------------------------- |
| [Read balances](/applications/appkit/howto/read-balances) | Toncoin and jetton reads for the selected wallet or any address. |
| [Send Toncoin](/applications/appkit/howto/send-toncoin) | Toncoin transfer flow, amount handling, and settlement checks. |
| [Send jettons](/applications/appkit/howto/send-jettons) | Jetton metadata, decimals, transfer requests, and settlement checks. |
| [NFTs](/applications/appkit/howto/nfts) | NFT reads, rendering, transfer requests, and ownership verification. |
| [Sign data](/applications/appkit/howto/sign-data) | Text, binary, and cell signatures with verifier-side checks. |
| [Streaming](/applications/appkit/howto/streaming) | Live balance, jetton, and transaction updates. |
## Product flows [#product-flows]
| Guide | What it covers |
| ----------------------------------------------------------- | ----------------------------------------------------------------- |
| [Swaps](/applications/appkit/howto/swaps) | Quote freshness, provider routing, build flow, and settlement. |
| [Staking](/applications/appkit/howto/staking) | Stake and unstake quotes, provider metadata, balances, and sends. |
| [Onramp](/applications/appkit/howto/onramp) | Fiat redirects, crypto deposits, provider status, and completion. |
| [Gasless](/applications/appkit/howto/gasless) | Jetton-paid fees, relayer estimates, wallet signing, and sends. |
| [Use UI widgets](/applications/appkit/howto/use-ui-widgets) | Default UI, render props, hooks, and vertical flow components. |
## Conventions [#conventions]
Every guide assumes an `AppKit` instance and the React provider are already mounted unless it is showing setup. Code samples use public package imports and keep product-state decisions separate from wallet approval.
# Networks (/applications/appkit/howto/networks)
A network in AppKit is the chain context AppKit uses to read data, submit requests, and compare wallet state against the app's expected chain.
## Configured networks [#configured-networks]
AppKit can be configured with more than one network at the same time. Each network is identified by a `Network` value with a `chainId`, and each configured chain has an API client behind it.
The API client is the app's source for chain reads: balances, transactions, block height, asset metadata, and request submission. AppKit includes Toncenter and TonAPI clients, and a pre-built client can be supplied when an app needs its own transport or authentication policy.
At least one network must be configured. If a flow tries to read from a chain that the AppKit instance does not know about, the app has no reliable source of truth for that chain.
## Default network [#default-network]
Some flows are explicitly scoped to a network. Others need a fallback when the caller does not pass one. The default network is that fallback.
Changing the default network changes the chain AppKit uses for reads and actions that do not specify a network. Connectors observe this change so wallet-facing flows can compare the selected wallet's network with the app's current expectation.
## Configure networks [#configure-networks]
Each network entry takes an `apiClient` — either the inline `{ url, key }` shape that targets TON Center, or a constructed `ApiClient` instance (such as `ApiClientTonApi`) for any other backend. The inline shape has preset URLs for mainnet and testnet, so `url` can be omitted for those.
### Configure multiple networks [#configure-multiple-networks]
Add more entries to `networks` to declare additional chains, including custom networks beyond mainnet and testnet. The example below configures mainnet and testnet through TON Center, plus a custom chain through a TonAPI client instance with its own endpoint URL.
```ts
const customNetwork = Network.custom('custom_chain_id');
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: {
key: 'your-mainnet-key',
},
},
[Network.testnet().chainId]: {
apiClient: {
url: 'https://testnet.toncenter.com',
key: 'your-testnet-key',
},
},
[customNetwork.chainId]: {
apiClient: new ApiClientTonApi({
network: customNetwork,
endpoint: 'https://your-custom-endpoint.example',
apiKey: 'your-custom-key',
}),
},
},
});
```
### Set and read the default network [#set-and-read-the-default-network]
Set the default network with `setDefaultNetwork`:
```ts
import { setDefaultNetwork } from '@ton/appkit';
setDefaultNetwork(appKit, { network: Network.testnet() });
```
Use `getDefaultNetwork` or the React `useDefaultNetwork` hook when UI needs to show the active chain. `useDefaultNetwork` returns a `[network, setNetwork]` tuple — the value is `Network | undefined`, and the setter updates the default network reactively.
```tsx
import { useDefaultNetwork } from '@ton/appkit-react';
const [network] = useDefaultNetwork();
return {network?.chainId} ;
```
## Network mismatch [#network-mismatch]
A network mismatch happens when the app expects one chain and the selected wallet or provider reports another. This is not a display issue — it changes where a transaction request would be signed and where a result would settle.
Block unsafe actions when the expected network and the reported network do not match. Surface the expected network and let the wallet or app flow resolve the mismatch before sending a transaction request.
## Tips [#tips]
* Develop on testnet first.
* Never derive product state from a network the AppKit instance is not configured to read.
* Block unsafe actions when the selected wallet network does not match the expected network.
## Related pages [#related-pages]
* [Providers](/applications/appkit/howto/providers)
* [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet)
* [How to](/applications/appkit/howto/howto)
# NFTs (/applications/appkit/howto/nfts)
Read, render, and transfer NFTs owned by the connected wallet.
**Verify NFT authenticity.** Scammers create fake NFTs that mimic popular collections. An NFT item contract can claim any collection address, so reading the `collection` field from the item alone is not sufficient. To verify that an NFT item genuinely belongs to a collection, query the collection contract with the item's index and check that the returned address matches the item's address. See [how to verify an NFT item](/blockchain-basics/standard/tokens/nft/verify) for the full procedure.
## How it works [#how-it-works]
NFTs are unique digital assets on TON, similar to ERC-721 tokens on Ethereum. Unlike jettons, which have a balance, a wallet either owns a specific NFT item or it does not. NFTs consist of a collection contract and individual NFT item contracts; each item carries an `ownerAddress` that reflects current ownership.
AppKit reads NFT ownership and metadata through the configured API client. NFT names, images, attributes, and collection fields are display data from contracts and indexers, so render them defensively.
Transfers are wallet-approved transaction requests. The wallet accepting the request starts the chain flow, while ownership verification confirms that the NFT moved.
## Before you begin [#before-you-begin]
A connected wallet and the React provider mounted. See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet).
## Read NFTs [#read-nfts]
```tsx
import { useNfts } from '@ton/appkit-react';
export function MyNfts() {
const { data, isLoading, isError, refetch } = useNfts({
query: { refetchInterval: 10000 },
});
if (isError) return refetch()}>Retry ;
if (isLoading) return Loading… ;
const nfts = data?.nfts ?? [];
return {nfts.length} NFT(s)
;
}
```
For a different address, use `useNftsByAddress({ address })`.
## Render with ` ` [#render-with-nftitem-]
`@ton/appkit-react` ships an `NftItem` component that renders the NFT card with image, name, and collection.
```tsx
import { NftItem, useNfts } from '@ton/appkit-react';
const { data } = useNfts();
const nfts = data?.nfts ?? [];
return (
{nfts.map((nft) => (
console.log(nft)} />
))}
);
```
## Transfer an NFT [#transfer-an-nft]
**Assets at risk.** Transferring an NFT is irreversible — once sent, only the new owner can transfer it back. Verify both the NFT address and the recipient address before initiating a transfer. A common failure mode is **stale ownership**: the NFT changes owners between the read and the transfer attempt. Reread `ownerAddress` before opening the wallet. If `isOnSale` is true, also check `realOwnerAddress`.
Before opening the wallet, make sure the sender's wallet has enough Toncoin to cover the [fees](/blockchain-basics/primitives/fees).
An NFT transfer carries the destination owner address, the NFT contract address, and an optional small Toncoin amount that is forwarded to the recipient message. For NFTs the recommended pattern is to build the request offline with `createTransferNftTransaction`, then hand it to ` `. This keeps the transaction shape testable.
```tsx
import { Send, useAppKit } from '@ton/appkit-react';
import { createTransferNftTransaction, getErrorMessage } from '@ton/appkit';
import { useCallback } from 'react';
export function TransferNft({ nftAddress, recipientAddress }: { nftAddress: string; recipientAddress: string }) {
const appKit = useAppKit();
const request = useCallback(
() => createTransferNftTransaction(appKit, { nftAddress, recipientAddress }),
[appKit, nftAddress, recipientAddress],
);
return (
console.log('done')}
onError={(e) => console.error(getErrorMessage(e))}
>
{({ isLoading, onSubmit, disabled, text }) => (
{isLoading ? 'Sending…' : text}
)}
);
}
```
The shorter route is the `useTransferNft` hook or the `transferNft` core action — both build the request internally and call the wallet directly.
```ts
import { transferNft } from '@ton/appkit';
await transferNft(appKit, {
nftAddress: 'EQ...',
recipientAddress: 'EQ...',
});
```
## Read a single NFT [#read-a-single-nft]
```ts
import { getNft } from '@ton/appkit';
const nft = await getNft(appKit, { address: 'EQ...' });
```
## Continuous ownership monitoring [#continuous-ownership-monitoring]
A discrete ownership check is fine for assembling an outgoing transfer, but UI state should not be derived from it — ownership can change between read and render. There is no `watchNfts` streaming action; to keep an NFT view in sync, mount a query hook with a refetch interval, or run a polling loop from vanilla code.
```tsx
import { useNfts } from '@ton/appkit-react';
const { data, isLoading, error, refetch } = useNfts({
limit: 100,
query: { refetchInterval: 10_000 },
});
```
From vanilla JS:
```ts
import { type AppKit, type NFT, getNfts } from '@ton/appkit';
/** Start polling. Returns a stop function. */
export function startNftOwnershipMonitoring(
appKit: AppKit,
onNftsUpdate: (nfts: NFT[]) => void,
intervalMs: number = 10_000,
): () => void {
let isRunning = true;
const poll = async () => {
while (isRunning) {
const result = await getNfts(appKit, { limit: 100 });
onNftsUpdate(result?.nfts ?? []);
await new Promise((resolve) => setTimeout(resolve, intervalMs));
}
};
poll();
return () => { isRunning = false; };
}
```
Pick an interval based on UX needs — shorter intervals provide fresher data but increase API usage. For large wallets, call `getNfts` with increasing `offset` to paginate.
## `NFT` type [#nft-type]
NFT-related queries produce objects that conform to the following interface:
```ts title="TypeScript"
/**
* Non-fungible token (NFT) on the TON blockchain.
*/
export interface NFT {
/** Contract address of the NFT item */
address: string;
/** Index of the item within its collection */
index?: string;
/** Display information about the NFT (name, description, images, etc.) */
info?: TokenInfo;
/** Custom attributes/traits of the NFT (e.g., rarity, properties) */
attributes?: NFTAttribute[];
/** Information about the collection this item belongs to */
collection?: NFTCollection;
/** Address of the auction contract, if the NFT is being auctioned */
auctionContractAddress?: string;
/** Hash of the NFT smart contract code */
codeHash?: string;
/** Hash of the NFT's on-chain data */
dataHash?: string;
/** Whether the NFT contract has been initialized */
isInited?: boolean;
/** Whether the NFT is soulbound (non-transferable) */
isSoulbound?: boolean;
/** Whether the NFT is currently listed for sale */
isOnSale?: boolean;
/** Current owner address of the NFT */
ownerAddress?: string;
/** Real owner address when NFT is on sale (sale contract becomes temporary owner) */
realOwnerAddress?: string;
/** Address of the sale contract, if the NFT is listed for sale */
saleContractAddress?: string;
/** Off-chain metadata of the NFT (key-value pairs) */
extra?: { [key: string]: unknown };
}
```
NFT display data (`info`, `attributes`, `extra`) is off-chain and untrusted. The contract address is the authoritative routing key. When `isOnSale` is `true`, `ownerAddress` points to the sale contract and `realOwnerAddress` points to the seller. Render the seller, but route on-chain interactions through `ownerAddress`.
## Confirm settlement [#confirm-settlement]
The wallet accepting the request does not prove the NFT moved. Track the transaction with [Streaming](/applications/appkit/howto/streaming) and verify ownership before crediting value.
## Common failures [#common-failures]
| Failure | Meaning |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| User rejected | The user closed or rejected the wallet request. |
| Stale ownership | The NFT changed owners between the read and the transfer. Reread `ownerAddress` before sending. |
| NFT on sale | `isOnSale === true` — the NFT is held by a sale contract. Cancel the listing or transfer through the sale contract flow. |
| Soulbound NFT | `isSoulbound === true` — the item cannot be transferred. |
| Invalid address | The recipient or NFT contract address is malformed or for the wrong network. |
## Tips [#tips]
* Verify the current `ownerAddress` before allowing a user-initiated transfer. NFTs can change owners between reads and transfers.
* Display **verified** fields first: contract address, owner address, real owner address, and collection address. Treat off-chain display data (`info`, `attributes`, `extra`) as **display data only**. Sanitize names and images, and never route on display metadata.
* Use `getTransactionStatus` to confirm settlement before updating NFT state in your app. The wallet response only proves the user signed.
* Refetch the NFT list after settlement so the owner fields are current.
* Do not concatenate NFT addresses for analytics keys. Use the contract address verbatim and `index` as a string when present.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) of an NFT list rendered with `useNfts` — [try it live](https://appkit-minter.vercel.app/).
## Related pages [#related-pages]
* [Use UI widgets](/applications/appkit/howto/use-ui-widgets)
* [AppKit reference](/applications/appkit/reference/reference)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
# Onramp (/applications/appkit/howto/onramp)
Onramp in AppKit covers external flows that bring value into a TON wallet through fiat payment providers or crypto bridge aggregators.
## Two external flows [#two-external-flows]
| Flow | What starts in AppKit | What finishes outside AppKit |
| ------------- | ----------------------------------------------------- | -------------------------------------------------------------------------- |
| Fiat onramp | A provider quote and hosted payment URL. | Fiat payment, KYC, provider settlement, and delivery to the TON address. |
| Crypto onramp | A bridge quote and source-chain deposit instructions. | Source-chain deposit, bridge processing, status updates, and TON delivery. |
Both flows use the same manager and provider idea as other AppKit integrations. The manager gives the app one surface to ask for quotes; the provider owns payment pages, bridge routes, fees, limits, and completion status.
## Fiat onramp [#fiat-onramp]
A fiat onramp sends the user to a hosted provider page. AppKit can collect quotes and produce the URL for Mercuryo, MoonPay, TON Pay, or another registered provider, but it does not process card payments or perform KYC.
The redirect is the beginning of an external process. The selected wallet address may be the destination, but wallet state alone is not the completion source for the provider flow.
```ts
import { buildOnrampUrl, getOnrampQuote } from '@ton/appkit';
const quote = await getOnrampQuote(appKit, {
fiatCurrency: 'USD',
cryptoCurrency: 'TON',
fiatAmount: '100',
destinationAddress: wallet.getAddress().toString(),
});
const url = await buildOnrampUrl(appKit, { quote });
window.location.assign(url);
```
## Crypto onramp [#crypto-onramp]
A crypto onramp starts with bridge intent: a source chain, a source asset, and a TON destination. AppKit asks the provider for a quote, creates a deposit, and exposes the chain-specific instructions needed to fund it.
Deposit addresses, memos, source-chain confirmations, bridge timing, and refunds are provider concerns. AppKit surfaces status so the app can track progress without pretending to move funds itself.
```ts
import { createCryptoOnrampDeposit, getCryptoOnrampQuote, getCryptoOnrampStatus } from '@ton/appkit';
const quote = await getCryptoOnrampQuote(appKit, {
fromChain: 'ethereum',
fromToken: 'USDT',
toToken: 'TON',
amount: '50',
destinationAddress: wallet.getAddress().toString(),
});
const deposit = await createCryptoOnrampDeposit(appKit, { quote });
const status = await getCryptoOnrampStatus(appKit, { depositId: deposit.id });
```
## Tips [#tips]
* Treat a hosted URL or deposit instruction as the start of a long-running provider process.
* Verify completion through provider status, not wallet state alone.
* Surface provider fees, limits, and timing as provider data rather than guaranteed outcomes.
## Related pages [#related-pages]
* [Providers](/applications/appkit/howto/providers)
* [Networks](/applications/appkit/howto/networks)
* [How to](/applications/appkit/howto/howto)
# Providers (/applications/appkit/howto/providers)
Providers connect AppKit to external data sources and DeFi services. AppKit uses four provider-related components: the **API client** that reads chain state, the **streaming provider** that delivers live updates, the **swap provider** that quotes and builds DEX transactions, and the **staking provider** that quotes and builds staking transactions. Each component is managed by the matching manager on the `AppKit` instance.
A provider is not a wallet and not a connector. The wallet still signs every transaction; the connector still owns the session. A provider is the source of *data* about the chain or about a DeFi protocol, and AppKit treats whatever it returns as external input — useful for showing prices, balances, and quotes, but never as proof of settlement.
| Type | Use | Manager |
| ------------------ | -------------------------------------------------------------------- | ------------------------- |
| API client | Reads blockchain data such as balances, jettons, and NFTs. | `AppKit.networkManager` |
| Streaming provider | Pushes live balance, transaction, and jetton updates over WebSocket. | `AppKit.streamingManager` |
| Swap provider | Returns swap quotes and builds swap transactions. | `AppKit.swapManager` |
| Staking provider | Returns staking quotes, balance, and builds stake transactions. | `AppKit.stakingManager` |
Only swap and staking providers are registered through `registerProvider`. Streaming providers are registered with `appKit.streamingManager.registerProvider(...)`, and API clients are configured per network through `networks[chainId].apiClient`.
## Swaps [#swaps]
A swap provider integrates a DEX or aggregator. It returns a **quote** for a route (input asset, output asset, amount, fees, and execution assumptions), then builds a `TransactionRequest` when the user accepts the quote. AppKit does not price markets itself; `SwapManager` coordinates the registered providers. Bundled options include Omniston and DeDust. See [Swaps](/applications/appkit/howto/swaps) for the full quote-then-build flow.
## Staking [#staking]
A staking provider quotes a stake or unstake intent for a specific pool or protocol, then builds the matching `TransactionRequest`.
Liquid-staking positions may appear in the wallet as derivative balances, such as tsTON. AppKit exposes pool metadata and APY as provider-supplied **display data**, not a guarantee of future yield or redemption timing.
Unstake mechanics — instant, delayed, or round-end — are provider-specific. The bundled staking provider is Tonstakers. See [Staking](/applications/appkit/howto/staking) for the full flow.
## How they are registered [#how-they-are-registered]
Provider setup uses three registration paths. **API clients** are bound to a network through the `networks` field of `AppKitConfig`. **Streaming providers** are also network-specific and are registered directly on `appKit.streamingManager`. **Swap** and **staking** providers are network-aware DeFi providers: pass them in `providers` at construction or register them later with `registerProvider`. Each DeFi provider declares its `type` so AppKit can route it to the correct manager.
Omniston requires its own SDK package — install it before registering the provider:
```bash
npm i @ston-fi/omniston-sdk
```
```ts
import { AppKit, Network, registerProvider } from '@ton/appkit';
import { OmnistonSwapProvider } from '@ton/appkit/swap/omniston';
import { createTonstakersProvider } from '@ton/appkit/staking/tonstakers';
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: { url: 'https://toncenter.com', key: 'your-mainnet-api-key' },
},
[Network.testnet().chainId]: {
apiClient: { url: 'https://testnet.toncenter.com', key: 'your-testnet-api-key' },
},
},
providers: [new OmnistonSwapProvider()],
});
registerProvider(appKit, createTonstakersProvider());
```
When a network entry does not provide a custom API client, AppKit creates a TonCenter client for that network. TonAPI and TonCenter streaming providers are available through WalletKit and can be registered on `appKit.streamingManager`. Omniston and DeDust are available as swap providers, and Tonstakers is available as a staking provider. Custom DeFi backends can use the same `registerProvider` path by implementing the swap or staking interface.
`registerProvider` returns `void`. To replace a provider, call `registerProvider` again with the same `providerId` — the registry entry is overwritten. If the previous provider owns resources you need to clean up, hold the reference and dispose of it yourself before re-registering.
## Two-step transactions [#two-step-transactions]
Swap and staking actions follow a quote-then-build pattern. `getSwapQuote` and `getStakingQuote` return provider offers, including fees, settlement amounts, and routing data. `buildSwapTransaction` and `buildStakeTransaction` turn an accepted quote into a `TransactionRequest`. Building the request does not broadcast it; the request still has to be submitted with `sendTransaction` and approved in the connected wallet.
```ts
import { AppKit, getSwapQuote, buildSwapTransaction, sendTransaction } from '@ton/appkit';
const quote = await getSwapQuote(appKit, {
amount: '1000000000',
from: { address: 'EQ-USDT-MASTER', decimals: 6 },
to: { address: 'ton', decimals: 9 },
network,
});
const request = await buildSwapTransaction(appKit, {
quote,
userAddress: wallet.getAddress().toString(),
});
await sendTransaction(appKit, request);
```
This separation matters because quotes can expire. The settlement amount shown when the quote is fetched is not guaranteed when the transaction lands on chain. Refetch the quote before building the transaction, and verify the on-chain result before updating product state.
## Custom providers [#custom-providers]
Apps that integrate their own DEX or staking backend implement the same provider interface as the bundled providers, then register the provider with `registerProvider`. Provider ids are singletons; registering another provider with the same `providerId` replaces the previous entry.
## Tips [#tips]
* Provider responses are external data. Validate critical outcomes, including settlement amounts, addresses, and signatures, before changing product state.
* Quotes can expire. Build the transaction soon after fetching the quote, or refetch before showing the user a final price.
* Do not assume a provider is registered. Call `getStakingProviders(appKit)` or `hasStreamingProvider(appKit, network)` and degrade gracefully when the list is empty or the provider is absent.
* Treat provider ids as singletons. Registering a second provider with the same id replaces the previous one.
## Related pages [#related-pages]
* [AppKit](/applications/appkit/howto/appkit)
* [Swaps](/applications/appkit/howto/swaps)
* [Staking](/applications/appkit/howto/staking)
* [Streaming](/applications/appkit/howto/streaming)
# Read balances (/applications/appkit/howto/read-balances)
Read Toncoin and jetton balances for the connected wallet or any address.
## How it works [#how-it-works]
Balance reads come from the configured API client for the active network. Selected-wallet hooks are convenient for wallet UI, while address-explicit hooks are better for receipts, profiles, admin views, and backend-confirmed destinations.
Live balance changes are streaming signals. They are useful for refreshing UI, but product decisions should still rely on a point-in-time read from the network the app is configured to trust.
## Before you begin [#before-you-begin]
A connected wallet (or a known address) and the React provider mounted. See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet).
## Pick the right hook [#pick-the-right-hook]
| Goal | Hook |
| --------------------------------------- | --------------------- |
| Toncoin balance for the selected wallet | `useBalance` |
| Toncoin balance for an explicit address | `useBalanceByAddress` |
| Jetton balances for the selected wallet | `useJettons` |
| Jetton balances for an explicit address | `useJettonsByAddress` |
All four are query hooks. They return `{ data, isLoading, error, refetch }` and accept a `query` field to forward TanStack Query options such as `refetchInterval`.
## Read the connected wallet [#read-the-connected-wallet]
```tsx
import { useBalance, useJettons } from '@ton/appkit-react';
export function Balances() {
const ton = useBalance({ query: { refetchInterval: 20000 } });
const jettons = useJettons({ query: { refetchInterval: 20000 } });
if (ton.isLoading || jettons.isLoading) return Loading… ;
if (ton.isError) return Failed to load TON ;
return (
TON: {ton.data ?? '0'}
Jettons: {jettons.data?.jettons.length ?? 0}
);
}
```
`ton.data` is a string in TON units. Render it directly, or use `toNano` only when another API expects raw nanotons.
Jetton reads return formatted balances in the token's own units. Use the token metadata for symbols and decimals when rendering a list.
## Read by address [#read-by-address]
Use the `*ByAddress` hooks to read any address — useful for receipt screens or admin tooling.
```tsx
import { useBalanceByAddress, useJettonsByAddress } from '@ton/appkit-react';
export function ProfileBalances({ address }: { address: string }) {
const ton = useBalanceByAddress({ address });
const jettons = useJettonsByAddress({ address });
return TON: {ton.data ?? '0'}
;
}
```
## Render a jetton row [#render-a-jetton-row]
The SDK ships `getFormattedJettonInfo` to normalize jetton metadata for display.
```tsx
import { getFormattedJettonInfo } from '@ton/appkit';
const formatted = getFormattedJettonInfo(jetton);
// formatted: { name, symbol, decimals, balance, image, address }
```
## Read from vanilla JS [#read-from-vanilla-js]
```ts
import { getBalanceByAddress, getJettonsByAddress } from '@ton/appkit';
const ton = await getBalanceByAddress(appKit, { address: 'EQ...' });
const jettons = await getJettonsByAddress(appKit, { address: 'EQ...' });
```
## Live updates [#live-updates]
Mount `useWatchBalance()` and `useWatchJettons()` once high in the tree to keep the cache pushed live. See [Stream live updates](/applications/appkit/get-started/streaming).
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) of TON and jetton balances rendered together with the same hooks documented above — [try it live](https://appkit-minter.vercel.app/).
## Related pages [#related-pages]
* [Streaming](/applications/appkit/howto/streaming)
* [AppKit reference](/applications/appkit/reference/reference)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
# Send jettons (/applications/appkit/howto/send-jettons)
Transfer a jetton (a TON fungible token) from the connected wallet to another address.
## How it works [#how-it-works]
Jettons are TON fungible tokens. Each holder has a jetton wallet contract derived from `(jettonMaster, ownerAddress)` — the owner is the user's TON wallet, and the jetton wallet is a separate contract owned by it. Transfer UI asks for the recipient's owner address, not their jetton wallet address. AppKit derives the sender's jetton wallet internally (that's the destination of the outer TON message), builds the inner jetton transfer payload that names the recipient's owner address, and wraps it in the outer message. The sender's jetton wallet then forwards the transfer to the recipient's jetton wallet on-chain. For example, USDT on TON is implemented as a jetton with the master address `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`.
Each jetton stores `name`, `symbol`, and `decimals` in its metadata. Amounts are decimal strings in the jetton's own units, so read the `decimals` field from chain metadata before building a transfer — different jettons can use different precision. USDT uses 6 decimals, so `'0.1'` represents 100,000 micro-USDT.
To deploy and mint a new jetton on the mainnet without writing code, use the dedicated official tool: [TON MINTER](https://minter.ton.org).
## Before you begin [#before-you-begin]
A connected wallet, the React provider mounted, and the jetton's master address. See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet) and [Read balances](/applications/appkit/howto/read-balances) to discover what the wallet holds.
**Funds at risk.** Transferring without accounting for `decimals` can send drastically more or fewer tokens than intended. Verify the `decimals` value from chain metadata before calculating transfer amounts.
Before opening the wallet, make sure the sender's wallet has enough Toncoin to cover the [fees](/blockchain-basics/primitives/fees).
## Component (recommended) [#component-recommended]
` ` accepts a `jetton` descriptor with `address`, `symbol`, and `decimals`.
```tsx
import { SendJettonButton } from '@ton/appkit-react';
import { getErrorMessage } from '@ton/appkit';
console.error(getErrorMessage(e))}
onSuccess={({ boc }) => console.log('sent', boc)}
>
{({ isLoading, onSubmit, disabled, text }) => (
{text}
)}
```
`amount` is a decimal string in jetton units (so `'1.0'` for one full token, regardless of `decimals`).
## Hook [#hook]
```tsx
import { useTransferJetton } from '@ton/appkit-react';
const transferJetton = useTransferJetton();
transferJetton.mutate({
recipientAddress: 'EQ...',
jettonAddress: 'EQ...',
amount: '1.0',
jettonDecimals: 6,
});
```
## Core action [#core-action]
```ts
import { transferJetton } from '@ton/appkit';
await transferJetton(appKit, {
recipientAddress: 'EQ...',
jettonAddress: 'EQ...',
amount: '1.0',
jettonDecimals: 6,
});
```
## Look up jetton metadata [#look-up-jetton-metadata]
When you need the symbol, decimals, or icon for a UI, call `getJettonInfo` and pass the result through `getFormattedJettonInfo`.
```ts
import { getJettonInfo, getFormattedJettonInfo } from '@ton/appkit';
const jetton = await getJettonInfo(appKit, { address: 'EQ...' });
const formatted = getFormattedJettonInfo(jetton);
// formatted: { name, symbol, decimals, balance, image, address }
```
## Parameters [#parameters]
| Field | Type | Required | Notes |
| ------------------ | -------- | -------- | --------------------------------------- |
| `recipientAddress` | `string` | Yes | TON address of the recipient. |
| `jettonAddress` | `string` | Yes | Address of the jetton master contract. |
| `amount` | `string` | Yes | Decimal jetton units, e.g. `'1.0'`. |
| `jettonDecimals` | `number` | Yes | Decimal precision of the jetton. |
| `comment` | `string` | No | Plain text memo on the jetton transfer. |
## Confirm settlement [#confirm-settlement]
Jetton transfers settle through the same trace API as Toncoin transfers, but typically produce multiple internal messages. Use `getTransactionStatus(appKit, { boc })` and inspect `onchainMessages`, `pendingMessages`, and `totalMessages` to track progress; treat only `status === 'completed'` as final.
Track the transaction with [Streaming](/applications/appkit/howto/streaming) and verify the recipient's jetton balance in your backend before delivering value.
If the recipient has never held this jetton, the transfer deploys the recipient's jetton wallet contract on first receive, which costs additional gas. The default outer-TON allowance on a built `transferJetton` request is designed to cover this case.
## Common failures [#common-failures]
| Failure | Meaning |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| User rejected | The user closed or rejected the wallet request. |
| Wrong decimals | The amount was scaled with the wrong `decimals` value. The transfer may move drastically more or fewer tokens than intended. |
| Insufficient balance | The wallet cannot cover the jetton amount or the outer TON fee allowance. |
| Invalid address | The recipient or jetton master address is malformed or for the wrong network. |
## Tips [#tips]
* Always pass the destination **owner address** as `recipientAddress`. AppKit derives the sender's jetton wallet contract and writes the destination owner address into the jetton transfer payload.
* Read decimals from chain metadata (`getJettonInfo`) before building a transfer. Different jettons can use different precision.
* Treat the `boc` from `sendTransaction` as "user signed". Verify settlement with `getTransactionStatus` before crediting an order.
* Refetch the user's jetton list and balances after settlement.
* Do not display jetton metadata without sanitizing — names and images are user-supplied.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) of jetton transfers built with these mutations — [try it live](https://appkit-minter.vercel.app/).
## Related pages [#related-pages]
* [Read balances](/applications/appkit/howto/read-balances)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
* [Use UI widgets](/applications/appkit/howto/use-ui-widgets)
# Send Toncoin (/applications/appkit/howto/send-toncoin)
Transfer Toncoin from the connected wallet. Pick the call style that fits your UI.
## How it works [#how-it-works]
Toncoin is the native asset on TON. AppKit keeps Toncoin amounts as decimal strings in human-readable TON units and converts them when it builds the wallet request. Precision is 9 digits — `'0.1'` is 100,000,000 nanoToncoin; the smallest representable amount is `'0.000000001'` (1 nanoToncoin).
The flow has three steps: AppKit assembles the request, the wallet signs and broadcasts, and the chain settles. A wallet response means the selected wallet accepted and submitted the request — it does not prove that the transaction settled on chain, so product state should wait for status tracking or a backend verification read.
## Before you begin [#before-you-begin]
A connected wallet and the React provider mounted. See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet). Use testnet during development.
## Component (recommended) [#component-recommended]
` ` builds the request, calls the wallet, and exposes the mutation state to a render-prop child.
```tsx
import { SendTonButton } from '@ton/appkit-react';
import { getErrorMessage } from '@ton/appkit';
import { useState } from 'react';
export function SendTon() {
const [error, setError] = useState(null);
return (
setError(getErrorMessage(e))}
onSuccess={({ boc }) => console.log('sent', boc)}
>
{({ isLoading, onSubmit, disabled, text }) => (
{isLoading ? 'Sending…' : text}
)}
);
}
```
`amount` is a decimal string in TON. The component accepts an optional `comment` for a memo on chain.
## Hook [#hook]
`useTransferTon` is the mutation hook behind the component.
```tsx
import { useTransferTon } from '@ton/appkit-react';
const transferTon = useTransferTon();
transferTon.mutate({
recipientAddress: 'EQ...',
amount: '0.05',
comment: 'Test payment',
});
```
Read `transferTon.isPending`, `transferTon.error`, and use `mutation.onSuccess` / `mutation.onError` if you initialize the hook with options.
## Core action [#core-action]
```ts
import { transferTon } from '@ton/appkit';
import { appKit } from './appkit';
await transferTon(appKit, {
recipientAddress: 'EQ...',
amount: '0.05',
comment: 'Test payment',
});
```
## Parameters [#parameters]
| Field | Type | Required | Notes |
| ------------------ | -------- | -------- | --------------------------------------------------- |
| `recipientAddress` | `string` | Yes | TON address. |
| `amount` | `string` | Yes | Decimal TON, e.g. `'0.05'`. |
| `comment` | `string` | No | Plain text memo. Mutually exclusive with `payload`. |
| `payload` | `string` | No | Base64 cell. Overrides `comment` when set. |
| `stateInit` | `string` | No | Base64 cell, used to deploy. |
## Confirm settlement [#confirm-settlement]
TON achieves transaction [finality](https://docs.ton.org/payments/overview#transaction-finality) after a single masterchain block confirmation, with new blocks produced roughly every 400 ms. Once a transaction appears in a masterchain block, it becomes irreversible.
`sendTransaction` returning a `boc` means **the user signed**. Settlement is a separate state — verify with `getTransactionStatus(appKit, { boc })`, which returns `'unknown' | 'pending' | 'completed' | 'failed'` along with `totalMessages`, `pendingMessages`, and `onchainMessages` for trace progress. Treat only `status === 'completed'` as final.
Applications should not block the UI while waiting for confirmation. Show a "signed / confirming" state, let [Streaming](/applications/appkit/howto/streaming) push live updates, and act on `completed` when it arrives. For finding a transaction by external message hash and applying normalization, see the [message lookup guide](/ecosystem/ton-connect/message-lookup).
## Common failures [#common-failures]
| Failure | Meaning |
| -------------------- | ------------------------------------------------------------ |
| User rejected | The user closed or rejected the wallet request. |
| Insufficient balance | The wallet cannot pay amount and fees. |
| Expired request | The transaction deadline passed before approval. |
| Invalid address | The recipient address is malformed or for the wrong network. |
## Tips [#tips]
* Validate the recipient address, amount, and expected network before calling any mutation. Do not rely on the wallet as the final input validator.
* Treat `sendTransaction` returning a `boc` as "user signed", not "settled". Wait for `getTransactionStatus` to return `completed` before delivering value.
* Do not block UI while waiting for settlement. Show a "signed / confirming" state, let `watchBalance` / `watchTransactions` update the view, and act on `completed` when it arrives.
* Refetch wallet balances and cached lists after settlement. Use trace status, not the immediate wallet response, as the trigger for product state changes.
* Do not derive product success from the wallet response shape. Verify on the chain.
* Keep amounts as strings or bigints until you display them. Floating-point math loses precision at TON's nine decimal places.
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) of TON transfers built with these mutations — [try it live](https://appkit-minter.vercel.app/).
## Related pages [#related-pages]
* [Send jettons](/applications/appkit/howto/send-jettons)
* [NFTs](/applications/appkit/howto/nfts)
* [Use UI widgets](/applications/appkit/howto/use-ui-widgets)
# Sign data (/applications/appkit/howto/sign-data)
Ask the wallet to sign a payload. AppKit supports plain text, raw binary, and TON cells.
## How it works [#how-it-works]
Signed data attests to application data without sending a transaction. It fits user-facing acknowledgments, off-chain receipts, and signatures that a backend or TON smart contract verifies later.
The wallet returns an Ed25519 signature, signing address, wallet timestamp, observed dApp domain, and the original payload. The verifier owns freshness, domain, nonce, and signer checks. For wallet-ownership sign-in, use `ton_proof` during connection instead.
## Before you begin [#before-you-begin]
You need a connected wallet and the React provider mounted. See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet).
## Pick the right call [#pick-the-right-call]
| Payload type | Hook | Core action |
| --------------- | --------------- | ------------ |
| Plain text | `useSignText` | `signText` |
| Binary (base64) | `useSignBinary` | `signBinary` |
| TON cell (BoC) | `useSignCell` | `signCell` |
All three hooks are mutation hooks. They return `{ mutate, mutateAsync, isPending, error, data }`.
## Sign text [#sign-text]
```tsx
import { useSignText } from '@ton/appkit-react';
const { mutate: signText, data } = useSignText();
signText({
text: 'Message to sign',
});
// data: { signature, address, timestamp, domain, payload }
```
## Sign binary [#sign-binary]
```tsx
import { useSignBinary } from '@ton/appkit-react';
const { mutate: signBinary, data } = useSignBinary();
signBinary({
bytes: 'base64-encoded-payload',
});
// data: { signature, address, timestamp, domain, payload }
```
## Sign a cell [#sign-a-cell]
For application protocols that exchange typed payloads, send a TON cell.
```tsx
import { useSignCell } from '@ton/appkit-react';
import { beginCell } from '@ton/core';
const { mutate: signCell, data } = useSignCell();
const cell = beginCell().storeUint(42, 32).storeStringTail('hello').endCell();
signCell({
cell: cell.toBoc().toString('base64'),
schema: 'message#_ value:uint32 text:Text = Message;',
});
// data: { signature, address, timestamp, domain, payload }
```
## Verify the signature [#verify-the-signature]
The wallet returns a signature response that includes `signature`, `address`, `timestamp`, `domain`, and the original `payload`. Verify the response server side against the payload and the wallet's public key before trusting it. Treat the client-side response as a hint, not proof.
## Related pages [#related-pages]
* [AppKit reference](/applications/appkit/reference/reference)
* [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet)
# Staking (/applications/appkit/howto/staking)
Quote a stake or unstake, build the transaction, and send it through the connected wallet.
## How it works [#how-it-works]
The `StakingManager` routes each quote and build call to a single registered staking provider — by default the first one you registered, or the one you pass as `providerId`. `setDefaultProvider` on the manager overrides the default; an unknown `providerId` throws. A quote describes the intent (`direction: 'stake' | 'unstake'`, `amount`, optional `unstakeMode`), and `useBuildStakeTransaction` turns an accepted quote into a `TransactionRequest`.
The protocol shape — derivative jetton, unstake modes, settlement timing, pool model — is provider-specific. Tonstakers, the bundled provider, issues `tsTON` and supports `INSTANT`, `WHEN_AVAILABLE`, and `ROUND_END` unstake modes. Read the user's staked-token balance with `useStakedBalance`, or query the jetton balance directly. `apy` and `instantUnstakeAvailable` from `useStakingProviderInfo` are provider-supplied display data, not guarantees of future yield or withdrawal timing.
## Before you begin [#before-you-begin]
You need a connected wallet and a staking provider registered on the AppKit instance. Tonstakers ships bundled — see [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered).
## Hooks [#hooks]
| Hook | Purpose |
| -------------------------- | ------------------------------------------------------ |
| `useStakingProviders` | List registered staking provider IDs. |
| `useStakingProviderInfo` | Read APY and instant-unstake liquidity for a provider. |
| `useStakedBalance` | Read the user's staked-token balance (e.g. `tsTON`). |
| `useStakingQuote` | Quote a stake or unstake intent. |
| `useBuildStakeTransaction` | Build a `TransactionRequest` from a quote. |
The first three are query hooks (`{ data, isLoading, isError, refetch }`); the last two are mutation/query pair used together. The built `TransactionRequest` is handed to ` ` from `@ton/appkit-react`, which exposes loading/error state.
## Read the user's staking balance [#read-the-users-staking-balance]
`useStakedBalance` returns `StakingBalance` for the given user address. The shape is `{ stakedBalance, rawStakedBalance, instantUnstakeAvailable, rawInstantUnstakeAvailable, providerId }`. Render `stakedBalance` as the user's tsTON amount and `instantUnstakeAvailable` as the pool's liquid TON.
```tsx
import { useAddress, useStakedBalance } from '@ton/appkit-react';
export function StakedBalance() {
const address = useAddress();
const { data, isLoading, isError } = useStakedBalance({
userAddress: address ?? '',
query: { refetchInterval: 10000, enabled: Boolean(address) },
});
if (isLoading) return … ;
if (isError) return — ;
return (
Staked: {data?.stakedBalance ?? '0'} tsTON
Instant unstake liquidity:{' '}
{data?.instantUnstakeAvailable ?? '0'} TON
);
}
```
## Quote a stake or unstake [#quote-a-stake-or-unstake]
`useStakingQuote` takes the intent and returns settlement amounts. For an unstake, pass `unstakeMode` (`UnstakeMode.INSTANT`, `UnstakeMode.WHEN_AVAILABLE`, or `UnstakeMode.ROUND_END`) when the provider supports more than one.
```tsx
import { UnstakeMode, useNetwork, useStakingQuote } from '@ton/appkit-react';
export function StakePreview({ amount }: { amount: string }) {
const network = useNetwork();
const { data: quote, isLoading, isError } = useStakingQuote({
amount,
direction: 'stake',
network,
});
if (isLoading) return Fetching quote… ;
if (isError || !quote) return Staking unavailable ;
const rate = Number(quote.amountOut) / Number(quote.amountIn);
return (
Stake {quote.amountIn} TON → receive {quote.amountOut} tsTON
Rate: 1 TON ≈ {rate.toFixed(4)} tsTON
);
}
```
For an unstake, swap `direction` and add `unstakeMode`:
```tsx
const { data: quote } = useStakingQuote({
amount,
direction: 'unstake',
unstakeMode: UnstakeMode.INSTANT,
network,
});
```
## Build and send the transaction [#build-and-send-the-transaction]
`useBuildStakeTransaction` is the mutation that turns an accepted quote into a `TransactionRequest`. Hand it to ` ` through a `request` callback.
```tsx
import { Send, useAddress, useBuildStakeTransaction } from '@ton/appkit-react';
import type { StakingQuote } from '@ton/appkit';
export function StakeSendButton({
quote,
}: {
quote: StakingQuote | undefined;
}) {
const address = useAddress();
const { mutateAsync: buildStakeTransaction } = useBuildStakeTransaction();
const request = async () => {
if (!quote || !address) {
throw new Error('Missing quote or address');
}
return buildStakeTransaction({ quote, userAddress: address });
};
return (
console.log('sent', boc)}
/>
);
}
```
## After the send [#after-the-send]
After the send completes, pass the response to `getTransactionStatus` to confirm settlement, then refetch `useStakedBalance` to see the new staked-token balance. The response carries either a `boc` or a `normalizedHash`; pass whichever is set.
## Tips [#tips]
* The user's stake is a derivative jetton (e.g. `tsTON`), not an opaque AppKit object. Refresh with `useStakedBalance` (or a jetton balance read) after sends.
* APY and instant-unstake liquidity from `useStakingProviderInfo` are provider-supplied display data, not guarantees of future yield or withdrawal timing.
* Unstake mechanics (instant, delayed, round-end) are provider-specific. Pass `unstakeMode` on the quote when the provider supports more than one.
## Related pages [#related-pages]
* [Providers](/applications/appkit/howto/providers#staking)
* [Read balances](/applications/appkit/howto/read-balances)
* [How to](/applications/appkit/howto/howto)
# Streaming (/applications/appkit/howto/streaming)
Streaming in AppKit is a per-network subscription layer that turns provider events into live balance, jetton, and transaction updates for the app.
## Live provider signals [#live-provider-signals]
Streaming complements point-in-time API reads. Instead of asking an API client for the latest state after every interaction, the app subscribes to changes for an address on a specific network.
The `StreamingManager` coordinates providers by `chainId`. A streaming provider implements one transport for one network, such as a Toncenter or TonAPI websocket stream. Registering another provider for the same network replaces the previous stream for that chain. Provider registration is covered on [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered).
## Subscription lifetime [#subscription-lifetime]
A subscription belongs to the consumer that created it. Balance, jetton, transaction, and combined watches all return an unsubscribe function, and that function is the app's handle for stopping updates when a component unmounts or a flow ends.
When the underlying transport drops and reconnects, the SDK does not replay events from the gap. Updates resume from the provider's current view of the chain, so any intermediate transitions on a watched address are lost.
## Before you begin [#before-you-begin]
You need a connected wallet (for the default-address `useWatch*` hooks) and a streaming provider registered on the AppKit instance. See [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered).
## Watch from React [#watch-from-react]
Mount watch hooks near the part of the tree that needs live data. The hook keeps related query caches fresh while it is mounted; passing `onChange` adds a side-effect callback on top of the cache refresh. Every React watch hook accepts an optional `{ onChange?, network? }`, and the `*ByAddress` variants additionally accept an `address`.
Mount as many watchers as you need. The SDK deduplicates subscribers by network, address, and type, so multiple hook instances watching the same data share one underlying socket subscription. There is no benefit to lifting watchers into a single root component just to share them — pull them into the component that actually needs the live value.
### Watch a balance [#watch-a-balance]
`useWatchBalance` refreshes the cache that `useBalance` reads. `useBalance` is a TanStack Query result (`{ data, isLoading, isError, refetch, ... }`); `data` is the formatted TON balance as a string when present.
```tsx
import { useBalance, useWatchBalance } from '@ton/appkit-react';
export function LiveBalance() {
useWatchBalance();
const balance = useBalance();
return {balance.data ?? '0'} TON ;
}
```
### Watch transactions [#watch-transactions]
`useWatchTransactions` reacts to transaction lifecycle changes. The update payload exposes `traceHash` and `status` (`'pending' | 'confirmed' | 'finalized' | 'invalidated'`). Plug in your own notification or state-update logic; the SDK does not pick a UI primitive for you.
```tsx
import { useWatchTransactions } from '@ton/appkit-react';
export function FinalizedLog() {
useWatchTransactions({
onChange: (update) => {
if (update.status === 'finalized' && update.traceHash) {
console.log('finalized', update.traceHash);
}
},
});
return null;
}
```
### Watch by address [#watch-by-address]
For receipt screens, admin tooling, or order-tracking widgets, subscribe to an address that may not be the connected wallet. The `*ByAddress` hooks take an `address` and keep the matching `useBalanceByAddress` / cache fresh while also delivering each update to `onChange`.
```tsx
import {
useBalanceByAddress,
useWatchBalanceByAddress,
useWatchTransactionsByAddress,
} from '@ton/appkit-react';
export function OrderTracker({ orderAddress }: { orderAddress: string }) {
useWatchBalanceByAddress({
address: orderAddress,
onChange: (update) => {
if (update.status === 'finalized') {
console.log('order balance', update.balance);
}
},
});
const balance = useBalanceByAddress({ address: orderAddress });
useWatchTransactionsByAddress({
address: orderAddress,
onChange: (update) => {
if (update.status === 'finalized') {
console.log('finalized txs', update.transactions.length);
}
},
});
return {balance.data ?? '0'} TON ;
}
```
### Watch jettons [#watch-jettons]
`useWatchJettons` pushes jetton balance changes for the connected wallet. Each update covers one jetton (`masterAddress`, `walletAddress`, `ownerAddress`, `rawBalance`) and may include `decimals` and a formatted `balance` when the jetton's decimals are known.
```tsx
import { useWatchJettons } from '@ton/appkit-react';
export function PortfolioWatcher() {
useWatchJettons({
onChange: (update) => {
if (update.status === 'finalized' && update.balance !== undefined) {
console.log(update.masterAddress, update.balance);
}
},
});
return null;
}
```
## From vanilla code [#from-vanilla-code]
A non-React consumer keeps the unsubscribe function returned by each `watch*` action and calls it when the screen or process no longer needs updates.
```ts
import { watchBalance } from '@ton/appkit';
const unsubscribe = watchBalance(appKit, {
onChange: (update) => {
console.log(update.address, update.balance);
},
});
unsubscribe();
```
The same shape applies to `watchBalanceByAddress`, `watchJettons`, `watchJettonsByAddress`, `watchTransactions`, and `watchTransactionsByAddress`. Each takes `{ network?, onChange }` (and `address` on the `*ByAddress` variants) and returns an unsubscribe function.
## Connection state [#connection-state]
Connection state describes transport health, not chain finality. A websocket can disconnect and reconnect while the underlying account state continues to change.
After reconnect, updates may resume from the provider's current view of the chain. A flow that needs certainty should refresh from the configured API client before it changes product state.
`appKit.streamingManager.onConnectionChange(network, callback)` registers a listener for the WebSocket connection state of one network. The callback receives `connected: boolean`; the method returns an unsubscribe function. Pair it with `useNetwork` so the listener follows the currently selected network.
```tsx
import { useEffect, useState } from 'react';
import { useAppKit, useNetwork } from '@ton/appkit-react';
export function StreamingHealth() {
const appKit = useAppKit();
const network = useNetwork();
const [connected, setConnected] = useState(true);
useEffect(() => {
if (!network) return;
return appKit.streamingManager.onConnectionChange(network, setConnected);
}, [appKit, network]);
return {connected ? 'live' : 'reconnecting'} ;
}
```
## Tips [#tips]
* Store every unsubscribe function and call it when the consumer goes away.
* Call `hasStreamingProvider` before subscribing on a network that may not have a provider registered, and degrade gracefully when it returns `false`.
* Treat streaming updates as best-effort UI refresh signals. Reconcile with a point-in-time read before changing product state that depends on correctness.
* `update.status` carries one of `'pending' | 'confirmed' | 'finalized' | 'invalidated'` on every streaming payload. Only `'finalized'` is irreversible; treat the others as intermediate.
## Related pages [#related-pages]
* [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered)
* [Networks](/applications/appkit/howto/networks)
* [Read balances](/applications/appkit/howto/read-balances)
# Swaps (/applications/appkit/howto/swaps)
Quote a swap, build the transaction, and send it through the connected wallet.
## How it works [#how-it-works]
The `SwapManager` routes each quote and build call to a single registered swap provider — by default the first one you registered, or the one you pass as `providerId`. `setDefaultProvider` on the manager overrides the default; an unknown `providerId` throws. A quote is the chosen provider's current offer for a route — input asset, output asset, amount, fees, and execution assumptions — and `useBuildSwapTransaction` turns an accepted quote into a `TransactionRequest`. AppKit does not price markets itself; the provider does.
The quote is provider-supplied data and can expire. Refresh it close to the moment the user confirms, and treat the displayed `toAmount` as an estimate, not a guarantee. The wallet still owns approval, signing, and rejection on the final send.
## Before you begin [#before-you-begin]
You need a connected wallet and at least one swap provider registered on the AppKit instance. Omniston and DeDust ship bundled — see [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered).
## Hooks [#hooks]
| Hook | Purpose |
| ------------------------- | ------------------------------------------ |
| `useSwapQuote` | Fetch a swap quote. |
| `useBuildSwapTransaction` | Build a `TransactionRequest` from a quote. |
`useSwapQuote` is a query hook (`{ data, isLoading, isError, refetch }`); `useBuildSwapTransaction` is a mutation hook (`{ mutate, mutateAsync, isPending, error }`). Pass the built `TransactionRequest` to ` ` from `@ton/appkit-react`, which exposes loading/error state.
## Quote a swap [#quote-a-swap]
`useSwapQuote` takes the asset pair and amount and returns the provider's current offer. Pass `network`, `slippageBps`, and an optional `providerId` to pin a specific provider.
```tsx
import { useNetwork, useSwapQuote } from '@ton/appkit-react';
const TON = { address: 'ton', decimals: 9, symbol: 'TON' };
const USDT = {
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
decimals: 6,
symbol: 'USDT',
};
export function SwapPreview({ amount }: { amount: string }) {
const network = useNetwork();
const { data: quote, isLoading, isError } = useSwapQuote({
amount,
from: USDT,
to: TON,
network,
slippageBps: 100,
});
if (isLoading) return Fetching quote… ;
if (isError || !quote) return Swap unavailable ;
return (
{quote.fromAmount} {USDT.symbol} → {quote.toAmount} {TON.symbol}
);
}
```
## Build and send the transaction [#build-and-send-the-transaction]
`useBuildSwapTransaction` is the mutation that turns an accepted quote into a `TransactionRequest`. Wrap it in a `request` callback and hand it to ` `; the component exposes loading/error state.
```tsx
import { Send, useAddress, useBuildSwapTransaction } from '@ton/appkit-react';
import type { SwapQuote } from '@ton/appkit';
export function SwapSendButton({ quote }: { quote: SwapQuote | undefined }) {
const address = useAddress();
const { mutateAsync: buildSwapTransaction } = useBuildSwapTransaction();
const request = async () => {
if (!quote || !address) {
throw new Error('Missing quote or address');
}
return buildSwapTransaction({ quote, userAddress: address });
};
return (
console.log('sent', boc)}
/>
);
}
```
## After the send [#after-the-send]
After the send completes, pass the response to `getTransactionStatus` to confirm settlement before updating balances, orders, or inventory. The response carries either a `boc` or a `normalizedHash`; pass whichever is set.
## Tips [#tips]
* Refresh a quote before building if the user paused on the confirmation screen — the route can move while the modal is open.
* Provider responses are external data; treat `toAmount` as an estimate, not a guarantee.
* `minReceived` is the slippage-protected lower bound on the output after `slippageBps` is applied. Compare against your product floor before letting the user sign.
* Slippage protection is provider-specific. `slippageBps` caps price drift; pass provider-specific fields through `providerOptions` when a provider needs more.
## Related pages [#related-pages]
* [Providers](/applications/appkit/howto/providers#swaps)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
* [How to](/applications/appkit/howto/howto)
# Use UI widgets (/applications/appkit/howto/use-ui-widgets)
`@ton/appkit-react` exports ready-to-use components for the most common AppKit flows. Drop them into your tree and connect callbacks. The default styles ship in `@ton/appkit-react/styles.css`.
## How it works [#how-it-works]
Widgets are React vertical flows over the same AppKit instance, selected wallet, network, and providers used by hooks and core actions. They are not a separate design system.
Use the default UI when the built-in flow fits. Use render props when the widget should keep AppKit state and behavior but the app owns layout. Use hooks directly when the product flow no longer matches one component.
## Before you begin [#before-you-begin]
You need the React providers mounted and the styles imported once at the entry file. See [Installation → Wrap the application](/applications/appkit/get-started/installation/react-app#wrap-the-application).
```tsx
import '@ton/appkit-react/styles.css';
```
## Component catalog [#component-catalog]
| Component | What it does |
| ------------------------- | --------------------------------------------------------------------------- |
| ` ` | Drop-in connect button. Opens the TON Connect modal and shows the address. |
| ` ` | Generic transaction submitter. Accepts a `request` factory. |
| ` ` | Toncoin transfer with `recipientAddress`, `amount`, `comment`. |
| ` ` | Jetton transfer. Takes a `jetton` descriptor plus the same transfer fields. |
| ` ` | Renders the lifecycle of a sent transaction. |
| ` ` | NFT card with image and metadata. |
| ` ` | Full swap UI: token select, amount, slippage, settings, submit. |
| ` ` | Full staking UI: stake/unstake tabs, amount, APY and exchange-rate readout. |
| ` ` | TON logo glyph as an inline SVG. |
| ` ` | Same glyph framed in a circle background. |
## Connect button [#connect-button]
```tsx
import { TonConnectButton } from '@ton/appkit-react';
;
```
See [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet) for the custom-selector alternative.
## Send Toncoin [#send-toncoin]
```tsx
import { SendTonButton } from '@ton/appkit-react';
;
```
The default rendering shows `Send {amount} TON`. Pass a `children` render-prop with `{ isLoading, onSubmit, disabled, text }` if you want to drive a custom button — the component still owns the request, the call to the wallet, and the loading/error state.
## Send a jetton [#send-a-jetton]
` ` mirrors ` ` but takes a `jetton` descriptor with the master address, ticker, and decimals so it knows which jetton wallet to call.
```tsx
import { SendJettonButton } from '@ton/appkit-react';
;
```
`jetton.address`, `jetton.symbol`, and `jetton.decimals` are all required. The default rendering shows `Send {amount} {jetton.symbol}`; pass a `children` render-prop if you want to drive a custom button.
## Send a prepared transaction [#send-a-prepared-transaction]
` ` accepts a `request` function that returns a `TransactionRequest`. Use it for transactions you build yourself (offline builders, swap quotes, NFT transfers). Set `text` to label the default button.
```tsx
import { Send, useAppKit } from '@ton/appkit-react';
import { createTransferNftTransaction } from '@ton/appkit';
const appKit = useAppKit();
const request = async () =>
createTransferNftTransaction(appKit, {
nftAddress: 'EQ...',
recipientAddress: 'EQ...',
});
console.log('sent', boc)}
/>;
```
Pass a `children` render-prop with `{ isLoading, onSubmit, disabled, text }` instead of (or alongside) `text` if you want full control over the button markup.
## Render an NFT [#render-an-nft]
```tsx
import { NftItem, useNfts } from '@ton/appkit-react';
const { data } = useNfts();
const nfts = data?.nfts ?? [];
{nfts.map((nft) => (
/* open detail */ undefined}
/>
))}
;
```
## Swap widget [#swap-widget]
` ` is the complete swap UI: pay/receive fields, token selector, flip button, slippage settings, and the submit button. Pass the list of tokens the user can pick between, optionally seed the default pair, and the widget handles quote fetching, building, and the wallet call internally.
```tsx
import { SwapWidget } from '@ton/appkit-react';
import { Network } from '@ton/appkit';
import type { AppkitUIToken } from '@ton/appkit-react';
const TOKENS: AppkitUIToken[] = [
{
symbol: 'TON',
name: 'Toncoin',
decimals: 9,
address: 'ton',
network: Network.mainnet(),
},
{
symbol: 'USDT',
name: 'Tether USD',
decimals: 6,
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
network: Network.mainnet(),
},
];
;
```
The required prop is `tokens`. `defaultFromSymbol`, `defaultToSymbol`, `defaultSlippage` (basis points, default `100` = 1%), `fiatSymbol` (default `'$'`), and `network` (defaults to the connected wallet's network) are all optional. Pass a `children` render-prop to replace the default UI while keeping the widget's internal state — the function receives `{ fromToken, toToken, fromAmount, toAmount, isQuoteLoading, canSubmit, setFromAmount, onFlip, ... }`.
## Staking widget [#staking-widget]
` ` is the complete staking UI: stake/unstake tabs, amount input, balance readout, current APY, exchange rate, and provider. The widget reads the registered staking provider (Tonstakers ships bundled — see [Providers → How they are registered](/applications/appkit/howto/providers#how-they-are-registered)) and handles quote, build, and the wallet call internally.
```tsx
import { StakingWidget } from '@ton/appkit-react';
import { Network } from '@ton/appkit';
;
// Or pin a specific network:
;
```
`network` is the only prop; pass it to override the connected wallet's network. Pass a `children` render-prop for a custom UI; the function receives `{ amount, quote, isQuoteLoading, canSubmit, setAmount, direction, setDirection, unstakeMode, setUnstakeMode, ... }` to drive your own controls against the widget's internal state.
## Show transaction progress [#show-transaction-progress]
After a send call resolves with a `boc`, hand it to ` ` to render the wallet → chain lifecycle UI.
```tsx
import { TransactionProgress } from '@ton/appkit-react';
;
```
The component renders its own default UI. For full layout control, pass a `children` render prop. The child receives `{ status, totalMessages, pendingMessages, onchainMessages, isFetching, error, boc, texts }`. For lighter customization, pass `classNames={{ container, icon, message }}` to restyle internal parts without owning the markup.
## TON glyphs [#ton-glyphs]
` ` is an inline SVG of the TON diamond; it follows the surrounding `color` (so it tints with `currentColor`). ` ` is the same glyph framed in a circular background. Both accept an optional `size` (defaults to `16`).
```tsx
import { TonIcon, TonIconCircle } from '@ton/appkit-react';
```
## Common props [#common-props]
The send components share a callback shape:
| Prop | Type | Notes |
| ----------- | -------------------------------------------------- | -------------------------------------------------------------- |
| `onSuccess` | `(response: SendTransactionResponse) => void` | Response carries `boc`, `normalizedBoc`, and `normalizedHash`. |
| `onError` | `(error: Error) => void` | Plain `Error`. Pair with `getErrorMessage` for UX-safe text. |
| `disabled` | `boolean` | Disable the underlying button externally. |
| children | `(state: { isLoading, onSubmit, disabled, text })` | Render-prop API for full styling control. |
| `text` | `ReactNode` | Label rendered when no children render-prop is provided. |
## Code example [#code-example]
See a [working example](https://github.com/ton-connect/kit/tree/main/apps/appkit-minter) that integrates ` ` and ` ` — [try it live](https://appkit-minter.vercel.app/).
## Related pages [#related-pages]
* [AppKit reference](/applications/appkit/reference/reference)
* [Connect to a wallet](/applications/appkit/howto/connect-to-a-wallet)
* [Send Toncoin](/applications/appkit/howto/send-toncoin)
* [NFTs](/applications/appkit/howto/nfts)
# AppKit React (/applications/appkit/reference/appkit-react)
## Hook [#hook]
### Balances [#balances]
#### useBalance [#usebalance]
React hook reading the Toncoin balance of the currently selected wallet through TanStack Query — auto-resolves the wallet address (use [`useBalanceByAddress`](#usebalancebyaddress) for an arbitrary address).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseBalanceParameters`](#usebalanceparameters) | TanStack Query overrides (`select`, `enabled`, `staleTime`, …) and an optional network override. |
| `parameters.address` | UserFriendlyAddress \| Address | Wallet address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseBalanceReturnType \ — TanStack Query result for the balance read.
**Example**
```tsx
const { data: balance, isLoading, error } = useBalance();
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return Balance: {balance}
;
```
#### useBalanceByAddress [#usebalancebyaddress]
React hook reading the Toncoin balance of an arbitrary address through TanStack Query — useful for addresses that aren't tied to the selected wallet (use [`useBalance`](#usebalance) for the selected wallet).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseBalanceByAddressParameters`](#usebalancebyaddressparameters) | Target address, optional network override, and TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress \| Address | Wallet address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseBalanceByAddressReturnType \ — TanStack Query result for the balance read.
**Example**
```tsx
const {
data: balance,
isLoading,
error,
} = useBalanceByAddress({
address: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return Balance: {balance}
;
```
#### useWatchBalance [#usewatchbalance]
Subscribe to Toncoin balance updates for the currently selected wallet. Updates flow into the TanStack Query cache so [`useBalance`](#usebalance) picks up the new data automatically (use [`useWatchBalanceByAddress`](#usewatchbalancebyaddress) for a fixed address). Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseWatchBalanceParameters`](#usewatchbalanceparameters) | Update callback and optional network override. |
| `parameters.onChange` | (update: BalanceUpdate ) => void | Callback fired on every balance update from the streaming provider. |
| `parameters.network` | Network | Network to watch on. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
Returns: `void`.
**Example**
```tsx
const { data: balance } = useBalance();
useWatchBalance();
return Current balance: {balance}
;
```
#### useWatchBalanceByAddress [#usewatchbalancebyaddress]
Subscribe to Toncoin balance updates for an arbitrary address — updates flow into the TanStack Query cache so [`useBalanceByAddress`](#usebalancebyaddress) picks up the new data automatically. Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters`\* | [`UseWatchBalanceByAddressParameters`](#usewatchbalancebyaddressparameters) | Address, update callback and optional network override. |
| `parameters.address` | UserFriendlyAddress \| Address | Wallet address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to watch on. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.onChange` | (update: BalanceUpdate ) => void | Callback fired on every balance update from the streaming provider. |
Returns: `void`.
**Example**
```tsx
const address = 'UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ';
const network = Network.mainnet();
const { data: balance } = useBalanceByAddress({ address, network });
useWatchBalanceByAddress({ address, network });
return Current balance: {balance}
;
```
### Connectors [#connectors]
#### useConnectorById [#useconnectorbyid]
Look up a connector by its id and stay subscribed to its registration lifecycle — updates when a connector with that id is registered (via AppKit's constructor or [`addConnector`](/applications/appkit/reference/appkit#addconnector)) or unregistered. Returns the matching [`Connector`](/applications/appkit/reference/appkit#connector), or `undefined` when none with that id is currently registered. Use [`useConnectedWallets`](#useconnectedwallets) if you want to react to wallet connect/disconnect events instead.
| Parameter | Type | Description |
| --------- | -------- | ------------------------------- |
| `id`\* | `string` | ID of the connector to look up. |
Returns: Connector | undefined — The matching [`Connector`](/applications/appkit/reference/appkit#connector), or `undefined` if none with that id is registered.
#### useConnectors [#useconnectors]
Read the list of connectors registered on this AppKit instance. Updates when a connector is registered or unregistered (use [`useConnectedWallets`](#useconnectedwallets) to react to wallet connect/disconnect events).
Returns: UseConnectorsReturnType — Read-only array of registered [`Connector`](/applications/appkit/reference/appkit#connector)s.
### Crypto Onramp [#crypto-onramp]
#### useCreateCryptoOnrampDeposit [#usecreatecryptoonrampdeposit]
Create a crypto-onramp deposit from a quote previously obtained via [`useCryptoOnrampQuote`](#usecryptoonrampquote). Call `mutate(options)` where `options` matches [`CreateCryptoOnrampDepositOptions`](/applications/appkit/reference/appkit#createcryptoonrampdepositoptions) (quote, refund address, optional provider override). On success, `data` is the [`CryptoOnrampDeposit`](/applications/appkit/reference/appkit#cryptoonrampdeposit) carrying the address and amount the user must send on the source chain to complete the onramp. Pair with [`useCryptoOnrampStatus`](#usecryptoonrampstatus) to poll the deposit until it settles.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseCreateCryptoOnrampDepositParameters`](#usecreatecryptoonrampdepositparameters) | TanStack Query mutation overrides (`parameters.mutation`). |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseCreateCryptoOnrampDepositReturnType \ — Mutation result for the deposit call.
#### useCryptoOnrampContext [#usecryptoonrampcontext]
Reads the `CryptoOnrampContext` populated by [`CryptoOnrampWidgetProvider`](#cryptoonrampwidgetprovider) — returns the widget's selection state, quote/deposit data and actions ([`CryptoOnrampContextType`](#cryptoonrampcontexttype)).
Returns: CryptoOnrampContextType .
#### useCryptoOnrampProvider [#usecryptoonrampprovider]
Read a registered crypto-onramp provider by id, or the default provider when no id is given — subscribes to [`watchCryptoOnrampProviders`](/applications/appkit/reference/appkit#watchcryptoonrampproviders) and re-reads via [`getCryptoOnrampProvider`](/applications/appkit/reference/appkit#getcryptoonrampprovider) so the result stays in sync. The read swallows the throw from [`getCryptoOnrampProvider`](/applications/appkit/reference/appkit#getcryptoonrampprovider) (which throws when no provider matches — or when no id is passed and no default has been registered) and yields `undefined` instead.
| Parameter | Type | Description |
| --------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `parameters` | [`UseCryptoOnrampProviderParameters`](#usecryptoonrampproviderparameters) | Optional provider id. |
| `parameters.id` | `string` | Provider ID to look up. When omitted, returns the registered default provider. |
Returns: UseCryptoOnrampProviderReturnType — The matching provider, or `undefined` when none is registered.
#### useCryptoOnrampProviders [#usecryptoonrampproviders]
List every crypto-onramp provider registered on the AppKit instance (both those passed via [`AppKitConfig`](/applications/appkit/reference/appkit#appkitconfig)'s `providers` and those added later through [`registerProvider`](/applications/appkit/reference/appkit#registerprovider)). Subscribes to [`watchCryptoOnrampProviders`](/applications/appkit/reference/appkit#watchcryptoonrampproviders) and re-reads via [`getCryptoOnrampProviders`](/applications/appkit/reference/appkit#getcryptoonrampproviders) so the array stays in sync.
Returns: UseCryptoOnrampProvidersReturnType — Array of registered crypto-onramp providers.
#### useCryptoOnrampQuote [#usecryptoonrampquote]
Quote a crypto-to-TON onramp — given a source asset/chain and the target TON asset, returns the rate, expected amount and the provider-specific metadata required to feed [`useCreateCryptoOnrampDeposit`](#usecreatecryptoonrampdeposit). `data` is the [`CryptoOnrampQuote`](/applications/appkit/reference/appkit#cryptoonrampquote) payload.
| Parameter | Type | Description |
| ---------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseCryptoOnrampQuoteParameters`](#usecryptoonrampquoteparameters) | Quote inputs and TanStack Query overrides. |
| `parameters.amount` | `string` | Amount to onramp (either source or target crypto, depending on isSourceAmount) |
| `parameters.sourceCurrencyAddress` | `string` | Source crypto currency address (contract address or 0x0... for native) |
| `parameters.sourceChain` | `string` | Source chain identifier in CAIP-2 format (e.g. 'eip155:1' for Ethereum mainnet, 'eip155:42161' for Arbitrum One). Providers map this to their own chain identifiers internally. |
| `parameters.targetCurrencyAddress` | `string` | Target crypto currency address on TON (contract address or 0x0... for native) |
| `parameters.recipientAddress` | `string` | TON address that will receive the target crypto. |
| `parameters.refundAddress` | `string` | Refund address for the source crypto. |
| `parameters.isSourceAmount` | `boolean` | If true, `amount` is the source amount to spend. If false, `amount` is the target amount to receive. Defaults to true when omitted. |
| `parameters.providerOptions` | `TProviderOptions = unknown` | Provider-specific options. |
| `parameters.providerId` | `string` | Provider to quote against. Defaults to the registered default provider. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseCryptoOnrampQuoteReturnType \ — TanStack Query result for the quote read.
#### useCryptoOnrampStatus [#usecryptoonrampstatus]
Read the current status of a crypto-onramp deposit previously created via [`useCreateCryptoOnrampDeposit`](#usecreatecryptoonrampdeposit). Typically polled via `refetchInterval` until `data` reaches a terminal state — `'success'` (delivered to the recipient) or `'failed'` (provider could not complete the deposit).
| Parameter | Type | Description |
| ----------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseCryptoOnrampStatusParameters`](#usecryptoonrampstatusparameters) | Deposit id, originating provider id and TanStack Query overrides. |
| `parameters.depositId` | `string` | Deposit id. |
| `parameters.providerId` | `string` | Identifier of the provider that issued this deposit. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseCryptoOnrampStatusReturnType \ — TanStack Query result for the status read.
### Jettons [#jettons]
#### useJettonBalanceByAddress [#usejettonbalancebyaddress]
React hook reading a jetton balance for a given owner through TanStack Query — derives the owner's jetton-wallet address from the master and formats the balance using the supplied decimals.
| Parameter | Type | Description |
| --------------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseJettonBalanceByAddressParameters`](#usejettonbalancebyaddressparameters) | Jetton master, owner address, decimals, optional network override and TanStack Query overrides. |
| `parameters.jettonAddress` | UserFriendlyAddress | Jetton master contract address (the token, not the user's wallet for it). |
| `parameters.ownerAddress` | UserFriendlyAddress | Owner of the jetton wallet — typically the connected user's address. |
| `parameters.jettonDecimals` | `number` | Decimals declared by the jetton master. Used to format the raw balance into a human-readable string. |
| `parameters.network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseJettonBalanceByAddressReturnType \ — TanStack Query result for the jetton balance read.
**Example**
```tsx
const {
data: balance,
isLoading,
error,
} = useJettonBalanceByAddress({
ownerAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
jettonAddress: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiXme1Xc56Iwobkzgnjj',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return Jetton Balance: {balance}
;
```
#### useJettonInfo [#usejettoninfo]
React hook reading jetton-master metadata (name, symbol, decimals, image, description) through TanStack Query.
| Parameter | Type | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseJettonInfoParameters`](#usejettoninfoparameters) | Jetton master address, optional network override and TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress | Jetton master contract address whose metadata is being fetched. |
| `parameters.network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseJettonInfoReturnType \ — TanStack Query result for the jetton info read.
**Example**
```tsx
const {
data: info,
isLoading,
error,
} = useJettonInfo({
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiXme1Xc56Iwobkzgnjj',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
Jetton Info
Name: {info?.name}
Symbol: {info?.symbol}
Decimals: {info?.decimals}
);
```
#### useJettonWalletAddress [#usejettonwalletaddress]
React hook deriving the owner's jetton-wallet address — the per-owner contract that actually holds the jetton balance for a given master — through TanStack Query.
| Parameter | Type | Description |
| -------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseJettonWalletAddressParameters`](#usejettonwalletaddressparameters) | Jetton master, owner address, optional network override and TanStack Query overrides. |
| `parameters.jettonAddress` | UserFriendlyAddress | Jetton master contract address. |
| `parameters.ownerAddress` | UserFriendlyAddress | Owner whose jetton wallet should be derived. |
| `parameters.network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: `UseQueryReturnType` — TanStack Query result for the jetton-wallet address read.
**Example**
```tsx
const {
data: walletAddress,
isLoading,
error,
} = useJettonWalletAddress({
ownerAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
jettonAddress: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiXme1Xc56Iwobkzgnjj',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return Jetton Wallet Address: {walletAddress}
;
```
#### useJettons [#usejettons]
React hook listing jettons held by the currently selected wallet through TanStack Query — auto-resolves the wallet address (use [`useJettonsByAddress`](#usejettonsbyaddress) for an arbitrary address).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseJettonsParameters`](#usejettonsparameters) | TanStack Query overrides (`select`, `enabled`, `staleTime`, …), pagination and an optional network override. |
| `parameters.address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read the jettons from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.limit` | `number` | Maximum number of jettons to return. |
| `parameters.offset` | `number` | Number of jettons to skip before returning results — used for pagination. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseJettonsReturnType \ — TanStack Query result for the jettons list.
**Example**
```tsx
const { data: jettons, isLoading, error } = useJettons();
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
Jettons
{jettons?.jettons.map((jetton) => (
{jetton.info.name}: {jetton.balance}
))}
);
```
#### useJettonsByAddress [#usejettonsbyaddress]
React hook listing jettons held by an arbitrary address through TanStack Query — useful for wallets that aren't selected in AppKit (use [`useJettons`](#usejettons) for the selected wallet).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseJettonsByAddressParameters`](#usejettonsbyaddressparameters) | Owner address, optional network override, pagination and TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read the jettons from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.limit` | `number` | Maximum number of jettons to return. |
| `parameters.offset` | `number` | Number of jettons to skip before returning results — used for pagination. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseJettonsByAddressReturnType \ — TanStack Query result for the jettons list.
**Example**
```tsx
const {
data: jettons,
isLoading,
error,
} = useJettonsByAddress({
address: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
Jettons
{jettons?.jettons.map((jetton) => (
{jetton.info.name}: {jetton.balance}
))}
);
```
#### useTransferJetton [#usetransferjetton]
Transfer a jetton from the selected wallet in one step — derives the owner's jetton-wallet from the master address, builds the transfer message, signs it through the wallet and broadcasts it. Call `mutate` with the `jettonAddress` (master), the `recipientAddress`, an `amount` (in jetton units as a human-readable decimal — converted into raw smallest units using `jettonDecimals`), the `jettonDecimals` itself and an optional `comment`. On success, `data` carries the BoC and normalized hash of the broadcast transaction. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseTransferJettonParameters`](#usetransferjettonparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseTransferJettonReturnType \ — Mutation result for the jetton transfer call.
**Example**
```tsx
const { mutate: transfer, isPending, error } = useTransferJetton();
const handleTransfer = () => {
transfer({
recipientAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
amount: '100', // 100 USDT
jettonAddress: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
jettonDecimals: 6,
});
};
return (
{isPending ? 'Transferring...' : 'Transfer Jetton'}
{error &&
Error: {error.message}
}
);
```
#### useWatchJettons [#usewatchjettons]
Subscribe to jetton-balance updates for the currently selected wallet. Updates flow into the TanStack Query cache so [`useJettons`](#usejettons) picks up the new data automatically (use [`useWatchJettonsByAddress`](#usewatchjettonsbyaddress) for a fixed address). Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `parameters` | [`UseWatchJettonsParameters`](#usewatchjettonsparameters) | Update callback and optional network override. |
| `parameters.onChange` | (update: JettonUpdate ) => void | Callback fired on every jetton-balance update from the streaming provider. |
| `parameters.network` | Network | Network to watch on. Defaults to the selected wallet's network. |
Returns: `void`.
**Example**
```tsx
const { data: jettons } = useJettons();
useWatchJettons();
return (
Your Jettons:
{jettons?.jettons.map((j) => (
{j.info.name}: {j.balance}
))}
);
```
#### useWatchJettonsByAddress [#usewatchjettonsbyaddress]
Subscribe to jetton-balance updates for an arbitrary owner address. Updates flow into the TanStack Query cache so [`useJettonsByAddress`](#usejettonsbyaddress) and [`useJettonBalanceByAddress`](#usejettonbalancebyaddress) pick up the new data automatically. Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters`\* | [`UseWatchJettonsByAddressParameters`](#usewatchjettonsbyaddressparameters) | Owner address, update callback and optional network override. |
| `parameters.address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.onChange` | (update: JettonUpdate ) => void | Callback fired on every jetton-balance update from the streaming provider. |
| `parameters.network` | Network | Network to watch on. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
Returns: `void`.
**Example**
```tsx
const address = 'UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ';
const { data: jettons } = useJettonsByAddress({ address });
useWatchJettonsByAddress({ address });
return (
Jettons for {address}:
{jettons?.jettons.map((j) => (
{j.info.name}: {j.balance}
))}
);
```
### NFTs [#nfts]
#### useNft [#usenft]
React hook reading metadata and ownership for a single NFT through TanStack Query, keyed by its contract address. `data` is `null` when the indexer has no record.
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `parameters` | [`UseNftParameters`](#usenftparameters) | NFT address, optional network override, and TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress \| Address | NFT contract address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseNftReturnType \ — TanStack Query result for the NFT read.
**Example**
```tsx
const {
data: nft,
isLoading,
error,
} = useNft({
address: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
NFT Details
Name: {nft?.info?.name}
Collection: {nft?.collection?.name}
Owner: {nft?.ownerAddress}
);
```
#### useNfts [#usenfts]
React hook that reads NFTs held by the currently selected wallet through TanStack Query — auto-resolves the wallet address (use [`useNftsByAddress`](#usenftsbyaddress) for an arbitrary address).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseNFTsParameters`](#usenftsparameters) | Optional pagination, network override, and TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read NFTs from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.limit` | `number` | Maximum number of NFTs to return. |
| `parameters.offset` | `number` | Number of NFTs to skip before returning results — used for pagination. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseNFTsReturnType \ — TanStack Query result for the NFTs read.
**Example**
```tsx
const {
data: nfts,
isLoading,
error,
} = useNfts({
limit: 10,
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
My NFTs
{nfts?.nfts.map((nft) => (
{nft.info?.name} ({nft.collection?.name})
))}
);
```
#### useNftsByAddress [#usenftsbyaddress]
React hook that reads NFTs held by an arbitrary address through TanStack Query — useful for wallets that aren't selected in AppKit (use [`useNfts`](#usenfts) for the selected wallet).
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseNFTsByAddressParameters`](#usenftsbyaddressparameters) | Owner address, optional pagination and network override, plus TanStack Query overrides. |
| `parameters.address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.network` | Network | Network to read NFTs from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.limit` | `number` | Maximum number of NFTs to return. |
| `parameters.offset` | `number` | Number of NFTs to skip before returning results — used for pagination. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseNFTsByAddressReturnType \ — TanStack Query result for the NFTs read.
**Example**
```tsx
const {
data: nfts,
isLoading,
error,
} = useNftsByAddress({
address: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
limit: 10,
});
if (isLoading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
NFTs
{nfts?.nfts.map((nft) => (
{nft.info?.name} ({nft.collection?.name})
))}
);
```
#### useTransferNft [#usetransfernft]
Transfer an NFT from the selected wallet in one step — builds the ownership-transfer message and broadcasts it. Call `mutate` with an `nftAddress`, the `recipientAddress`, an optional `amount` (the TON attached for gas — defaults to AppKit's NFT gas-fee constant when omitted) and an optional `comment`. On success, `data` carries the BoC and normalized hash of the broadcast transaction. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseTransferNftParameters`](#usetransfernftparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseTransferNftReturnType \ — Mutation result for the transfer call.
**Example**
```tsx
const { mutate: transfer, isPending, error } = useTransferNft();
const handleTransfer = () => {
transfer({
nftAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
recipientAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
comment: 'Gift for you',
});
};
return (
{isPending ? 'Transferring...' : 'Transfer NFT'}
{error &&
Error: {error.message}
}
);
```
### Networks [#networks]
#### useBlockNumber [#useblocknumber]
React hook reading the latest masterchain seqno through TanStack Query — useful for freshness checks and pagination cursors.
| Parameter | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseBlockNumberParameters`](#useblocknumberparameters) | TanStack Query overrides and optional network. |
| `parameters.network` | Network | Network to query. Defaults to mainnet when omitted. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseBlockNumberReturnType \ — TanStack Query result for the seqno read.
#### useDefaultNetwork [#usedefaultnetwork]
Read and write AppKit's default network — the network connectors use for new wallet connections. Returns a `useState`-style tuple. The read side updates when the default changes through any source (this hook, [`setDefaultNetwork`](/applications/appkit/reference/appkit#setdefaultnetwork), manager events).
Returns: UseDefaultNetworkReturnType — Tuple `[network, setNetwork]`.
#### useNetwork [#usenetwork]
Read the [`Network`](/applications/appkit/reference/appkit#network) the selected wallet is connected to. Updates when the wallet's network changes (e.g. user switches mainnet/testnet inside the wallet).
Returns: UseNetworkReturnType — Selected wallet's network, or `undefined` when no wallet is selected.
#### useNetworks [#usenetworks]
Read the list of networks configured on AppKit. Updates when [`AppKitNetworkManager`](/applications/appkit/reference/appkit#appkitnetworkmanager) adds, replaces or drops a network.
Returns: UseNetworksReturnType — Array of configured [`Network`](/applications/appkit/reference/appkit#network)s.
### Settings [#settings]
#### useAppKit [#useappkit]
Read the [`AppKit`](/applications/appkit/reference/appkit#appkit) instance hosted by [`AppKitProvider`](#appkitprovider). Throws when the hook is rendered outside the provider tree.
Returns: AppKit — The AppKit instance shared with descendant hooks/components.
#### useAppKitTheme [#useappkittheme]
State hook that mirrors the active appkit-react theme to `document.body[data-ta-theme]` — returns a `[theme, setTheme]` tuple just like `useState`.
Returns: `readonly [string, Dispatch>]` — Tuple `[theme, setTheme]` for reading and switching the active theme.
#### useI18n [#usei18n]
Read the i18n context published by [`I18nProvider`](#i18nprovider) (or the wrapping [`AppKitProvider`](#appkitprovider)). Returns the active locale, translation function and helpers to switch locales or merge dictionaries. Throws when rendered outside the provider tree.
Returns: I18nContextType — The i18n context ([`I18nContextType`](#i18ncontexttype)) with `activeLocale`, `t`, `locale` and `addDict`.
### Signing [#signing]
#### useSignBinary [#usesignbinary]
Ask the selected wallet to sign an opaque binary blob (Base64-encoded), without on-chain structure. Call `mutate` from an event handler with the `bytes` to sign and an optional `network` override. On success, `data` carries the signature plus the signer address, timestamp and dApp domain the wallet bound to the signature. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseSignBinaryParameters`](#usesignbinaryparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseSignBinaryReturnType \ — Mutation result for the signing call.
#### useSignCell [#usesigncell]
Ask the selected wallet to sign a TON cell — typically so the signature can later be verified on-chain by a contract. Call `mutate` from an event handler with the `cell` content, a TL-B-style `schema` (used by the wallet to render the payload to the user before signing) and an optional `network` override. On success, `data` carries the signature plus the signer address, timestamp and dApp domain. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseSignCellParameters`](#usesigncellparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseSignCellReturnType \ — Mutation result for the signing call.
#### useSignText [#usesigntext]
Ask the selected wallet to sign a plain-text message — useful for off-chain login proofs and signed challenges. Call `mutate` from an event handler with the `text` to sign and an optional `network` override. On success, `data` carries the signature plus the canonicalized signer address, timestamp and dApp domain the wallet bound to the signature. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseSignTextParameters`](#usesigntextparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseSignTextReturnType \ — Mutation result for the signing call.
### Staking [#staking]
#### useBuildStakeTransaction [#usebuildstaketransaction]
Build a stake/unstake [`TransactionRequest`](/applications/appkit/reference/appkit#transactionrequest) from a [`StakingQuote`](/applications/appkit/reference/appkit#stakingquote) (obtained via [`useStakingQuote`](#usestakingquote)) without sending it — lets the UI inspect, batch, or pass the request to [`useSendTransaction`](#usesendtransaction) separately. Call `mutate(params)` where `params` matches [`BuildStakeTransactionOptions`](/applications/appkit/reference/appkit#buildstaketransactionoptions) (quote + user address, optional provider override). The resulting `TransactionRequest` is in `data` once the mutation resolves.
Returns: UseBuildStakeTransactionReturnType \ — Mutation result for the build call.
#### useStakedBalance [#usestakedbalance]
React hook reading a user's staked balance from a staking provider through TanStack Query — total staked plus, depending on the provider, any instant-unstake balance available right now. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Parameter | Type | Description |
| ------------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseStakedBalanceParameters`](#usestakedbalanceparameters) | Owner address, optional `providerId`, optional network override, and TanStack Query overrides. |
| `parameters.userAddress` | UserFriendlyAddress | Owner whose staked balance should be read. |
| `parameters.network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.providerId` | `string` | Provider to query. Defaults to the registered default staking provider. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseStakedBalanceReturnType \ — TanStack Query result for the staked-balance read.
#### useStakingContext [#usestakingcontext]
Reads the [`StakingContextType`](#stakingcontexttype) from the nearest [`StakingWidgetProvider`](#stakingwidgetprovider) (or [`StakingWidget`](#stakingwidget)). Outside a provider, returns the default context (empty inputs, no-op actions) so a custom UI can still mount without crashing.
Returns: StakingContextType .
#### useStakingProvider [#usestakingprovider]
React hook returning a registered staking provider. Subscribes to provider-registry changes via [`watchStakingProviders`](/applications/appkit/reference/appkit#watchstakingproviders) and looks up by `id`, or returns the registered default when no id is given. Returns `undefined` when no provider matches and no default has been registered (where the underlying [`getStakingProvider`](/applications/appkit/reference/appkit#getstakingprovider) action would throw).
| Parameter | Type | Description |
| --------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `parameters` | [`UseStakingProviderParameters`](#usestakingproviderparameters) | Optional provider id. |
| `parameters.id` | `string` | Provider ID to look up. When omitted, returns the registered default staking provider. |
Returns: UseStakingProviderReturnType — Matching staking provider instance, or `undefined` when none resolves.
#### useStakingProviderInfo [#usestakingproviderinfo]
React hook reading live staking-pool info for a provider through TanStack Query — APY, instant-unstake liquidity and (for liquid staking) the current exchange rate. Use [`useStakingProviderMetadata`](#usestakingprovidermetadata) for static metadata (name, stake/receive tokens, supported unstake modes). Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Parameter | Type | Description |
| ----------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseStakingProviderInfoParameters`](#usestakingproviderinfoparameters) | Optional `providerId`, network override, and TanStack Query overrides. |
| `parameters.network` | Network | Network whose staking pool should be inspected. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.providerId` | `string` | Provider to query. Defaults to the registered default staking provider. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseStakingProviderInfoReturnType \ — TanStack Query result for the live provider info.
#### useStakingProviderMetadata [#usestakingprovidermetadata]
Read static metadata for a staking provider — display name, stake/receive tokens, supported unstake modes and contract address. Returns `undefined` when no provider matches and no default is registered. Use [`useStakingProviderInfo`](#usestakingproviderinfo) for live values (APY, instant-unstake liquidity, exchange rate). Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Parameter | Type | Description |
| ----------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseStakingProviderMetadataParameters`](#usestakingprovidermetadataparameters) | Optional `providerId` and network override. |
| `parameters.network` | Network | Network whose provider metadata should be read. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `parameters.providerId` | `string` | Provider to query. Defaults to the registered default staking provider. |
Returns: StakingProviderMetadata | undefined — Static [`StakingProviderMetadata`](/applications/appkit/reference/appkit#stakingprovidermetadata), or `undefined` when the provider can't be resolved.
#### useStakingProviders [#usestakingproviders]
React hook returning every staking provider registered on the AppKit instance (both those passed via config and those added later). Subscribes to provider-registry changes via [`watchStakingProviders`](/applications/appkit/reference/appkit#watchstakingproviders).
Returns: UseStakingProvidersReturnType — Array of registered staking providers.
#### useStakingQuote [#usestakingquote]
Quote a stake or unstake — given an amount, direction (`'stake'` / `'unstake'`) and the target asset, returns the rate, expected output and the provider-specific metadata required to feed [`useBuildStakeTransaction`](#usebuildstaketransaction). `data` is the [`StakingQuote`](/applications/appkit/reference/appkit#stakingquote) payload. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Parameter | Type | Description |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `parameters` | [`UseStakingQuoteParameters`](#usestakingquoteparameters) | Quote parameters, optional `providerId`, optional network override, and TanStack Query overrides. |
| `parameters.direction` | StakingQuoteDirection | Direction of the quote (stake or unstake) |
| `parameters.amount` | `string` | Amount of tokens to stake or unstake. |
| `parameters.userAddress` | UserFriendlyAddress | Address of the user. |
| `parameters.network` | Network | Network on which the staking will be executed. |
| `parameters.unstakeMode` | UnstakeModes | Unstake-timing mode the quote should target — see [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode) for the supported flavours (`'INSTANT'`, `'WHEN_AVAILABLE'`, `'ROUND_END'`). Only meaningful when `direction === 'unstake'` and the provider lists the mode in `supportedUnstakeModes`. |
| `parameters.isReversed` | `boolean` | If true, for unstake requests the amount is specified in the staking coin (e.g. TON) instead of the Liquid Staking Token (e.g. tsTON). |
| `parameters.providerOptions` | `TProviderOptions = unknown` | Provider-specific options. |
| `parameters.providerId` | `string` | Provider to quote against. Defaults to the registered default staking provider. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseStakingQuoteReturnType \ — TanStack Query result for the quote read.
### Swap [#swap]
#### useBuildSwapTransaction [#usebuildswaptransaction]
Build a swap [`TransactionRequest`](/applications/appkit/reference/appkit#transactionrequest) from a [`SwapQuote`](/applications/appkit/reference/appkit#swapquote) (obtained via [`useSwapQuote`](#useswapquote)) without sending it — lets the UI inspect, batch, or pass the request to [`useSendTransaction`](#usesendtransaction) separately. Call `mutate(params)` where `params` matches [`BuildSwapTransactionOptions`](/applications/appkit/reference/appkit#buildswaptransactionoptions) (quote, user address, optional slippage/deadline overrides). The resulting `TransactionRequest` is in `data` once the mutation resolves.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseBuildSwapTransactionParameters`](#usebuildswaptransactionparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseBuildSwapTransactionReturnType \ — Mutation result for the build call.
#### useSwapContext [#useswapcontext]
Reads the [`SwapContextType`](#swapcontexttype) populated by the nearest [`SwapWidgetProvider`](#swapwidgetprovider) (or the [`SwapWidget`](#swapwidget) that mounts one). Outside a provider it returns the no-op default value.
Returns: SwapContextType .
#### useSwapProvider [#useswapprovider]
Read and switch the default swap provider — subscribes to [`watchSwapProviders`](/applications/appkit/reference/appkit#watchswapproviders) and re-reads via [`getSwapProvider`](/applications/appkit/reference/appkit#getswapprovider). Returns a `useState`-style tuple. The read swallows the throw from [`getSwapProvider`](/applications/appkit/reference/appkit#getswapprovider) (which throws when no provider matches — or when no id is passed and no default has been registered) and yields `undefined` instead.
Returns: UseSwapProviderReturnType — Tuple `[provider, setProviderId]`.
#### useSwapProviders [#useswapproviders]
List every swap provider registered on the AppKit instance (both those passed via [`AppKitConfig`](/applications/appkit/reference/appkit#appkitconfig)'s `providers` and those added later through [`registerProvider`](/applications/appkit/reference/appkit#registerprovider)). Subscribes to [`watchSwapProviders`](/applications/appkit/reference/appkit#watchswapproviders) and re-reads via [`getSwapProviders`](/applications/appkit/reference/appkit#getswapproviders) so the array stays in sync.
Returns: UseSwapProvidersReturnType — Array of registered swap providers.
#### useSwapQuote [#useswapquote]
Quote a swap — given source/target tokens and an amount, returns the rate, expected output and the provider-specific metadata required to feed [`useBuildSwapTransaction`](#usebuildswaptransaction). `data` is the [`SwapQuote`](/applications/appkit/reference/appkit#swapquote) payload. The `network` field defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Parameter | Type | Description |
| -------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseSwapQuoteParameters`](#useswapquoteparameters) | Source and target tokens, amount, optional network/provider override, and TanStack Query overrides. |
| `parameters.amount` | `string` | Amount of tokens to swap (incoming or outgoing depending on isReverseSwap) |
| `parameters.from` | SwapToken | Token to swap from. |
| `parameters.to` | SwapToken | Token to swap to. |
| `parameters.network` | Network | Network on which the swap will be executed. |
| `parameters.slippageBps` | `number` | Slippage tolerance in basis points (1 bp = 0.01%) |
| `parameters.maxOutgoingMessages` | `number` | Maximum number of outgoing messages |
| `parameters.providerOptions` | `TProviderOptions = unknown` | Provider-specific options. |
| `parameters.isReverseSwap` | `boolean` | If true, amount is the amount to receive (buy). If false, amount is the amount to spend (sell). |
| `parameters.providerId` | `string` | Provider to quote against. Defaults to the registered default swap provider. |
| `parameters.query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
Returns: UseSwapQuoteReturnType \ — TanStack Query result for the swap quote.
### Transactions [#transactions]
#### useSendTransaction [#usesendtransaction]
Hand a pre-built [`TransactionRequest`](/applications/appkit/reference/appkit#transactionrequest) to the selected wallet for signing and broadcast — typically the second step after a `buildX` / `createX` action (e.g. [`useBuildSwapTransaction`](#usebuildswaptransaction), [`useBuildStakeTransaction`](#usebuildstaketransaction)) produces the request. Call `mutate(request)`. On success, `data` carries the BoC and normalized hash of the broadcast transaction. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseSendTransactionParameters`](#usesendtransactionparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseSendTransactionReturnType \ — Mutation result for the send call.
#### useTransactionStatus [#usetransactionstatus]
Poll the status of a sent transaction by its BoC or normalized hash. In TON a single external message triggers a tree of internal messages, so the transaction is `'completed'` only once the entire trace finishes — pair with `refetchInterval` to keep polling until `data.status` is `'completed'` or `'failed'`. Pass either `boc` or `normalizedHash` (not both). The underlying action throws `Error('Either boc or normalizedHash must be provided')` when neither is supplied — TanStack Query surfaces it via the query's `error`.
| Parameter | Type | Description |
| -------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `parameters`\* | [`UseTransactionStatusParameters`](#usetransactionstatusparameters) | `boc` xor `normalizedHash`, optional network and TanStack Query overrides. |
Returns: UseTransactionStatusReturnType \ — TanStack Query result for the status read.
#### useTransferTon [#usetransferton]
Send TON from the selected wallet in one step — builds the transfer message, hands it to the wallet for signing and broadcasts it. Call `mutate` with a `recipientAddress`, an `amount` (in TON as a human-readable decimal, converted to nano-TON internally) and any of the optional `comment` / `payload` / `stateInit` fields. On success, `data` carries the BoC and normalized hash of the broadcast transaction — pair with [`useTransactionStatus`](#usetransactionstatus) to poll the trace to completion. Throws `Error('Wallet not connected')` if no wallet is currently selected — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseTransferTonParameters`](#usetransfertonparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseTransferTonReturnType \ — Mutation result for the transfer call.
#### useWatchTransactions [#usewatchtransactions]
Subscribe to incoming-transaction events for the currently selected wallet (use [`useWatchTransactionsByAddress`](#usewatchtransactionsbyaddress) for a fixed address). Auto-rebinds when the user connects, switches or disconnects. Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| `parameters` | [`UseWatchTransactionsParameters`](#usewatchtransactionsparameters) | Update callback. |
| `parameters.onChange` | (update: TransactionsUpdate ) => void | Callback fired on every transactions update from the streaming provider. |
Returns: `void`.
**Example**
```tsx
const [lastUpdate, setLastUpdate] = useState(null);
useWatchTransactions({
onChange: (update) => {
setLastUpdate(update);
},
});
return (
{lastUpdate ? (
Last update for: {lastUpdate.address}
Transactions count: {lastUpdate.transactions.length}
) : (
'Waiting for transactions...'
)}
);
```
#### useWatchTransactionsByAddress [#usewatchtransactionsbyaddress]
Subscribe to incoming-transaction events for an arbitrary address (use [`useWatchTransactions`](#usewatchtransactions) for the selected wallet). Requires a streaming provider registered for the network — the hook exits silently with a console warning when none is configured.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters`\* | [`UseWatchTransactionsByAddressParameters`](#usewatchtransactionsbyaddressparameters) | Address, update callback and optional network override. |
| `parameters.address` | UserFriendlyAddress \| Address | Address to watch — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `parameters.onChange` | (update: TransactionsUpdate ) => void | Callback fired on every transactions update from the streaming provider. |
| `parameters.network` | Network | Network to watch on. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
Returns: `void`.
**Example**
```tsx
const address = 'UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ';
const [lastUpdate, setLastUpdate] = useState(null);
useWatchTransactionsByAddress({
address,
onChange: (update) => {
setLastUpdate(update);
},
});
return (
{lastUpdate ? (
New transactions for: {lastUpdate.address}
Count: {lastUpdate.transactions.length}
) : (
'Waiting for transactions...'
)}
);
```
### Wallets [#wallets]
#### useAddress [#useaddress]
Read the user-friendly address of the currently selected wallet. Updates when the selection changes.
Returns: UseAddressReturnType — Selected wallet's address, or `undefined` when none is selected.
#### useConnect [#useconnect]
Open a registered connector's connection flow (e.g., the TonConnect modal) and await its completion. Call `mutate` from a Connect button with the `connectorId` of the connector to drive. Once the user finishes the flow the new wallet becomes available via [`useSelectedWallet`](#useselectedwallet) / [`useConnectedWallets`](#useconnectedwallets). Throws `Error('Connector with id "" not found')` when no connector with that id is registered — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseConnectParameters`](#useconnectparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseConnectReturnType \ — Mutation result for the connect call.
#### useConnectedWallets [#useconnectedwallets]
Read the list of currently connected wallets across all registered connectors. Updates when a wallet connects or disconnects.
Returns: UseConnectedWalletsReturnType — Read-only array of [`WalletInterface`](/applications/appkit/reference/appkit#walletinterface)s.
#### useDisconnect [#usedisconnect]
Tear down the session on a registered connector, disconnecting whichever wallet it currently holds. Call `mutate` from a Log out / Disconnect button with the `connectorId` of the connector to tear down. Once it resolves the wallet drops out of [`useSelectedWallet`](#useselectedwallet) / [`useConnectedWallets`](#useconnectedwallets). Throws `Error('Connector with id "" not found')` when no connector with that id is registered — TanStack Query surfaces it via the mutation's `error`.
| Parameter | Type | Description |
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | [`UseDisconnectParameters`](#usedisconnectparameters) | TanStack Query mutation overrides. |
| `parameters.mutation` | [`MutationOptionsOverride`](/applications/appkit/reference/appkit#mutationoptionsoverride) | TanStack Query mutation options forwarded to `useMutation` (`onSuccess`, `onError`, `onMutate`, `retry`, …). `mutationFn`, `mutationKey` and `throwOnError` are managed by the wrapper. |
Returns: UseDisconnectReturnType \ — Mutation result for the disconnect call.
#### useSelectedWallet [#useselectedwallet]
Read and switch the wallet that AppKit treats as active — most action hooks ([`useBalance`](#usebalance), [`useSignText`](#usesigntext), [`useTransferTon`](#usetransferton)) target this wallet implicitly. Returns a `useState`-style tuple.
Returns: UseSelectedWalletReturnType — Tuple `[wallet, setWalletId]`.
## Component [#component]
### Balances [#balances-1]
#### SendJettonButton [#sendjettonbutton]
Pre-wired button that builds a jetton transfer with [`createTransferJettonTransaction`](/applications/appkit/reference/appkit#createtransferjettontransaction) and dispatches it through the standard `Send` flow on click — disabled until `recipientAddress`, `amount`, `jetton.address` and `jetton.decimals` are all set. Throws inside the click handler when `jetton.address` or `jetton.decimals` is missing.
| Prop | Type | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recipientAddress`\* | `string` | Recipient address. |
| `amount`\* | `string` | Amount in jetton units as a human-readable decimal string. Converted to raw smallest units via `jetton.decimals`. |
| `jetton`\* | `{ address: string; symbol: string; decimals: number; }` | Jetton master metadata — `address` (master contract), `symbol` (rendered in the button label) and `decimals` (used to format `amount`). |
| `comment` | `string` | Optional human-readable comment attached to the transfer. |
| `text` | `ReactNode` | Override the button label. Defaults to "Send". |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
| `children` | `(props: SendRenderProps) => ReactNode` | Custom render function — replaces the default button with the caller's UI. Receives the current send state and click handler via [`SendRenderProps`](#sendrenderprops). |
| `onError` | `(error: Error) => void` | Called when the wallet rejects the request or the send fails. Receives the raised `Error`. |
| `onSuccess` | (response: SendTransactionReturnType ) => void | Called once the transaction is broadcast. Receives the wallet's [`SendTransactionReturnType`](/applications/appkit/reference/appkit#sendtransactionreturntype) (BoC + normalized hash). |
**Example**
```tsx
return (
console.log('Transaction sent:', result)}
onError={(error) => console.error('Transaction failed:', error)}
/>
);
```
#### SendTonButton [#sendtonbutton]
Pre-wired button that builds a TON transfer with [`createTransferTonTransaction`](/applications/appkit/reference/appkit#createtransfertontransaction) and dispatches it through the standard `Send` flow on click — disabled until both `recipientAddress` and `amount` are set.
| Prop | Type | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recipientAddress`\* | `string` | Recipient address. |
| `amount`\* | `string` | Amount in TON as a human-readable decimal string (e.g., `"1.5"`). Converted to nano-TON internally. |
| `comment` | `string` | Optional human-readable comment attached to the transfer. |
| `text` | `ReactNode` | Override the button label. Defaults to "Send". |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
| `children` | `(props: SendRenderProps) => ReactNode` | Custom render function — replaces the default button with the caller's UI. Receives the current send state and click handler via [`SendRenderProps`](#sendrenderprops). |
| `onError` | `(error: Error) => void` | Called when the wallet rejects the request or the send fails. Receives the raised `Error`. |
| `onSuccess` | (response: SendTransactionReturnType ) => void | Called once the transaction is broadcast. Receives the wallet's [`SendTransactionReturnType`](/applications/appkit/reference/appkit#sendtransactionreturntype) (BoC + normalized hash). |
**Example**
```tsx
return (
console.log('Transaction sent:', result)}
onError={(error) => console.error('Transaction failed:', error)}
/>
);
```
### Crypto Onramp [#crypto-onramp-1]
#### CryptoOnrampWidget [#cryptoonrampwidget]
Drop-in widget for buying TON-side tokens with a crypto payment from another chain — wraps [`CryptoOnrampWidgetProvider`](#cryptoonrampwidgetprovider) (which drives token/method selection, quote fetching, deposit creation and status polling) around [`CryptoOnrampWidgetUI`](#cryptoonrampwidgetui). Pass a `children` render function to swap in a fully custom UI while keeping the same provider state.
| Prop | Type | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | (props: CryptoOnrampWidgetRenderProps ) => ReactNode | Custom render function. When provided, replaces the default [`CryptoOnrampWidgetUI`](#cryptoonrampwidgetui) and is called with the full [`CryptoOnrampWidgetRenderProps`](#cryptoonrampwidgetrenderprops) (context state, actions and forwarded `` props), so callers can build a fully custom UI on top of the same provider. |
| `tokens` |
CryptoOnrampToken \[] | Target tokens (what the user buys on TON). Defaults to a built-in list. |
| `tokenSections` |
CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `paymentMethods` |
CryptoPaymentMethod \[] | Source crypto payment methods (what the user pays with on another chain). Defaults to a built-in list. |
| `methodSections` |
PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `chains` |
Record\ChainInfo> | Custom CAIP-2 → chain display info overrides. Merged on top of the built-in defaults, so consumers only need to provide what they want to override or add — for example, a single entry keyed by `'eip155:42161'` with a `name` of `'Arbitrum'` and a `logo` URL. |
| `defaultTokenId` | `string` | ID of the target token pre-selected on mount. |
| `defaultMethodId` | `string` | ID of the source payment method pre-selected on mount. |
**Example**
```tsx
// Uses built-in defaults for tokens, payment methods and chain display info.
// Make sure a crypto-onramp provider (Layerswap / swaps.xyz) is registered on AppKit.
return
;
```
#### CryptoOnrampWidgetProvider [#cryptoonrampwidgetprovider]
Context provider that powers the crypto-to-TON onramp widget — wires together token/method selection state, quote fetching ([`useCryptoOnrampQuote`](#usecryptoonrampquote)), deposit creation ([`useCreateCryptoOnrampDeposit`](#usecreatecryptoonrampdeposit)), deposit status polling ([`useCryptoOnrampStatus`](#usecryptoonrampstatus)), the target-token balance and validation. Consumers read the state via [`useCryptoOnrampContext`](#usecryptoonrampcontext).
| Prop | Type | Description |
| ----------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tokens` |
CryptoOnrampToken \[] | Target tokens (what the user buys on TON). Defaults to a built-in list. |
| `tokenSections` |
CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `paymentMethods` |
CryptoPaymentMethod \[] | Source crypto payment methods (what the user pays with on another chain). Defaults to a built-in list. |
| `methodSections` |
PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `chains` |
Record\ChainInfo> | Custom CAIP-2 → chain display info overrides. Merged on top of the built-in defaults, so consumers only need to provide what they want to override or add — for example, a single entry keyed by `'eip155:42161'` with a `name` of `'Arbitrum'` and a `logo` URL. |
| `defaultTokenId` | `string` | ID of the target token pre-selected on mount. |
| `defaultMethodId` | `string` | ID of the source payment method pre-selected on mount. |
#### CryptoOnrampWidgetUI [#cryptoonrampwidgetui]
Presentational UI for the crypto-to-TON onramp widget — renders the from/to selectors, amount input with presets, continue button, info block (you-get / balance / provider) and the token-pick / method-pick / refund-address / deposit modals. All state and actions come from props ([`CryptoOnrampWidgetRenderProps`](#cryptoonrampwidgetrenderprops)). Typically rendered inside [`CryptoOnrampWidgetProvider`](#cryptoonrampwidgetprovider) via [`CryptoOnrampWidget`](#cryptoonrampwidget).
| Prop | Type | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `tokens`\* |
CryptoOnrampToken \[] | Full list of target tokens the user can buy. |
| `tokenSections` |
CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `selectedToken`\* |
CryptoOnrampToken \| null | Currently selected target token to buy. `null` until tokens load. |
| `setSelectedToken`\* |
(token: CryptoOnrampToken ) => void | Updates `selectedToken`. |
| `paymentMethods`\* |
CryptoPaymentMethod \[] | Available source crypto payment methods. |
| `methodSections` |
PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `selectedMethod`\* |
CryptoPaymentMethod | Currently selected source payment method. |
| `setSelectedMethod`\* |
(method: CryptoPaymentMethod ) => void | Updates `selectedMethod`. |
| `chains`\* |
Record\ChainInfo> | CAIP-2 → chain display info map (built-in defaults merged with consumer overrides). |
| `amount`\* | `string` | Current amount input value as a decimal string. |
| `setAmount`\* | `(value: string) => void` | Updates `amount`. |
| `amountInputMode`\* |
CryptoAmountInputMode | Which side `amount` is denominated in — see [`CryptoAmountInputMode`](#cryptoamountinputmode). |
| `setAmountInputMode`\* |
(mode: CryptoAmountInputMode ) => void | Updates `amountInputMode`. |
| `convertedAmount`\* | `string` | Other side of `amount` after applying the current quote's rate. |
| `presetAmounts`\* |
OnrampAmountPreset \[] | Quick-pick amount buttons rendered in the widget. |
| `quote`\* |
CryptoOnrampQuote \| null | Current quote, or `null` if not yet fetched / invalidated. |
| `isLoadingQuote`\* | `boolean` | Whether a quote is in flight (includes the input-debounce window). |
| `quoteError`\* | `string \| null` | Quote-side validation/fetch error as an i18n key, or `null`. |
| `quoteProviderName`\* | `string \| null` | Display name of the provider behind the current quote, when available. |
| `deposit`\* |
CryptoOnrampDeposit \| null | Current deposit returned by the provider once `createDeposit` succeeded. |
| `isCreatingDeposit`\* | `boolean` | Whether `createDeposit` is in flight. |
| `depositError`\* | `string \| null` | Deposit-side error as an i18n key, or `null`. |
| `depositAmount`\* | `string` | Formatted deposit amount the user must send on the source chain. |
| `createDeposit`\* | `() => void` | Triggers deposit creation from the current quote. |
| `depositStatus`\* |
CryptoOnrampStatus \| null | Latest deposit status polled via [`useCryptoOnrampStatus`](#usecryptoonrampstatus), or `null`. |
| `isRefundAddressRequired`\* | `boolean` | Whether the current quote provider requires a refund address before deposit. |
| `isReversedAmountSupported`\* | `boolean` | Whether the current quote provider supports reversed (target-amount) input. |
| `refundAddress`\* | `string` | Refund address the user typed, if `isRefundAddressRequired`. |
| `setRefundAddress`\* | `(address: string) => void` | Updates `refundAddress`. |
| `targetBalance`\* | `string` | Connected wallet's balance of the selected target token (formatted, token units). |
| `isLoadingTargetBalance`\* | `boolean` | Whether the target token balance is being fetched. |
| `isWalletConnected`\* | `boolean` | Whether a TON wallet is currently connected. |
| `canContinue`\* | `boolean` | Whether the user can proceed — valid amount, quote available, and wallet connected. |
| `onReset`\* | `() => void` | Invalidates the active quote and clears the deposit, returning the widget to its initial state. |
### NFTs [#nfts-1]
#### NftItem [#nftitem]
Card-style button rendering an NFT's image, name and collection name with an "On Sale" badge when applicable — falls back to a placeholder icon when the image is missing or fails to load.
| Prop | Type | Description |
| ------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `nft`\* |
NFT | NFT to render — name, collection name, image and on-sale state are derived via `getFormattedNftInfo`. |
**Example**
```tsx
return
console.log('NFT clicked')} />;
```
### Providers [#providers]
#### AppKitProvider [#appkitprovider]
Top-level React provider that wires AppKit, the TonConnect bridge and i18n into the component tree — wrap your app once near the root so descendant hooks ([`useAppKit`](#useappkit), [`useBalance`](#usebalance), …) and components can resolve their context.
| Prop | Type | Description |
| ---------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `appKit`\* | AppKit | Runtime instance constructed at app startup. Shared across every appkit-react hook and component. |
**Example**
```tsx
return (
My App
{/* Your App Content */}
);
```
#### I18nProvider [#i18nprovider]
React provider that mounts the i18n context for [`useI18n`](#usei18n) and child components — already wrapped by [`AppKitProvider`](#appkitprovider), so apps usually only render it directly when they need to override the locale or dictionaries.
| Prop | Type | Description |
| ---------- | ---------------------- | -------------------------------------------------------------------------------------------- |
| `locale` | `string` | Initial locale code. Defaults to the i18n library's default when omitted. |
| `lngDicts` | `Record` | Translation dictionaries keyed by locale. Loaded into the underlying i18n instance on mount. |
**Example**
```tsx
// Override the locale. Pass `lngDicts` with your own translations when you need them.
return (
My App
);
```
### Shared [#shared]
#### AmountPresets [#amountpresets]
Horizontal row of preset amount buttons — typically used next to an amount input to offer quick fills.
| Prop | Type | Description |
| ------------------ | -------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `presets`\* | AmountPreset \[] | Preset buttons to render, in order. |
| `currencySymbol` | `string` | Optional symbol (e.g., `"$"`) prepended to each preset label. |
| `onPresetSelect`\* | `(value: string) => void` | Called with the selected preset's `amount` unless the preset defines its own `onSelect`. |
**Example**
```tsx
return (
);
```
#### CopyButton [#copybutton]
Icon-only button that copies `value` to the clipboard on click and flips its icon to a checkmark for a short confirmation window.
| Prop | Type | Description |
| -------------- | -------- | --------------------------------------------------------- |
| `value`\* | `string` | Text written to the clipboard when the button is clicked. |
| `aria-label`\* | `string` | Accessible label for screen readers. |
**Example**
```tsx
return ;
```
#### CurrencyItem [#currencyitem]
Compound row used inside currency/token select lists: shows a token logo, name + ticker, optional verified badge, and an optional balance / under-balance on the right. Pass top-level props for the default layout, or pass `children` made of the sub-components for full control.
**Members**
| Member | Description |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `CurrencyItem.Container` | Root `` wrapper — receives all native button props. |
| `CurrencyItem.Logo` | Token logo cell rendered as a 40px [`Logo`](#logo). |
| `CurrencyItem.Info` | Vertical block holding the [`CurrencyItem.Header`](#currencyitem) and [`CurrencyItem.Ticker`](#currencyitem). |
| `CurrencyItem.VerifiedBadge` | Verified checkmark badge — rendered next to the name when `isVerified` is set. |
| `CurrencyItem.Header` | Top line of `Info` (name + verified badge). |
| `CurrencyItem.Name` | Primary text line — defaults to the token name, falling back to the ticker when no name is provided. |
| `CurrencyItem.Ticker` | Secondary text line — renders the ticker, and when both ticker and name are present appends `• ` followed by the name. |
| `CurrencyItem.RightSide` | Right-aligned column for balance values. |
| `CurrencyItem.MainBalance` | Primary balance number (top of `RightSide`). |
| `CurrencyItem.UnderBalance` | Secondary balance value (e.g., fiat) shown under `MainBalance`. |
**Example**
```tsx
// Top-level props give you the default layout in one line.
return (
console.log('Picked USDT')}
/>
);
```
#### CurrencySelect [#currencyselect]
Compound currency-select primitives — compose [`CurrencySelect.Modal`](#currencyselect) with a [`CurrencySelect.Search`](#currencyselect) and [`CurrencySelect.ListContainer`](#currencyselect) of [`CurrencySelect.Section`](#currencyselect) rows to build a custom token picker. For a ready-made implementation see [`TokenSelectModal`](#tokenselectmodal).
**Members**
| Member | Description |
| ------------------------------ | ----------------------------------------------- |
| `CurrencySelect.Modal` | Modal wrapper. |
| `CurrencySelect.Search` | Auto-focused search input row. |
| `CurrencySelect.ListContainer` | Scrollable list area with built-in empty state. |
| `CurrencySelect.SectionHeader` | Header label rendered above a section. |
| `CurrencySelect.Section` | Container for a group of currency rows. |
#### LowBalanceModal [#lowbalancemodal]
Modal shown when a transaction would leave insufficient TON to cover fees — adapts its body and buttons to the [`LowBalanceMode`](#lowbalancemode).
| Prop | Type | Description |
| --------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls visibility of the modal. |
| `mode`\* | LowBalanceMode | `reduce` — user can fix it by reducing the amount (shows Change/Cancel). `topup` — reducing doesn't help, user must top up TON (shows Close only). |
| `requiredTon`\* | `string` | Required amount in TON, formatted as a decimal string (e.g. `"0.423"`). |
| `onChange`\* | `() => void` | Called when the user clicks the primary "Change" action (only in `reduce` mode). |
| `onCancel`\* | `() => void` | Called when the user dismisses the modal (Cancel, Close, or backdrop click). |
**Example**
```tsx
return (
{
console.log('Reduce amount to fit balance');
setOpen(false);
}}
onCancel={() => setOpen(false)}
/>
);
```
#### OptionSwitcher [#optionswitcher]
Compact dropdown selector — renders the current option's label and a chevron, opening a [`Select`](#select) popover with the remaining choices. Falls back to the raw `value` or `"—"` when no option matches.
| Prop | Type | Description |
| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------- |
| `value`\* | `string \| undefined` | Currently selected option value. |
| `options`\* | OptionSwitcherOption \[] | Available options. |
| `onChange`\* | `(value: string) => void` | Called when the user picks an option. |
| `disabled` | `boolean` | When true, the trigger is non-interactive and dimmed. |
| `className` | `string` | Extra class applied to the trigger button. |
**Example**
```tsx
return ;
```
#### SettingsButton [#settingsbutton]
Icon-only secondary button with a sliders icon — drop-in trigger for opening settings panels.
| Prop | Type | Description |
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onClick` | `() => void` | Click handler — typically used to open a settings modal. |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
**Example**
```tsx
return console.log('Open settings')} />;
```
#### TokenSelectModal [#tokenselectmodal]
Ready-made token picker modal — renders a search field and a sectioned list of [`CurrencyItem`](#currencyitem) rows backed by [`CurrencySelect`](#currencyselect). Search matches by symbol, name, or exact address. Selecting a row fires `onSelect`, closes the modal, and resets the search.
| Prop | Type | Description |
| ------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls modal visibility. |
| `onClose`\* | `() => void` | Called when the modal is dismissed (selection, backdrop click, or escape). |
| `tokens`\* | T = AppkitUIToken \[] | Full set of tokens available for selection and search. |
| `tokenSections` | TokenSectionConfig \[] | Optional sectioning rules. When omitted, all tokens render as a single untitled section. |
| `onSelect`\* | (token: T = AppkitUIToken ) => void | Called with the picked token. The modal closes and resets its search on selection. |
| `title`\* | `string` | Modal header title. |
| `searchPlaceholder` | `string` | Placeholder shown inside the search input. |
**Example**
```tsx
return (
setOpen(false)}
tokens={tokens}
title="Select a token"
searchPlaceholder="Search by name or address"
onSelect={(token) => {
console.log('Picked:', token.symbol);
setOpen(false);
}}
/>
);
```
#### TokenSelector [#tokenselector]
Compact pill button used as the trigger for a token picker — shows the token icon (optionally with a network badge), its symbol, and a chevron unless `readOnly` is set.
| Prop | Type | Description |
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`\* | `string` | Label shown next to the icon — typically the token symbol. |
| `icon` | `string` | Token logo URL. |
| `iconFallback` | `string` | Single-character fallback used when `icon` fails to load. Defaults to the first character of `title`. |
| `networkIcon` | `string` | When provided, renders a network badge overlay on the icon. |
| `readOnly` | `boolean` | Hide chevron and suppress click handling — use when there's nothing to pick. |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
**Example**
```tsx
return (
console.log('Open token picker')}
/>
);
```
### Staking [#staking-1]
#### SelectUnstakeMode [#selectunstakemode]
Collapsible selector for the unstake mode (instant / round-end / when-available). Filters options by `providerMetadata.supportedUnstakeModes` and renders nothing when only one mode is supported. Annotates the instant option with the provider's current instant-unstake limit.
| Prop | Type | Description |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `value`\* | UnstakeModes | Currently selected unstake mode (see [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode)). |
| `onValueChange`\* | (mode: UnstakeModes ) => void | Called when the user picks a different mode. |
| `providerInfo`\* | StakingProviderInfo \| undefined | Dynamic provider info — used to show the instant-unstake limit when available. |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Static provider metadata — supplies `supportedUnstakeModes` and stake-token formatting. |
**Example**
```tsx
return (
);
```
#### StakingBalanceBlock [#stakingbalanceblock]
Row showing the user's relevant balance for the current direction: wallet balance of the stake token when staking, staked balance when unstaking. Renders a token icon (native TON when the token address is `'ton'`, otherwise a jetton icon resolved via [`useJettonInfo`](#usejettoninfo)), a label, the formatted amount with ticker, and an optional `MAX` button.
| Prop | Type | Description |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Provider metadata — supplies the stake/receive tokens (address, ticker, decimals). |
| `direction`\* | StakingQuoteDirection | Operation direction. Selects which token and balance to render. |
| `stakedBalance` | `string` | User's currently staked amount, used when `direction === 'unstake'`. |
| `isStakedBalanceLoading` | `boolean` | True while the staked balance is being fetched. |
| `balance` | `string` | User's wallet balance of the stake token, used when `direction === 'stake'`. |
| `isBalanceLoading` | `boolean` | True while the wallet balance is being fetched. |
| `onMaxClick` | `() => void` | When provided, renders a `MAX` button that invokes this callback. |
**Example**
```tsx
return (
console.log('Use max balance')}
/>
);
```
#### StakingInfo [#stakinginfo]
Summary block rendered below the staking input. Shows the amount the user will receive, the provider's current APY, the stake-token to receive-token exchange rate (only when the provider has a receive token), and the provider name. The exchange-rate row always reads as `1 stakeToken = X receiveToken`, regardless of `direction`.
| Prop | Type | Description |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `quote`\* | StakingQuote \| undefined | Current staking quote — its `amountOut` is rendered in the "You get" row. |
| `isQuoteLoading`\* | `boolean` | True while the quote is being fetched. Swaps the "You get" value for a skeleton. |
| `providerInfo`\* | StakingProviderInfo \| undefined | Dynamic provider info — supplies APY and exchange rate. |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Static provider metadata — supplies token tickers/decimals and the provider name. |
| `isProviderInfoLoading`\* | `boolean` | True while provider info is being fetched. |
| `direction` | StakingQuoteDirection | Operation direction — controls which token's decimals/ticker label the "You get" amount. Defaults to `'stake'`. |
#### StakingSettingsModal [#stakingsettingsmodal]
Modal that lets the user pick the active staking provider. The selection is staged locally and only committed via `onProviderChange` when the user presses `Save`. Closing the modal otherwise discards the change. Each option is labeled with the provider's metadata `name`, falling back to its `providerId` if metadata is unavailable on the given network.
| Prop | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls modal visibility. |
| `onClose`\* | `() => void` | Called when the user dismisses the modal or after a successful save. |
| `provider`\* | StakingProvider \| undefined | Currently active staking provider — used to preselect the option when the modal opens. |
| `providers`\* | StakingProvider \[] | All registered staking providers to choose from. |
| `onProviderChange`\* | `(providerId: string) => void` | Invoked with the chosen `providerId` when the user saves a different selection. |
| `network` | Network | Network used to resolve each provider's display name via its metadata. |
**Example**
```tsx
// Source `provider` and `providers` from `useStakingProvider` and
// `useStakingProviders` in real usage — they refresh as providers register
// through AppKit.
const provider: StakingProvider | undefined = undefined;
const providers: StakingProvider[] = [];
return (
setOpen(false)}
provider={provider}
providers={providers}
onProviderChange={(id) => console.log('Switch to', id)}
network={Network.mainnet()}
/>
);
```
#### StakingWidget [#stakingwidget]
High-level staking widget that wires the full stake/unstake flow: pick a provider, enter an amount (with optional reverse input on supported providers), review the quote (APY, exchange rate, "you get"), then submit the transaction. Internally wraps [`StakingWidgetProvider`](#stakingwidgetprovider) around [`StakingWidgetUI`](#stakingwidgetui). Consumers can replace the UI by passing a render-prop `children` while keeping the widget's state, quoting, balance checks, and submission logic.
| Prop | Type | Description |
| ---------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | (props: StakingWidgetRenderProps ) => ReactNode | Optional render-prop. When provided, the default [`StakingWidgetUI`](#stakingwidgetui) is bypassed and this function is called with the full [`StakingWidgetRenderProps`](#stakingwidgetrenderprops) (context state + forwarded `` props), letting consumers build a custom UI on top of the widget's internal logic. |
| `network` |
Network | Network used for quote fetching, balance reads, and transactions. Falls back to the connected wallet's network when omitted. |
**Example**
```tsx
// Falls back to the connected wallet's network when `network` is omitted.
// Make sure a staking provider (e.g. Tonstakers) is registered on AppKit.
return
;
```
#### StakingWidgetProvider [#stakingwidgetprovider]
Headless provider that drives the staking-widget flow — owns the input state (amount, direction, unstake mode, reverse-input toggle), fetches quotes and balances, validates the input, and builds + submits the transaction with a low-balance guard. Children read everything through [`useStakingContext`](#usestakingcontext); pair with [`StakingWidgetUI`](#stakingwidgetui) (or pass a custom UI to [`StakingWidget`](#stakingwidget)'s `children`).
| Prop | Type | Description |
| --------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `network` |
Network | Network used for quote fetching, balance reads, and transactions. Falls back to the connected wallet's network when omitted. |
#### StakingWidgetUI [#stakingwidgetui]
Default staking-widget UI. Renders a stake/unstake tabbed layout: a centered amount input with optional reversed input, a [`StakingBalanceBlock`](#stakingbalanceblock) for the relevant balance, the submit button (wired through `ButtonWithConnect` so a disconnected user is prompted to connect first), a settings button that opens [`StakingSettingsModal`](#stakingsettingsmodal), the unstake-mode picker ([`SelectUnstakeMode`](#selectunstakemode), unstake tab only), and a [`StakingInfo`](#stakinginfo) summary. A [`LowBalanceModal`](#lowbalancemodal) surfaces when the built transaction would exceed the user's TON balance. All state is consumed from props — typically supplied by [`StakingWidgetProvider`](#stakingwidgetprovider).
| Prop | Type | Description |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount`\* | `string` | Amount the user wants to stake (string to preserve input UX) |
| `canSubmit`\* | `boolean` | Whether the user can proceed with staking (checks balance, amount validity, etc.) |
| `quote`\* |
StakingQuote \| undefined | Raw staking quote from the provider |
| `isQuoteLoading`\* | `boolean` | True while the stake quote is being fetched |
| `error`\* | `string \| null` | Current validation/fetch error for staking, null when everything is ok |
| `providerInfo`\* |
StakingProviderInfo \| undefined | Staking provider dynamic info (APY, instant unstake availability, etc.) |
| `providerMetadata`\* |
StakingProviderMetadata \| undefined | Staking provider static metadata |
| `stakingProvider`\* |
StakingProvider \| undefined | Currently selected staking provider (defaults to the first registered one) |
| `stakingProviders`\* |
StakingProvider \[] | All registered staking providers |
| `setStakingProviderId`\* | `(providerId: string) => void` | Updates the selected staking provider |
| `network`\* |
Network \| undefined | Network the widget is operating on (resolved from prop or wallet) |
| `direction`\* |
StakingQuoteDirection | Current operation direction: 'stake' or 'unstake' |
| `isProviderInfoLoading`\* | `boolean` | True while provider info is being fetched |
| `balance`\* | `string \| undefined` | Base balance (native or jetton) available for staking |
| `isBalanceLoading`\* | `boolean` | True while base balance is being fetched |
| `stakedBalance`\* |
StakingBalance \| undefined | User's currently staked balance |
| `isStakedBalanceLoading`\* | `boolean` | True while staked balance is being fetched |
| `unstakeMode`\* |
UnstakeModes | Selected unstake-timing mode — `'INSTANT'`, `'WHEN_AVAILABLE'`, or `'ROUND_END'`. See [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode). |
| `setAmount`\* | `(amount: string) => void` | Sets the input amount |
| `setUnstakeMode`\* |
(mode: UnstakeModes ) => void | Sets the unstake mode |
| `sendTransaction`\* | `() => Promise
` | Triggers the staking/unstaking transaction |
| `onChangeDirection`\* | (direction: StakingQuoteDirection ) => void | Changes the direction (stake/unstake) |
| `isSendingTransaction`\* | `boolean` | True while a transaction is being processed |
| `isReversed`\* | `boolean` | True if the user is inputting the output amount ("I want to get X") |
| `toggleReversed`\* | `() => void` | Toggles between inputting from amount and output amount |
| `reversedAmount`\* | `string` | Amount displayed in the reversed (bottom) input |
| `onMaxClick`\* | `() => void` | Sets the input amount to the maximum available balance (leaves room for TON gas on native stake) |
| `isLowBalanceWarningOpen`\* | `boolean` | True when the built transaction outflow exceeds the user's TON balance |
| `lowBalanceMode`\* | `'reduce' \| 'topup'` | `reduce` when the outgoing token is TON (user can fix by changing amount), `topup` otherwise. |
| `lowBalanceRequiredTon`\* | `string` | Required TON amount for the pending operation, formatted as a decimal string. Empty when no pending op. |
| `onLowBalanceChange`\* | `() => void` | Replace the input with a value that fits within the current TON balance and close the warning. |
| `onLowBalanceCancel`\* | `() => void` | Dismiss the low-balance warning without changing the input. |
### Swap [#swap-1]
#### SwapField [#swapfield]
One row of the swap form. Renders the amount input, fiat conversion, balance line, and a token-selector chip. The `pay` variant is editable and exposes a "max" shortcut. The `receive` variant is read-only and shows the quote result.
| Prop | Type | Description | | |
| ---------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --- | ------------------------- |
| `type`\* | `'pay' \| 'receive'` | `pay` renders the editable source row with a "max" shortcut. `receive` renders the read-only target row. | | |
| `amount`\* | `string` | Current amount shown in the input as a human-readable decimal string. | | |
| `fiatSymbol` | `string` | Fiat currency symbol displayed in front of the converted value. Defaults to `"$"`. | | |
| `token` | AppkitUIToken | Currently selected token. Controls the token selector label, balance formatting and fiat conversion. | | |
| `onAmountChange` | `(value: string) => void` | Called with the raw input value when the user edits the amount. Only fired for `type: "pay"`. | | |
| `balance` | `string` | Formatted balance of `token` for the active wallet, as a human-readable decimal string. Rendered in the balance line beneath the input. | | |
| `isBalanceLoading` | `boolean` | When true, the balance area renders a skeleton placeholder instead of the value. | | |
| `loading` | `boolean` | When true, the underlying input renders its loading state — used while a fresh quote is in flight. | | |
| `onMaxClick` | `() => void` | Called when the user clicks the "max" shortcut to fill the maximum spendable amount. | | |
| `onTokenSelectorClick` | `() => void` | Called when the user clicks the token selector chip — typically opens a `SwapTokenSelectModal`. | | |
| `size` | `InputSize` | Size token applied to the input control(s) inside: \`'s' | 'm' | 'l'`. Defaults to `'m'\`. |
| `variant` | `InputVariant` | Visual variant: `'default'` paints a filled field. `'unstyled'` drops the chrome. | | |
| `disabled` | `boolean` | When true, descendant input controls are disabled. | | |
| `error` | `boolean` | When true, the field renders in error styling and [`Input.Caption`](#input) switches to error text. | | |
| `resizable` | `boolean` | When true, [`Input.Input`](#input) scales its font down to fit the available width as the user types. | | |
**Example**
```tsx
return (
setAmount('12.5')}
onTokenSelectorClick={() => console.log('Open token picker')}
/>
);
```
#### SwapFlipButton [#swapflipbutton]
Round button rendered between the source and target [`SwapField`](#swapfield) rows. Clicking it flips the selected tokens. Visual rotation is driven by `rotated`.
| Prop | Type | Description |
| --------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `onClick` | `() => void` | Called when the user clicks the button. Wire this to a handler that swaps the source/target tokens (e.g. `onFlip` from the swap context). |
| `rotated` | `boolean` | When true, the icon is drawn in its rotated state — used to animate between flips. |
**Example**
```tsx
// Drop it between the source and target `SwapField` rows. Wire `onClick` to your token-flip handler.
return setRotated((prev) => !prev)} />;
```
#### SwapInfo [#swapinfo]
Summary block rendered under the swap form. Shows the minimum amount the user is guaranteed to receive after slippage, the configured slippage tolerance, and the active [`SwapProvider`](/applications/appkit/reference/appkit#swapprovider).
| Prop | Type | Description |
| ---------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `toToken`\* | AppkitUIToken \| null | Target token the user is receiving. Used to format `minReceived` with the right decimals and symbol. |
| `slippage`\* | `number` | Slippage tolerance in basis points (`100` = 1%). Rendered as a percentage. |
| `provider` | SwapProvider | Current [`SwapProvider`](/applications/appkit/reference/appkit#swapprovider). Its display name is shown in the provider row. |
| `quote` | SwapQuote | Quote whose `minReceived` value is displayed. When undefined the value falls back to `0` (still suffixed with the token symbol). |
| `isQuoteLoading` | `boolean` | When true, the minimum-received value renders a skeleton placeholder instead of the formatted number. |
**Example**
```tsx
// In the swap widget `quote` and `provider` come from `useSwapContext`; until
// those resolve the min-received row shows `0 USDT` and the provider row a
// skeleton placeholder.
return ;
```
#### SwapWidget [#swapwidget]
Drop-in swap UI that walks the user through picking the source/target tokens, entering an amount, reviewing the quote (rate, min-received, slippage, provider), and confirming the swap — which builds the transaction via [`useBuildSwapTransaction`](#usebuildswaptransaction) and dispatches it through the standard send flow. Internally mounts a [`SwapWidgetProvider`](#swapwidgetprovider) so the rendered UI (default [`SwapWidgetUI`](#swapwidgetui) or a custom `children` render-prop) can read state through [`useSwapContext`](#useswapcontext).
| Prop | Type | Description |
| ------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | (props: SwapWidgetRenderProps ) => ReactNode | Optional render-prop receiving the full swap context plus the forwarded `` props. When supplied it replaces the default [`SwapWidgetUI`](#swapwidgetui). |
| `network` |
Network | Network used for quote fetching and balance reads. When omitted, falls back to the selected wallet's network via [`useNetwork`](#usenetwork). |
| `tokens`\* |
AppkitUIToken \[] | Full list of tokens available for swapping in the UI. Filtered to the active network internally. |
| `tokenSections` |
TokenSectionConfig \[] | Optional section configs for grouping tokens inside the `SwapTokenSelectModal`. |
| `defaultFromSymbol` | `string` | Symbol of the token pre-selected as the source on first mount (e.g. `"TON"`). |
| `defaultToSymbol` | `string` | Symbol of the token pre-selected as the target on first mount. |
| `fiatSymbol` | `string` | Fiat currency symbol displayed next to converted amounts. Defaults to `"$"`. |
| `defaultSlippage` | `number` | Initial slippage tolerance in basis points (`100` = 1%). Defaults to `100`. |
**Example**
```tsx
// Make sure a swap provider (e.g. DeDust / Omniston) is registered on AppKit.
return
;
```
#### SwapWidgetProvider [#swapwidgetprovider]
Provider that wires up the full swap state machine — debounces the entered amount, fetches the quote via [`useSwapQuote`](#useswapquote), reads source/target balances, validates the input, exposes the active [`SwapProvider`](/applications/appkit/reference/appkit#swapprovider), and offers `sendSwapTransaction` which builds the transaction with [`useBuildSwapTransaction`](#usebuildswaptransaction) and sends it (raising the low-balance warning when the outflow exceeds the user's TON balance). Children read everything through [`useSwapContext`](#useswapcontext).
| Prop | Type | Description |
| ------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `tokens`\* |
AppkitUIToken \[] | Full list of tokens available for swapping in the UI. Filtered to the active network internally. |
| `tokenSections` |
TokenSectionConfig \[] | Optional section configs for grouping tokens inside the `SwapTokenSelectModal`. |
| `defaultFromSymbol` | `string` | Symbol of the token pre-selected as the source on first mount (e.g. `"TON"`). |
| `defaultToSymbol` | `string` | Symbol of the token pre-selected as the target on first mount. |
| `network` |
Network | Network used for quote fetching and balance reads. When omitted, falls back to the selected wallet's network via [`useNetwork`](#usenetwork). |
| `fiatSymbol` | `string` | Fiat currency symbol displayed next to converted amounts. Defaults to `"$"`. |
| `defaultSlippage` | `number` | Initial slippage tolerance in basis points (`100` = 1%). Defaults to `100`. |
#### SwapWidgetUI [#swapwidgetui]
Default visual implementation of the swap widget — composes [`SwapField`](#swapfield) (source, then target), a [`SwapFlipButton`](#swapflipbutton) between them, the submit button (auto-prompts wallet connect when no wallet is selected), the settings trigger that opens `SwapSettingsModal`, a `SwapTokenSelectModal` for picking source/target tokens, the [`SwapInfo`](#swapinfo) summary, and a low-balance warning. Drives all state from the swap context props it receives — pair with [`SwapWidgetProvider`](#swapwidgetprovider), or use [`SwapWidget`](#swapwidget) which mounts both.
| Prop | Type | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `tokens`\* |
AppkitUIToken \[] | Full list of available tokens for swapping |
| `tokenSections` |
TokenSectionConfig \[] | Optional section configs for grouping tokens in the selector |
| `fromToken`\* |
AppkitUIToken \| null | Currently selected source token |
| `toToken`\* |
AppkitUIToken \| null | Currently selected target token |
| `fromAmount`\* | `string` | Amount the user wants to swap (string to preserve input UX) |
| `toAmount`\* | `string` | Calculated receive amount from the current quote |
| `fiatSymbol`\* | `string` | Fiat currency symbol for price display, e.g. "\$" |
| `fromBalance`\* | `string \| undefined` | User's balance of the "from" token |
| `toBalance`\* | `string \| undefined` | User's balance of the "to" token |
| `isFromBalanceLoading`\* | `boolean` | True while the "from" balance is being fetched |
| `isToBalanceLoading`\* | `boolean` | True while the "to" balance is being fetched |
| `canSubmit`\* | `boolean` | Whether the user can proceed with the swap (checks balance, amount, quote) |
| `quote`\* | `GetSwapQuoteData \| undefined` | Raw swap quote from the provider |
| `isQuoteLoading`\* | `boolean` | True while the quote is being fetched from the API |
| `error`\* | `string \| null` | Current validation or fetch error, null when everything is ok |
| `slippage`\* | `number` | Slippage tolerance in basis points (100 = 1%) |
| `swapProvider`\* |
SwapProvider \| undefined | Currently selected swap provider (defaults to the first registered one) |
| `swapProviders`\* |
SwapProvider \[] | All registered swap providers |
| `setSwapProviderId`\* | `(providerId: string) => void` | Updates the selected swap provider |
| `setFromToken`\* |
(token: AppkitUIToken ) => void | Updates the source token |
| `setToToken`\* |
(token: AppkitUIToken ) => void | Updates the target token |
| `setFromAmount`\* | `(amount: string) => void` | Updates the swap amount |
| `setSlippage`\* | `(slippage: number) => void` | Updates the slippage tolerance |
| `onFlip`\* | `() => void` | Swaps source and target tokens |
| `onMaxClick`\* | `() => void` | Sets the "from" amount to the maximum available balance |
| `sendSwapTransaction`\* | `() => Promise
` | Executes the swap transaction |
| `isSendingTransaction`\* | `boolean` | True while a transaction is being built or sent |
| `isLowBalanceWarningOpen`\* | `boolean` | True when the built transaction outflow exceeds the user's TON balance |
| `lowBalanceMode`\* | `'reduce' \| 'topup'` | `reduce` when the outgoing token is TON (user can fix by changing amount), `topup` otherwise. |
| `lowBalanceRequiredTon`\* | `string` | Required TON amount for the pending operation, formatted as a decimal string. Empty when no pending op. |
| `onLowBalanceChange`\* | `() => void` | Replace the input with a value that fits within the current TON balance and close the warning. |
| `onLowBalanceCancel`\* | `() => void` | Dismiss the low-balance warning without changing the input. |
### UI [#ui]
#### Block [#block]
Flex container primitive — renders a `` that lays its children out vertically (`'column'`) or horizontally (`'row'`).
| Prop | Type | Description |
| ----------- | ------------------- | ---------------------------------------------------- |
| `direction` | `'row' \| 'column'` | Flex direction of the block. Defaults to `'column'`. |
**Example**
```tsx
return (
Left
Right
);
```
#### Button [#button]
Themed `
` with size, border-radius, and variant tokens. Renders an optional leading `icon`, swaps content for a spinner while `loading`, and is disabled whenever `disabled` or `loading` is true.
| Prop | Type | Description |
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
**Example**
```tsx
return (
console.log('Clicked')}>
Send transaction
);
```
#### CenteredAmountInput [#centeredamountinput]
Center-aligned, auto-resizing amount input with optional leading symbol and trailing ticker. Scales the font down to fit the container when the rendered text overflows, and clicking the wrapper focuses the input.
| Prop | Type | Description |
| ----------------- | ------------------------- | ------------------------------------------------------------- |
| `value`\* | `string` | Controlled input value (decimal string). |
| `onValueChange`\* | `(value: string) => void` | Called with the new string whenever the user edits the input. |
| `ticker` | `string` | Optional trailing ticker label (e.g., `'TON'`). |
| `symbol` | `string` | Optional leading currency symbol (e.g., `'$'`). |
| `placeholder` | `string` | Placeholder shown when `value` is empty. Defaults to `'0'`. |
| `disabled` | `boolean` | When true, the underlying ` ` is disabled. |
**Example**
```tsx
return ;
```
#### Collapsible [#collapsible]
Animated collapsible container — transitions its height between `0` and the content's natural height when `open` toggles. Sets `aria-hidden` to mirror the open state.
| Prop | Type | Description |
| -------- | --------- | ------------------------------------------------------------------------------- |
| `open`\* | `boolean` | When true, the content is expanded. When false, it is collapsed to zero height. |
**Example**
```tsx
return (
setOpen((prev) => !prev)}>{open ? 'Hide details' : 'Show details'}
Hidden details about the transaction.
);
```
#### InfoBlock [#infoblock]
Compound component for rendering a stacked list of label/value rows (e.g., transaction details, settings summaries). Sub-components forward extra props to the underlying DOM element so callers can layer custom classes and handlers.
**Members**
| Member | Description |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `InfoBlock.Container` | Outer wrapper — vertical container that hosts the rows. |
| `InfoBlock.Row` | Horizontal row that pairs a label with a value. |
| `InfoBlock.Label` | Label cell — typically the muted descriptor on the left. |
| `InfoBlock.Value` | Value cell — typically the emphasized content on the right. |
| `InfoBlock.LabelSkeleton` | Skeleton placeholder for a [`InfoBlock.Label`](#infoblock) while data is loading. Defaults to `width=64`, `height='1lh'`. |
| `InfoBlock.ValueSkeleton` | Skeleton placeholder for a [`InfoBlock.Value`](#infoblock) while data is loading. Defaults to `width=80`, `height='1lh'`. |
**Example**
```ts
return (
Rate
1 TON ≈ $5.43
Network fee
0.01 TON
);
```
#### Input [#input]
Compound text-input component. Use the default export as the outer wrapper (it is the [`Input.Container`](#input)) and compose sub-components for the header, field, slots, control, and caption. State flags (`disabled`, `error`, `loading`, `resizable`, `size`) live on the container and are read by the inner control via context.
**Members**
| Member | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------------------- |
| `Input.Container` | Outer wrapper that provides input context (size, variant, disabled, error, loading, resizable). |
| `Input.Header` | Header row above the field — holds the title and optional trailing controls. |
| `Input.Title` | Title text shown inside [`Input.Header`](#input). |
| `Input.Field` | Horizontal row that holds slots and the input control. |
| `Input.Slot` | Side-anchored slot used for adornments such as icons or buttons. |
| `Input.Input` | The actual ` ` control. Respects context flags and reads its size/variant from [`Input.Container`](#input). |
| `Input.Caption` | Caption / helper text below the field. Switches to error styling when the container has `error` set. |
**Example**
```tsx
return (
Recipient
setValue(event.target.value)} placeholder="EQ..." />
Paste a TON wallet address.
);
```
#### Logo [#logo]
Square logo / avatar primitive — renders an ` ` when `src` loads successfully, otherwise shows a text fallback (after a brief delay to avoid flicker). Useful for token icons, wallet avatars, and project logos.
| Prop | Type | Description |
| ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `size` | `number` | Square size in pixels for the rendered logo. Defaults to `30`. |
| `src` | `string` | Image URL to render. While loading or on failure, the fallback is shown. |
| `alt` | `string` | Alt text passed to the underlying ` `. When `fallback` is not provided, its first character is shown as the fallback. If both are missing, no fallback is rendered. |
| `fallback` | `string` | Text shown in place of the image when `src` fails or is missing (defaults to the first character of `alt`). |
**Example**
```tsx
return ;
```
#### LogoWithNetwork [#logowithnetwork]
Token logo with an overlaid network badge — wraps [`Logo`](#logo) and renders a smaller secondary logo as a corner badge to indicate which network the asset belongs to.
| Prop | Type | Description |
| ------------ | -------- | ---------------------------------------------------------------------------------------------- |
| `size` | `number` | Size of the main logo in pixels. Defaults to `30`. The network badge is sized to `size * 0.4`. |
| `src` | `string` | Image source for the main logo. |
| `alt` | `string` | Alt text for the main logo. |
| `fallback` | `string` | Fallback text shown when the main logo image fails or is missing. |
| `networkSrc` | `string` | Image source for the network badge overlay. When omitted, the badge is not rendered. |
| `networkAlt` | `string` | Alt text for the network badge. |
**Example**
```tsx
return (
);
```
#### Modal [#modal]
Centered modal dialog with a header (optional title + close button) and a scrollable body. Clicking the overlay closes the modal. Clicks on the content do not bubble through.
| Prop | Type | Description |
| --------------- | ------------------------- | ------------------------------------------------------------------------------------------------ |
| `open` | `boolean` | Controlled open state. |
| `onOpenChange` | `(open: boolean) => void` | Called whenever the open state changes (e.g., via the close button, overlay click, or `Escape`). |
| `title` | `string` | Optional title rendered in the modal header. |
| `children` | `ReactNode` | Modal body content. |
| `className` | `string` | Additional class name applied to the content container. |
| `bodyClassName` | `string` | Additional class name applied to the body container. |
**Example**
```tsx
return (
setOpen(true)}>Open modal
Are you sure you want to proceed?
);
```
#### Select [#select]
Compound select / dropdown component with controlled or uncontrolled state. The content is portaled to `document.body` and positioned relative to the trigger. Closes on outside click, `Escape`, or item selection.
**Members**
| Member | Description |
| ---------------- | --------------------------------------------------------------------------------------------------------- |
| `Select.Root` | Provider that owns the selected value and open state, controlled or uncontrolled. |
| `Select.Trigger` | [`Button`](#button)-based trigger that toggles the popover and exposes `aria-expanded`. |
| `Select.Content` | Portaled popover that renders the list of items. Positioned under the trigger with optional `sideOffset`. |
| `Select.Item` | Selectable option row. Commits its `value` to the root on click. |
**Example**
```ts
return (
{value === 'mainnet' ? 'Mainnet' : 'Testnet'}
Mainnet
Testnet
);
```
#### Skeleton [#skeleton]
Animated placeholder block used while data is loading. Supply `width` / `height` to match the dimensions of the eventual content.
| Prop | Type | Description |
| -------- | ------------------ | -------------------------------------------------------------------------------------------- |
| `width` | `string \| number` | Width of the placeholder. Accepts any valid CSS length or a number (interpreted as pixels). |
| `height` | `string \| number` | Height of the placeholder. Accepts any valid CSS length or a number (interpreted as pixels). |
**Example**
```tsx
return ;
```
#### Tabs [#tabs]
Root tabs container — owns the active value (controlled or uncontrolled) and shares it with descendant [`TabsList`](#tabslist), [`TabsTrigger`](#tabstrigger), and [`TabsContent`](#tabscontent) via context.
| Prop | Type | Description |
| --------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `value` | `string` | Controlled active tab value. |
| `defaultValue` | `string` | Initial active tab when uncontrolled. Defaults to `''`. |
| `onValueChange` | `(value: string) => void` | Called whenever the active tab changes. |
| `children`\* | `ReactNode` | Compound sub-components — typically [`TabsList`](#tabslist) (with [`TabsTrigger`](#tabstrigger)s) followed by [`TabsContent`](#tabscontent)s. |
**Example**
```tsx
return (
Stake
Unstake
Stake your TON to earn rewards.
Withdraw your staked TON.
);
```
#### TabsContent [#tabscontent]
Tab panel rendered with `role="tabpanel"`. Returns `null` unless its `value` matches the active [`Tabs`](#tabs) value.
| Prop | Type | Description |
| ------------ | ----------- | ----------------------------------------------------------------------------------------------------- |
| `value`\* | `string` | Value this panel is associated with — rendered only when the parent [`Tabs`](#tabs) is on this value. |
| `children`\* | `ReactNode` | Panel content. |
#### TabsList [#tabslist]
Horizontal list of tab triggers with `role="tablist"`.
| Prop | Type | Description |
| ------------ | ----------- | -------------------------------------------------------------------- |
| `children`\* | `ReactNode` | Tab triggers — typically one or more [`TabsTrigger`](#tabstrigger)s. |
#### TabsTrigger [#tabstrigger]
Tab trigger button with `role="tab"`. Activates its `value` on click and reflects active state via `aria-selected` and `data-state`.
| Prop | Type | Description |
| ------------ | ----------- | ----------------------------------------------------------------------------- |
| `value`\* | `string` | Value committed to the parent [`Tabs`](#tabs) when this trigger is activated. |
| `children`\* | `ReactNode` | Trigger label / content. |
#### TonIcon [#tonicon]
TON brand diamond glyph — solid, inherits color from `currentColor`.
| Prop | Type | Description |
| ------ | -------- | ----------------------------------------------------------------------------------------- |
| `size` | `number` | Square size of the icon in pixels. Defaults to [`DEFAULT_ICON_SIZE`](#default_icon_size). |
#### TonIconCircle [#toniconcircle]
TON brand glyph rendered inside a filled circle, using the TON brand color token.
| Prop | Type | Description |
| ------ | -------- | ----------------------------------------------------------------------------------------- |
| `size` | `number` | Square size of the icon in pixels. Defaults to [`DEFAULT_ICON_SIZE`](#default_icon_size). |
## Type [#type]
### Balances [#balances-2]
#### SendJettonButtonProps [#sendjettonbuttonprops]
Props accepted by [`SendJettonButton`](#sendjettonbutton) — extends the base `Send` button props (button text, sizing, callbacks) with the jetton-transfer details.
| Field | Type | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recipientAddress`\* | `string` | Recipient address. |
| `amount`\* | `string` | Amount in jetton units as a human-readable decimal string. Converted to raw smallest units via `jetton.decimals`. |
| `jetton`\* | `{ address: string; symbol: string; decimals: number; }` | Jetton master metadata — `address` (master contract), `symbol` (rendered in the button label) and `decimals` (used to format `amount`). |
| `comment` | `string` | Optional human-readable comment attached to the transfer. |
| `text` | `ReactNode` | Override the button label. Defaults to "Send". |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
| `children` | `(props: SendRenderProps) => ReactNode` | Custom render function — replaces the default button with the caller's UI. Receives the current send state and click handler via [`SendRenderProps`](#sendrenderprops). |
| `onError` | `(error: Error) => void` | Called when the wallet rejects the request or the send fails. Receives the raised `Error`. |
| `onSuccess` | (response: SendTransactionReturnType ) => void | Called once the transaction is broadcast. Receives the wallet's [`SendTransactionReturnType`](/applications/appkit/reference/appkit#sendtransactionreturntype) (BoC + normalized hash). |
#### SendTonButtonProps [#sendtonbuttonprops]
Props accepted by [`SendTonButton`](#sendtonbutton) — extends the base `Send` button props (button text, sizing, callbacks) with the TON-transfer details.
| Field | Type | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recipientAddress`\* | `string` | Recipient address. |
| `amount`\* | `string` | Amount in TON as a human-readable decimal string (e.g., `"1.5"`). Converted to nano-TON internally. |
| `comment` | `string` | Optional human-readable comment attached to the transfer. |
| `text` | `ReactNode` | Override the button label. Defaults to "Send". |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
| `children` | `(props: SendRenderProps) => ReactNode` | Custom render function — replaces the default button with the caller's UI. Receives the current send state and click handler via [`SendRenderProps`](#sendrenderprops). |
| `onError` | `(error: Error) => void` | Called when the wallet rejects the request or the send fails. Receives the raised `Error`. |
| `onSuccess` | (response: SendTransactionReturnType ) => void | Called once the transaction is broadcast. Receives the wallet's [`SendTransactionReturnType`](/applications/appkit/reference/appkit#sendtransactionreturntype) (BoC + normalized hash). |
#### UseBalanceByAddressParameters [#usebalancebyaddressparameters]
Parameters accepted by [`useBalanceByAddress`](#usebalancebyaddress) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the target address and optional network override.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Wallet address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseBalanceByAddressReturnType [#usebalancebyaddressreturntype]
Return type of [`useBalanceByAddress`](#usebalancebyaddress) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseBalanceByAddressReturnType = UseQueryReturnType<
selectData,
GetBalanceErrorType
>;
```
#### UseBalanceParameters [#usebalanceparameters]
Parameters accepted by [`useBalance`](#usebalance) — same shape as [`UseBalanceByAddressParameters`](#usebalancebyaddressparameters). The hook resolves `address` from the selected wallet and overrides any value supplied here.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Wallet address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseBalanceReturnType [#usebalancereturntype]
Return type of [`useBalance`](#usebalance) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseBalanceReturnType = UseBalanceByAddressReturnType;
```
#### UseWatchBalanceByAddressParameters [#usewatchbalancebyaddressparameters]
Parameters accepted by [`useWatchBalanceByAddress`](#usewatchbalancebyaddress) — same fields as [`WatchBalanceByAddressOptions`](/applications/appkit/reference/appkit#watchbalancebyaddressoptions), all optional so callers can render the hook before the address is known.
```ts
type UseWatchBalanceByAddressParameters = Partial;
```
#### UseWatchBalanceParameters [#usewatchbalanceparameters]
Parameters accepted by [`useWatchBalance`](#usewatchbalance) — same fields as [`UseWatchBalanceByAddressParameters`](#usewatchbalancebyaddressparameters) minus `address`, which the hook resolves from the selected wallet.
```ts
type UseWatchBalanceParameters = Omit;
```
### Connectors [#connectors-1]
#### UseConnectorsReturnType [#useconnectorsreturntype]
Return type of [`useConnectors`](#useconnectors) — same shape as [`GetConnectorsReturnType`](/applications/appkit/reference/appkit#getconnectorsreturntype).
```ts
type UseConnectorsReturnType = GetConnectorsReturnType;
```
### Crypto Onramp [#crypto-onramp-2]
#### ChainInfo [#chaininfo]
Display info for a CAIP-2 chain — used by the crypto onramp widget to render chain names and logos.
| Field | Type | Description |
| -------- | -------- | ---------------------------------------------------------------- |
| `name`\* | `string` | Human-readable chain name (e.g. `"Ethereum"`, `"Arbitrum One"`). |
| `logo` | `string` | Optional logo URL for the chain. |
#### CryptoAmountInputMode [#cryptoamountinputmode]
Which side the amount input is currently denominated in — `token` means the user is entering the target-token amount, `method` means they are entering the source payment-method amount.
```ts
type CryptoAmountInputMode = 'token' | 'method';
```
#### CryptoOnrampContextType [#cryptoonrampcontexttype]
Shape of the `CryptoOnrampContext` value — selection state, quote/deposit data and actions exposed by [`CryptoOnrampWidgetProvider`](#cryptoonrampwidgetprovider) to the widget UI (and to custom render callbacks passed to [`CryptoOnrampWidget`](#cryptoonrampwidget)).
| Field | Type | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `tokens`\* | CryptoOnrampToken \[] | Full list of target tokens the user can buy. |
| `tokenSections` | CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `selectedToken`\* | CryptoOnrampToken \| null | Currently selected target token to buy. `null` until tokens load. |
| `setSelectedToken`\* | (token: CryptoOnrampToken ) => void | Updates `selectedToken`. |
| `paymentMethods`\* | CryptoPaymentMethod \[] | Available source crypto payment methods. |
| `methodSections` | PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `selectedMethod`\* | CryptoPaymentMethod | Currently selected source payment method. |
| `setSelectedMethod`\* | (method: CryptoPaymentMethod ) => void | Updates `selectedMethod`. |
| `chains`\* | Record\ChainInfo> | CAIP-2 → chain display info map (built-in defaults merged with consumer overrides). |
| `amount`\* | `string` | Current amount input value as a decimal string. |
| `setAmount`\* | `(value: string) => void` | Updates `amount`. |
| `amountInputMode`\* | CryptoAmountInputMode | Which side `amount` is denominated in — see [`CryptoAmountInputMode`](#cryptoamountinputmode). |
| `setAmountInputMode`\* | (mode: CryptoAmountInputMode ) => void | Updates `amountInputMode`. |
| `convertedAmount`\* | `string` | Other side of `amount` after applying the current quote's rate. |
| `presetAmounts`\* | OnrampAmountPreset \[] | Quick-pick amount buttons rendered in the widget. |
| `quote`\* | CryptoOnrampQuote \| null | Current quote, or `null` if not yet fetched / invalidated. |
| `isLoadingQuote`\* | `boolean` | Whether a quote is in flight (includes the input-debounce window). |
| `quoteError`\* | `string \| null` | Quote-side validation/fetch error as an i18n key, or `null`. |
| `quoteProviderName`\* | `string \| null` | Display name of the provider behind the current quote, when available. |
| `deposit`\* | CryptoOnrampDeposit \| null | Current deposit returned by the provider once `createDeposit` succeeded. |
| `isCreatingDeposit`\* | `boolean` | Whether `createDeposit` is in flight. |
| `depositError`\* | `string \| null` | Deposit-side error as an i18n key, or `null`. |
| `depositAmount`\* | `string` | Formatted deposit amount the user must send on the source chain. |
| `createDeposit`\* | `() => void` | Triggers deposit creation from the current quote. |
| `depositStatus`\* | CryptoOnrampStatus \| null | Latest deposit status polled via [`useCryptoOnrampStatus`](#usecryptoonrampstatus), or `null`. |
| `isRefundAddressRequired`\* | `boolean` | Whether the current quote provider requires a refund address before deposit. |
| `isReversedAmountSupported`\* | `boolean` | Whether the current quote provider supports reversed (target-amount) input. |
| `refundAddress`\* | `string` | Refund address the user typed, if `isRefundAddressRequired`. |
| `setRefundAddress`\* | `(address: string) => void` | Updates `refundAddress`. |
| `targetBalance`\* | `string` | Connected wallet's balance of the selected target token (formatted, token units). |
| `isLoadingTargetBalance`\* | `boolean` | Whether the target token balance is being fetched. |
| `isWalletConnected`\* | `boolean` | Whether a TON wallet is currently connected. |
| `canContinue`\* | `boolean` | Whether the user can proceed — valid amount, quote available, and wallet connected. |
| `onReset`\* | `() => void` | Invalidates the active quote and clears the deposit, returning the widget to its initial state. |
#### CryptoOnrampProviderProps [#cryptoonrampproviderprops]
Props for [`CryptoOnrampWidgetProvider`](#cryptoonrampwidgetprovider) — configures the target tokens and payment methods exposed to the widget, plus optional chain display overrides.
| Field | Type | Description |
| ----------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tokens` | CryptoOnrampToken \[] | Target tokens (what the user buys on TON). Defaults to a built-in list. |
| `tokenSections` | CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `paymentMethods` | CryptoPaymentMethod \[] | Source crypto payment methods (what the user pays with on another chain). Defaults to a built-in list. |
| `methodSections` | PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `chains` | Record\ChainInfo> | Custom CAIP-2 → chain display info overrides. Merged on top of the built-in defaults, so consumers only need to provide what they want to override or add — for example, a single entry keyed by `'eip155:42161'` with a `name` of `'Arbitrum'` and a `logo` URL. |
| `defaultTokenId` | `string` | ID of the target token pre-selected on mount. |
| `defaultMethodId` | `string` | ID of the source payment method pre-selected on mount. |
#### CryptoOnrampToken [#cryptoonramptoken]
Target token (what the user is buying on TON) in the crypto onramp widget. Kept separate from `AppkitUIToken` because `address` is the raw form expected by the onramp provider (e.g. `"0x0000000000000000000000000000000000000000"` for native TON, `"EQCx..."` for USDT jetton master).
| Field | Type | Description |
| ------------ | -------- | ------------------------------------------------------------------ |
| `id`\* | `string` | Stable identifier used by section configs and pre-selection props. |
| `symbol`\* | `string` | Token symbol, e.g. `"TON"`, `"USDT"`. |
| `name`\* | `string` | Full token name, e.g. `"Toncoin"`, `"Tether"`. |
| `decimals`\* | `number` | Number of decimals for the token. |
| `address`\* | `string` | Address as the onramp provider expects it. |
| `logo` | `string` | Optional logo URL. |
#### CryptoOnrampTokenSectionConfig [#cryptoonramptokensectionconfig]
Section configuration grouping [`CryptoOnrampToken`](#cryptoonramptoken) entries by id in a picker.
| Field | Type | Description |
| --------- | ---------- | ---------------------------------------------------------------------------------------------- |
| `title`\* | `string` | Section header (typically already localized by the caller). |
| `ids`\* | `string[]` | Ids of [`CryptoOnrampToken`](#cryptoonramptoken) entries to include in this section, in order. |
#### CryptoOnrampWidgetProps [#cryptoonrampwidgetprops]
Props for [`CryptoOnrampWidget`](#cryptoonrampwidget) — extends [`CryptoOnrampProviderProps`](#cryptoonrampproviderprops) (tokens, payment methods, defaults, chain overrides) plus the native `` props the widget root forwards.
| Field | Type | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` |
(props: CryptoOnrampWidgetRenderProps ) => ReactNode | Custom render function. When provided, replaces the default [`CryptoOnrampWidgetUI`](#cryptoonrampwidgetui) and is called with the full [`CryptoOnrampWidgetRenderProps`](#cryptoonrampwidgetrenderprops) (context state, actions and forwarded `
` props), so callers can build a fully custom UI on top of the same provider. |
| `tokens` |
CryptoOnrampToken \[] | Target tokens (what the user buys on TON). Defaults to a built-in list. |
| `tokenSections` |
CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `paymentMethods` |
CryptoPaymentMethod \[] | Source crypto payment methods (what the user pays with on another chain). Defaults to a built-in list. |
| `methodSections` |
PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `chains` |
Record\ChainInfo> | Custom CAIP-2 → chain display info overrides. Merged on top of the built-in defaults, so consumers only need to provide what they want to override or add — for example, a single entry keyed by `'eip155:42161'` with a `name` of `'Arbitrum'` and a `logo` URL. |
| `defaultTokenId` | `string` | ID of the target token pre-selected on mount. |
| `defaultMethodId` | `string` | ID of the source payment method pre-selected on mount. |
#### CryptoOnrampWidgetRenderProps [#cryptoonrampwidgetrenderprops]
Props for [`CryptoOnrampWidgetUI`](#cryptoonrampwidgetui) (and for the custom render callback on [`CryptoOnrampWidget`](#cryptoonrampwidget)) — the full [`CryptoOnrampContextType`](#cryptoonrampcontexttype) state and actions, plus the native `
` props the widget root forwards (`className`, `style`, etc.).
| Field | Type | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `tokens`\* |
CryptoOnrampToken \[] | Full list of target tokens the user can buy. |
| `tokenSections` |
CryptoOnrampTokenSectionConfig \[] | Optional section configs grouping `tokens` in the picker. |
| `selectedToken`\* |
CryptoOnrampToken \| null | Currently selected target token to buy. `null` until tokens load. |
| `setSelectedToken`\* |
(token: CryptoOnrampToken ) => void | Updates `selectedToken`. |
| `paymentMethods`\* |
CryptoPaymentMethod \[] | Available source crypto payment methods. |
| `methodSections` |
PaymentMethodSectionConfig \[] | Optional section configs grouping `paymentMethods` in the picker. |
| `selectedMethod`\* |
CryptoPaymentMethod | Currently selected source payment method. |
| `setSelectedMethod`\* |
(method: CryptoPaymentMethod ) => void | Updates `selectedMethod`. |
| `chains`\* |
Record\ChainInfo> | CAIP-2 → chain display info map (built-in defaults merged with consumer overrides). |
| `amount`\* | `string` | Current amount input value as a decimal string. |
| `setAmount`\* | `(value: string) => void` | Updates `amount`. |
| `amountInputMode`\* |
CryptoAmountInputMode | Which side `amount` is denominated in — see [`CryptoAmountInputMode`](#cryptoamountinputmode). |
| `setAmountInputMode`\* |
(mode: CryptoAmountInputMode ) => void | Updates `amountInputMode`. |
| `convertedAmount`\* | `string` | Other side of `amount` after applying the current quote's rate. |
| `presetAmounts`\* |
OnrampAmountPreset \[] | Quick-pick amount buttons rendered in the widget. |
| `quote`\* |
CryptoOnrampQuote \| null | Current quote, or `null` if not yet fetched / invalidated. |
| `isLoadingQuote`\* | `boolean` | Whether a quote is in flight (includes the input-debounce window). |
| `quoteError`\* | `string \| null` | Quote-side validation/fetch error as an i18n key, or `null`. |
| `quoteProviderName`\* | `string \| null` | Display name of the provider behind the current quote, when available. |
| `deposit`\* |
CryptoOnrampDeposit \| null | Current deposit returned by the provider once `createDeposit` succeeded. |
| `isCreatingDeposit`\* | `boolean` | Whether `createDeposit` is in flight. |
| `depositError`\* | `string \| null` | Deposit-side error as an i18n key, or `null`. |
| `depositAmount`\* | `string` | Formatted deposit amount the user must send on the source chain. |
| `createDeposit`\* | `() => void` | Triggers deposit creation from the current quote. |
| `depositStatus`\* |
CryptoOnrampStatus \| null | Latest deposit status polled via [`useCryptoOnrampStatus`](#usecryptoonrampstatus), or `null`. |
| `isRefundAddressRequired`\* | `boolean` | Whether the current quote provider requires a refund address before deposit. |
| `isReversedAmountSupported`\* | `boolean` | Whether the current quote provider supports reversed (target-amount) input. |
| `refundAddress`\* | `string` | Refund address the user typed, if `isRefundAddressRequired`. |
| `setRefundAddress`\* | `(address: string) => void` | Updates `refundAddress`. |
| `targetBalance`\* | `string` | Connected wallet's balance of the selected target token (formatted, token units). |
| `isLoadingTargetBalance`\* | `boolean` | Whether the target token balance is being fetched. |
| `isWalletConnected`\* | `boolean` | Whether a TON wallet is currently connected. |
| `canContinue`\* | `boolean` | Whether the user can proceed — valid amount, quote available, and wallet connected. |
| `onReset`\* | `() => void` | Invalidates the active quote and clears the deposit, returning the widget to its initial state. |
#### CryptoPaymentMethod [#cryptopaymentmethod]
Source crypto payment method (what the user pays with on another chain) in the crypto onramp widget.
| Field | Type | Description |
| ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`\* | `string` | Stable identifier for the method — used for selection state and `methodSections.ids` |
| `symbol`\* | `string` | Token symbol, e.g. "USDC", "USDT". |
| `name`\* | `string` | Full token name shown in the picker, e.g. "USD Coin", "Tether". |
| `chain`\* | `string` | Source chain in CAIP-2 format, e.g. "eip155:8453", "eip155:56" — passed as `sourceChain` to the onramp provider. The widget resolves a display name and logo for it via the `chains` map (see `CryptoOnrampWidgetProvider`). |
| `decimals`\* | `number` | Number of decimals for the token (used to convert between display and base units) |
| `address`\* | `string` | Token contract address on the source network (empty string / zero address for native) |
| `logo` | `string` | Token logo URL shown in the picker and selectors. |
#### OnrampAmountPreset [#onrampamountpreset]
Quick-pick amount button shown above the crypto-onramp input (carried on [`CryptoOnrampContextType`](#cryptoonrampcontexttype)'s `presetAmounts`).
| Field | Type | Description |
| ---------- | -------- | ------------------------------------------------------- |
| `amount`\* | `string` | Amount value the preset sets on click (decimal string). |
| `label`\* | `string` | Button label shown to the user. |
#### PaymentMethodSectionConfig [#paymentmethodsectionconfig]
Section configuration grouping [`CryptoPaymentMethod`](#cryptopaymentmethod) entries by id in a picker.
| Field | Type | Description |
| --------- | ---------- | -------------------------------------------------------------------------------------------------- |
| `title`\* | `string` | Section header (typically already localized by the caller). |
| `ids`\* | `string[]` | Ids of [`CryptoPaymentMethod`](#cryptopaymentmethod) entries to include in this section, in order. |
#### UseCreateCryptoOnrampDepositParameters [#usecreatecryptoonrampdepositparameters]
Parameters accepted by [`useCreateCryptoOnrampDeposit`](#usecreatecryptoonrampdeposit) — TanStack Query mutation options forwarded via `parameters.mutation`.
```ts
type UseCreateCryptoOnrampDepositParameters = CreateCryptoOnrampDepositMutationOptions
;
```
#### UseCreateCryptoOnrampDepositReturnType [#usecreatecryptoonrampdepositreturntype]
Return type of [`useCreateCryptoOnrampDeposit`](#usecreatecryptoonrampdeposit) — TanStack Query mutation result.
```ts
type UseCreateCryptoOnrampDepositReturnType = UseMutationResult<
CreateCryptoOnrampDepositData,
CreateCryptoOnrampDepositErrorType,
CreateCryptoOnrampDepositVariables,
context
>;
```
#### UseCryptoOnrampProviderParameters [#usecryptoonrampproviderparameters]
Parameters accepted by [`useCryptoOnrampProvider`](#usecryptoonrampprovider) — optional provider id forwarded to [`getCryptoOnrampProvider`](/applications/appkit/reference/appkit#getcryptoonrampprovider).
```ts
type UseCryptoOnrampProviderParameters = GetCryptoOnrampProviderOptions;
```
#### UseCryptoOnrampProviderReturnType [#usecryptoonrampproviderreturntype]
Return type of [`useCryptoOnrampProvider`](#usecryptoonrampprovider) — the matching [`CryptoOnrampProviderInterface`](/applications/appkit/reference/appkit#cryptoonrampproviderinterface), or `undefined` when none is registered (the hook swallows the throw from [`getCryptoOnrampProvider`](/applications/appkit/reference/appkit#getcryptoonrampprovider)).
```ts
type UseCryptoOnrampProviderReturnType = GetCryptoOnrampProviderReturnType | undefined;
```
#### UseCryptoOnrampProvidersReturnType [#usecryptoonrampprovidersreturntype]
Return type of [`useCryptoOnrampProviders`](#usecryptoonrampproviders) — array of every [`CryptoOnrampProviderInterface`](/applications/appkit/reference/appkit#cryptoonrampproviderinterface) currently registered on the AppKit instance.
```ts
type UseCryptoOnrampProvidersReturnType = GetCryptoOnrampProvidersReturnType;
```
#### UseCryptoOnrampQuoteParameters [#usecryptoonrampquoteparameters]
Parameters accepted by [`useCryptoOnrampQuote`](#usecryptoonrampquote) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the source/target assets, amount and optional provider override forwarded to [`getCryptoOnrampQuote`](/applications/appkit/reference/appkit#getcryptoonrampquote).
| Field | Type | Description |
| ----------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount` | `string` | Amount to onramp (either source or target crypto, depending on isSourceAmount) |
| `sourceCurrencyAddress` | `string` | Source crypto currency address (contract address or 0x0... for native) |
| `sourceChain` | `string` | Source chain identifier in CAIP-2 format (e.g. 'eip155:1' for Ethereum mainnet, 'eip155:42161' for Arbitrum One). Providers map this to their own chain identifiers internally. |
| `targetCurrencyAddress` | `string` | Target crypto currency address on TON (contract address or 0x0... for native) |
| `recipientAddress` | `string` | TON address that will receive the target crypto. |
| `refundAddress` | `string` | Refund address for the source crypto. |
| `isSourceAmount` | `boolean` | If true, `amount` is the source amount to spend. If false, `amount` is the target amount to receive. Defaults to true when omitted. |
| `providerOptions` | `TProviderOptions = unknown` | Provider-specific options. |
| `providerId` | `string` | Provider to quote against. Defaults to the registered default provider. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseCryptoOnrampQuoteReturnType [#usecryptoonrampquotereturntype]
Return type of [`useCryptoOnrampQuote`](#usecryptoonrampquote) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseCryptoOnrampQuoteReturnType = UseQueryReturnType<
selectData,
GetCryptoOnrampQuoteErrorType
>;
```
#### UseCryptoOnrampStatusParameters [#usecryptoonrampstatusparameters]
Parameters accepted by [`useCryptoOnrampStatus`](#usecryptoonrampstatus) — TanStack Query options (`select`, `enabled`, `refetchInterval`, …) plus the deposit id, originating provider id and optional provider override forwarded to [`getCryptoOnrampStatus`](/applications/appkit/reference/appkit#getcryptoonrampstatus).
| Field | Type | Description |
| ------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `depositId` | `string` | Deposit id. |
| `providerId` | `string` | Identifier of the provider that issued this deposit. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseCryptoOnrampStatusReturnType [#usecryptoonrampstatusreturntype]
Return type of [`useCryptoOnrampStatus`](#usecryptoonrampstatus) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseCryptoOnrampStatusReturnType = UseQueryReturnType<
selectData,
GetCryptoOnrampStatusErrorType
>;
```
### Jettons [#jettons-1]
#### UseJettonBalanceByAddressParameters [#usejettonbalancebyaddressparameters]
Parameters accepted by [`useJettonBalanceByAddress`](#usejettonbalancebyaddress) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the jetton master, owner address, decimals and optional network override.
| Field | Type | Description |
| ---------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jettonAddress` | UserFriendlyAddress | Jetton master contract address (the token, not the user's wallet for it). |
| `ownerAddress` | UserFriendlyAddress | Owner of the jetton wallet — typically the connected user's address. |
| `jettonDecimals` | `number` | Decimals declared by the jetton master. Used to format the raw balance into a human-readable string. |
| `network` | Network | Network to read the balance from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseJettonBalanceByAddressReturnType [#usejettonbalancebyaddressreturntype]
Return type of [`useJettonBalanceByAddress`](#usejettonbalancebyaddress) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseJettonBalanceByAddressReturnType = UseQueryReturnType<
selectData,
GetJettonBalanceErrorType
>;
```
#### UseJettonInfoParameters [#usejettoninfoparameters]
Parameters accepted by [`useJettonInfo`](#usejettoninfo) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the jetton master address and optional network override.
| Field | Type | Description |
| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress | Jetton master contract address whose metadata is being fetched. |
| `network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseJettonInfoReturnType [#usejettoninforeturntype]
Return type of [`useJettonInfo`](#usejettoninfo) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions. `data` is `null` when the indexer has no record for that master address.
```ts
type UseJettonInfoReturnType = UseQueryReturnType<
selectData,
GetJettonInfoErrorType
>;
```
#### UseJettonWalletAddressParameters [#usejettonwalletaddressparameters]
Parameters accepted by [`useJettonWalletAddress`](#usejettonwalletaddress) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the jetton master, owner address and optional network override.
| Field | Type | Description |
| --------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jettonAddress` | UserFriendlyAddress | Jetton master contract address. |
| `ownerAddress` | UserFriendlyAddress | Owner whose jetton wallet should be derived. |
| `network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseJettonWalletAddressReturnType [#usejettonwalletaddressreturntype]
Return type of [`useJettonWalletAddress`](#usejettonwalletaddress) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseJettonWalletAddressReturnType = UseQueryReturnType<
selectData,
GetJettonWalletAddressErrorType
>;
```
#### UseJettonsByAddressParameters [#usejettonsbyaddressparameters]
Parameters accepted by [`useJettonsByAddress`](#usejettonsbyaddress) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the owner address, optional network override and pagination.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read the jettons from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `limit` | `number` | Maximum number of jettons to return. |
| `offset` | `number` | Number of jettons to skip before returning results — used for pagination. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseJettonsByAddressReturnType [#usejettonsbyaddressreturntype]
Return type of [`useJettonsByAddress`](#usejettonsbyaddress) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseJettonsByAddressReturnType = UseQueryReturnType<
selectData,
GetJettonsErrorType
>;
```
#### UseJettonsParameters [#usejettonsparameters]
Parameters accepted by [`useJettons`](#usejettons) — same shape as [`UseJettonsByAddressParameters`](#usejettonsbyaddressparameters). The hook resolves `address` from the selected wallet and overrides any value supplied here.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read the jettons from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `limit` | `number` | Maximum number of jettons to return. |
| `offset` | `number` | Number of jettons to skip before returning results — used for pagination. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseJettonsReturnType [#usejettonsreturntype]
Return type of [`useJettons`](#usejettons) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseJettonsReturnType = UseJettonsByAddressReturnType;
```
#### UseTransferJettonParameters [#usetransferjettonparameters]
Parameters accepted by [`useTransferJetton`](#usetransferjetton) — TanStack Query mutation options.
```ts
type UseTransferJettonParameters = TransferJettonOptions;
```
#### UseTransferJettonReturnType [#usetransferjettonreturntype]
Return type of [`useTransferJetton`](#usetransferjetton) — TanStack Query mutation result.
```ts
type UseTransferJettonReturnType = UseMutationReturnType<
TransferJettonData,
TransferJettonErrorType,
TransferJettonVariables,
context,
(
variables: TransferJettonVariables,
options?: MutateOptions,
) => void,
MutateFunction
>;
```
#### UseWatchJettonsByAddressParameters [#usewatchjettonsbyaddressparameters]
Parameters accepted by [`useWatchJettonsByAddress`](#usewatchjettonsbyaddress) — same fields as [`WatchJettonsByAddressOptions`](/applications/appkit/reference/appkit#watchjettonsbyaddressoptions), all optional so callers can render the hook before the address is known.
```ts
type UseWatchJettonsByAddressParameters = Partial;
```
#### UseWatchJettonsParameters [#usewatchjettonsparameters]
Parameters accepted by [`useWatchJettons`](#usewatchjettons) — update callback and optional network override. The hook resolves the address from the selected wallet.
```ts
type UseWatchJettonsParameters = Partial;
```
### NFTs [#nfts-2]
#### NftItemProps [#nftitemprops]
Props accepted by [`NftItem`](#nftitem) — extends the native `` props (`onClick`, `disabled`, `className`, …) with the NFT to render.
| Field | Type | Description |
| ------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `nft`\* | NFT | NFT to render — name, collection name, image and on-sale state are derived via `getFormattedNftInfo`. |
#### UseNFTsByAddressParameters [#usenftsbyaddressparameters]
Parameters accepted by [`useNftsByAddress`](#usenftsbyaddress) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the owner address, optional pagination (`limit`, `offset`) and network override.
The `network` field defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read NFTs from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `limit` | `number` | Maximum number of NFTs to return. |
| `offset` | `number` | Number of NFTs to skip before returning results — used for pagination. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseNFTsByAddressReturnType [#usenftsbyaddressreturntype]
Return type of [`useNftsByAddress`](#usenftsbyaddress) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseNFTsByAddressReturnType = UseQueryReturnType;
```
#### UseNFTsParameters [#usenftsparameters]
Parameters accepted by [`useNfts`](#usenfts) — same shape as [`UseNFTsByAddressParameters`](#usenftsbyaddressparameters). The hook resolves `address` from the selected wallet and overrides any value supplied here.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address` | UserFriendlyAddress \| Address | Owner address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to read NFTs from. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `limit` | `number` | Maximum number of NFTs to return. |
| `offset` | `number` | Number of NFTs to skip before returning results — used for pagination. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseNFTsReturnType [#usenftsreturntype]
Return type of [`useNfts`](#usenfts) — TanStack Query result carrying `data`, `isLoading`, `error` and the standard companions.
```ts
type UseNFTsReturnType = UseNFTsByAddressReturnType;
```
#### UseNftParameters [#usenftparameters]
Parameters accepted by [`useNft`](#usenft) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the NFT contract address and optional network override.
The `network` field defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `address` | UserFriendlyAddress \| Address | NFT contract address — pass a [`UserFriendlyAddress`](/applications/appkit/reference/appkit#userfriendlyaddress) string or an `Address` instance from `@ton/core`. |
| `network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseNftReturnType [#usenftreturntype]
Return type of [`useNft`](#usenft) — TanStack Query result carrying `data` (the NFT or `null` when the indexer has no record), `isLoading`, `error` and the standard companions.
```ts
type UseNftReturnType = UseQueryReturnType;
```
#### UseTransferNftParameters [#usetransfernftparameters]
Parameters accepted by [`useTransferNft`](#usetransfernft) — TanStack Query mutation options.
```ts
type UseTransferNftParameters = TransferNftOptions;
```
#### UseTransferNftReturnType [#usetransfernftreturntype]
Return type of [`useTransferNft`](#usetransfernft) — TanStack Query mutation result.
```ts
type UseTransferNftReturnType = UseMutationReturnType<
TransferNftData,
TransferNftErrorType,
TransferNftVariables,
context,
(
variables: TransferNftVariables,
options?: MutateOptions,
) => void,
MutateFunction
>;
```
### Networks [#networks-1]
#### UseBlockNumberParameters [#useblocknumberparameters]
Parameters accepted by [`useBlockNumber`](#useblocknumber) — TanStack Query options plus an optional network override. Defaults to the selected wallet's network. If no wallet is selected, falls back to mainnet.
| Field | Type | Description |
| --------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `network` | Network | Network to query. Defaults to mainnet when omitted. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseBlockNumberReturnType [#useblocknumberreturntype]
Return type of [`useBlockNumber`](#useblocknumber) — TanStack Query result.
```ts
type UseBlockNumberReturnType = UseQueryReturnType<
selectData,
GetBlockNumberErrorType
>;
```
#### UseDefaultNetworkReturnType [#usedefaultnetworkreturntype]
Return type of [`useDefaultNetwork`](#usedefaultnetwork) — `[network, setNetwork]` tuple. `network` is the current default (or `undefined`). `setNetwork` calls [`setDefaultNetwork`](/applications/appkit/reference/appkit#setdefaultnetwork) and emits `networks:default-changed`.
```ts
type UseDefaultNetworkReturnType = [
network: GetDefaultNetworkReturnType,
setNetwork: (network: Network | undefined) => void,
];
```
#### UseNetworkReturnType [#usenetworkreturntype]
Return type of [`useNetwork`](#usenetwork) — `undefined` when no wallet is currently selected.
```ts
type UseNetworkReturnType = Network | undefined;
```
#### UseNetworksReturnType [#usenetworksreturntype]
Return type of [`useNetworks`](#usenetworks) — same shape as [`GetNetworksReturnType`](/applications/appkit/reference/appkit#getnetworksreturntype).
```ts
type UseNetworksReturnType = GetNetworksReturnType;
```
### Providers [#providers-1]
#### I18nContextType [#i18ncontexttype]
Shape returned by [`useI18n`](#usei18n) — current locale, translation function and helpers to switch locales or merge new dictionaries at runtime.
| Field | Type | Description |
| ---------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `activeLocale`\* | `string` | Currently active locale code (e.g., `"en"`, `"ru"`). |
| `t`\* | `I18n['t']` | Translation function — accepts a key plus interpolation values and returns the localized string. |
| `locale`\* | `(lang: string, dict?: Dict) => void` | Switch to a new locale. Pass an optional `dict` to install translations alongside the switch. |
| `addDict`\* | `(lang: string, dict: Dict) => void` | Merge a translation dictionary for `lang` without changing the active locale. |
#### I18nProviderProps [#i18nproviderprops]
Props accepted by [`I18nProvider`](#i18nprovider).
| Field | Type | Description |
| ---------- | ---------------------- | -------------------------------------------------------------------------------------------- |
| `locale` | `string` | Initial locale code. Defaults to the i18n library's default when omitted. |
| `lngDicts` | `Record` | Translation dictionaries keyed by locale. Loaded into the underlying i18n instance on mount. |
### Settings [#settings-1]
#### AppKitTheme [#appkittheme]
Theme value accepted by [`useAppKitTheme`](#useappkittheme) — `'light'`, `'dark'`, or any custom string mapped to a `data-ta-theme` token in the host's CSS.
```ts
type AppKitTheme = 'light' | 'dark' | string;
```
### Shared [#shared-1]
#### AmountPreset [#amountpreset]
Single preset entry rendered as a button in [`AmountPresets`](#amountpresets).
| Field | Type | Description |
| ---------- | ------------ | ------------------------------------------------------------------------------------------------------ |
| `label`\* | `string` | Text shown inside the button (e.g., `"25%"`, `"Max"`, `"100"`). |
| `amount`\* | `string` | Value passed to [`AmountPresetsProps.onPresetSelect`](#amountpresetsprops) when the button is clicked. |
| `onSelect` | `() => void` | Optional custom click handler — when set, it runs instead of `onPresetSelect`. |
#### AmountPresetsProps [#amountpresetsprops]
Props accepted by [`AmountPresets`](#amountpresets).
| Field | Type | Description |
| ------------------ | -------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `presets`\* | AmountPreset \[] | Preset buttons to render, in order. |
| `currencySymbol` | `string` | Optional symbol (e.g., `"$"`) prepended to each preset label. |
| `onPresetSelect`\* | `(value: string) => void` | Called with the selected preset's `amount` unless the preset defines its own `onSelect`. |
#### AppkitUIToken [#appkituitoken]
UI-side token descriptor consumed by appkit-react widgets ([`SwapWidget`](#swapwidget), [`SwapField`](#swapfield), currency selectors, etc.) — identifies the token in the picker UI and carries display + on-chain fields the widget needs to render and quote.
| Field | Type | Description |
| ------------ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `id`\* | `string` | Stable id used for picker selection state and section grouping. |
| `symbol`\* | `string` | Ticker symbol shown in the picker and selector chip (e.g., `"TON"`, `"USDT"`). |
| `name`\* | `string` | Full token name shown in the picker (e.g., `"Toncoin"`). |
| `decimals`\* | `number` | Number of decimal places used to format raw amounts. |
| `address`\* | `string` | Token contract address. Pass `'ton'` for native TON; otherwise the jetton master's user-friendly address. |
| `logo` | `string` | Optional URL of the token logo shown in the picker and selector chip. |
| `rate` | `string` | Optional fiat exchange rate (`1 token = rate fiat units`). Used by widgets to render fiat conversions next to amounts. |
| `network`\* | Network | [`Network`](/applications/appkit/reference/appkit#network) the token lives on. Widgets filter their token universe by the active network. |
#### CopyButtonProps [#copybuttonprops]
Props accepted by [`CopyButton`](#copybutton).
| Field | Type | Description |
| -------------- | -------- | --------------------------------------------------------- |
| `value`\* | `string` | Text written to the clipboard when the button is clicked. |
| `aria-label`\* | `string` | Accessible label for screen readers. |
#### CurrencyItemProps [#currencyitemprops]
Props accepted by [`CurrencyItem`](#currencyitem) when used as a single-shot button. Passing `children` switches it into compound mode and bypasses these fields.
| Field | Type | Description |
| -------------- | --------- | ------------------------------------------------------------------------------------------------- |
| `ticker` | `string` | Token symbol (e.g., `"TON"`) — also used as the icon fallback and rendered in the secondary line. |
| `name` | `string` | Human-readable token name shown as the primary line. Falls back to `ticker` when absent. |
| `balance` | `string` | Main balance value shown on the right side (already-formatted string). |
| `underBalance` | `string` | Optional secondary value (e.g., fiat equivalent) shown beneath the main balance. |
| `icon` | `string` | URL of the token logo. |
| `isVerified` | `boolean` | When true, renders a verified checkmark badge next to the name. |
#### CurrencySelectListContainerProps [#currencyselectlistcontainerprops]
Props accepted by [`CurrencySelect.ListContainer`](#currencyselect).
| Field | Type | Description |
| ----------- | --------- | ------------------------------------------------------------------ |
| `isEmpty`\* | `boolean` | When true, renders the built-in empty state instead of `children`. |
#### CurrencySelectSearchProps [#currencyselectsearchprops]
Props accepted by [`CurrencySelect.Search`](#currencyselect).
| Field | Type | Description | | |
| ------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------- | --- | ------------------------- |
| `searchValue`\* | `string` | Current search query. | | |
| `onSearchChange`\* | `(value: string) => void` | Called whenever the user types in the search input. | | |
| `placeholder` | `string` | Placeholder text shown when the input is empty. | | |
| `size` | `InputSize` | Size token applied to the input control(s) inside: \`'s' | 'm' | 'l'`. Defaults to `'m'\`. |
| `variant` | `InputVariant` | Visual variant: `'default'` paints a filled field. `'unstyled'` drops the chrome. | | |
| `loading` | `boolean` | When true, [`Input.Input`](#input) renders a skeleton placeholder instead of an ` `. | | |
| `disabled` | `boolean` | When true, descendant input controls are disabled. | | |
| `error` | `boolean` | When true, the field renders in error styling and [`Input.Caption`](#input) switches to error text. | | |
| `resizable` | `boolean` | When true, [`Input.Input`](#input) scales its font down to fit the available width as the user types. | | |
#### LowBalanceModalProps [#lowbalancemodalprops]
Props accepted by [`LowBalanceModal`](#lowbalancemodal).
| Field | Type | Description |
| --------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls visibility of the modal. |
| `mode`\* | LowBalanceMode | `reduce` — user can fix it by reducing the amount (shows Change/Cancel). `topup` — reducing doesn't help, user must top up TON (shows Close only). |
| `requiredTon`\* | `string` | Required amount in TON, formatted as a decimal string (e.g. `"0.423"`). |
| `onChange`\* | `() => void` | Called when the user clicks the primary "Change" action (only in `reduce` mode). |
| `onCancel`\* | `() => void` | Called when the user dismisses the modal (Cancel, Close, or backdrop click). |
#### LowBalanceMode [#lowbalancemode]
Behavior mode for [`LowBalanceModal`](#lowbalancemodal) — see [`LowBalanceModalProps.mode`](#lowbalancemodalprops).
```ts
type LowBalanceMode = 'reduce' | 'topup';
```
#### OptionSwitcherOption [#optionswitcheroption]
Single entry rendered as an item inside [`OptionSwitcher`](#optionswitcher).
| Field | Type | Description |
| --------- | -------- | ------------------------------------------------------------------------------------------------- |
| `value`\* | `string` | Stable value passed back to [`OptionSwitcherProps.onChange`](#optionswitcherprops) when selected. |
| `label`\* | `string` | Human-readable label shown in the trigger and dropdown item. |
#### OptionSwitcherProps [#optionswitcherprops]
Props accepted by [`OptionSwitcher`](#optionswitcher).
| Field | Type | Description |
| ------------ | ------------------------------------------------------------------------ | ----------------------------------------------------- |
| `value`\* | `string \| undefined` | Currently selected option value. |
| `options`\* | OptionSwitcherOption \[] | Available options. |
| `onChange`\* | `(value: string) => void` | Called when the user picks an option. |
| `disabled` | `boolean` | When true, the trigger is non-interactive and dimmed. |
| `className` | `string` | Extra class applied to the trigger button. |
#### SettingsButtonProps [#settingsbuttonprops]
Props accepted by [`SettingsButton`](#settingsbutton) — extends the base [`Button`](#button) props.
| Field | Type | Description |
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onClick` | `() => void` | Click handler — typically used to open a settings modal. |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
| `icon` | `ReactNode` | Optional leading icon rendered before `children` when not loading. |
#### TokenBase [#tokenbase]
Minimal shape every token in [`TokenSelectModal`](#tokenselectmodal) must satisfy. Callers may use richer types (e.g., `AppkitUIToken`) — `TokenBase` only fixes the fields the modal reads.
| Field | Type | Description |
| ----------- | -------- | ----------------------------------------------------------------------------------------------- |
| `id`\* | `string` | Stable identifier used to match tokens against [`TokenSectionConfig.ids`](#tokensectionconfig). |
| `symbol`\* | `string` | Ticker (e.g., `"TON"`) — used for display and search matching. |
| `name`\* | `string` | Human-readable name — used for display and search matching. |
| `address`\* | `string` | Token contract address — used for exact-address search matching and as the React `key`. |
| `logo` | `string` | Optional logo URL. |
#### TokenSectionConfig [#tokensectionconfig]
Configuration that maps token `id`s to a named section in [`TokenSelectModal`](#tokenselectmodal). Tokens not covered are placed in an "Other tokens" trailing section.
| Field | Type | Description |
| --------- | ---------- | -------------------------------------------------------------------------------- |
| `title`\* | `string` | Section header label. |
| `ids`\* | `string[]` | [`TokenBase.id`](#tokenbase) values to include in this section, in render order. |
#### TokenSelectModalProps [#tokenselectmodalprops]
Props accepted by [`TokenSelectModal`](#tokenselectmodal).
| Field | Type | Description |
| ------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls modal visibility. |
| `onClose`\* | `() => void` | Called when the modal is dismissed (selection, backdrop click, or escape). |
| `tokens`\* | T = AppkitUIToken \[] | Full set of tokens available for selection and search. |
| `tokenSections` | TokenSectionConfig \[] | Optional sectioning rules. When omitted, all tokens render as a single untitled section. |
| `onSelect`\* | (token: T = AppkitUIToken ) => void | Called with the picked token. The modal closes and resets its search on selection. |
| `title`\* | `string` | Modal header title. |
| `searchPlaceholder` | `string` | Placeholder shown inside the search input. |
#### TokenSelectorProps [#tokenselectorprops]
Props accepted by [`TokenSelector`](#tokenselector) — extends the base [`Button`](#button) props.
| Field | Type | Description |
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`\* | `string` | Label shown next to the icon — typically the token symbol. |
| `icon` | `string` | Token logo URL. |
| `iconFallback` | `string` | Single-character fallback used when `icon` fails to load. Defaults to the first character of `title`. |
| `networkIcon` | `string` | When provided, renders a network badge overlay on the icon. |
| `readOnly` | `boolean` | Hide chevron and suppress click handling — use when there's nothing to pick. |
| `size` | `ButtonSize` | Size class applied to the button. Pass `'unset'` to skip the size class entirely (no padding, no typography) — useful with `variant="unstyled"`. |
| `borderRadius` | `ButtonBorderRadius` | Border radius token. Defaults to a size-dependent value (`s` → `2xl`, `m` → `l`, `l` → `xl`). |
| `variant` | `ButtonVariant` | Visual variant. Use `'unstyled'` to opt out of all built-in styling — the consumer is fully responsible for visuals via `className`. The Button still provides ref forwarding, `disabled`/`loading` plumbing, and `icon`/`children` rendering. |
| `loading` | `boolean` | When true, renders a spinner instead of `icon`/`children` and disables the button. |
| `fullWidth` | `boolean` | When true, the button stretches to fill its container width. |
### Signing [#signing-1]
#### UseSignBinaryParameters [#usesignbinaryparameters]
Parameters accepted by [`useSignBinary`](#usesignbinary) — TanStack Query mutation options.
```ts
type UseSignBinaryParameters = SignBinaryOptions;
```
#### UseSignBinaryReturnType [#usesignbinaryreturntype]
Return type of [`useSignBinary`](#usesignbinary) — TanStack Query mutation result.
```ts
type UseSignBinaryReturnType = UseMutationResult<
SignBinaryData,
SignBinaryErrorType,
SignBinaryVariables,
context
>;
```
#### UseSignCellParameters [#usesigncellparameters]
Parameters accepted by [`useSignCell`](#usesigncell) — TanStack Query mutation options.
```ts
type UseSignCellParameters = SignCellOptions;
```
#### UseSignCellReturnType [#usesigncellreturntype]
Return type of [`useSignCell`](#usesigncell) — TanStack Query mutation result.
```ts
type UseSignCellReturnType = UseMutationResult<
SignCellData,
SignCellErrorType,
SignCellVariables,
context
>;
```
#### UseSignTextParameters [#usesigntextparameters]
Parameters accepted by [`useSignText`](#usesigntext) — TanStack Query mutation options.
```ts
type UseSignTextParameters = SignTextOptions;
```
#### UseSignTextReturnType [#usesigntextreturntype]
Return type of [`useSignText`](#usesigntext) — TanStack Query mutation result.
```ts
type UseSignTextReturnType = UseMutationResult<
SignTextData,
SignTextErrorType,
SignTextVariables,
context
>;
```
### Staking [#staking-2]
#### SelectUnstakeModeProps [#selectunstakemodeprops]
Props accepted by [`SelectUnstakeMode`](#selectunstakemode).
| Field | Type | Description |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `value`\* | UnstakeModes | Currently selected unstake mode (see [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode)). |
| `onValueChange`\* | (mode: UnstakeModes ) => void | Called when the user picks a different mode. |
| `providerInfo`\* | StakingProviderInfo \| undefined | Dynamic provider info — used to show the instant-unstake limit when available. |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Static provider metadata — supplies `supportedUnstakeModes` and stake-token formatting. |
#### StakingBalanceBlockProps [#stakingbalanceblockprops]
Props accepted by [`StakingBalanceBlock`](#stakingbalanceblock).
| Field | Type | Description |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Provider metadata — supplies the stake/receive tokens (address, ticker, decimals). |
| `direction`\* | StakingQuoteDirection | Operation direction. Selects which token and balance to render. |
| `stakedBalance` | `string` | User's currently staked amount, used when `direction === 'unstake'`. |
| `isStakedBalanceLoading` | `boolean` | True while the staked balance is being fetched. |
| `balance` | `string` | User's wallet balance of the stake token, used when `direction === 'stake'`. |
| `isBalanceLoading` | `boolean` | True while the wallet balance is being fetched. |
| `onMaxClick` | `() => void` | When provided, renders a `MAX` button that invokes this callback. |
#### StakingContextType [#stakingcontexttype]
Shape of the staking context exposed by [`StakingWidgetProvider`](#stakingwidgetprovider) and read via [`useStakingContext`](#usestakingcontext). Aggregates inputs (amount, direction, unstake mode), fetched data (balances, quote, provider info/metadata), derived flags (`canSubmit`, `error`, loading states), and the actions used by [`StakingWidgetUI`](#stakingwidgetui) (send transaction, switch provider, max, low-balance handling).
| Field | Type | Description |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount`\* | `string` | Amount the user wants to stake (string to preserve input UX) |
| `canSubmit`\* | `boolean` | Whether the user can proceed with staking (checks balance, amount validity, etc.) |
| `quote`\* | StakingQuote \| undefined | Raw staking quote from the provider |
| `isQuoteLoading`\* | `boolean` | True while the stake quote is being fetched |
| `error`\* | `string \| null` | Current validation/fetch error for staking, null when everything is ok |
| `providerInfo`\* | StakingProviderInfo \| undefined | Staking provider dynamic info (APY, instant unstake availability, etc.) |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Staking provider static metadata |
| `stakingProvider`\* | StakingProvider \| undefined | Currently selected staking provider (defaults to the first registered one) |
| `stakingProviders`\* | StakingProvider \[] | All registered staking providers |
| `setStakingProviderId`\* | `(providerId: string) => void` | Updates the selected staking provider |
| `network`\* | Network \| undefined | Network the widget is operating on (resolved from prop or wallet) |
| `direction`\* | StakingQuoteDirection | Current operation direction: 'stake' or 'unstake' |
| `isProviderInfoLoading`\* | `boolean` | True while provider info is being fetched |
| `balance`\* | `string \| undefined` | Base balance (native or jetton) available for staking |
| `isBalanceLoading`\* | `boolean` | True while base balance is being fetched |
| `stakedBalance`\* | StakingBalance \| undefined | User's currently staked balance |
| `isStakedBalanceLoading`\* | `boolean` | True while staked balance is being fetched |
| `unstakeMode`\* | UnstakeModes | Selected unstake-timing mode — `'INSTANT'`, `'WHEN_AVAILABLE'`, or `'ROUND_END'`. See [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode). |
| `setAmount`\* | `(amount: string) => void` | Sets the input amount |
| `setUnstakeMode`\* | (mode: UnstakeModes ) => void | Sets the unstake mode |
| `sendTransaction`\* | `() => Promise` | Triggers the staking/unstaking transaction |
| `onChangeDirection`\* | (direction: StakingQuoteDirection ) => void | Changes the direction (stake/unstake) |
| `isSendingTransaction`\* | `boolean` | True while a transaction is being processed |
| `isReversed`\* | `boolean` | True if the user is inputting the output amount ("I want to get X") |
| `toggleReversed`\* | `() => void` | Toggles between inputting from amount and output amount |
| `reversedAmount`\* | `string` | Amount displayed in the reversed (bottom) input |
| `onMaxClick`\* | `() => void` | Sets the input amount to the maximum available balance (leaves room for TON gas on native stake) |
| `isLowBalanceWarningOpen`\* | `boolean` | True when the built transaction outflow exceeds the user's TON balance |
| `lowBalanceMode`\* | `'reduce' \| 'topup'` | `reduce` when the outgoing token is TON (user can fix by changing amount), `topup` otherwise. |
| `lowBalanceRequiredTon`\* | `string` | Required TON amount for the pending operation, formatted as a decimal string. Empty when no pending op. |
| `onLowBalanceChange`\* | `() => void` | Replace the input with a value that fits within the current TON balance and close the warning. |
| `onLowBalanceCancel`\* | `() => void` | Dismiss the low-balance warning without changing the input. |
#### StakingInfoProps [#stakinginfoprops]
Props accepted by [`StakingInfo`](#stakinginfo).
| Field | Type | Description |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `quote`\* | StakingQuote \| undefined | Current staking quote — its `amountOut` is rendered in the "You get" row. |
| `isQuoteLoading`\* | `boolean` | True while the quote is being fetched. Swaps the "You get" value for a skeleton. |
| `providerInfo`\* | StakingProviderInfo \| undefined | Dynamic provider info — supplies APY and exchange rate. |
| `providerMetadata`\* | StakingProviderMetadata \| undefined | Static provider metadata — supplies token tickers/decimals and the provider name. |
| `isProviderInfoLoading`\* | `boolean` | True while provider info is being fetched. |
| `direction` | StakingQuoteDirection | Operation direction — controls which token's decimals/ticker label the "You get" amount. Defaults to `'stake'`. |
#### StakingProviderProps [#stakingproviderprops]
Props accepted by [`StakingWidgetProvider`](#stakingwidgetprovider).
| Field | Type | Description |
| --------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `network` | Network | Network used for quote fetching, balance reads, and transactions. Falls back to the connected wallet's network when omitted. |
#### StakingSettingsModalProps [#stakingsettingsmodalprops]
Props accepted by [`StakingSettingsModal`](#stakingsettingsmodal).
| Field | Type | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `open`\* | `boolean` | Controls modal visibility. |
| `onClose`\* | `() => void` | Called when the user dismisses the modal or after a successful save. |
| `provider`\* | StakingProvider \| undefined | Currently active staking provider — used to preselect the option when the modal opens. |
| `providers`\* | StakingProvider \[] | All registered staking providers to choose from. |
| `onProviderChange`\* | `(providerId: string) => void` | Invoked with the chosen `providerId` when the user saves a different selection. |
| `network` | Network | Network used to resolve each provider's display name via its metadata. |
#### StakingWidgetProps [#stakingwidgetprops]
Props accepted by [`StakingWidget`](#stakingwidget). Extends [`StakingProviderProps`](#stakingproviderprops) (e.g. `network`) and standard `` props forwarded to the default UI.
| Field | Type | Description |
| ---------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` |
(props: StakingWidgetRenderProps ) => ReactNode | Optional render-prop. When provided, the default [`StakingWidgetUI`](#stakingwidgetui) is bypassed and this function is called with the full [`StakingWidgetRenderProps`](#stakingwidgetrenderprops) (context state + forwarded `
` props), letting consumers build a custom UI on top of the widget's internal logic. |
| `network` |
Network | Network used for quote fetching, balance reads, and transactions. Falls back to the connected wallet's network when omitted. |
#### StakingWidgetRenderProps [#stakingwidgetrenderprops]
Props accepted by [`StakingWidgetUI`](#stakingwidgetui) (also the argument type for the `StakingWidget` render-prop). Combines the full [`StakingContextType`](#stakingcontexttype) with standard `
` props forwarded to the outer wrapper.
| Field | Type | Description |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount`\* | `string` | Amount the user wants to stake (string to preserve input UX) |
| `canSubmit`\* | `boolean` | Whether the user can proceed with staking (checks balance, amount validity, etc.) |
| `quote`\* |
StakingQuote \| undefined | Raw staking quote from the provider |
| `isQuoteLoading`\* | `boolean` | True while the stake quote is being fetched |
| `error`\* | `string \| null` | Current validation/fetch error for staking, null when everything is ok |
| `providerInfo`\* |
StakingProviderInfo \| undefined | Staking provider dynamic info (APY, instant unstake availability, etc.) |
| `providerMetadata`\* |
StakingProviderMetadata \| undefined | Staking provider static metadata |
| `stakingProvider`\* |
StakingProvider \| undefined | Currently selected staking provider (defaults to the first registered one) |
| `stakingProviders`\* |
StakingProvider \[] | All registered staking providers |
| `setStakingProviderId`\* | `(providerId: string) => void` | Updates the selected staking provider |
| `network`\* |
Network \| undefined | Network the widget is operating on (resolved from prop or wallet) |
| `direction`\* |
StakingQuoteDirection | Current operation direction: 'stake' or 'unstake' |
| `isProviderInfoLoading`\* | `boolean` | True while provider info is being fetched |
| `balance`\* | `string \| undefined` | Base balance (native or jetton) available for staking |
| `isBalanceLoading`\* | `boolean` | True while base balance is being fetched |
| `stakedBalance`\* |
StakingBalance \| undefined | User's currently staked balance |
| `isStakedBalanceLoading`\* | `boolean` | True while staked balance is being fetched |
| `unstakeMode`\* |
UnstakeModes | Selected unstake-timing mode — `'INSTANT'`, `'WHEN_AVAILABLE'`, or `'ROUND_END'`. See [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode). |
| `setAmount`\* | `(amount: string) => void` | Sets the input amount |
| `setUnstakeMode`\* |
(mode: UnstakeModes ) => void | Sets the unstake mode |
| `sendTransaction`\* | `() => Promise
` | Triggers the staking/unstaking transaction |
| `onChangeDirection`\* | (direction: StakingQuoteDirection ) => void | Changes the direction (stake/unstake) |
| `isSendingTransaction`\* | `boolean` | True while a transaction is being processed |
| `isReversed`\* | `boolean` | True if the user is inputting the output amount ("I want to get X") |
| `toggleReversed`\* | `() => void` | Toggles between inputting from amount and output amount |
| `reversedAmount`\* | `string` | Amount displayed in the reversed (bottom) input |
| `onMaxClick`\* | `() => void` | Sets the input amount to the maximum available balance (leaves room for TON gas on native stake) |
| `isLowBalanceWarningOpen`\* | `boolean` | True when the built transaction outflow exceeds the user's TON balance |
| `lowBalanceMode`\* | `'reduce' \| 'topup'` | `reduce` when the outgoing token is TON (user can fix by changing amount), `topup` otherwise. |
| `lowBalanceRequiredTon`\* | `string` | Required TON amount for the pending operation, formatted as a decimal string. Empty when no pending op. |
| `onLowBalanceChange`\* | `() => void` | Replace the input with a value that fits within the current TON balance and close the warning. |
| `onLowBalanceCancel`\* | `() => void` | Dismiss the low-balance warning without changing the input. |
#### UseBuildStakeTransactionReturnType [#usebuildstaketransactionreturntype]
Return type of [`useBuildStakeTransaction`](#usebuildstaketransaction) — TanStack Query mutation result that resolves to a [`TransactionRequest`](/applications/appkit/reference/appkit#transactionrequest).
```ts
type UseBuildStakeTransactionReturnType = UseMutationResult<
BuildStakeTransactionData,
BuildStakeTransactionErrorType,
BuildStakeTransactionVariables,
context
>;
```
#### UseStakedBalanceParameters [#usestakedbalanceparameters]
Parameters accepted by [`useStakedBalance`](#usestakedbalance) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus the owner address, optional network override and optional `providerId`.
| Field | Type | Description |
| ------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `userAddress` | UserFriendlyAddress | Owner whose staked balance should be read. |
| `network` | Network | Network to query. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `providerId` | `string` | Provider to query. Defaults to the registered default staking provider. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseStakedBalanceReturnType [#usestakedbalancereturntype]
Return type of [`useStakedBalance`](#usestakedbalance) — TanStack Query result carrying the user's staked balance.
```ts
type UseStakedBalanceReturnType = UseQueryReturnType<
selectData,
GetStakedBalanceErrorType
>;
```
#### UseStakingProviderInfoParameters [#usestakingproviderinfoparameters]
Parameters accepted by [`useStakingProviderInfo`](#usestakingproviderinfo) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus an optional `providerId` and network override.
| Field | Type | Description |
| ------------ | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `network` | Network | Network whose staking pool should be inspected. Defaults to the selected wallet's network. If no wallet is selected, falls back to AppKit's default network, or mainnet when none is set. |
| `providerId` | `string` | Provider to query. Defaults to the registered default staking provider. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseStakingProviderInfoReturnType [#usestakingproviderinforeturntype]
Return type of [`useStakingProviderInfo`](#usestakingproviderinfo) — TanStack Query result carrying live [`StakingProviderInfo`](/applications/appkit/reference/appkit#stakingproviderinfo).
```ts
type UseStakingProviderInfoReturnType = UseQueryReturnType<
selectData,
GetStakingProviderInfoErrorType
>;
```
#### UseStakingProviderMetadataParameters [#usestakingprovidermetadataparameters]
Parameters accepted by [`useStakingProviderMetadata`](#usestakingprovidermetadata) — optional `providerId` and network override.
```ts
type UseStakingProviderMetadataParameters = GetStakingProviderMetadataOptions;
```
#### UseStakingProviderMetadataReturnType [#usestakingprovidermetadatareturntype]
Return type of [`useStakingProviderMetadata`](#usestakingprovidermetadata) — static [`StakingProviderMetadata`](/applications/appkit/reference/appkit#stakingprovidermetadata) for the resolved provider, or `undefined` when no provider matches and no default is registered (the hook swallows the throw from [`getStakingProviderMetadata`](/applications/appkit/reference/appkit#getstakingprovidermetadata)).
```ts
type UseStakingProviderMetadataReturnType = GetStakingProviderMetadataReturnType | undefined;
```
#### UseStakingProviderParameters [#usestakingproviderparameters]
Parameters accepted by [`useStakingProvider`](#usestakingprovider) — optional provider id forwarded to [`getStakingProvider`](/applications/appkit/reference/appkit#getstakingprovider).
```ts
type UseStakingProviderParameters = GetStakingProviderOptions;
```
#### UseStakingProviderReturnType [#usestakingproviderreturntype]
Return type of [`useStakingProvider`](#usestakingprovider) — the matching staking provider, or `undefined` when none resolves (the hook swallows the throw from [`getStakingProvider`](/applications/appkit/reference/appkit#getstakingprovider)).
```ts
type UseStakingProviderReturnType = GetStakingProviderReturnType | undefined;
```
#### UseStakingProvidersReturnType [#usestakingprovidersreturntype]
Return type of [`useStakingProviders`](#usestakingproviders) — array of registered staking providers.
```ts
type UseStakingProvidersReturnType = GetStakingProvidersReturnType;
```
#### UseStakingQuoteParameters [#usestakingquoteparameters]
Parameters accepted by [`useStakingQuote`](#usestakingquote) — TanStack Query options (`select`, `enabled`, `staleTime`, …) plus stake/unstake amount, direction, target asset and optional `providerId`/network override.
| Field | Type | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `direction` | StakingQuoteDirection | Direction of the quote (stake or unstake) |
| `amount` | `string` | Amount of tokens to stake or unstake. |
| `userAddress` | UserFriendlyAddress | Address of the user. |
| `network` | Network | Network on which the staking will be executed. |
| `unstakeMode` | UnstakeModes | Unstake-timing mode the quote should target — see [`UnstakeMode`](/applications/appkit/reference/appkit#unstakemode) for the supported flavours (`'INSTANT'`, `'WHEN_AVAILABLE'`, `'ROUND_END'`). Only meaningful when `direction === 'unstake'` and the provider lists the mode in `supportedUnstakeModes`. |
| `isReversed` | `boolean` | If true, for unstake requests the amount is specified in the staking coin (e.g. TON) instead of the Liquid Staking Token (e.g. tsTON). |
| `providerOptions` | `TProviderOptions = unknown` | Provider-specific options. |
| `providerId` | `string` | Provider to quote against. Defaults to the registered default staking provider. |
| `query` | [`QueryOptionsOverride`](/applications/appkit/reference/appkit#queryoptionsoverride) | TanStack Query options forwarded to `useQuery` (`enabled`, `staleTime`, `refetchInterval`, `select`, …). `queryKey` and `queryFn` are managed by the wrapper. |
#### UseStakingQuoteReturnType [#usestakingquotereturntype]
Return type of [`useStakingQuote`](#usestakingquote) — TanStack Query result carrying a [`StakingQuote`](/applications/appkit/reference/appkit#stakingquote).
```ts
type UseStakingQuoteReturnType = UseQueryReturnType<
selectData,
GetStakingQuoteErrorType
>;
```
### Swap [#swap-2]
#### SwapContextType [#swapcontexttype]
Shape of the value exposed by [`useSwapContext`](#useswapcontext). Holds the selected source/target tokens, the entered amount and the latest quote, balance readouts, validation state, slippage / provider settings, and the callbacks needed to mutate them or to submit the swap transaction.
| Field | Type | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `tokens`\* | AppkitUIToken \[] | Full list of available tokens for swapping |
| `tokenSections` | TokenSectionConfig \[] | Optional section configs for grouping tokens in the selector |
| `fromToken`\* | AppkitUIToken \| null | Currently selected source token |
| `toToken`\* | AppkitUIToken \| null | Currently selected target token |
| `fromAmount`\* | `string` | Amount the user wants to swap (string to preserve input UX) |
| `toAmount`\* | `string` | Calculated receive amount from the current quote |
| `fiatSymbol`\* | `string` | Fiat currency symbol for price display, e.g. "\$" |
| `fromBalance`\* | `string \| undefined` | User's balance of the "from" token |
| `toBalance`\* | `string \| undefined` | User's balance of the "to" token |
| `isFromBalanceLoading`\* | `boolean` | True while the "from" balance is being fetched |
| `isToBalanceLoading`\* | `boolean` | True while the "to" balance is being fetched |
| `canSubmit`\* | `boolean` | Whether the user can proceed with the swap (checks balance, amount, quote) |
| `quote`\* | `GetSwapQuoteData \| undefined` | Raw swap quote from the provider |
| `isQuoteLoading`\* | `boolean` | True while the quote is being fetched from the API |
| `error`\* | `string \| null` | Current validation or fetch error, null when everything is ok |
| `slippage`\* | `number` | Slippage tolerance in basis points (100 = 1%) |
| `swapProvider`\* | SwapProvider \| undefined | Currently selected swap provider (defaults to the first registered one) |
| `swapProviders`\* | SwapProvider \[] | All registered swap providers |
| `setSwapProviderId`\* | `(providerId: string) => void` | Updates the selected swap provider |
| `setFromToken`\* | (token: AppkitUIToken ) => void | Updates the source token |
| `setToToken`\* | (token: AppkitUIToken ) => void | Updates the target token |
| `setFromAmount`\* | `(amount: string) => void` | Updates the swap amount |
| `setSlippage`\* | `(slippage: number) => void` | Updates the slippage tolerance |
| `onFlip`\* | `() => void` | Swaps source and target tokens |
| `onMaxClick`\* | `() => void` | Sets the "from" amount to the maximum available balance |
| `sendSwapTransaction`\* | `() => Promise` | Executes the swap transaction |
| `isSendingTransaction`\* | `boolean` | True while a transaction is being built or sent |
| `isLowBalanceWarningOpen`\* | `boolean` | True when the built transaction outflow exceeds the user's TON balance |
| `lowBalanceMode`\* | `'reduce' \| 'topup'` | `reduce` when the outgoing token is TON (user can fix by changing amount), `topup` otherwise. |
| `lowBalanceRequiredTon`\* | `string` | Required TON amount for the pending operation, formatted as a decimal string. Empty when no pending op. |
| `onLowBalanceChange`\* | `() => void` | Replace the input with a value that fits within the current TON balance and close the warning. |
| `onLowBalanceCancel`\* | `() => void` | Dismiss the low-balance warning without changing the input. |
#### SwapFieldProps [#swapfieldprops]
Props accepted by [`SwapField`](#swapfield) — a single source/target row inside the swap widget that hosts the amount input, token picker trigger, fiat conversion and balance line.
| Field | Type | Description | | |
| ---------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --- | ------------------------- |
| `type`\* | `'pay' \| 'receive'` | `pay` renders the editable source row with a "max" shortcut. `receive` renders the read-only target row. | | |
| `amount`\* | `string` | Current amount shown in the input as a human-readable decimal string. | | |
| `fiatSymbol` | `string` | Fiat currency symbol displayed in front of the converted value. Defaults to `"$"`. | | |
| `token` |