# Security audits (https://docs.ton.org/llms/audits/content.md)
The reports below document external security assessments of TON blockchain components. Each report applies to the scope and code version it identifies. Audits do not guarantee that software is free of vulnerabilities.
Responsibly report genuine security issues through the [TON Security Bug Bounty program](https://github.com/ton-blockchain/bug-bounty).
## TON Blockchain [#ton-blockchain]
* [Trail of Bits audit report](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TON_Blockchain_ToB.pdf)
* [SlowMist audit report](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TON_Blockchain_SlowMist.pdf)
* [CertiK audit report](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TON_Blockchain_CertiK.pdf)
* [CertiK formal verification of masterchain contracts](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TON_Blockchain_Formal_Verification_CertiK.pdf)
## TON Blockchain library, `tonlib` [#ton-blockchain-library-tonlib]
`tonlib` is the native C++ client library for TON blockchain.
* [Zellic security assessment](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TON_Blockchain_tonlib_Zellic.pdf)
## TVM [#tvm]
* [Trail of Bits: TVM and Fift audit report](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TVM_and_Fift_ToB.pdf)
* [Trail of Bits: 2023 TVM upgrade audit report](https://raw.githubusercontent.com/ton-community/ton-docs/refs/heads/main/static/audits/TVM_Upgrade_ToB_2023.pdf)
# Coming from Ethereum (https://docs.ton.org/llms/from-ethereum/content.md)
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://tonscan.org/tx/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](https://docs.ton.org/llms/tvm/get-method/content.md). 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](https://docs.ton.org/llms/foundations/addresses/overview/content.md), 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](https://docs.ton.org/llms/contracts/standard/wallets/comparison/content.md) 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](https://docs.ton.org/llms/foundations/config/content.md) for contract storage is 65,536 unique cells contract storage, where a cell [stores up to](https://docs.ton.org/llms/foundations/serialization/cells/content.md) 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](https://docs.ton.org/llms/contracts/techniques/contract-sharding/content.md) should be used.
## Ecosystem [#ecosystem]
### Tooling [#tooling]
The recommended programming language for smart contract development in TON is [Tolk](https://docs.ton.org/llms/tolk/overview/content.md). 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](https://docs.ton.org/llms/applications/sdks/content.md) 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), [`@ton-community/assets-sdk`](https://github.com/ton-community/assets-sdk) |
| Wallet connection protocol | WalletConnect, Wagmi | [WalletKit](https://docs.ton.org/llms/applications/walletkit/overview/content.md) that works on [TON Connect](https://github.com/ton-blockchain/ton-connect) |
| Dev environment framework / scripting | Hardhat, Truffle, Foundry | [Acton](https://github.com/ton-blockchain/acton), [Blueprint (legacy)](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).
### Services [#services]
[TON Explorer](https://explorer.toncoin.org/) is a low-level open-source dev explorer.
[TxTracer](https://txtracer.ton.org/) is a set of web tools to trace and analyze TON Blockchain transactions, visualize execution, and inspect and debug smart contracts with a code editor and user-friendly interface.
Additionally, TxTracer hosts several interactive playgrounds:
* [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.
* [Message Emulator](https://txtracer.ton.org/emulate/) - Emulate sending single messages or message batches to see the full transaction tree and trace execution flow.
There is no web IDE — instead, use the local [Acton toolchain](https://docs.ton.org/llms/contract-dev/acton/content.md).
### Standards [#standards]
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.
The table maps Ethereum standards and proposals, including ERC and EIP, to their closest TON counterparts: [TON Enhancement Proposals (TEPs)](https://github.com/ton-blockchain/teps).
| Description | Ethereum standard | TON Standard (TEP) |
| --------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------- |
| Fungible token standard | ERC-20 | [Jettons (TEP-0074)](https://docs.ton.org/llms/contracts/standard/tokens/jettons/overview/content.md) |
| Non-fungible token standard | ERC-721 | [NFT standard (TEP-0062)](https://docs.ton.org/llms/contracts/standard/tokens/nft/overview/content.md) |
| Token metadata | ERC-4955 (Not exactly, but close match) | [Token Data Standard (TEP-0064)](https://docs.ton.org/llms/contracts/standard/tokens/metadata/content.md) |
| NFT royalty standard | EIP-2981 | [NFT Royalty Standard (TEP-0066)](https://docs.ton.org/llms/contracts/standard/tokens/nft/comparison/content.md) |
| DNS-like registry | ENS (EIP-137) | [DNS Standard (TEP-0081)](https://docs.ton.org/llms/foundations/web3/overview/content.md) |
| Soulbound / account-bound token concept | EIP-4973 | [SBT Standard (TEP-0085)](https://docs.ton.org/llms/contracts/standard/tokens/nft/comparison/content.md) |
| Wallet connection protocol | WalletConnect / EIP-1193 | [TonConnect (TEP-0115)](https://docs.ton.org/llms/applications/ton-connect/overview/content.md) |
# Get support (https://docs.ton.org/llms/get-support/content.md)
Use Ctrl + K to do an indexed search. Supply the `llms.txt` file to an AI agent for accurate context.
## Telegram chats, channels, and bots [#telegram-chats-channels-and-bots]
* [Official TON Developers folder](https://t.me/addlist/dyiIa5Skb3JiN2Fk) - main collection of channels to subscribe to:
* Mainnet and testnet status updates.
* Developer news.
* Contests and grants.
* Job opportunities.
* Ecosystem news.
* [TON Dev Chat (EN)](https://t.me/tondev_eng) - main development discussion chat.
* [TON Dev Chat (RU)](https://t.me/tondev) - Russian-speaking chat.
* [TON Dev Chat (中文)](https://t.me/tondev_zh) - Chinese-speaking chat.
* [TON Core](https://t.me/toncore) - channel with updates from the TON Core development team.
Validators and nodes:
* [TON Validators Support bot](https://t.me/validators_help_bot) - tech support for validators.
* [TON Node Help chat](https://t.me/ton_node_help) - tech support chat group for non-validator nodes, like archive nodes or liteservers.
APIs:
* [TON Center API Tech Support bot](https://t.me/toncenter_help_bot) - tech support for [TON Center APIs](https://toncenter.com).
* To get API keys, use the general [TON Center bot](https://t.me/toncenter)
Miscellaneous:
* [TON Help bot](https://t.me/ton_help_bot) - tech support for TON Core products (bridge, vesting, multisig, etc).
## Bug bounty programs [#bug-bounty-programs]
* [TON Security Bug Bounty on GitHub](https://github.com/ton-blockchain/bug-bounty) - description and links to all relevant projects and resources to research vulnerabilities in.
* [TON Security Bug Bounty bot in Telegram](https://t.me/ton_bugs_bot) - send general blockchain security reports to this Telegram bot.
## GitHub repositories [#github-repositories]
* [Main TON monorepo](https://github.com/ton-blockchain/ton) - source code for the node and validator, `lite-client`, tonlib, Tolk compiler, and other tools.
* [Acton monorepo](https://github.com/ton-blockchain/acton) - source code for the [Acton toolchain](https://docs.ton.org/llms/contract-dev/acton/content.md).
# Start here (https://docs.ton.org/llms/start-here/content.md)
The documentation is organized by layers of detail, with lower-level details appearing later on the sidebar on the left.
| | |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Onboarding | Overview of the basic tools to onboard in TON: from AI and wallets to explorers and analytics. |
| Nodes | Guides for running TON infrastructure: nodes, validators, staking setups, and related tooling. |
| Applications | Tools and guides for building user-facing dApps: SDKs, WalletKit, TON Connect, as well as guides on monitoring and handling blockchain transactions for business applications. |
| APIs | Options for reading TON data and interacting with it from the off-chain world. |
| Smart contracts | Working with the most popular standardized contracts and guides on developing new smart contracts. |
| Tolk language | Reference documentation for the official TON smart contract language. |
| TON Virtual Machine | Description of the low-level language that runs smart-contracts, and details of the runtime. |
| Blockchain foundations | Comprehensive description of the blockchain. Includes web version of whitepapers. |
| Legacy languages | Documentation for older TON languages kept for maintaining older contracts and understanding historical tooling. |
| Contributing | Documentation on writing this documentation. |
This is a condensed description of TON. The rest of the documentation may assume that all of this is already known to the reader.
## TON overview [#ton-overview]
*TON* is a [blockchain](https://en.wikipedia.org/wiki/Blockchain). It provides a distributed platform for storing data and code, as well as running computations, all the ingredients to host applications. Roughly speaking, it works as if it were a single server executing all the code. The hosted applications are called *smart-contracts*.
The platform runs on a set of servers, called [nodes](https://docs.ton.org/llms/nodes/overview/content.md). Most important type of nodes, *validators*, are owned by individuals or organizations with a [large stake in TON and great interest](https://docs.ton.org/llms/nodes/staking/overview/content.md) in keeping the platform safe, fair, and operational. Validators have to reach [consensus](https://en.wikipedia.org/wiki/Consensus_\(computer_science\)) on the state of the blockchain. Typically, the process takes below a second to reach [transaction finality](https://docs.ton.org/llms/applications/payments/overview/content.md), a time to mint a new block.
## Network communication [#network-communication]
The nodes that run the blockchain interact via the [ADNL](https://docs.ton.org/llms/foundations/whitepapers/ton/content.md) protocol. User-facing applications usually use [servers](https://docs.ton.org/llms/api/overview/content.md) that proxy JSON HTTP requests into the ADNL network. The official version of such a proxy server is provided by the [liteserver](https://docs.ton.org/llms/nodes/overview/content.md) software. There are public instances of liteserver, so developers are not required to host one on their own servers.
## Gram and fees [#gram-and-fees]
*Gram* (GRAM) is the TON's primary [cryptocurrency](https://en.wikipedia.org/wiki/Cryptocurrency). It is used to pay for the execution of smart contracts, the storage of their data, and network traffic. Such payments are called [fees](https://docs.ton.org/llms/foundations/fees/content.md).
## Mainnet and testnet [#mainnet-and-testnet]
There are two instances of TON blockchain: mainnet and testnet.
*Mainnet* is the "real" network. It's where actual payments in Gram are made. Applications use the mainnet by default.
The other network is *testnet*, and it is used by TON developers to check that their applications work correctly before deploying them to mainnet. It uses "test coins" that barely have any value.
Usually, when the TON blockchain gets an update, it is first deployed to testnet, and then to mainnet after a brief period of testing, so sometimes they may run different software. Also, their [configuration](https://docs.ton.org/llms/foundations/config/content.md), availability, and throughput might be different.
## Workchains and shards [#workchains-and-shards]
A *workchain* is a TON blockchain with its own rules and account space. The *masterchain* holds global configuration and system smart contracts, while the *basechain* host most accounts and user space smart contracts and can be split into shardchains for scalability. In future there might be new workchains with there own set of rules and logic. Practical note: [addresses](https://docs.ton.org/llms/foundations/addresses/overview/content.md) include the workchain ID, and most apps use workchain 0 (basechain).
Each network is split into [workchains](https://docs.ton.org/llms/foundations/shards/content.md) that can freely interact with each other, but their implementations may differ significantly.
At the moment, there are two workchains: *basechain* (`workchain_id = 0`) for regular use, and a very similar *masterchain* (`workchain_id = -1`) for TON's [internal](https://docs.ton.org/llms/applications/payments/overview/content.md) [bookkeeping](https://docs.ton.org/llms/foundations/system/content.md). The masterchain follows mostly the same rules, except that using it is more expensive to limit the amount of traffic that interferes with TON's internals.
To be freely scalable, each workchain is split into *shards*. The number of shards is [determined dynamically](https://docs.ton.org/llms/foundations/shards/content.md) based on the current network load. Internally, every shard is implemented as a separate blockchain. Except for increased latency, the effect on the user-facing code is minimal.
## Accounts [#accounts]
It's easiest to visualize the blockchain as a set of [accounts](https://docs.ton.org/llms/foundations/addresses/overview/content.md). Each account has an address and a status.
### Account statuses [#account-statuses]
Over its lifetime, an account changes its [status](https://docs.ton.org/llms/foundations/status/content.md) among four values:
* `nonexist`: There wasn't a single operation with the account, or it was removed. It has neither a balance, nor code.
* `uninit`: If some Gram is transferred to an account, it now exists, but there is still no smart contract code on it. It now has a balance.
* `active`: After a deploy message (see below) with code and initial data is sent to an account, it becomes active and can process other messages. It now has a balance, code, and internal state.
* `frozen`: If an account is overdue on its [storage fees](https://docs.ton.org/llms/foundations/fees/content.md), it will be frozen until the fees are paid. If the overdue amount reaches a maximum limit specified by the blockchain, the account goes completely bankrupt, is removed, and ceases to exist.
### Smart contracts [#smart-contracts]
The *code* on an active account is a smart contract. The term *contract* is often used for an account that holds the code.
### Account addresses [#account-addresses]
The [internal address](https://docs.ton.org/llms/foundations/addresses/overview/content.md) of an account is a pair of two numbers: its workchain ID and a 256-bit number. It may be displayed in the [raw format](https://docs.ton.org/llms/foundations/addresses/formats/content.md) (e.g., `0:4098805d2272a61b375350c6b2f5faaaf27c8267d8e7521ff2045104fdc7de76`), but is usually shown in a user-friendly format (e.g., `UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI`).
## Messages [#messages]
Addresses specify where [messages](https://docs.ton.org/llms/foundations/messages/overview/content.md) should be delivered. There are three types of messages:
* [internal](https://docs.ton.org/llms/foundations/messages/internal/content.md) messages are sent between accounts;
* [incoming external](https://docs.ton.org/llms/foundations/messages/external-in/content.md) messages are sent from code outside the blockchain to a contract;
* [outgoing external](https://docs.ton.org/llms/foundations/messages/external-out/content.md) messages are broadcast to the external network; somewhat similar to adding them into the globally available list of all outgoing external messages that ever happened.
Every internal message should have some Gram attached to it so that it can pay for the cost of handling it. External messages cannot have Gram attached to them because they come from or go to "outside" the blockchain, where Gram does not exist.
Incoming external messages come from an external address, and outgoing external messages go to an external address.
## `StateInit` [#stateinit]
The *state* of the account changes only when it handles messages. Messages also change the account's balance. An account is `active` when it has a state and a balance.
A message might also be a [deploy message](https://docs.ton.org/llms/foundations/messages/deploy/content.md) if it has a `StateInit` structure attached with its initial code and data. When such a message is sent to a destination address [derived](https://docs.ton.org/llms/foundations/addresses/derive/content.md) from the `StateInit` hash, the code and data are stored in the account at that address, and the account becomes active. Both the code and data stored in the account may change in the future, but its address will remain the same as when it was originally deployed.
## Transactions [#transactions]
Formally, a message is only an intent: it has a destination, possibly some Gram, and data. After the message is handled and all the necessary changes are applied to the blockchain, the message is packed, along with a description of those changes, into a single packet of data, called a [transaction](https://docs.ton.org/llms/foundations/messages/ordinary-tx/content.md). A transaction records the state changes on an account. [Some transactions](https://docs.ton.org/llms/foundations/messages/overview/content.md) might happen without any message.
## TON Virtual Machine [#ton-virtual-machine]
Internal and incoming external messages execute the account's code. The code is interpreted by [TON Virtual Machine](https://docs.ton.org/llms/tvm/overview/content.md) (TVM). It is written in *bitcode*, a binary format specific to TVM. In the future, TVM might support multiple binary languages, *codepages*, but at the moment there is only codepage 0 (`CP0`).
### Phases [#phases]
When execution [starts](https://docs.ton.org/llms/tvm/initialization/content.md), the message and current account state are provided to the code. By the end of execution, the account might change its state or code, or send internal or outgoing external messages.
The execution follows a process whose steps are called [phases](https://docs.ton.org/llms/foundations/phases/content.md). [Fees](https://docs.ton.org/llms/foundations/fees/content.md) are deducted during this process. Fees might be deducted from the account's balance or from the Gram the message carries, depending on the [mode](https://docs.ton.org/llms/foundations/messages/modes/content.md) of the message, or by [explicit choice](https://docs.ton.org/llms/foundations/messages/external-in/content.md) made in the contract's code.
### Gas [#gas]
Execution cost is first measured in *gas* units, then converted to Gram. This unit is separate so that if code execution becomes computationally cheaper (or more expensive), validators can vote to change the [price of gas](https://docs.ton.org/llms/foundations/config/content.md) in Gram.
### Exit codes [#exit-codes]
If something goes wrong, a non-zero [exit code](https://docs.ton.org/llms/tvm/exit-codes/content.md) might be returned, no changes to state or code are saved, and no further messages are sent. If the message that resulted in a failed transaction is marked as *bounceable*, a [bounce message](https://docs.ton.org/llms/foundations/messages/internal/content.md) is sent back to the sender. Bounce messages are used to inform the sender that handling of their message failed. They can carry either truncated or full body of the original message.
## Traces [#traces]
The most common reason a code is executed is when some account has received a message. Internal messages can only be sent by another contract executing some code, and that contract must have received a message from somewhere too. In the end, every message can be considered part of some *trace*: a tree of messages between accounts that starts with an incoming external message, continues with internal messages, and possibly ends with some outgoing external messages.
### Asynchronous execution [#asynchronous-execution]
When some interaction with the blockchain involves multiple contracts, their code may not be executed in the same block. Contracts have to exchange messages with each other, and two such concurrent traces may interleave their messages. This fact is usually referred to as "*asynchronous* message handling." This feature of TON allows a limit to be placed on the maximum complexity of atomic computation and aids its scalability, but it is important to keep it in mind because it might create [race conditions](https://docs.ton.org/llms/contracts/techniques/security/content.md).
## Languages [#languages]
Most development is done in [Tolk](https://docs.ton.org/llms/tolk/overview/content.md), a high-level programming language. Its compiler is included in the [Acton](https://docs.ton.org/llms/contract-dev/acton/content.md) development environment.
Originally, [Fift](https://docs.ton.org/llms/languages/fift/overview/content.md), a Forth-like assembly language, and [FunC](https://docs.ton.org/llms/languages/func/overview/content.md), a C-like intermediate-level language, were the first languages for TON smart contract development.
## Get methods [#get-methods]
If an external service needs to extract data from the blockchain, it can call a [get method](https://docs.ton.org/llms/tvm/get-method/content.md): an arbitrary function implemented in the code deployed to an account. Every call of a get method spawns a separate instance of TVM. Any changes to the blockchain made during the execution of a get method are not committed to the blockchain.
Unlike in [other blockchains](https://docs.ton.org/llms/from-ethereum/content.md), get methods cannot be called by other contracts. It is intentional for several reasons:
* by the time another contract receives the result of such a call, other messages may have been processed and may have changed the result;
* get methods are executed completely separately, and changes from the blockchain are not guaranteed to be propagated to the server running the code of a get method.
## Wallets [#wallets]
The main user of incoming external messages is a [wallet](https://docs.ton.org/llms/contracts/standard/wallets/how-it-works/content.md). A wallet is an account with a specific kind of smart contract deployed on it, which can handle incoming external messages, specifically *transfer* messages. A transfer message is a request to send an internal message to another account. Thus, a wallet transforms incoming external messages to internal messages.
### Wallet contract types [#wallet-contract-types]
There are several [implementations](https://docs.ton.org/llms/contracts/standard/wallets/comparison/content.md) of wallets, with varying extra functionality and protection. [`V5R1`](https://docs.ton.org/llms/contracts/standard/wallets/v5/content.md) is the latest official general-purpose wallet. The text below describes only the functionality common to most wallets.
### How wallets work [#how-wallets-work]
A transfer message consists of a destination address and, optionally, an internal message, both serialized and signed with a [private key](https://en.wikipedia.org/wiki/Public-key_cryptography). The wallet stores a public key and uses it to check that a transfer message was signed with the corresponding private key. If the check succeeds, it sends that internal message to the destination address. This ensures only the user (or a service) who knows the private key can use the wallet.
Private and public keys are generated in a program or service outside the blockchain. Public key is used in a `StateInit` during the deploy, and determines the address of the wallet account. Keypair is usually derived from a set of 24 random words called a [mnemonic](https://docs.ton.org/llms/contracts/standard/wallets/mnemonics/content.md).
Before the code of the wallet can be deployed on an account with an incoming external message, some other account has to transfer Gram to the wallet account. As external messages cannot have any Gram attached to them, if no funds are in the account when it handles an external message, it cannot pay for the message that deploys a wallet. The transfer of Gram to a wallet account usually comes from an exchange or another user. In testnet, there is [a bot](https://docs.ton.org/llms/onboarding/wallet-apps/get-coins/content.md) that sends test coins to an account for free.
Usually, a transfer message is sent without an additional payload and only instructs the wallet to transfer some Gram to a destination address. This is the reason this type of smart contract is called a wallet.
An internal message might be a request to some other contract or even a deploy message that deploys code on other accounts. In this way, a wallet acts as a proxy between a user (or an external service) and the rest of the blockchain.
### Wallet apps [#wallet-apps]
End users usually use [wallet apps](https://docs.ton.org/llms/onboarding/wallet-apps/web/content.md) to create and use wallets. An exchange will usually create a wallet for a user as well.
## Standard contracts [#standard-contracts]
The other [important types](https://docs.ton.org/llms/contracts/standard/tokens/overview/content.md) of contracts are
* [Jetton](https://docs.ton.org/llms/contracts/standard/tokens/jettons/overview/content.md) tokens roughly correspond to coins and allow developers to mint their own currency;
* [NFT](https://docs.ton.org/llms/contracts/standard/tokens/nft/overview/content.md) tokens are similar to tickets: unique items that can be sold;
* [SBT](https://docs.ton.org/llms/contracts/standard/tokens/nft/sbt/content.md) tokens are like medals: unique items that can be given to someone but can never be sold or transferred.
Many popular contract types have been standardized in [TON Enhancement Proposals](https://github.com/ton-blockchain/TEPs) (*TEP*), mostly describing expected contract interfaces with TL-B schemas. This allows tooling to be reused between similar contracts. For example, explorers detect TEP-standardized contracts and display their binary messages in a user-friendly format, and provide an interface to call their get methods.
## Explorers [#explorers]
An [*explorer*](https://docs.ton.org/llms/onboarding/explorers/content.md) is a type of web app that displays information about the current state of accounts (including wallets, Jettons, and NFTs) and the history of transactions. Discover [popular TON explorers](https://duckduckgo.com/?q=ton+explorer).
## APIs and SDKs [#apis-and-sdks]
To interact with wallets, Jettons, and other contracts, data has to be sent through an ADNL or HTTP API into the network. There are several ways to connect:
* directly call the [API](https://docs.ton.org/llms/api/overview/content.md), or
* use [an SDK](https://docs.ton.org/llms/applications/sdks/content.md) that simplifies working with an API by wrapping its methods in a more user-friendly interface; the most popular TypeScript SDK for this is [`@ton/ton`](https://github.com/ton-org/ton).
## TON Connect [#ton-connect]
When an application has to use a wallet to prove the user's identity, it needs access to the wallet's private key. Giving arbitrary applications access to the private key is insecure, as they could perform arbitrary actions with the wallet. To address this, there is the [TON Connect](https://docs.ton.org/llms/applications/ton-connect/overview/content.md) set of SDKs that provide interfaces
* for an application to perform an action through the wallet app;
* for a wallet app to handle these requests.
For example, Telegram apps use TON Connect to access a wallet that is integrated into Telegram.
## Data storage model [#data-storage-model]
All data on TON is stored as trees of [cells](https://docs.ton.org/llms/foundations/serialization/cells/content.md): the state of contracts, their code, and messages. Each cell stores up to 1023 bits of data and can have up to 4 *refs* to other cells. Each cell has a hash computed from its bits and refs. Because the hash of a cell that directly or indirectly references itself would require knowing the same hash, creating cyclic data structures is impossible.
Standard serialization of such a data structure into a single binary string is the [bag of cells](https://docs.ton.org/llms/foundations/serialization/boc/content.md) (*BoC*). When cells need to be stored in a file or sent over the network, they are commonly serialized into a BoC. Smart contract code is also compiled into BoC files.
### Binary representation [#binary-representation]
To tell other developers how a certain type of data is stored in cells, a [TL-B](https://docs.ton.org/llms/foundations/tlb/overview/content.md) schema language is used. Its purpose is similar to that of [protocol buffers](https://en.wikipedia.org/wiki/Protocol_Buffers) or [binary templates](https://en.wikipedia.org/wiki/010_Editor#Binary_Templates), but it provides more features for structuring data at the bit level.
[There are libraries](https://docs.ton.org/llms/applications/sdks/content.md) for assembling data structures out of cells. For TypeScript, the most popular one is [`@ton/core`](https://github.com/ton-org/ton-core).
The TL-B schemas for binary representations of messages, transactions, initial contract state, and most other data structures used by the blockchain can be found in the [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in the [TON monorepo](https://github.com/ton-blockchain/ton). TypeScript functions for serializing and deserializing them are provided by the [`@ton/core`](https://github.com/ton-org/ton-core) and [`@ton/ton`](https://github.com/ton-org/ton) libraries.
In general, a library that converts data structures between cells and the format native to a programming language, or allows calling contract methods as native functions of the language, is called a *wrapper* or *binding*. For example, functions that deserialize Jetton-related cell data into TypeScript objects can be found in the [`assets-sdk`](https://github.com/ton-community/assets-sdk/blob/5285cd75a97acbb15999e7dfb3b8e4ec9e98b4ed/src/jetton/types/JettonBurnMessage.ts) library. [Acton toolchain](https://docs.ton.org/llms/contract-dev/acton/content.md) can generate bindings from the Tolk contract's source code. The "rule of thumb" is that production-grade code should not include low-level manipulation of binary data, and should instead rely on a library with bindings. This reduces the chance of mistakes and ensures the code has more users. With widely reused code, there are more opportunities to detect mistakes, and they are more likely to be fixed quickly.
### Blockchain interaction [#blockchain-interaction]
So, to interact with the blockchain, a couple of libraries are usually used: one that handles the connection to the blockchain and another that works with the specific type of data sent over that connection.
Not all computation has to be done *on-chain*, i.e., executed inside TVM and paid for with Gram. Computing and storing data on the blockchain is significantly more expensive than doing so on a regular CPU. Instead, much of the work can be done in *off-chain* code, in a regular programming language, before or after sending a request to the blockchain. The recommended development practice is to write a TypeScript library that calls contracts implemented in Tolk.
## Next steps [#next-steps]
* [Coming from Ethereum or similar synchronous blockchains?](https://docs.ton.org/llms/from-ethereum/content.md) — compare the differences in execution model and ecosystem.
* [Want to host nodes or get involved in staking?](https://docs.ton.org/llms/nodes/overview/content.md) — pick the right TON node setup and understand the required operational work.
* [Aiming to build a new dApp or integrate existing one with TON?](https://docs.ton.org/llms/applications/overview/content.md) — use the rich toolset of the TON application layer.
* Aspire to write new or audit existing smart contracts? — set up the [toolchain and editor plugins](https://docs.ton.org/llms/contracts/overview/content.md), work with [standard contracts](https://docs.ton.org/llms/contracts/standard/overview/content.md), learn the [techniques](https://docs.ton.org/llms/contracts/overview/content.md) to write new contracts, master the [Tolk language](https://docs.ton.org/llms/tolk/overview/content.md) and the [TVM runtime](https://docs.ton.org/llms/tvm/overview/content.md).
# How to adopt sub-second finality (https://docs.ton.org/llms/subsecond/content.md)
The TON Core team has [released Catchain 2.0](https://t.me/toncore/104) on mainnet. This consensus upgrade enables sub-second block finality, reducing the block interval from about 2.5s to about 400ms.
However, faster block production does not automatically reduce end-to-end latency for users. Projects must adapt their applications so transaction status updates and UI changes use the new timing guarantees.
## Current status [#current-status]
Sub-second finality is live on TON mainnet.
As of April 9th 2026, mainnet runs with a block interval of about 400 ms instead of \~2.5 s before the upgrade, producing roughly 6.25x more blocks per second. Target finalization lag is reduced from \~10 s to about 1 s.
| Network | Block interval | Blocks per second | Finalization lag |
| ---------------------------- | -------------- | ----------------- | ---------------- |
| Mainnet | \~400ms | \~2.5 | \~1s |
| Testnet | \~450ms | \~2.2 | \~1–2s |
| Mainnet before Apr 9th, 2026 | \~2.5s | \~0.4 | \~10s |
* Together with the consensus update, the [Streaming API v2](#ton-center-streaming-api-v2) delivers status updates with 30 to 100ms latency.
* Testnet remains the primary environment for project testing.
## Example of sub-second user experience in action [#example-of-sub-second-user-experience-in-action]
Popular [wallets](https://mytonwallet.io/) and [explorers](https://tonscan.org) already use Streaming API v2 on both mainnet and testnet to deliver transaction status updates with low latency. These projects have nearly halved interface delays, and the mainnet upgrade will further reduce them.
## What projects need to do [#what-projects-need-to-do]
### Wallets and dApps [#wallets-and-dapps]
A faster chain alone does not reduce end-to-end latency if the application continues to use HTTP polling. In this case, transaction status updates can still arrive 10 seconds or more after inclusion. To support sub-second latency, deliver transaction updates through streaming APIs instead of polling.
#### Actions [#actions]
* Switch to a streaming API such as [TON Center Streaming API v2](#ton-center-streaming-api-v2).
Handle all four transaction statuses: `"pending"`, `"confirmed"`, `"finalized"`, and `"trace_invalidated"`.
* If Streaming API cannot be used, reduce polling intervals and adjust assumptions about transaction timing.
Interfaces should be designed to expect results in under 1 second.
### Self-hosted nodes, liteservers, and TON Center instances [#self-hosted-nodes-liteservers-and-ton-center-instances]
#### Actions [#actions-1]
1. Update all self-hosted components to the versions that include Catchain 2.0 support:
* TON node and liteserver – update to a release that supports the live mainnet consensus.
* Self-hosted TON Center – update to a version with Streaming API v2 support.
2. After updating, verify each component on testnet and confirm that it operates correctly under the higher block rate. If any component still runs a pre-upgrade version, update it before relying on it in production.
### Indexers [#indexers]
Indexers must process about 6.25x more blocks per second without accumulating lag. If an indexer was tuned for 2.5s block intervals, it can fall behind under 400ms intervals.
#### Actions [#actions-2]
1. Connect the indexer to testnet.
2. Run for 30 or more minutes.
3. Measure lag continuously.
4. If lag increases, identify and resolve bottlenecks such as database writes, network latency, and parsing throughput.
5. Generate the typical mainnet load profile on testnet and verify that the indexer keeps up.
See [Expected user experience](#expected-user-experience) and [Test on testnet](#test-on-testnet) for guidance.
## Expected user experience [#expected-user-experience]
### Behavior without Streaming APIs [#behavior-without-streaming-apis]
Even with blocks produced about 6.25x faster, applications that do not use the Streaming API would still:
* Poll HTTP endpoints at fixed intervals.
* Wait for full block finalization before updating the UI.
* Show delays of 10+ seconds to users.
A typical sequence for polling-based integrations:
1. 0s – user clicks "Send";
2. \~0.4s – transaction included in a shard block;
3. \~0.8s – shard block committed to masterchain;
4. \~10s – UI updates on the next HTTP polling request.
User perception: "You said the blockchain is fast. Why does my transfer still take 10 seconds?". In this model, the blockchain is fast, but the user interface still appears slow.
### Behavior with Streaming APIs [#behavior-with-streaming-apis]
1. 0s – user clicks "Send";
2. \~0.1s – `"pending"` status with expected outcome is displayed;
3. \~0.4s – transaction included in a shard block and `"confirmed"` status is displayed;
4. \~0.8s – shard block committed to masterchain and `"finalized"` status is displayed.
If the interface does not update quickly, users will not notice any improvement despite the blockchain upgrade.
### Why this matters [#why-this-matters]
The sub-second finality upgrade is enabled on mainnet, but coordinated ecosystem changes are still required:
* TON Core delivers faster block production and low-latency APIs.
* Ecosystem projects must adapt indexers and UI layers to surface this speed.
If applications do not adapt, the upgrade will not become apparent. Projects that have adapted will showcase the intended behavior and user experience.
## How to integrate [#how-to-integrate]
### Recommended stack [#recommended-stack]
For projects building on TON:
* Streaming API: [TON Center](#ton-center-streaming-api-v2).
* Data layer: [TON Center API v3](https://docs.ton.org/llms/api/v3/overview/content.md).
* SDK: [WalletKit][walletkit] for balances, tokens, NFTs, and contract interactions.
* Finality: wait for `"finalized"` in critical flows.
### Public liteserver [#public-liteserver]
Public liteservers are available for both mainnet and testnet. Use global config files to discover and connect to them:
* Mainnet: [`ton.org/global.config.json`](https://ton.org/global.config.json)
* Testnet: [`ton.org/testnet-global.config.json`](https://ton.org/testnet-global.config.json)
Public liteservers are suitable for testing only. Use private liteservers in production.
### Self-hosted liteserver [#self-hosted-liteserver]
If a liteserver node is self-hosted, ensure it is updated before mainnet rollout.
#### Actions [#actions-3]
Confirm that the node version supports the new consensus.
### TON Center Streaming API v2 [#ton-center-streaming-api-v2]
TON Center [Streaming API v2][streaming] provides:
* Push-based delivery of transaction status updates.
* Four statuses: `"pending"`, `"confirmed"`, `"finalized"`, `"trace_invalidated"`.
* Latency: 30–100ms from chain event to the client.
#### API token [#api-token]
* For testing purposes, any valid token for TON Center allows for 2 concurrent streaming connections.
* For production usage, higher connection limits require a paid plan.
#### Endpoints [#endpoints]
SSE and WebSocket are available. Choose based on the stack:
* SSE – browser-friendly, server-to-client only (unidirectional).
* WebSocket – bidirectional, allows dynamic subscribe and unsubscribe after connection.
| Protocol | Testnet URL | Mainnet URL |
| --------- | ---------------------------------------------------- | -------------------------------------------- |
| SSE | `https://testnet.toncenter.com/api/streaming/v2/sse` | `https://toncenter.com/api/streaming/v2/sse` |
| WebSocket | `wss://testnet.toncenter.com/api/streaming/v2/ws` | `wss://toncenter.com/api/streaming/v2/ws` |
TON Center's [Streaming API v2 documentation][streaming] can serve as the protocol reference for some other API providers that use the same SSE and WebSocket interface.
| Protocol | Testnet URL | Mainnet URL |
| --------- | -------------------------------------------- | ------------------------------------ |
| SSE | `https://testnet.tonapi.io/streaming/v2/sse` | `https://tonapi.io/streaming/v2/sse` |
| WebSocket | `wss://testnet.tonapi.io/streaming/v2/ws` | `wss://tonapi.io/streaming/v2/ws` |
Authentication uses an [API key](https://tonconsole.com/tonapi/api-keys).
1. Rate limit on reconnect (429 error).
If a client reconnects immediately after a disconnect, the previous connection may still be open for \~1 minute. The reconnect attempt receives a 429 error. Use exponential backoff or an enterprise API key.
2. POST-only subscription.
Despite SSE typically using `GET`, this endpoint requires a `POST` with the subscription JSON in the request body. `GET` is not supported yet.
3. No invalidation signal for `account_state_change` / `jettons_change`.
If a `confirmed` account state or jetton balance update is later rolled back, no `"trace_invalidated"` notification is sent for these event types. Teams using `account_state_change` or `jettons_change` at `"confirmed"` finality should be aware of this gap and consider waiting for `"finalized"` for balance-critical flows.
#### Transaction status flow to implement [#transaction-status-flow-to-implement]
1. Initiate the transaction after the user's request.
2. Subscribe to the sender or recipient address through the Streaming API before or immediately after sending.
* On `pending`, display a processing indicator.
* On `confirmed`, optionally display optimistic success.
* On `finalized`, display confirmed success and update state.
* On `trace_invalidated`, discard a cached trace and recheck the status manually.
#### Configure `min_finality` [#configure-min_finality]
The `min_finality` parameter controls the earliest status delivered. The default value is `"finalized"`.
If the parameter is omitted, only `"finalized"` events are delivered. `"pending"` and `"confirmed"` updates are not sent.
| Use case | `min_finality` value |
| ------------------------------ | --------------------------------------------- |
| Send flow (real-time feedback) | `"pending"` to receive four status updates. |
| History and balance display | `"finalized"` to work only with settled data. |
Example subscription (send flow):
```json
{
"accounts": ["
"],
"min_finality": "pending"
}
```
#### WebSocket keepalive [#websocket-keepalive]
* Send a `ping` every 15 seconds to keep the connection alive.
* SSE connections receive automatic server-side keepalive (`: keepalive`) every 15 seconds; no client action required.
## Test on testnet [#test-on-testnet]
Testnet runs at sub-second block generation speed. Use it for testing projects before shipping production changes on mainnet.
### Testnet endpoints [#testnet-endpoints]
Use the [public API endpoints overview](https://docs.ton.org/llms/api/overview/content.md) for testnet endpoints, including TON Center's streaming endpoints.
### How to get test tokens [#how-to-get-test-tokens]
For the standard faucet, up to 2 GRAM per hour, [use Telegram Testgiver TON bot](https://docs.ton.org/llms/onboarding/wallet-apps/get-coins/content.md) or [Acton's faucet](https://ton-blockchain.github.io/acton/docs/wallets#fund-a-wallet-on-testnet).
### What to test [#what-to-test]
Perform the following tests to validate UX and wallet behavior.
#### For indexer teams [#for-indexer-teams]
1. Connect indexer to testnet.
2. Run for 30+ minutes under normal conditions.
3. Measure indexer lag as the time between block production and indexer processing.
4. Ensure lag remains below 500ms and no backlog accumulates.
#### For UX and app teams [#for-ux-and-app-teams]
1. Connect to testnet endpoints.
2. Initiate a GRAM transfer.
3. Observe three statuses in sequence: `"pending"` → `"confirmed"` → `"finalized"`.
4. Measure time from transaction send to `"finalized"`. It should be under 1 second on testnet.
5. Test `"trace_invalidated"` path: intentionally send a malformed transaction and confirm that UI handles it correctly.
#### For wallet teams [#for-wallet-teams]
1. Verify balance updates reflect within 1 second of `"finalized"` status.
2. Verify transaction history updates in real time.
## Resources [#resources]
* [Announcement, Telegram channel](https://t.me/toncoin/2304)
* [TON Core deployment progress, Telegram channel](https://t.me/toncore/99)
* [TON Core R\&D technical overview, Telegram channel](https://t.me/toncore/98)
* [UX approaches for sub-second finality, Telegraph](https://telegra.ph/New-Approaches-to-Blockchain-User-Experience-08-02)
* [TON Center Streaming API v2][streaming]
* [API overview and public endpoints](https://docs.ton.org/llms/api/overview/content.md)
* [WalletKit documentation][walletkit]
## Get support [#get-support]
Use the [sub-second finality support chat](https://t.me/subsecond_upgrade) for questions about this upgrade.
[walletkit]: https://docs.ton.org/llms/applications/walletkit/overview/content.md
[streaming]: https://docs.ton.org/llms/api/streaming/overview/content.md
# 100,000 Transactions Per Second (TPS) (https://docs.ton.org/llms/tps/content.md)
On 31 October, the TON Blockchain set the world record as the fastest and most scalable blockchain. Thanks to its unique architecture, allowing infinite scaling to process millions of transactions per second from billions of users, TON sets the standard for the ultimate Web3 infrastructure.
## Public test [#public-test]
During the livestream hosted by the TON Foundation and audited by Certik, **the TON Blockchain set a world record by achieving 104,715 transactions per second.**
This is an astonishing result for any blockchain, but what's even more exceptional is the fact that this performance significantly outperforms even the most used centralized payment systems:
For a comparison, let's look at the top 25 blockchains from CoinMarketCap:
As you can see, TON outperforms both well-known blockchains and bank payment networks by a margin and, in most cases, by dozens of times.
## Overview of the test [#overview-of-the-test]
For the test, TON rented 256 servers from Alibaba Cloud for validator nodes and launched a separate TON Blockchain network.
Next, we created a special "bomb" smart contract that clones itself and continuously transmits transactions so that the load on the network grows exponentially.
The test had to be performed on a separate test network, as such a “bomb” would result in spending astronomical money to pay network fees. On the test network, this method creates massive amounts of transactions, as if millions of users were sending them.
We detonated the "bomb" for 10 minutes, resulting in intense load growth, and the network split into shardchains. Finally, the network split into 512 shards and processed 90-110K transactions per second. The network maintained this load for a while until we manually shut it down.
The entire test was conducted publicly in real-time by TON's core team, overseen by independent auditor Certik, and documented in detail. All technical details and test results can be found here.
## How TON achieves this scalability and speed [#how-ton-achieves-this-scalability-and-speed]
Special blockchain nodes called validators process user transactions, such as sending coins from one user to another or exchanging assets on a decentralized exchange. These nodes are the core building blocks of the TON Blockchain.
The efficiency of the TON Blockchain lies in the fact that as the number of users or load grows, it can split into "sub-blockchains," called [shardchains](https://docs.ton.org/llms/foundations/shards/content.md). Each shardchain is operated by its own group of validators, distributing the load. When the load decreases, the shardchains "collapse" back together.
In technical language, this is called "dynamic sharding." Few modern blockchains can boast such an architecture, and TON is a leader among them.
## No limits [#no-limits]
The most impressive thing is that the result is far from the limit. TON can handle millions of transactions per second if there are enough validator nodes in the network.
While preparing for today's test, we encountered that no cloud provider or data center is interested in renting out thousands of productive servers for the short time required for the test. We will try to solve this administrative challenge to show you the following tests with even more grandiose results.
In a real-world network, servers for validator nodes are rented for long periods by independent operators in different data centers. Part of the network commission from each transaction goes to validators as a reward for keeping the network running. If there is a heavy load and a large number of transactions, the total reward will increase accordingly, stimulating organic growth in the number of new validators.
## TON vs. Solana [#ton-vs-solana]
The previous title holder of the fastest blockchain was Solana. Let's compare TON and Solana separately.
In addition to the fact that TON beats Solana's confirmed result in absolute numbers by a margin, there are qualitative differences that show that TON is the next-generation blockchain.
* As described above, the TON blockchain uses dynamic sharding. The main advantage of this approach is that the blockchain can scale almost infinitely by adding new validator nodes. In contrast, monolithic blockchains such as Solana have their physical limit, after which it's impossible to scale further.
* In a separate post, we provide three historical examples that prove that vertical scaling has always been a technological dead end, replaced by horizontal scaling or sharding.
* TON allows fast processing of not only simple transactions such as transferring coins between users but also fast execution of Turing-complete smart contracts. This means complex decentralized exchanges, marketplaces, or other decentralized applications do not slow down the blockchain. That's why we used the complex smart contract in this public test.
While Solana's blockchain is optimized for the swift execution of specialized and predefined transactions, the performance dramatically decreases when executing arbitrary transactions.
## Comparing blockchain speeds [#comparing-blockchain-speeds]
### Time to finality [#time-to-finality]
When users interact with the blockchain, they create transactions, which are grouped into blocks, and the blocks are added to the blockchain. In many blockchains, a block can still change after it has been added, so you need to wait a while to be assured that the payment has gone through.
This is called Time-to-finality. In Bitcoin, it is about 60 minutes, and in Ethereum, it is about 13 minutes.
This indicator must be considered because it is important not only to send a transaction but also to ensure it is successfully and irreversibly completed. For example, the seller is unlikely to give you the goods until he is absolutely sure that he has received the payment.
The good news is that in TON, once a block is written to the blockchain, it is final and cannot be changed. Currently, on the main network, blocks are created approximately every 4-6 seconds, so the time-to-finality of TON is 6 seconds.
Since the original test and publication, the time to finality in TON has been reduced to less than a second per masterchain block after implementing the [Catchain 2.0 consensus upgrade](https://t.me/toncore/104). See the [sub-second finality](https://docs.ton.org/llms/subsecond/content.md) article for more details and actionable steps for projects on TON.
### Transactions [#transactions]
When comparing metrics, we should ensure that all blockchains adhere to the same meaning of terms.
We use the common meaning of "transaction" - some atomic action, such as a balance change or the execution of a smart contract, the result of which is recorded to the block.
It is worth noting that some blockchains understand something different under this term. As an example, the SUI blockchain shows hundreds of thousands of "transactions," but it refers to transactions as operations, and a single atomic write to a block can contain dozens of such operations. At one operation per write, the speed in SUI drops to 10K TPS.
### Layer 1 and Layer 2 [#layer-1-and-layer-2]
Full-fledged blockchains are called Layer 1 or L1 networks. These blockchains include, for example, Bitcoin, Ethereum, and TON.
Some projects supercharge and enhance blockchains - called Layer 2 or L2, respectively. This approach has both pros and cons. Given that these solutions are not decentralized blockchains, it is easy for them to achieve greater speed and performance at the cost of decentralization or functionality. An example of an L2 blockchain that offers better performance but significantly reduces functionality is Bitcoin's Lightning Network.
While TON, being Layer 1, outperforms most Layer 2 solutions in speed and performance, we are also working on our own Layer 2 solution, the TON Payment Network.
This solution will enable instant micropayments without network fees, which could be useful for several applications. The first stage of work, the payment channel technology, has already been completed, and you can explore our future plans in the roadmap.
## Space for optimization [#space-for-optimization]
While working on the test, we discovered that TON can scale further not only by adding validator nodes but also by optimizing the node itself.
We already performed such optimization - splitting the validator into two nodes - a collator and a validator. This kernel update, “Accelerator,” will be released on the mainnet after thorough testing. We have also planned other optimization and parallelization that can make the performance of the node even better.
## Conclusion [#conclusion]
The goal of the TON project is to achieve mass adoption of cryptocurrencies and decentralized technologies. We are systematically moving towards this goal - a vivid example is the recently announced joint initiative of TON with Telegram, a messenger with 800+ million monthly active users.
With today's public test, we have confirmed that TON is technically ahead of all other existing blockchain projects and is ready for mass adoption.
## References [#references]
* Visa, Annual Report For SEC, September 30, 2022. According to this document, Visa processed 192,530 million transactions in 2022. Thus average TPS is 6,105 (192530e6 / 365 / 24 / 60 / 60). Maximum TPS is 65,000 according to Visa's Fact Sheet.
* MasterCard, Cointelegraph's Network Comparison stated maximum TPS at 5,000
* PayPal, Annual Report For SEC, December 31, 2022. According to this document, PayPal processed 22.3 billion transactions in 2022. Thus the average TPS is 707 (22.3e9 / 365 / 24 / 60 / 60).
* Ethereum and Bitcoin TPS are sourced from Binance Academy
* For Solana, we exclude the “test in an ideal laboratory environment,” and look at the test results on the testnet.
* SUI states, “The TPS capacity measurement most consistent with Sui's design, least application-dependent, and most practical to track, is the number of individual transactions within a Programmable Transaction Block (PTB) executed per second. For this and future updates, all mentions and measurements of TPS follow this convention.” Tests show 10,871 TPS if PTB contains 1 transaction.
*
Ethereum Time-to-Finality
*
Bitcoin Time-to-Finality
# Get your TON Center API key (https://docs.ton.org/llms/api/get-api-key/content.md)
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 GRAM/month)
* **Advanced** – 100 requests/sec, 10 tokens per network (25 GRAM/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 GRAM 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)
# APIs (https://docs.ton.org/llms/api/overview/content.md)
Access TON data via public liteservers, hosted APIs such as [TON Center APIs](#ton-center), or self-hosted options.
For available SDKs that rely on some of these APIs, see the [SDK overview](https://docs.ton.org/llms/applications/sdks/content.md).
## Comparison table [#comparison-table]
### Requests [#requests]
| Feature | Public liteservers | TON Center API v2 | TON Center API v3 |
| ------------------------- | --------------------------------- | ------------------------ | --------------------- |
| **Can be self-hosted?** | ✅ | ✅ | ✅ |
| **Open-source** | ✅ | ✅ | ✅ |
| **Indexer**1 | ❌ | ❌ | ✅ |
| **Archival**2 | 🟡 Varies | 🟡 Depends on liteserver | ✅ |
| **Proofs**3 | ✅ | ❌ | ❌ |
| **Mainnet endpoint** | [Config][c] | [Endpoint][etc-v2] | [Endpoint][etc-v3] |
| **Testnet endpoint** | [Config][c-tn] | [Endpoint][etc-v2-tn] | [Endpoint][etc-v3-tn] |
| **Source / Deploy guide** | [Run node / liteserver][ls-setup] | [Deploy][etc-v2-src] | [Source][etc-v3-src] |
| **Documentation** | [Guide][ls-doc] | [Docs][etc-v2-doc] | [Docs][etc-v3-doc] |
1 **Indexer** means the service maintains its own database derived from blockchain data for richer queries (traces, jettons, NFTs, etc.), beyond raw liteserver RPC.
2 **Archival** indicates historical data retention. For liteservers, this depends on the node's archival configuration; hosted indexers typically keep full history, but exact retention policies are service-specific.
3 **Proofs** denote responses that can be verified without trust using cryptographic proofs from the network (liteserver/tonlib-based). HTTP indexers typically do not return proof bundles in their REST/GraphQL responses.
### Streaming [#streaming]
| Feature | TON Center Streaming API v2 |
| -------------------------- | ------------------------------------------ |
| **Protocol compatibility** | Native reference implementation |
| **Mainnet endpoints** | [SSE][etc-sse], [WebSocket][etc-wss] |
| **Testnet endpoints** | [SSE][etc-sse-tn], [WebSocket][etc-wss-tn] |
| **Authentication** | [API key][etc-key] |
| **Documentation** | [Docs][etc-stream-doc] |
## TON Center [#ton-center]
TON Center is the official provider of HTTP APIs for TON: 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.
## References [#references]
* [TON node and liteserver source](https://github.com/ton-blockchain/ton)
* [Mainnet liteserver config][c], [testnet config][c-tn]
* [TON Center landing page](https://toncenter.com)
* [TON Center v2 (C++, newer, recommended) source and deploy instructions][etc-v2-src]
* [TON Center v2 (Python, older) source and deploy instructions](https://github.com/toncenter/ton-http-api)
* [TON Center v3 source and deploy instructions][etc-v3-src]
[c]: https://ton-blockchain.github.io/global.config.json
[c-tn]: https://ton-blockchain.github.io/testnet-global.config.json
[etc-v2]: https://toncenter.com/api/v2
[etc-v2-tn]: https://testnet.toncenter.com/api/v2
[etc-v2-src]: https://github.com/toncenter/ton-http-api-cpp
[etc-v2-doc]: https://docs.ton.org/llms/api/v2/overview/content.md
[etc-v3]: https://toncenter.com/api/v3
[etc-v3-tn]: https://testnet.toncenter.com/api/v3
[etc-v3-src]: https://github.com/toncenter/ton-indexer
[etc-v3-doc]: https://docs.ton.org/llms/api/v3/overview/content.md
[etc-sse]: https://toncenter.com/api/streaming/v2/sse
[etc-sse-tn]: https://testnet.toncenter.com/api/streaming/v2/sse
[etc-wss]: wss://toncenter.com/api/streaming/v2/ws
[etc-wss-tn]: wss://testnet.toncenter.com/api/streaming/v2/ws
[etc-key]: https://docs.ton.org/llms/api/get-api-key/content.md
[etc-stream-doc]: https://docs.ton.org/llms/api/streaming/overview/content.md
[ls-setup]: https://docs.ton.org/llms/nodes/cpp/setup-mytonctrl/content.md
[ls-doc]: https://docs.ton.org/llms/nodes/overview/content.md
# Jetton prices API (https://docs.ton.org/llms/api/price/content.md)
Each swap operation, whether between a native asset (Gram) and Jetton or between two distinct Jettons, has its price, a fixed exchange rate of one asset to another. This price is calculated by the internal DEX math algorithm, called [AMM](https://www.coinbase.com/learn/advanced-trading/what-is-an-automated-market-maker-amm). Some services require information about previous swaps on the blockchain to use it in their internal business logic or to simply show statistics to users.
## Off-chain API [#off-chain-api]
The most common use case for the price API is to fetch Jetton info on the web2 backend and use aggregated data inside the service. There are [several](https://www.coingecko.com/en/api/ton) [historical](https://dyor.io/tonapi) Jetton price providers in TON.
There is no established solution for real-time jetton swap market data; however, one can explore [this websocket API](https://docs.coingecko.com/websocket).
## On-chain API [#on-chain-api]
Currently, it is not possible to retrieve **historical** jetton prices on-chain - since TON contracts [are limited by storage](https://docs.ton.org/llms/from-ethereum/content.md), it is quite hard to implement such an API fully on-chain. However, it is possible to retrieve **current** prices via the Request-Response pattern on some DEXes; refer to the specific service documentation to learn more about it.
Since the TON [execution model is asynchronous](https://docs.ton.org/llms/from-ethereum/content.md), the jetton price might change between the moment of the response from the price provider and the moment the contract processes the response. Consider this factor in smart contract logic.
For example, on a [popular DEX](https://dedust.io), it is possible to retrieve pool information on-chain using an internal message with the following [TL-B](https://docs.ton.org/llms/foundations/tlb/overview/content.md) schema:
```tlb
provide_pool_state#6e24728d query_id:uint64 include_assets:Bool = InMsgBody;
take_pool_state#bddd4954 query_id:uint64 reserve0:Coins reserve1:Coins total_supply:Coins
assets:(Maybe ^[ asset0:Asset asset1:Asset ]) = InMsgBody;
# See:
# https://hub.dedust.io/contracts/v2/reference/core/pool#operation-provide_pool_stat
```
Here is a smart contract snippet in [Tolk](https://docs.ton.org/llms/tolk/overview/content.md) illustrating how one can send the `provide_pool_state` message:
```tolk title="Tolk"
struct (0x6e24728d) ProvideDeDustPool {
queryId: uint64
doIncludeAssets: bool
}
fun main() {
val requestDeDustPoolInfoMsg = createMessage({
body: ProvideDeDustPool { queryId: 1, doIncludeAssets: true },
bounce: true,
dest: dedustPoolAddress,
value: 0,
});
requestDeDustPoolInfoMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}
```
# Rate limits (https://docs.ton.org/llms/api/rate-limit/content.md)
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](https://docs.ton.org/llms/api/get-api-key/content.md) 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.
# Applications overview (https://docs.ton.org/llms/applications/overview/content.md)
Integrate TON into applications and wallet services, manage payments, or interact with the blockchain directly.
## SDKs [#sdks]
There are many libraries for accessing and interacting with blockchain in dApps and tools written in various programming languages: [SDKs](https://docs.ton.org/llms/applications/sdks/content.md). For an overview of the blockchain APIs that many SDKs are built around, see the [API overview](https://docs.ton.org/llms/api/overview/content.md).
The rest of the page covers higher-level SDKs composed of a variety of smaller libraries.
## WalletKit [#walletkit]
[WalletKit](https://docs.ton.org/llms/applications/walletkit/overview/content.md) is an SDK for integrating TON into wallet services. It allows custodial and non-custodial wallet providers to manage wallets, sign transactions, and integrate TON across web, mobile, and browser extension platforms.
* Repository on GitHub: [`ton-connect/kit`](https://github.com/ton-connect/kit)
* NPM package: [`@ton/walletkit`](https://www.npmjs.com/package/@ton/walletkit)
Read more about [WalletKit](https://docs.ton.org/llms/applications/walletkit/overview/content.md).
## TON Connect [#ton-connect]
[TON Connect](https://docs.ton.org/llms/applications/ton-connect/overview/content.md) is the standard wallet connection protocol for the TON blockchain. TON Connect is the underlying communication layer behind WalletKit. It enables applications and wallets to communicate with each other in a standardized way.
* Specification repository on GitHub: [`ton-blockchain/ton-connect`](https://github.com/ton-blockchain/ton-connect)
* NPM packages:
* [`@tonconnect/ui-react`](https://docs.ton.org/llms/applications/ton-connect/api-reference/ui-react/content.md) — hooks and prebuilt components for React
* [`@tonconnect/ui`](https://docs.ton.org/llms/applications/ton-connect/api-reference/ui/content.md) — framework-agnostic UI, same components without React bindings
* [`@tonconnect/sdk`](https://docs.ton.org/llms/applications/ton-connect/api-reference/sdk/content.md) — headless connector for server-side flows or custom UI
* [`@tonconnect/protocol`](https://docs.ton.org/llms/applications/ton-connect/api-reference/protocol/content.md) — wire-format types and session cryptography for wallet and SDK implementations
Read more about [TON Connect](https://docs.ton.org/llms/applications/ton-connect/overview/content.md).
## Payment processing [#payment-processing]
Conceptual overview of correct ways of monitoring and handling blockchain transactions for business applications: [Payment processing](https://docs.ton.org/llms/applications/payments/overview/content.md).
# SDKs (https://docs.ton.org/llms/applications/sdks/content.md)
For available APIs, see the [API overview](https://docs.ton.org/llms/api/overview/content.md). When building dApps and wallet services, use [WalletKit](https://docs.ton.org/llms/applications/walletkit/overview/content.md).
There are several ways to interact with TON blockchain:
* **HTTP** libraries connect through HTTP JSON APIs to read and write to the blockchain. HTTP servers mostly relay these requests to the ADNL network.
* **ADNL** libraries connect to [liteserver](https://docs.ton.org/llms/nodes/overview/content.md).
Here's a small comparison of these protocols:
| | HTTP | ADNL |
| ---------------------------------------------------- | --------------- | --------------- |
| Standardized | No | Yes |
| Can connect from a web page | Yes | No |
| Has free third-party servers | Yes | Yes |
| Can be self-hosted | Yes | Yes |
| Requires trusting third parties | Yes1 | No |
| First connection takes time for data synchronization | No | Yes2 |
1 Some HTTP servers do provide proofs, but there is no out-of-the-box library that verifies them. 2 If proofs returned by liteservers are ignored, the first connection skips data synchronization; however, this requires trusting the liteserver.
SDKs might also provide some other functionality:
* **Core** libraries implement standard TON data structures (cell, slice), formats (address, mnemonic), cryptography, etc.
* **Wrappers** provide high-level APIs for interacting with standard contracts (Wallet, Jetton, NFT).
* **Emulator** libraries provide an execution environment similar to a real blockchain for testing purposes.
| | | HTTP | ADNL | Core | Wrappers | Emulator | Language | | | |
| -- | ---------------------------------- | ---- | ---- | ---- | -------- | -------- | ---------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- |
| ⭐ | `@ton/ton` | ✅ | | | ✅ | | TypeScript | [Code](https://github.com/ton-org/ton) | | [Chat](https://t.me/tondev_eng) |
| ⭐ | `@ton/core` | | | ✅ | | | TypeScript | [Code](https://github.com/ton-org/ton-core) | [Docs](https://ton-org.github.io/ton-core/) | |
| ⭐ | `@ton/sandbox` | | | | | ✅ | TypeScript | [Code](https://github.com/ton-org/sandbox) | | |
| ⭐ | `ton4j` | ✅ | | ✅ | | ✅ | Java | [Code](https://github.com/neodix42/ton4j) | | [Chat](https://t.me/ton4java) |
| ⭐ | `tonutils-go` | | ✅ | ✅ | ✅ | | Go | [Code](https://github.com/xssnick/tonutils-go) | | [Chat](https://t.me/tonutils) |
| ⭐ | `tonutils` | ✅ | ✅ | ✅ | ✅ | | Python | [Code](https://github.com/nessshon/tonutils) | [Docs](https://tonutils.ness.su/) | [Chat](https://t.me/pythonnton) |
| | `@ton-community/assets-sdk` | ✅ | | | ✅ | | TypeScript | [Code](https://github.com/ton-community/assets-sdk) | | |
| | `adnl` | | ✅ | | | | TypeScript | [Code](https://github.com/tonkite/adnl) | | |
| | `tonutils` | | ✅ | | | | TypeScript | [Code](https://github.com/thekiba/tonutils) | | |
| | `tonlib-java` | | ✅ | | | | Java | [Code](https://github.com/ton-blockchain/tonlib-java) | | |
| | `tonlib` | | ✅ | | | | C++ | [Code](https://github.com/ton-blockchain/ton/tree/master/tonlib) | [Docs](https://github.com/ton-blockchain/ton/tree/master/example/cpp) | |
| | `pytonlib` | | ✅ | | | | Python | [Code](https://github.com/toncenter/pytonlib) | | |
| | `pytoniq` | | ✅ | | | | Python | [Code](https://github.com/yungwine/pytoniq) | [Docs](https://yungwine.gitbook.io/pytoniq-doc/) | [Chat](https://t.me/pythonnton) |
| | `pytoniq-core` | | | ✅ | | | Python | [Code](https://github.com/yungwine/pytoniq-core) | [Docs](https://yungwine.gitbook.io/pytoniq-doc/) | [Chat](https://t.me/pythonnton) |
| | `mytonlib` | | ✅ | ✅ | | | Python | [Code](https://github.com/igroman787/mytonlib) | | |
| | `tonpy` | | | ✅ | | | Python | [Code](https://github.com/disintar/tonpy) | [Docs](https://tonpy.dton.io/) | |
| | `tvm_valuetypes` | | | ✅ | | | Python | [Code](https://github.com/toncenter/tvm_valuetypes) | | |
| | `pytvm` | | | | | ✅ | Python | [Code](https://github.com/yungwine/pytvm) | | |
| | `tongo` | | ✅ | ✅ | ✅ | ✅ | Go | [Code](https://github.com/tonkeeper/tongo) | | |
| | `ton` | ✅ | | | | | PHP | [Code](https://github.com/olifanton/ton) | | |
| | `interop` | | | ✅ | | | PHP | [Code](https://github.com/olifanton/interop) | | |
| | `ton-rs` | | ✅ | ✅ | ✅ | ✅ | Rust | [Code](https://github.com/ston-fi/ton-rs) | | |
| | `ton-grpc` | | ✅ | | | | Rust | [Code](https://github.com/getgems-io/ton-grpc) | | |
| | `tonsdk.net` | | ✅ | ✅ | | | C# | [Code](https://github.com/continuation-team/TonSdk.NET) | | [Chat](https://t.me/cont_team/104) |
| | `tonlib.net` | | ✅ | ✅ | ✅ | | C# | [Code](https://github.com/justdmitry/TonLib.NET) | | |
| | `ton` | | | ✅ | | | Elixir | [Code](https://github.com/ayrat555/ton) | | |
| | `@tetherto/wdk-wallet-ton` | ✅ | | | ✅ | | JavaScript | [Code](https://github.com/tetherto/wdk-wallet-ton) | [Docs](https://github.com/tetherto/wdk-docs/tree/main/sdk/wallet-modules/wallet-ton) | |
| | `@tetherto/wdk-wallet-ton-gasless` | ✅ | | | ✅ | | JavaScript | [Code](https://github.com/tetherto/wdk-wallet-ton-gasless) | [Docs](https://github.com/tetherto/wdk-docs/tree/main/sdk/wallet-modules/wallet-ton-gasless) | |
| | ~~`ton-kotlin`~~ | | ✅ | ✅ | | | Kotlin | [Code](https://github.com/ton-blockchain/ton-kotlin) | [Docs](https://github.com/ton-blockchain/ton-kotlin/wiki/TON-Kotlin-documentation) | |
| | ~~`tonlib-go`~~ | | ✅ | | | | Go | [Code](https://github.com/ton-blockchain/tonlib-go) | | |
| | ~~`tonweb`~~ | ✅ | | | | | JavaScript | [Code](https://github.com/toncenter/tonweb) | | |
| | ~~`node-tonlib`~~ | | ✅ | | | | JavaScript | [Code](https://github.com/labraburn/node-tonlib) | | |
| | ~~`tontools`~~ | ✅ | ✅ | | | | Python | [Code](https://github.com/yungwine/TonTools) | | |
| | ~~`swiftyton`~~ | | ✅ | | | | Swift | [Code](https://github.com/labraburn/SwiftyTON) | | |
| | ~~`tonlib-xcframework`~~ | | ✅ | | | | Swift | [Code](https://github.com/labraburn/tonlib-xcframework) | | |
| | ~~`tonlib-rs`~~ | | ✅ | ✅ | ✅ | ✅ | Rust | [Code](https://github.com/ston-fi/ton-rs) | | |
See also:
* [WDK Core](https://github.com/tetherto/wdk-core), JavaScript - Modular library from Tether, which supports wallet management and various swap, bridge, and lending services for many blockchains at once.
# Smart contracts (https://docs.ton.org/llms/contracts/overview/content.md)
This section covers the recommended toolchain, editor support, standard contracts, reusable techniques, and the legacy TypeScript environment.
The Web IDE at `ide.ton.org` has been retired and is no longer available. Develop locally with the [Acton toolchain](#toolchain) and one of the [editor plugins](#ides-and-editor-plugins) below.
## Toolchain [#toolchain]
[Tolk](https://docs.ton.org/llms/tolk/overview/content.md) is the recommended language for TON smart contracts. [Acton ↗️](https://docs.ton.org/llms/contract-dev/acton/content.md) is the recommended all-in-one toolchain for the entire contract development lifecycle, including building, testing, and deploying Tolk contracts.
[Acton ↗️](https://docs.ton.org/llms/contract-dev/acton/content.md) documentation is hosted and updated externally.
### IDEs and editor plugins [#ides-and-editor-plugins]
Add support for the Acton toolchain, Tolk language, and intermediate TON languages to a local editor:
* [VS Code and forks](https://docs.ton.org/llms/contracts/ide/vscode/content.md) — extension for VS Code, VSCodium, Cursor, Windsurf, and other VS Code-based editors
* [JetBrains IDEs](https://docs.ton.org/llms/contracts/ide/jetbrains/content.md) — plugin for IntelliJ IDEA, WebStorm, CLion, PyCharm, and other JetBrains IDEs
## Quick start [#quick-start]
Follow the [quickstart page in the Acton documentation](https://ton-blockchain.github.io/acton/docs/quickstart).
## Standard contracts [#standard-contracts]
Descriptions of the most popular standardized contracts and how to work with them: [Standard contracts](https://docs.ton.org/llms/contracts/standard/overview/content.md).
## Techniques [#techniques]
Focused how-to guides for advanced smart contract tasks:
* [Signing and signature verification](https://docs.ton.org/llms/contracts/techniques/signing/content.md)
* [Contract sharding](https://docs.ton.org/llms/contracts/techniques/contract-sharding/content.md)
* [Security best practices](https://docs.ton.org/llms/contracts/techniques/security/content.md)
* [Gas optimization](https://docs.ton.org/llms/contracts/techniques/gas/content.md)
* [On-chain jetton processing](https://docs.ton.org/llms/contracts/techniques/on-chain-jetton-processing/content.md)
* [Using on-chain libraries](https://docs.ton.org/llms/contracts/techniques/using-on-chain-libraries/content.md)
* [Random number generation](https://docs.ton.org/llms/contracts/techniques/random/content.md)
* [Contract upgrades](https://docs.ton.org/llms/contracts/techniques/upgrades/content.md)
* [Vanity addresses](https://docs.ton.org/llms/contracts/techniques/vanity/content.md)
* [Zero-knowledge proofs](https://docs.ton.org/llms/contracts/techniques/zero-knowledge/content.md)
* [Groth16 examples](https://docs.ton.org/llms/contracts/techniques/groth16-examples/content.md)
## Blueprint (legacy) [#blueprint-legacy]
[Blueprint](https://docs.ton.org/llms/contracts/blueprint/overview/content.md) is a legacy TypeScript environment that is still supported for older projects.
# TON documentation style guide (https://docs.ton.org/llms/contribute/style-guide-extended/content.md)
## Purpose, scope, and normative terms [#purpose-scope-and-normative-terms]
Purpose. This guide defines the required writing style for all public, developer-facing TON documentation. Its goal is to maximize reading experience and task success: a developer should be able to land on the right page, follow it once, and succeed. This document is intentionally explicit so both humans and automated tools (including LLM reviewers) can apply it consistently. (Why: a single, explicit house style reduces cognitive load, prevents voice drift, and enables reliable human and automated review.)
Scope. These rules **MUST** be followed on all pages in the docs site, including, for example: step-by-step/how-tos, explanations, and references (CLI, TVM, standard contracts, network, config, serialization). Exceptions **MUST** be documented in Style exceptions with owner and expiry. (Why: consistent coverage avoids fragmented micro-styles; documented exceptions stay accountable and temporary.)
Normative terms. The keywords **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, **RECOMMENDED**, and **OPTIONAL** are to be interpreted as described in RFC 2119/8174. (Why: shared semantics eliminate ambiguity about what is mandatory vs. optional.)
Definitions (used throughout).
* Page — a single documentation article.
* Doc type — one of: Step by step, How-to guide, Explanation, Reference (see [§3](#3-documentation-framework-content-types)).
* Snippet — any code or command block.
* Partial snippet — a focused excerpt that **MAY** be non-runnable by itself and **MUST** be labeled as such (see [§10](#10-code-and-command-examples)).
* Placeholder — a value the reader must replace; formatted as ``.
* Admonition — a callout such as Note, Tip, Important, Caution, or Warning.
* Reference anchor — a deep link to a specific item in a reference page (flag, field, error code, and similar items).
Out of scope. Editorial process, CI wiring, analytics/metrics, and governance live outside this guide. (This guide is about writing.) (Why: focusing on writing rules keeps this document stable and avoids process churn.)
Living document. This guide evolves with the documentation. Editors **MAY** update rules as the information architecture and best practices change. When the guide changes, all existing documentation **MUST** be re-validated against the new rules and updated as needed to keep the docs consistent. (Why: styles must adapt as the product and the information architecture evolve; re-validation prevents long-term drift.)
### Severity model (release-blocking) [#severity-model-release-blocking]
Legend. \[HIGH] blocks release; \[MEDIUM] warns (non-blocking); \[LOW] suggestion.
Defaults. Unless marked otherwise: MUST/MUST NOT → \[MEDIUM]; SHOULD/SHOULD NOT → \[LOW]; MAY/OPTIONAL/RECOMMENDED → \[LOW].
Global overrides (always \[HIGH]). Safety callouts ([§11](#11-safety-critical-content-blockchain-specific)) when required; secrets in examples; copy/paste hazards (prompts in commands, mixed command+output, hard-wrapped commands, undefined placeholders); destructive flags without warnings; broken/missing anchors or linking to superseded pages as normative; non-HTTPS/tracked/unofficial links when official exists; use of `{}`/`[]` placeholders in commands; silent truncation of IDs/addresses.
Annotation scope. To keep the doc clean, inline badges are added only to \[HIGH] items; all other items inherit the defaults above.
## Goals and principles (reader-first, answer-first) [#1-goals-and-principles-reader-first-answer-first]
* Intent. Every page exists to help a developer finish a real task quickly and correctly.
* Pages **MUST** optimize for clarity, scannability, accuracy, and trust;
* Pages **MUST NOT** contain marketing language in technical sections. \[HIGH]
* Pages **SHOULD** be answer-first (solution before theory) and example-first (real code before exposition). (Why: task-focused, plain, and scannable pages help readers complete work on the first try; marketing copy and theory up front slow readers and reduce trust.)
Principles.
1. Answer-first. Open with purpose, outcome, and prerequisites. Then show the steps (or the API signature in reference). Background theory moves to its own Explanation page or a brief end section. (Why: leading with the solution shortens time-to-success; moving theory prevents detours for readers who just need to act.)
Example (good):
Goal: “Send a jetton from a web app.” Prerequisites: JS SDK, funded testnet wallet. Steps: 1–5. Verify: expected output. Troubleshoot: common errors.
2. Example-first and precise. Provide copy-pasteable snippets with expected output. Use `` values and define them at first use. Avoid unnecessary narrative around code. (Why: runnable, minimal examples remove guesswork; placeholders prevent users from pasting unsafe, hard-coded values.)
3. Minimal concepts in task pages. Do not front-load long explanations in step-by-step/how-tos. Link to a concept page instead. (Why: keeping theory separate avoids cognitive overload; readers can pull background only if they need it.)
4. Single source of truth. Don’t duplicate reference tables in guides. Summarize only what's needed, then link to the reference anchor. (Why: duplication drifts and conflicts; deep links keep guides brief and ensure details stay correct in one place.)
5. Scannability. Prefer short paragraphs (≤ \~5 sentences) and short sentences (\~15–20 words). Use headings, lists, and tables to chunk information. See [§8](#8-readability-and-scannability) for norms and flexibility. (Why: short, well-chunked text is faster to scan and reduces rereads and errors.)
Anti-patterns (MUST NOT). Vague claims (“blazingly fast”), filler (“simply”, “just”, “obviously”, “please note”), and long theoretical detours in task pages. (Why: vague or padded text wastes time and hides the action; front-loaded theory blocks progress for users who came to do a task.)
## Audience and assumptions [#2-audience-and-assumptions]
Default audience. The primary reader is new to blockchain but experienced in software development. (Why: sets a clear baseline so pages explain TON concepts without re-teaching general programming.) Pages **MUST NOT** re-teach generic developer skills (e.g., basic shell, Git, Python/JS syntax) unless a step is unusual for TON. (Why: keeps pages focused and shorter; duplicating generic skills adds noise and goes stale quickly.)
Declaring prerequisites. Step by step and how-to pages **SHOULD** include a Prerequisites block at the top. Reference pages **SHOULD** include a one-line Summary to orient the reader. (Why: consistent placement improves scanning and lets readers self-select quickly.)
### 2.1 What belongs in Prerequisites [#21-what-belongs-in-prerequisites]
Prerequisites are entry conditions: things the reader must have or have done before starting. Each item **MUST** be concrete and verifiable. (Why: readers should be able to check each prerequisite before starting to avoid wasted effort.)
Examples of valid prerequisite categories:
* **Software already installed** (not installed during the guide). Specify version and link to download page.
* **Accounts or access already obtained**: API keys, RPC endpoints, wallet accounts.
* **Artifacts from prior work**: `"A deployed contract from [Deploy a counter](https://docs.ton.org/llms/path/to/guide/content.md)"`, `"A funded testnet wallet"`.
* **Funds or tokens**: "Testnet GRAM from the [faucet](https://...)".
* **Unusual hardware** (only when relevant): "A machine with at least 16 GiB RAM".
### 2.2 What does not belong in Prerequisites [#22-what-does-not-belong-in-prerequisites]
* **Obvious assumptions**. You **MUST NOT** list: internet connection, an operating system, a keyboard, a terminal/shell, a browser, a text editor, or similar universal tools. (Why: obvious items waste space and insult reader intelligence.) \[HIGH]
* **Things installed or created during the guide**. If step 1 is "Install the SDK", the SDK is **NOT** a prerequisite — the prerequisite is what is needed to install it (e.g., Node.js). You **MUST NOT** list items that the guide itself provides. (Why: listing in-guide installations as prerequisites confuses readers about what they need beforehand.) \[HIGH]
* **Skills or knowledge**. "Familiarity with TypeScript" or "Understanding of smart contracts" are audience statements, not prerequisites. Use a separate "Audience" note for these (e.g., "Audience: Intermediate. Assumes working knowledge of TypeScript and async/await."). You **MUST NOT** mix skills into the Prerequisites list. (Why: skills cannot be "installed" or verified the same way; separating them clarifies what readers need to do vs. know.) \[HIGH]
* **Background reading or concept links**. `"Read the [Account model](https://docs.ton.org/llms/foundations/accounts/content.md) page first"` belongs in prose or a "Background" section, not Prerequisites. If understanding a concept is truly required, state it as an audience assumption. You **SHOULD NOT** put learning links in Prerequisites. (Why: prerequisites are for artifacts and tools, not reading assignments.)
### 2.3 Version specifications [#23-version-specifications]
* Software prerequisites **MUST** specify at least the version tested in the guide. (Why: unversioned requirements cause "works on my machine" failures.) \[HIGH]
* Software prerequisites **SHOULD** specify a supported range when known (e.g., "Node.js 20 or later LTS", "Python 3.10+"). (Why: ranges tell readers whether their existing installation works.)
* You **MUST NOT** use vague terms like "latest" or "recent version". (Why: "latest" changes over time and provides no actionable information.) \[HIGH]
### 2.4 Links in Prerequisites [#24-links-in-prerequisites]
* Each software prerequisite **MUST** link to an official download or installation page, not to the project homepage or documentation root. (Why: readers need to act, not browse; download pages are actionable.) \[HIGH]
* For tools with OS-specific installers, you **MAY** link to a general downloads page that offers all variants.
* For TON-ecosystem tools documented in these docs, link to the internal installation guide if one exists.
### 2.5 Prerequisite examples [#25-prerequisite-examples]
Good:
```text
Prerequisites:
- [Node.js](https://nodejs.org/en/download/) 20 or later LTS
- A funded testnet wallet (get testnet GRAM from the [faucet](https://t.me/testgiver_ton_bot))
- An RPC endpoint — use a public endpoint or get one from [TON Center](https://toncenter.com/)
```
Bad:
```text
Prerequisites:
- A computer with internet access ← obvious
- Node.js ← no version, no link
- Install the TON SDK ← installed in the guide, not a prerequisite
- Familiarity with JavaScript ← skill, not a prerequisite
- Read the [wallets overview](https://docs.ton.org/llms/wallets/content.md) ← background reading, not a prerequisite
```
### 2.6 Audience and skill assumptions [#26-audience-and-skill-assumptions]
Pages with advanced requirements **MUST** state them at the top in a separate Audience note, not in Prerequisites. (Why: separating "what you need to have" from "what you need to know" helps readers self-select.)
Example:
```text
Audience: Advanced. Assumes understanding of TVM exit codes and TL-B schemas.
See: [TVM exit codes](https://docs.ton.org/llms/tvm/exit-codes/content.md), [TL-B overview](https://docs.ton.org/llms/data-formats/tlb/content.md).
```
Inclusive/global readers. Use plain, international English; avoid idioms and culture-specific references. Prefer neutral, inclusive terms (e.g., allowlist/denylist). (Why: idioms and local metaphors confuse non-native readers; inclusive terms are more precise and avoid unintended exclusion.)
## Documentation framework (content types) [#3-documentation-framework-content-types]
Rule. Each page **MUST** be one of the following: Step by step, How-to guide, Explanation, or Reference. Types **MUST NOT** be mixed on a single page. The chosen type **MUST** be clear from the title and content. (Why: single-purpose pages are easier to find and follow; mixing types blurs intent and causes duplication.)
Small, clearly marked asides (e.g., a 1–2-step “Verify” box in an Explanation) **MAY** appear when they aid comprehension; the page’s primary type remains unchanged. (Why: tiny, labeled asides help understanding without turning a concept page into a task page.)
### 3.1 What each type means (and looks like) [#31-what-each-type-means-and-looks-like]
* Step by step (first success). Single happy path for newcomers. Hand-holding is **RECOMMENDED**. (Why: one clear path gets novices to a working result quickly; branching early increases drop-off.)
Title style: “Deploy a counter contract on testnet”. (Why: action-oriented titles set expectations and help search/TOC scanning.)
Sections (suggested): Objective → Prerequisites → Steps → Verify → Troubleshoot → Next steps. Keep Next steps minimal (1–3 essential links) or omit when the path is linear. **SHOULD** avoid theory beyond two short bullets; link to an Explanation page. (Why: predictable structure reduces cognitive load; keeping theory brief prevents blocking progress.)
* How-to guide (goal-oriented procedure). A recipe to achieve a specific outcome. **MUST** be procedural and concise. (Why: readers come for a recipe; extra narrative slows execution and invites errors.)
Title style: “How to mint a jetton with the CLI”. (Why: the “How to …” pattern matches search intent and signals page type while staying specific.)
Rule: **MUST NOT** embed long background; link to concepts as needed. (Why: avoids duplication and keeps the guide focused; background stays current in one canonical place.)
* Explanation (concepts/why). Background, architecture, trade-offs. **SHOULD** avoid step lists and commands. (Why: separating “why” from “how” improves comprehension and prevents pages from doing two jobs badly.)
Title style: “Account model and messages in TON”. (Why: noun-based titles signal conceptual content and improve browseability.)
* Reference (complete, factual). Exhaustive specs for APIs/CLI/SDK/types/errors. Non-narrative tables and exact semantics. (Why: factual, uniform entries are scannable and machine-linkable; narrative slows lookups.)
Title style: “`tvm.runvm` — interface and exit codes”. (Why: placing the exact identifier in the title improves search and deep linking.)
Rule: **MUST** be precise, consistent, and anchor-linkable. (Why: deep anchors let guides link directly; precision prevents support churn and conflicting copies.)
## Voice and tone [#4-voice-and-tone]
Objective. Sound like a helpful expert: professional, precise, and approachable. Use the same voice across all pages. (Why: a consistent, expert tone builds trust and reduces cognitive load; readers know what to expect across the site.)
Rules (binding).
* Use present tense, active voice, and the imperative mood. Write steps as commands (e.g., “Run the validator.”), not future tense or passive voice. Avoid addressing the reader with “you”. (Why: imperative, active phrasing makes the action clear without personal address and reduces ambiguity in steps.)
* Be neutral and inclusive. Avoid slang, idioms, culture-specific jokes, or hype. (Why: neutral language is easier for non-native readers and translators, and avoids alienating parts of the audience.)
* **MUST NOT** use filler or patronizing words: simply, just, obviously, clearly, please note. Replace with exact instructions (Why: filler wastes time and can sound condescending; precise verbs tell the reader exactly what to do.)
* Emojis in prose and headings **MUST NOT** appear. Use clear text or an `` when emphasis is needed. (Why: emojis are ambiguous, distract from procedures, and do not localize reliably.)
* Emojis in code/command blocks **MAY** appear only when they are part of runnable code or a literal command/output string. Do not add emojis for decoration; the snippet **MUST** remain copy-pasteable and executable as shown. If quoting a UI/log message that contains an emoji, keep it verbatim inside quotes. (Why: runnable examples take precedence; avoiding decorative emojis preserves clarity and execution.)
* Emojis in compact tables **MAY** be used sparingly as visual indicators only when they follow a widely understood convention (for example, `✅` / `❌` for supported/not supported, or `★` to mark a recommended option) and **MUST** be paired with a text label in the same cell or a descriptive header (e.g., “Supported — Yes/No”). Do not rely on an emoji alone to convey meaning, and **MUST NOT** use decorative or non-standard pictograms (for example, a play triangle to indicate videos). (Why: paired, conventional icons preserve clarity for screen readers, localization, and cases where emojis don’t render.)
* Even where emojis are technically allowed (code/output or compact tables), they **SHOULD** be rare and **MUST** have a clear purpose. If the same meaning is clear without the emoji, remove it. (Why: conventional text remains clearer for global readers and translators.)
* Use plain terms over legalese/Latinisms. “Use” not “utilize”; “before” not “prior to.” (Why: common words improve comprehension and reduce rereads; they are also translated more consistently.)
* Avoid first-person pronouns (“we”, “I”, “our”). When an organization, product, or service is the actor, use its proper name (e.g., “MyTonWallet”, “TON”) or a neutral noun (“the node”, “the SDK”). Prefer imperative instructions without “you”. See [§5.8](#5-8-dont-get-personal) and [§5.10](#5-10-pronouns-and-person-references). (Why: neutral, explicit actors read cleanly and translate reliably.)
Marketing and promotional language (ban).
* You **MUST NOT** use marketing-style language anywhere in technical content, including titles, headings, steps, tables, references, and callouts. This includes: \[HIGH]
* Superlatives and hype: "blazingly fast", "revolutionary", "world-class", "seamless", "best-in-class", "powerful", "cutting-edge".
* Vague positive adjectives: "reliable", "robust", "essential", "elegant", "intuitive", "flexible", "comprehensive", "scalable" (when used without measurable criteria).
* Dramatic or emotional framing: "elusive", "challenging", "painful", "frustrating", "nightmare", "perfectly", "beautifully". Technical writing states facts, not feelings.
* Intensity words that exaggerate: "instantly", "immediately" (unless literally true), "extremely", "incredibly", "massive", "huge" (for non-quantified values).
* Storytelling openers: "Imagine…", "Picture this…", "Have you ever…", "What if…". Start with the task or fact instead.
(Why: hype and drama erode trust, slow scanning, obscure required actions, and age poorly.)
* Replace subjective claims with measurable facts (numbers, constraints, conditions) or remove them entirely. If a claim cannot be tested or measured, delete it. (Why: facts enable correct implementation and reproducible results.) \[HIGH]
* When describing benefits, state **what** happens and **under what conditions**, not how it feels. (Why: readers need actionable information, not emotional appeals.)
* Bad: "This approach provides a robust and reliable solution."
* Good: "This approach retries failed requests up to three times with exponential backoff."
* Bad: "Tests catch issues instantly."
* Good: "Tests run in under 2 seconds and fail on the first assertion violation."
Micro-examples.
* Bad: “We’ll just quickly configure the node; it’s super easy!”
Good: “Configure the node.”
* Bad: “Let’s go ahead and utilize the script.”
Good: “Run the script.”
* Bad: “Obviously, the transaction fails if the fee is low.”
Good: “The transaction fails if the fee is too low.”
## Grammar and usage [#5-grammar-and-usage]
Objective. Make sentences easy to parse on first read. (Why: clear, low-friction sentences reduce rereads and mistakes during implementation.)
### 5.1 Voice, tense, and person [#51-voice-tense-and-person]
* You **MUST** use active voice by default. Passive voice **MAY** be used only when the actor is unknown or irrelevant. (Why: active voice makes who does what explicit; passive hides responsibility and confuses steps.)
* Good: “The validator stops if the config is invalid.”
* Bad: “The validator is stopped if the config is invalid.”
* You **MUST** use the present tense for general behavior and instructions; the future tense **SHOULD** be reserved for time-dependent statements. (Why: present tense reads simpler and matches how-to steps; future tense adds unnecessary words and ambiguity.)
* Good: “The API returns JSON.”
* Bad: “The API will return JSON.”
* Prefer imperative instructions without addressing the reader (“you”). Avoid first-person pronouns (“we”, “I”, “our”); when an organization, product, or service is the actor, use its proper name (e.g., “TON Center”, “TON”). See [§5.8](#5-8-dont-get-personal) and [§5.10](#5-10-pronouns-and-person-references). (Why: imperative, neutral phrasing keeps actors clear without personal address.)
### 5.2 Plain, precise wording [#52-plain-precise-wording]
* You **SHOULD** prefer common words over legalese or Latinisms. (Why: familiar words are understood faster and translated more reliably.)
* Use “use,” not “utilize.” Use “before,” not “prior to.”
* Hedging and filler **MUST NOT** appear: simply, just, obviously, clearly, please note. Replace with exact actions or facts. (Why: filler wastes time and can sound condescending; specifics tell readers exactly what to do.)
### 5.3 Acronyms and terms [#53-acronyms-and-terms]
* On first mention, you **MUST** spell out the term and follow with the acronym in parentheses. Use the acronym thereafter. (Why: defines terms once and keeps later text concise.)
* Example: “The Open Network (TON)…”
* Project terminology **MUST** follow the term bank/glossary (see [§13](#13-terminology-and-naming)). Avoid introducing synonyms for the same concept. (Why: one canonical term prevents confusion and search/indexing issues.)
### 5.4 Audience calibration [#54-audience-calibration]
* Assume developers are new to blockchain (but experienced in software). **MUST NOT** re-teach generic developer skills unless a TON-specific nuance requires it (see [§2](#2-audience-and-assumptions)). Provide concise prerequisites when needed. (Why: focusing on TON reduces noise and keeps pages shorter and more relevant.)
### 5.5 Global and inclusive language [#55-global-and-inclusive-language]
* You **MUST** avoid idioms, cultural references, and biased terms. Prefer neutral alternatives (e.g., allowlist/denylist). Use people-neutral wording and accessible examples. (Why: idioms and bias exclude readers and harm translation; neutral wording is clearer for everyone.)
### 5.6 Spelling and contractions [#56-spelling-and-contractions]
* Spelling **MUST** follow American English (e.g., color, analyze). (Why: a single spelling standard prevents mixed variants and review churn.)
* Contractions (don’t, can’t) **MAY** be used when they improve flow and do not reduce clarity. (Why: natural phrasing is easier to read as long as the meaning stays clear.)
### 5.7 Avoid unfinished work [#57-avoid-unfinished-work]
Articles **MUST NOT** have any TODO, mentions of the work on the article to be done in future, itemized or text plans on its continuation, unfinished sections (headers without any text afterwards). The only exception is use of the `` component to tell the whole page is not finished yet. \[HIGH]
### 5.8 Don't get personal [#58-dont-get-personal]
Articles **MUST NOT** use pronouns "you", "your" to refer to a reader, and **MUST NOT** use pronouns "we", "I", "our" to refer to an author. (Why: documentation must only describe facts; it knows no facts about readers; most facts about writers are off-topic). \[HIGH]
### 5.9 Avoid tautology, pleonasm, throat-clearing, and circular references [#59-avoid-tautology-pleonasm-throat-clearing-and-circular-references]
Objective. Remove wordy redundancies and self-referential boilerplate so the reader gets the signal only. (Why: cutting redundancy speeds reading and reduces confusion.)
#### Rules (normative) [#rules-normative]
* You **MUST** remove tautologies/pleonasms (duplicate meaning in different words). (Why: redundant pairs add length without adding meaning.)
* Bad: “End result” → Good: “result”
* Bad: “Advance planning” → Good: “planning”
* Bad: “Free gift” → Good: “gift”
* You **MUST NOT** use throat-clearing/circular openers that describe the doc instead of delivering value. (Why: readers come to act; meta-introductions delay the task.) \[HIGH]
* Bad: “In this section, we will discuss how to…”, “This document aims to explain…”
* Good: “Deploy a validator on testnet.” (start with the action)
* You **SHOULD** collapse wordy boilerplate into precise verbs. (Why: shorter, direct phrasing is faster to parse.)
* Bad: “In order to” → Good: “To”
* Bad: “For the purpose of” → Good: “To”
* Bad: “Due to the fact that” → Good: “Because”
* You **MUST** avoid doublets/triplets (pairs that mean the same thing). (Why: repeating the same idea signals uncertainty and wastes space.)
* Bad: “each and every”, “basic fundamentals”, “final outcome”, “past history”, “future plans going forward”, “merge together”, “close proximity”, “completely eliminate”
* You **MUST** avoid tautological logic and circular definitions. (Why: circular text doesn’t explain behavior and blocks understanding.)
* Bad: “A jetton is a jetton if it conforms to the jetton standard.”
* Good: “A jetton is a fungible token on TON defined by the Jetton standard, which specifies message formats for mint/transfer/burn.”
* You **SHOULD** replace hedges and intensifiers with facts. (Why: intensity words add emotion, not information; facts reduce ambiguity.) \[HIGH]
* Avoid: “basically”, “essentially”, “really”, “very”, “actually”, “literally” (unless literal).
* If precision matters, give a number, constraint, or example instead.
* You **MUST NOT** use and/or. (Why: it is ambiguous; readers cannot tell if both are allowed or required.)
* Write: “A, B, or both” or “A or B” (choose one).
* You **SHOULD NOT** use etc. in procedures or lists. (Why: open-ended lists leave readers unsure what is required.)
* Either complete the list or write “for example” and stop.
* You **MUST** avoid “as mentioned above/below”; link to the exact anchor instead (see [§12](#12-links-and-cross-references)). (Why: relative references break when pages change; links stay accurate.)
* You **SHOULD** simplify “whether or not” → “whether”; “the reason is because” → “because”; “not uncommon” → “common/often.” (Why: simpler forms are clearer and shorter.)
See also: [Appendix B](#b-banned-and-preferred-terms) lists additional banned intensifiers and tone words.
#### Before/after micro-examples [#beforeafter-micro-examples]
* Throat-clearing
* Before: “In this guide, we will show you how to configure a validator.”
* After: “Configure a validator.”
* Tautology
* Before: “The final outcome of the deployment process…”
* After: “The result of the deployment…”
* Wordy boilerplate
* Before: “In order to reduce fees, you need to…”
* After: “To reduce fees, …”
* Hedge + intensifier
* Before: “It’s basically very important to verify the address.”
* After: “Verify the address.”
* Circular reference
* Before: “Sharding improves scalability because it shards the chain.”
* After: “Sharding splits the chain into parallel shards that process transactions concurrently, increasing throughput.”
### 5.10 Pronouns and person references [#510-pronouns-and-person-references]
* You **MUST** use gender-neutral singular “they/them/their” when referring to an unspecified or generic person. **MUST NOT** use gendered or split forms such as “he”, “she”, “he/she”, “s/he”, or “(s)he” for generic subjects. \[HIGH] (Why: singular “they” is inclusive, concise, and avoids awkward constructions.)
* Prefer imperative instructions or role nouns to avoid pronouns when possible (e.g., “Deploy the contract.” or “The operator updates the config.”). (Why: direct phrasing is clearer and reduces ambiguity.)
* When referring to a named individual who has stated pronouns, use that person’s pronouns; if unknown or irrelevant, default to “they”. (Why: respect individuals while keeping language inclusive.)
* Do **NOT** anthropomorphize software or networks with gendered pronouns. Use neutral nouns or “it” (e.g., “the node restarts”, “it fails to start”). (Why: avoids confusion and maintains technical tone.)
* For organizations, products, and services, use the proper name (e.g., “TON”, “MyTonWallet”) or the neutral “it”; do not use “we/I/our” in documentation. (Why: consistent, neutral references read cleanly and translate reliably.)
### 5.11 Parentheses [#511-parentheses]
* Parentheses **MAY** be used for short clarifications and abbreviation expansions (for example, “The Open Network (TON)”) but **SHOULD NOT** be used for extended side remarks. (Why: side remarks buried in parentheses are easy to miss and hard to translate.)
* When a parenthetical includes an extra idea, condition, or step, split the sentence into two sentences or move the extra idea into its own sentence or list item instead of nesting it in parentheses. (Why: one idea per sentence is easier to parse and localize.)
* Where a parenthetical is necessary for precision, keep it short and avoid chaining more than one set of parentheses in the same sentence. (Why: multiple nested asides make sentences hard to read.)
## Punctuation and mechanics [#6-punctuation-and-mechanics]
Objective. Remove ambiguity and increase scan speed with consistent mechanics. (Why: predictable punctuation choices make sentences easier to parse and reduce misreads.)
### 6.1 Commas, colons, semicolons [#61-commas-colons-semicolons]
* The Oxford (serial) comma **MUST** be used in lists of three or more items: “nodes, wallets, and explorers.” (Why: prevents ambiguity about whether the last two items are grouped.)
* Comma splices **MUST NOT** occur. If two clauses can stand alone, use a period or a coordinating conjunction. (Why: run-on sentences are hard to scan; separating clauses improves clarity.)
* Bad: “The node restarts, it begins syncing.”
* Good: “The node restarts. It then begins syncing.”
* Colons **SHOULD** introduce lists or explanations after a complete clause. Semicolons **SHOULD** be rare. Prefer shorter sentences. (Why: correct colon use signals structure; semicolons slow scanning and can often be replaced by periods.)
### 6.2 Quotation marks and emphasis [#62-quotation-marks-and-emphasis]
* Quotation marks **MUST** be used only for actual quotations or literal UI text/messages, not for emphasis. (Why: quotes indicate exact strings; using them for emphasis misleads readers and translators.)
* Good: The error message “Account not found” appears.
* Bad: The “validator” node… (do not quote terms)
* House rule — quoting style: Use the international style with American spelling. Quotation punctuation **MUST** remain outside closing quotes unless it is part of the quoted text. This differs from American book style; keep it consistent. (Why: keeps code-adjacent strings accurate and avoids adding punctuation that isn’t part of the literal.) \[HIGH]
* Use double quotation marks for log/error strings and other literal UI text when quoting it as text; place punctuation outside unless it is part of the string. (Why: quotes remain the convention for messages/text and keep literals copyable.)
* This rule applies to quoted UI/log/error strings only; it does not apply to code spans or headings. (Why: code spans and headings have their own styling rules.)
* Log messages and error strings **MUST** appear verbatim in quotation marks; **MUST NOT** add emphasis or change casing/punctuation. (Why: exact copying/grepping depends on matching strings.) \[HIGH]
* When referencing interactive controls or keyboard keys that the reader should click or press, you **MUST** use `Label` for the control or key name. You **MUST NOT** use quotation marks, bold, or italics to style controls in instructions. (Why: `` is designed for controls/keys and keeps actions easy to scan and copy.)
* Good: Click `Settings`, then select `Network`.
* Bad: Click “Settings” or **Settings**.
* UI or menu labels that appear in screenshots or descriptive text but are not being presented as actions **MAY** be written in quotes. Avoid mixing `` and quoted labels arbitrarily; prefer one style consistently within a page/section. For quoted UI strings, follow the house quoting style above. Punctuation follows normal sentence rules outside ``. (Why: consistent styling keeps text readable and copyable.)
* Error codes/identifiers **MUST** use code formatting: `ERR_FEE_TOO_LOW`, `EADDRINUSE`, `ENOENT`. (Why: code styling distinguishes tokens from prose and aids scanning and copy/paste.)
* When paraphrasing behavior, you **MUST NOT** alter message semantics; label paraphrases clearly and avoid quotation marks. (Why: altered wording leads to mismatches during troubleshooting.)
#### Emphasis (bold and italics) [#emphasis-bold-and-italics]
* Bold and italics **SHOULD** be used sparingly in body text. Prefer structure (headings, lists), precise wording, or an admonition over visual emphasis. (Why: heavy emphasis reduces scan speed and harms raw-Markdown readability.)
##### Bold [#bold]
* Bold **SHOULD** mark scan points: a skimming reader should be able to bounce between bolded words and still understand the key actions or constraints in a section. (Why: using bold as a scan path keeps pages easy to scan.)
* Use bold for a few critical words in a heading or paragraph, not whole sentences. If the paragraph still communicates the same information when bold is removed, prefer plain text and drop the bold. (Why: unnecessary bold increases noise without adding meaning.)
* You **MUST NOT** bold entire sentences, paragraphs, or whole list items. If a label is needed, use a heading or an appropriate callout instead. (Why: large bold blocks create visual noise and duplicate heading semantics.) \[HIGH]
* You **MUST NOT** use bold to style tokens, flags, filenames, or UI/log messages; use code font for tokens, quotation marks for log/error strings and UI text, and `` for UI/menu labels and key names. (Why: consistent, literal styling keeps examples copy-pasteable, searchable, and accessible.) \[HIGH]
* Within a paragraph, you **SHOULD NOT** use more than one short bold span (≤ 3 words). Reserve it for rare emphasis that clarifies meaning, not for decoration. (Why: limiting emphasis keeps true highlights noticeable.)
##### Italics [#italics]
* Italics **MAY** be used for first-mention term emphasis or titles of publications, books, papers, or standards. Avoid using italics for recurring emphasis in procedures. (Why: minimal, conventional italics aid comprehension.)
* When introducing an important concept on a concept or explanation page and a glossary link is not attached, you **MAY** italicize the first meaningful mention to signal definition, then stop italicizing later mentions. (Why: one highlighted introduction is enough to draw attention without cluttering the scan path.)
* Use italics for subtle emphasis that matters in sentence context but should not become a scan target. Use bold when the reader should find a word while scanning quickly. (Why: separating roles for bold and italics keeps both predictable.)
* Link text **MUST NOT** be styled with bold or italics. Do not wrap links in emphasis (for example, `**[Foo](https://docs.ton.org/llms/foo/content.md)**`, `_ [Foo](https://docs.ton.org/llms/foo/content.md)_`) and do not put bold or italic markup inside the link label. When the link label is a code identifier, use inline code as the label (for example, ``[`foo_bar`](https://docs.ton.org/llms/ref/foo_bar/content.md)``). (Why: links are already visually distinct; extra emphasis adds noise and makes scanning harder.) \[HIGH]
### 6.3 Code styling [#63-code-styling]
* Code, filenames, paths, API endpoints, flags, and literals **MUST** use code formatting (inline backticks or fenced blocks). **MUST NOT** add punctuation inside code that isn’t part of the code. (Why: visual separation prevents misreading and keeps examples copy-pasteable without edits.) \[HIGH]
### 6.4 Lists [#64-lists]
* Use numbered lists for procedures and bulleted lists for unordered sets. If list items are full sentences, **SHOULD** end with periods; otherwise, omit terminal punctuation consistently. (Why: matching list type to purpose improves comprehension; consistent punctuation keeps visual noise low.)
* Unordered list markers **MUST** be `-` (hyphen). **MUST NOT** use `*` or `+`. (Why: a single marker keeps diffs cleaner and avoids mixed styles.)
* Ordered lists **MUST** use `1.` for every item; let the MDX parser auto-number in the rendered output. (Why: auto-numbering prevents renumber churn when inserting/reordering steps.)
### 6.5 Thematic breaks [#65-thematic-breaks]
* Thematic breaks / horizontal rules (`---`, `***`, `___`, or HTML ``) **MUST NOT** be used. Use headings, whitespace, or an admonition to separate sections. (Why: horizontal rules fragment structure, reduce screen-reader/navigation cues, and add noise in raw Markdown.)
* You **MUST NOT** simulate separators with repeated characters or ASCII art (e.g., `=====`, `-----`). (Why: pseudo-rules create the same problems and look like code noise.)
* This rule does not apply to YAML frontmatter delimiters `---` at the top of a file. Frontmatter **MAY** use `---` as required by the site generator. (Why: frontmatter is metadata, not content.)
### 6.6 Blockquotes [#66-blockquotes]
* Blockquotes **MUST** be reserved for literal quotations from a source (another page in these docs or an external source). Include attribution inline or in the sentence introducing the quote; internal quotes **SHOULD** link to the exact anchor; external quotes **SHOULD** link to the canonical HTTPS source. (Why: clear attribution preserves trust and lets readers verify context.)
* Blockquotes **MUST NOT** be used for callouts/admonitions, warnings, tips, examples, emphasis, or general instructions. Use the `` component for callouts (see [§11.2](#11-2-how-to-write-the-callout), [Appendix A](#a-admonition-levels-and-usage)) and headings/lists for structure. (Why: misusing blockquotes harms structure, accessibility, and localization.)
* Visual callouts (Note/Tip/Caution/Warning) **MUST** use only the `` component. The only supported `type` values are `"note"`, `"tip"`, `"caution"`, and `"danger"`; do **NOT** use other components or type values. \[HIGH] (Why: a single component and fixed types keep rendering, accessibility, and localization consistent.)
* Short phrases or UI/log strings **SHOULD** use inline quotation marks instead of a blockquote. Tokens and identifiers **MUST** use code font, not blockquotes. (Why: inline quotes and code font are more precise and copy-friendly.)
* Keep quotations brief (prefer ≤ two sentences or one short paragraph). For longer material, summarize in your own words and link to the source. (Why: long quotes impede scanning and duplicate external content.)
* Nested blockquotes **MUST NOT** be used. Quoted code or output **SHOULD** appear in fenced code blocks with attribution above the block, not inside a blockquote. (Why: fenced blocks remain copy-pasteable and render consistently.)
## Headings and titles [#7-headings-and-titles]
Objective. Make navigation obvious and sections self-explanatory. (Why: clear, self-describing headings reduce misclicks, speed scanning, and make deep links understandable out of context.)
### 7.1 Case and form [#71-case-and-form]
* Site-managed H1. Pages **MUST NOT** include an in-body H1. The page title is provided by the site generator/frontmatter. The first visible heading in the page content **MUST** be an H2. (Why: the template renders the title; omitting an in-body H1 avoids duplicate titles and keeps a consistent heading hierarchy.)
* In MDX content, you **MUST NOT** write `# ` (H1), `
`, or use components that render an H1. Start headings at `##` (H2). (Why: syntax-level bans prevent accidental H1s in raw Markdown/MDX and keep navigation consistent.)
* Imported snippets/partials **MUST NOT** emit H1 headings; they **MUST** begin at H2 or lower within the host page’s hierarchy. (Why: embedded content inherits the page’s structure and must not reset the heading level.)
* All headings **MUST** use sentence case (capitalize only the first word and proper nouns). (Why: sentence case is easier to read, avoids random capitalization, and localizes more reliably.) \[HIGH]
* Task (procedure) headings **MUST** start with an imperative verb; concept headings **SHOULD** be noun phrases. (Why: imperatives signal actions the reader takes; noun phrases signal explanatory content, improving navigation and search relevance.)
* Task: “Deploy a validator.”
* Concept: “Validator architecture.”
* How-to titles. For the How-to doc type, the page title **MUST** follow “How to X”. Internal section headings (H2/H3) remain imperative. (Why: the pattern clarifies page type and improves discoverability without changing procedural heading style.)
### 7.2 Gerunds and labels [#72-gerunds-and-labels]
* For task/procedure headings (H2/H3), gerunds (e.g., “Creating…”, “Configuring…”) **SHOULD NOT** be used. Prefer imperative verbs. (Why: gerunds are vague about action vs. state; imperatives are clearer and translate better.)
* Concept headings **MAY** use concise noun phrases (e.g., “Naming”, “Spelling”, “Versioning”). (Why: short labels act as clear section tags and improve scan speed.)
* Fixed labels like Troubleshooting, Changelog, or FAQ are acceptable. Imperatives read cleaner and translate better in procedural sections. (Why: common labels match user expectations and TOC patterns; imperatives keep steps actionable.)
* House default: use “Troubleshoot” by default; “Troubleshooting” is acceptable when aligning with established ecosystem conventions. (Why: one default reduces variance; allowing the alternate keeps external consistency where needed.)
### 7.3 Uniqueness and linkability [#73-uniqueness-and-linkability]
* Headings **MUST** be unique at the same nesting level within a page and **MUST** make sense out of context (as TOC/sidebar links). Avoid repeated “Introduction” sections; prefer specific names. (Why: unique, descriptive headings prevent anchor collisions and make links meaningful in search and sharing.)
### 7.4 Formatting restrictions [#74-formatting-restrictions]
* Headings **MUST NOT** contain styling other than text: no bold, italics, `code`, quotes, or ALL CAPS (acronyms permitted). Keep headings clean; use formatting in body text only. (Why: extra styling harms scannability, clutters the TOC, and causes inconsistent rendering.)
* Exceptions:
* Reference pages only: Headings **MAY** include code font for identifiers (API names, flags, error codes), e.g., `tvm.runvm` — interface and exit codes. (Why: monospaced identifiers preserve exact casing and aid search/copy.)
* When the heading contains a literal UI/log/error message, quotation marks **MAY** be included (e.g., Fix “Account not found”). (Why: quoting exact strings shows what to grep or match without altering punctuation.)
### 7.5 Practical length norms [#75-practical-length-norms]
* Headings **SHOULD** be concise. As a norm, Page title (site/frontmatter) ≤ \~60 characters; H2/H3 ≤ \~70 characters. Exceed only for clarity. (Why: concise titles fit sidebars and search results without truncation; brevity improves scanning.)
Examples (good):
* “Run a validator on testnet” (H2, imperative)
* “Account model and messages in TON” (H2, concept)
Examples (bad):
* “Running and configuring the validator” (gerunds)
* “How the `validator` works” (code in heading)
## Readability and scannability [#8-readability-and-scannability]
Objective. Keep text fast to read and effortless to scan. (Why: quick comprehension reduces rereads and mistakes during implementation.)
### 8.1 Paragraphs and sentences [#81-paragraphs-and-sentences]
* One idea per paragraph. Paragraphs **SHOULD** be ≤ 5 sentences; single-sentence paragraphs are acceptable for emphasis. These are recommended norms, not hard caps—exceed only when clarity requires it. (Why: tight, focused paragraphs are easier to scan; short norms keep pages consistent without blocking necessary detail.)
* Each sentence **SHOULD** convey one main idea. If a sentence starts to describe two distinct actions or conditions, split it into two sentences or convert the extra actions into a list. (Why: one-idea sentences are easier to scan and translate; lists make multi-step actions obvious.)
* Sentences **SHOULD** average 15–20 words. Long, multi-clause sentences **SHOULD** be split. Front-load key points. (Why: mid-length sentences reduce cognitive load; splitting prevents misreads; leading with the main point speeds understanding.)
### 8.2 Structure for scanning [#82-structure-for-scanning]
* Use subheadings, lists, and tables to break up dense text. Provide breathing room around code, tables, and images (blank lines before/after blocks). (Why: chunking and whitespace make structure visible and stop content from blending together.)
* Highlight critical notes with admonitions (Note/Tip/Important/Caution/Warning) sparingly so they retain impact. (Why: overuse causes readers to ignore callouts; sparing use signals importance.)
* This guidance does not limit required safety callouts in [§11](#11-safety-critical-content-blockchain-specific); when in doubt, include the safety callout. (Why: preventing harm overrides brevity and visual economy.)
### 8.3 Micro-examples [#83-micro-examples]
Before (hard to scan):
“After deploying, if fees are misconfigured, the transaction might fail and the node logs a warning; you can retry after adjusting the config, but it’s better to verify the fee policy first because otherwise the wallet may reject the message.”
After (scannable):
* Verify fees before deploying.
* If the transaction fails with `FEE_TOO_LOW`:
1. Update the fee policy.
2. Retry the deployment.
* The node logs a warning on failure.
## Recommended page structures (by type) [#9-recommended-page-structures-by-type]
Objective. Make pages predictable without forbidding alternatives. (Why: predictable shapes reduce scanning time and help readers know what to expect.)
Rule. The patterns below are **RECOMMENDED**. You **MAY** deviate when another structure improves clarity, but pages in the same section **SHOULD** be consistent. (Why: consistency within a section helps navigation and comparison; flexibility allows better fit for edge cases.)
### 9.1 Step by step (first success) [#91-step-by-step-first-success]
Recommended sections:
Objective → Prerequisites → Steps (3–7) → Verify (expected output or result) → Troubleshoot (common errors) → Next steps. Keep Next steps minimal (1–3 essential links) or omit when the path is linear. (Why: this flow gets newcomers to a working result, confirms success, handles common failures, and points to what to do next.)
Notes: Keep a single happy path; theory **SHOULD** be limited to ≤ two bullets and linked to an Explanation page. (Why: branching and long theory cause drop-offs; brief links keep momentum while offering depth when needed.)
Example outline (good):
* Objective: “Deploy a counter contract on testnet.”
* Prerequisites: Node.js 20+, TON SDK JS, funded testnet wallet, ``.
* Steps: 1) Initialize project … 2) Compile … 3) Deploy …
* Verify: “Expected output” block showing successful deployment.
* Troubleshoot: `INSUFFICIENT_FUNDS`, `INVALID_WORKCHAIN` fixes.
* Next steps: Link to contract upgrades guide.
### 9.2 How-to guides (goal-oriented procedures) [#92-how-to-guides-goal-oriented-procedures]
Recommended sections:
Goal → Prerequisites → Steps → Result → Links to Reference (anchor each flag/param). (Why: the reader sees what they’re trying to achieve, what they need, how to do it, what outcome to expect, and where to look up details.)
Notes: Do not embed long background; link to concepts instead. Keep each step a single action with sub-bullets for options. (Why: separating theory prevents duplication and keeps the guide tight; one action per step reduces ambiguity and errors.)
### 9.3 Explanations (concepts/why) [#93-explanations-conceptswhy]
Recommended sections:
What/Why → Core concepts → Trade-offs → Related topics. (Why: this order frames purpose first, then explains mechanics, then consequences, and finally directs to adjacent ideas.)
Notes: Avoid command sequences. Use diagrams and short examples to illustrate concepts. (Why: commands distract from understanding; visuals and minimal examples clarify ideas without turning the page into a procedure.)
### 9.4 Reference (complete, factual) [#94-reference-complete-factual]
Recommended sections:
Summary → Parameters/Fields (tables) → Returns/Responses → Errors (codes, meanings) → Examples (minimal usage) → Optional See also (1–3 essential anchors). (Why: a uniform, tabular layout makes lookups fast and supports deep linking and automation.)
Notes: Be exhaustive and anchor-linkable; minimize narrative. Keep formats consistent across entries. (Why: completeness and anchors enable precise links from guides; minimal prose speeds lookup; consistency lets readers scan different entries the same way.)
## Code and command examples [#10-code-and-command-examples]
Objective. Ensure examples are precise, copy-pasteable, and unambiguous. (Why: readers should be able to run examples without editing or guessing.)
### 10.1 General rules [#101-general-rules]
* Examples **MUST** be copy-pasteable. **MUST NOT** include shell prompts (`$`, `>`) in command blocks. (Why: prompts get copied accidentally and break commands.) \[HIGH]
* Command and expected output **MUST** be presented as separate fenced blocks. (Why: mixing them causes copy errors and makes results hard to recognize.) \[HIGH]
* Placeholders **MUST** use `` (e.g., ``, ``), and each placeholder **MUST** be defined on first use. (Why: a consistent, visible pattern prevents pasting unsafe hard-coded values.) \[HIGH]
* Fenced code blocks **MUST** specify a language (` ```bash `, ` ```rust `, ` ```json `, …). (Why: language tags enable correct highlighting and tooling.)
* Filenames shown in examples **MUST** be realistic and kebab-case (e.g., `wallet-config.json`, not `MyConfig.json`). (Why: examples should model the conventions we require elsewhere.)
* Long commands **MUST NOT** be hard-wrapped. Prefer UI soft wrap. If a tool supports safe line continuation (e.g., `\` in POSIX shells), continuation **MAY** be used and must be copy-pasteable as shown. (Why: hard wraps break execution; soft wrap or continuations keep commands runnable.)
* You **SHOULD** favor examples that run end-to-end on testnet by default. (Why: safer defaults reduce risk and support quick validation.)
* Inside language code, placeholders **SHOULD** be neutral (e.g., `UPPER_SNAKE` inside strings or comments) when angle brackets would clash with language syntax; in commands and prose, placeholders **MUST** use ``. (Why: avoids syntax errors in code while keeping a single placeholder style in prose/CLI.)
* In runnable examples, configuration values and other parameters that the reader is expected to change **MUST** be collected in one clearly visible block near the top of the snippet. When the language allows top-level declarations, this block **MUST** use top-level constants instead of redefining values inside the entry function or helpers; when the language forbids top-level declarations, group these parameters at the start of the entry function. (Why: collecting adjustable values in one visible place makes examples easier to understand and update.) \[HIGH]
### Error and log style [#error-and-log-style]
* Quoted UI/log messages **MUST** appear verbatim in quotation marks. (Why: exact strings are searchable and prevent confusion.)
* Error codes and identifiers **MUST** be rendered in code font (e.g., `ERR_FEE_TOO_LOW`). (Why: monospace distinguishes tokens and aids copy/paste.)
* When summarizing behavior instead of quoting, **MUST NOT** change semantics and avoid using quotes; indicate that it is a summary. (Why: paraphrases should not be mistaken for literal messages and must stay accurate.)
Good:
````text
```bash
ton-node start --ledger --network testnet
```
There,
`` — path to the local ledger directory.
`` — HTTPS endpoint of the TON RPC provider.
Expected output:
```text
Node started. Workchain: 0 Shard: -1 Status: running
```
````
Bad:
````text
```bash
$ ton-node start --ledger /home/bob/ledger --network mainnet # includes prompt, hard-coded values
```
````
### 10.2 Partial snippets [#102-partial-snippets]
* Partial snippets (focused excerpts) **MAY** be used when teaching a narrow concept, even if not runnable alone. (Why: small, targeted examples clarify one idea without setup noise.)
* Partial snippets **MUST** be labeled clearly in the comment on the first line of the block: “// Not runnable: brief how to make it runnable”. (Why: prevents readers from attempting to execute incomplete code. In the explanation, be concise and try to keep it below 100 characters)
* Partial snippets **SHOULD** link to a full runnable example or reference entry showing complete context. (Why: gives readers a path to working code.)
```rust
// Not runnable: replace EQC_REPLACE_WITH_ADDRESS with a real address.
let to = Address::from_str("EQC_REPLACE_WITH_ADDRESS").unwrap();
let amount = Coins::from_nano(1_000_000_000);
let body = build_transfer_body(to, amount);
```
### 10.3 Safety and secrets in code [#103-safety-and-secrets-in-code]
* Secrets (keys, mnemonics, API tokens) **MUST NOT** appear in examples. Use placeholders or test keys that are clearly invalid. (Why: prevents accidental leaks and unsafe copying.) \[HIGH]
* Commands that could cause loss of funds or data **MUST** be guarded by a Warning/Caution per [§11](#11-safety-critical-content-blockchain-specific) and **SHOULD** default to testnet. (Why: explicit risk labeling and safe defaults protect readers.) \[HIGH]
### 10.4 OS and language variants [#104-os-and-language-variants]
* When steps differ by OS or language, you **SHOULD** provide tabs or distinct subsections (e.g., Linux / macOS / Windows; JS / Python / Rust). (Why: separates platform differences so readers don’t mix instructions.)
* If only one variant is provided, the page **MUST** state that limitation. (Why: sets expectations and avoids readers searching for missing variants.)
### 10.5 Comments and omissions [#105-comments-and-omissions]
* Use language-appropriate comments to mark omissions (`// …`); **MUST NOT** use literal ellipses that change syntax. (Why: literal ellipses can create invalid code.) \[HIGH]
* Explanatory comments in examples **MUST** appear on their own line immediately above the code they describe; **MUST NOT** use trailing end-of-line comments such as `foo(42); // sends a test message` in documentation snippets. (Why: stacked comment-then-code is easier to scan and keeps copy-pasted lines clean.) \[HIGH]
* Exception: Fift and TVM assembly stack comments **MAY** appear as trailing end-of-line comments to show the stack state at that point (e.g., `1 2 + // 3`). This is idiomatic in stack-based languages and aids comprehension. (Why: stack comments are a well-established convention in Fift and TVM assembly; forcing them to a separate line would harm readability.)
* Keep comments minimal and instructional; avoid commentary or humor. (Why: extraneous remarks distract from the task and age poorly.)
## Safety-critical content (blockchain-specific) [#11-safety-critical-content-blockchain-specific]
Objective. Prevent reader harm when funds, keys, or validator/network state are involved. (Why: mistakes here can cause irreversible loss or outages.)
### 11.1 When a safety callout is required [#111-when-a-safety-callout-is-required]
A Caution or Warning **MUST** appear when a page or step: (Why: visible callouts make risk obvious before a reader runs a command.) \[HIGH]
* moves funds or changes fee/withdrawal behavior; (Why: users can lose money or block withdrawals.) \[HIGH]
* exposes, stores, or transmits private keys/mnemonics; (Why: leaked secrets allow account takeover and theft.) \[HIGH]
* modifies validator configuration, networking, or consensus-affecting parameters; (Why: misconfiguration can halt or fork nodes and degrade the network.) \[HIGH]
* performs chain-affecting operations (e.g., resharding, pruning, halting, replay). (Why: these actions can corrupt the state, reduce availability, or cause data loss.) \[HIGH]
If page has many actions potentially requiring a safety callout, you **MAY** combine these into a page-level safety summary plus short local callouts instead of repeating full details every time. (Why: a shared summary avoids repetition while still making risks visible.)
### 11.2 How to write the callout [#112-how-to-write-the-callout]
A page that contains safety-critical actions **MUST** clearly communicate all of the following, either in a page-level safety summary, in local callouts near each step, or in combination: (Why: readers need to know the risk, scope, recovery, and safe environment before proceeding.) \[HIGH]
1. Risk (what can go wrong), (Why: sets severity and helps decide whether to proceed.)
2. Scope (what the command affects), (Why: clarifies blast radius—single node, wallet, or network.)
3. Rollback/mitigation steps where feasible, and (Why: gives a path to recovery or damage control.)
4. Environment label (testnet vs mainnet) with safer default instructions first. (Why: testnet reduces harm; explicit labels prevent accidental mainnet use.)
* These elements describe the information the reader needs; they are **NOT** required as literal labels such as “Risk:” or “Scope:”. Safety callouts **SHOULD** read as concise, natural prose rather than templated checklists. (Why: natural language is easier to read and avoids robotic, placeholder-style warnings.)
Common patterns:
* Page-level safety summary. Place a single `` near the top of the guide that describes overall risk, scope, rollback/mitigation strategy, and testnet/mainnet expectations for the full set of commands. (Why: one visible summary prevents readers from missing critical context.)
* Local step-level warnings. Add short `` elements next to each hazardous step that call out the specific risk or environment for that step and, when needed, refer back to the page-level summary instead of repeating full details (for example, “See the safety note at the top of this page before running this on mainnet.”). (Why: local notes tie the warning to the exact action without duplicating the whole summary.)
Rendering (component) \[HIGH]
* Safety callouts **MUST** use the `` component; **MUST NOT** use Markdown blockquotes (`>`) or headings to simulate warnings. (Why: a single component keeps appearance, accessibility, and behavior consistent.)
* Mapping: use `type="caution"` for Caution; use `type="danger"` for Warning. Set an explicit `title` when needed (e.g., `title="Funds at risk"`). (Why: consistent severity mapping aligns wording with visual severity.)
* Allowed types: The only supported `` `type` values are `"note"`, `"tip"`, `"caution"`, and `"danger"`. Do not use other values (e.g., `"important"`, `"warning"`). To display those labels, set `title` (e.g., `title="Important"`) while keeping a supported `type`. (Why: keeping to the supported set ensures consistent rendering and avoids runtime fallbacks.)
Example (MDX)
````mdx
Sending TON on mainnet is irreversible. Start with a small transfer on TON Testnet, then repeat on TON Mainnet only after checking the address and network carefully; there is no rollback on mainnet.
```bash
jetton transfer --to --amount --network testnet
```
````
### 11.3 Safer defaults [#113-safer-defaults]
* Task pages **SHOULD** use testnet endpoints by default and mention the switch to mainnet explicitly. (Why: safe defaults prevent costly mistakes.)
* Destructive flags (e.g., `--purge`, `--force`) **MUST** be opt-in and accompanied by a callout. (Why: explicit opt-in and warnings reduce accidental data loss.) \[HIGH]
### 11.4 Key handling and storage [#114-key-handling-and-storage]
* Keys **MUST** be represented as placeholders or generated ephemeral testing artifacts. (Why: prevents real secrets from being copied into scripts or screenshots.) \[HIGH]
* In guides, prefer environment variables or keystores; never inline secrets. (Why: avoids persisting secrets in history, logs, or source control.) \[HIGH]
* Reference pages **MAY** document secure storage options but **MUST NOT** encourage unsafe patterns. (Why: guidance is helpful, but normalizing bad practices leads to leaks.) \[HIGH]
## Links and cross-references [#12-links-and-cross-references]
Objective. Reduce duplication and let readers jump straight to detail. (Why: direct links cut search time and prevent restating facts in multiple places.)
### 12.1 Link text [#121-link-text]
* Link text **MUST** be descriptive and indicate the destination. You **MUST NOT** use generic labels like "click here", "here", "this", "this link", "this page", or bare URLs as link text. \[HIGH] (Why: meaningful text lets readers scan quickly to determine where a link leads; generic labels force readers to examine surrounding context.)
* You **MUST NOT** use mechanics-focused verbs like "click", "tap", "follow", or "go to" as part of link text. Focus on content, not interaction mechanics. \[HIGH] (Why: drawing attention to the clicking action distracts from the content; not all users click — some tap, use keyboards, or use assistive technology.)
* Link text **SHOULD** describe the destination, not the action of navigating. One effective technique: use the title or topic of the target page as the link text and integrate it into the sentence.
* Bad: `"To learn about fees, click [here](https://docs.ton.org/llms/fees/content.md)."`
* Bad: `"Click [here](https://docs.ton.org/llms/fees/content.md) for fee information."`
* Bad: `"[This page](https://docs.ton.org/llms/fees/content.md) explains fees."`
* Good: `"The [fee structure](https://docs.ton.org/llms/fees/content.md) determines transaction costs."`
* Good: `"Transaction costs depend on the [fee structure](https://docs.ton.org/llms/fees/content.md)."`
* When a link must stand alone (e.g., at the end of a sentence or after a colon), make the link text self-explanatory:
* Bad: `"For more details, see [here](https://docs.ton.org/llms/validator-setup/content.md)."`
* Good: `"For more details, see [Validator setup](https://docs.ton.org/llms/validator-setup/content.md)."`
* Good: `"Related guide: [Set up a validator](https://docs.ton.org/llms/validator-setup/content.md)."`
* Link labels **SHOULD** be plain text or inline code for identifiers (see [§6.2](#6-2-quotation-marks-and-emphasis) for emphasis restrictions on link text). (Why: unstyled labels keep links readable and avoid redundant visual emphasis.)
* Standalone "stub" sentences whose only job is to say "See …" or "Read here …" followed by a link (for example, `[Read here](https://docs.ton.org/llms/contracts/standard/wallets/mnemonics/content.md) to learn more.` or `See [mnemonics](https://docs.ton.org/llms/contracts/standard/wallets/mnemonics/content.md) for more details.`) **MUST NOT** appear in running prose. Instead, attach the link to the relevant term or phrase in a normal sentence (for example, `The [mnemonics guide](https://docs.ton.org/llms/contracts/standard/wallets/mnemonics/content.md) explains why.`). (Why: inline links keep the text flowing and avoid postponing useful links to trailing meta-sentences.) \[HIGH]
* Accessibility and SEO note: Screen readers often present links out of context (e.g., a list of all links on a page). Generic link text like "here" or "click here" becomes meaningless when read in isolation. Search engines also use link text to understand page relationships. Descriptive link text improves both accessibility and discoverability. (Why: links must make sense without surrounding prose.)
### 12.2 What to link (and what not) [#122-what-to-link-and-what-not]
* In a guide, the first useful mention of a flag, parameter, error code, or data type on the page **MUST** link to the canonical reference anchor. You **MAY** also link its first mention in other H2/H3 sections on long pages that are frequently deep-linked or read out of order. (Why: readers see the spec at the moment they need it, even when entering mid-page.) \[HIGH]
* This rule explicitly includes TVM exit codes (e.g., `-13`, `37`), send modes (e.g., `mode 64`, `mode 128`), reserve modes, and similar numeric constants that have documented meanings. These **MUST** be linked to their corresponding reference anchors on first mention, not left as bare code spans. (Why: numeric constants are opaque without context; links let readers understand them instantly.) \[HIGH]
* Within a single H2/H3 section, link only the first meaningful mention of an important term or reference target. When the same term appears in a different H2/H3 section, you **MAY** link its first mention again there. Avoid linking every occurrence inside one section; add a repeated link only when separated by many screens and it clearly helps the reader. (Why: per-section first links help when deep-linking to a subsection without turning the page into a link farm.)
* Link concepts judiciously: if the reader is likely to wonder “what does that mean?”, link the term on its first useful mention in that H2/H3 section. Subsequent mentions in the same section **SHOULD** be plain text unless the gap is large and a repeated link clearly helps. (Why: section-local first links help readers who land on a deep link without over-linking common words.)
* On the first useful mention of a core TON term on a page, you **SHOULD** link to the Glossary (Foundations → Glossary), unless the page itself defines it. On long pages, you **MAY** also link the first mention of that term in other H2/H3 sections, following the per-section rules above. (Why: keeps definitions consistent and easy to find while still helping readers who enter mid-page.)
* Over-linking common words is discouraged; link what is plausibly useful. (Why: excessive links slow reading and distract from the task.)
* Guides **MUST NOT** duplicate reference tables; summarize and link instead. (Why: duplication drifts and creates conflicting sources of truth.)
* Internal first. When both an internal TON Docs page and an external source exist, you **MUST** link the internal page by default (including instead of the TEPs repository). Exception: pages whose purpose is to document a standard contract/TEP **MAY** also link the corresponding TEP as the canonical spec. If no relevant internal page exists, linking to the external source is acceptable. (Why: internal pages are newcomer-friendly; TEPs are normative but hard to parse for new readers.)
Example (good)
Start the node with `--threads` (see [validator flags → `--threads`](https://docs.ton.org/llms/nodes/overview/content.md)) to increase parallelism.
### 12.3 Link targets and format [#123-link-targets-and-format]
* Internal links **MUST** be root-absolute and stable (start with `/`), yet relative to the `content/` directory; anchors **MUST** resolve correctly. **MUST NOT** use relative segments like `./` or `../` in Markdown/MDX link URLs or HTML/JSX. (Why: files and folders move frequently; root-absolute links remain correct across moves; relative segments are brittle and costly to maintain.) \[HIGH]
* Cross-section links **SHOULD** deep-link to the exact section or anchor instead of the page top. (Why: deep links land readers on the exact answer.)
* A See also section **MAY** close a page with 1–3 essential links; prefer a linear path that needs none. (Why: minimal exits keep readers on task while still offering critical follow-ups.)
* When linking to the same internal target multiple times on a page, you **SHOULD** prefer reference-style Markdown links so the URL appears once in a shared definition block. For example:
```md
Use the [jetton wallet][jetton-wallet] contract where applicable; the [jetton wallet reference][jetton-wallet] describes all fields.
[jetton-wallet]: https://docs.ton.org/llms/content/standard/jettons/wallet/content.md
```
This keeps body text readable and makes URL updates cheaper, while still requiring root-absolute URLs in the reference definition. (Why: shared link definitions reduce visual noise and simplify maintenance.)
### 12.4 Avoid circularity and drift [#124-avoid-circularity-and-drift]
* Each fact **MUST** have a single canonical home. If you need the same fact elsewhere, link to it. (Why: one source avoids conflicting copies and simplifies updates.)
* **MUST NOT** link to outdated or superseded pages except when documenting historical behavior. (Why: stale links propagate errors and erode trust.) \[HIGH]
### 12.5 Images and media [#125-images-and-media]
* Images **MUST** be embedded using the `` MDX component. Markdown image syntax `` and raw `` are **PROHIBITED**. (Why: the component provides dark-theme control, consistent sizing/zoom, and stable rendering.) \[HIGH]
* Image sources **MUST** be root-absolute and live under `/public/images/`, yet be given without `/public` in the URL (for example, ``, where `` is the logical image category and `` is the filename). **MUST NOT** use relative `src` such as `./` or `../`. (Why: content moves often; root-absolute paths remain valid.) \[HIGH]
* Provide a `darkSrc` when contrast or readability differs in dark mode. Keep aspect ratios consistent across a page to avoid layout shift. (Why: visual stability improves reading flow.)
* SVG note: if `src` points to an SVG and `darkSrc` is omitted, the dark-theme image is auto-inverted. Supply an explicit `darkSrc` when inversion is not desired. (Why: ensures accurate colors and legibility.)
* Provide meaningful, non-empty `alt` text for every image; `alt` **MUST NOT** be empty. (Why: screen readers rely on `alt` to convey image meaning; empty `alt` hides content from assistive tech.) \[HIGH]
* When using ``, prefer the `width`/`height` props for predictable layout; avoid arbitrary inline styling. (Why: predictable dimensions prevent layout shift and maintain consistency.)
### 12.6 External references [#126-external-references]
Objective. Use authoritative, stable sources and deep links; avoid volatile or non-authoritative pages. (Why: reliable links reduce drift, link rot, and conflicting guidance.)
* Authority order. You **MUST** prefer: (1) official project documentation/specs/standards (link internal TON Docs when available before external repos); (2) vendor documentation for tools used; (3) primary sources (RFCs, papers). Community wikis/blogs **MAY** be linked only when no official source exists and **MUST** be labeled as background. (Why: authoritative sources change less and carry clearer guarantees; internal docs are optimized for comprehension.)
* Wikipedia and crowd-edited sources. Wikipedia **MAY** be linked for general, well-known non-TON concepts when the link is informational and not supporting a requirement or API/behavior semantics. For normative claims or when precision matters, **MUST** link a spec or official docs (e.g., RFC 8032 for Ed25519). (Why: Wikipedia is useful for broad context; specs are stable for requirements.)
* Q/A forums and social posts. Stack Overflow, Reddit, and personal blogs **MUST NOT** be used as normative references. They **MAY** appear as background in the Explanation pages when no official source exists. (Why: anecdotal content is volatile and easily outdated.)
* TEPs specifics. Prefer the internal TON Docs page that explains a standard over linking directly to the TEPs repository. On pages that are themselves standards or reference docs (e.g., standard contracts), you **MAY** include a precise deep link to the corresponding TEP as the canonical spec. Avoid linking the repository root; link the exact TEP and section. (Why: TEPs are normative but difficult for newcomers; internal docs provide context while still letting experts reach the spec.)
* Stable permalinks (situation-aware). When linking to specific code/files/lines or exact doc sections where content must remain reproducible, you **SHOULD** use a versioned or permanent URL (e.g., GitHub tag/commit permalink; versioned docs; DOI). If a versioned URL exists and the reference is normative or precision-critical, you **MUST NOT** link to moving targets like “main”, “HEAD”, or “latest”. For general project references (homepage or repo root), you **MAY** use the canonical current URL. (Why: permalinks keep exact references stable; simple links are fine when versioning adds no value.) \[HIGH]
* Deep links. You **SHOULD** link to the exact section/anchor that holds the needed fact, not the page top. (Why: deep links land readers on the answer and reduce scanning.)
* Clean URLs. Links **MUST** use HTTPS, **MUST NOT** include shorteners or tracking parameters (e.g., `utm_*`), and **MUST NOT** point to unofficial mirrors/gists when an official location exists. (Why: clean, canonical URLs are trustworthy and durable.) \[HIGH]
* Language and availability. Link to the English source by default. If the authoritative page is non-English, **MUST** label the link with the language (e.g., “(in Russian)”). Avoid paywalled sources as primary; if unavoidable, **SHOULD** provide an open alternative or summarize key facts locally. (Why: sets expectations and preserves access.)
## Terminology and naming [#13-terminology-and-naming]
Objective. Enforce a single source of truth for terms and casing. (Why: one authoritative lexicon prevents confusion, reduces review churn, and keeps search/indexing consistent.)
### 13.1 Term bank (canonical source) [#131-term-bank-canonical-source]
* A project term bank **MUST** define canonical terms, spellings, hyphenation, casing, and banned variants with replacements (e.g., allowlist/denylist for whitelist/blacklist). (Why: clear entries stop ad-hoc wording and mixed casing from spreading.)
* You **MUST** consult the term bank before introducing new names; additions **SHOULD** be reviewed by editors. (Why: gatekeeping new terms prevents drift and conflicting synonyms.)
* The term bank **SHOULD** mark which terms are link-worthy for first-use cross-links and record their canonical doc URLs. First-use linking rules in [§12.2](#12-2-what-to-link-and-what-not) **SHOULD** apply only to terms above this importance threshold to avoid over-linking minor notions. (Why: a curated set of link-worthy terms keeps pages readable while still making key concepts discoverable.)
* Flags, parameters, error codes, and data types documented in guides **MUST** be included in this link-worthy set so first-use links in [§12.2](#12-2-what-to-link-and-what-not) always have a canonical target. This includes TVM exit codes, send modes, reserve modes, and other numeric constants with documented semantics. (Why: treating these technical items as link-worthy ensures readers can jump straight to their reference definitions.) \[HIGH]
### 13.2 General casing rules [#132-general-casing-rules]
* Generic concepts **MUST NOT** be capitalized mid-sentence (use "smart contract," not "Smart Contract"). (Why: random caps imply proper nouns and slow reading.) \[HIGH]
* Proper nouns and official product/feature names **MUST** follow the term bank (e.g., TON, TON Connect). (Why: consistent branding and accurate references.)
* Code identifiers (types, fields, flags) **MUST** appear in code font with exact case. (Why: preserves copy/paste fidelity and distinguishes code from prose.) \[HIGH]
### 13.3 Hyphenation and abbreviations [#133-hyphenation-and-abbreviations]
* Multi-word mechanism names are common nouns and **SHOULD** be hyphenated: proof-of-stake, zero-knowledge. (Why: hyphenation clarifies compounds and matches industry norms.)
* Abbreviated forms **MUST** follow the project style: ZK-proof, ZK-rollup (uppercase ZK, hyphenated compound). (Why: consistent abbreviation improves recognition and search.)
* Use mainnet as a common noun; use TON Mainnet (or just "mainnet") when referring to the proper name of the network. (Declare this explicitly in the term bank.) (Why: distinguishes generic network type from the named network.)
* Use testnet as a common noun; use TON Testnet (or just "testnet") when referring to the proper name of the network. (Why: same distinction as mainnet; avoids mixed casing.)
### 13.4 TON-specific examples [#134-ton-specific-examples]
Non-exhaustive; finalize in the term bank. (Why: examples guide writers now, while the term bank remains the single source of truth.)
* TON, TON Blockchain, TON Ecosystem (proper nouns).
* The native TON currency is called `Gram` (**NOT** `Toncoin`), and its ticker is `GRAM` (**NOT** `TON`).
* Do **NOT** use "TON" when meaning the currency, not the blockchain. Instead, use "Gram" as the currency and "GRAM" as the token ticker.
* Do **NOT** use "GRAM" when meaning the blockchain, not the currency ticker.
* smart contract, wallet, account, message, jetton, nominator, validator, collator, node, liteserver (common nouns, lowercase mid-sentence).
* accountchain, shardchain, workchain, masterchain, basechain — common nouns; use lowercase mid-sentence. **MUST NOT** use CamelCase forms (`ShardChain`, `WorkChain`, `MasterChain`, `BaseChain`, `AccountChain`) or spaced variants (e.g., “Shard Chain”).
* BoC (abbrev.) / bag of cells (common noun). Abbreviation **MUST** be “BoC” (not “BOC”).
Note: Do **NOT** introduce “master/slave” metaphors in new text; use primary/replica or similar. (Why: maintains inclusive language.)
### 13.5 Placeholder names [#135-placeholder-names]
* In commands and prose, placeholders **MUST** be `` with descriptive names: ``, ``, ``. (Why: a single, visible pattern reduces copy/paste mistakes.)
* In programming-language code, placeholders **MAY** use `UPPER_SNAKE` without angle brackets when `< >` would clash with syntax (see [§10.1](#10-1-general-rules)). (Why: avoids syntax errors while keeping placeholders obvious.)
* **MUST NOT** use `{curly}` or `[square]` placeholder syntax in copy-pasteable commands, as they are easy to misread as literal characters. (Why: braces/brackets are often treated as literals by shells and new users.) \[HIGH]
### 13.6 Banned and preferred terms [#136-banned-and-preferred-terms]
* Banned (inclusive/biased): whitelist/blacklist; master/slave; sanity check. \[HIGH]
* Banned (filler/tone): simply, just, obviously, clearly, please note.
* Banned (outdated): Toncoin (use Gram instead).
* Preferred: (omit filler); allowlist/denylist; primary/replica; smoke check or basic check.
Rationale: clarity, inclusivity, and reduced ambiguity.
## Numbers, units, date, and time [#14-numbers-units-date-and-time]
Objective. Present quantitative information unambiguously for a global developer audience. (Why: consistent formats prevent locale-based misreads and implementation errors.)
### 14.1 Numerals and separators [#141-numerals-and-separators]
* You **MUST** use numerals for all technical quantities (latency, memory, fees, block heights, versions, ports), regardless of size. (Why: digits are faster to scan and less ambiguous than words in technical contexts.)
* Good: “Set the fee to 0.2 GRAM.”
* For general prose without units, you **MAY** spell out zero–nine and use numerals for 10+, but prefer numerals whenever a value matters to a task. (Why: numbers highlight actionable values and make comparisons obvious.)
* You **SHOULD** use thousands separators for numbers ≥ 10,000: 10,000, 1,234,567. (Why: separators improve readability and reduce digit-counting mistakes.)
* **MUST NOT** add separators to codes/IDs (e.g., block hashes, transaction IDs, addresses), even if they contain digits; keep copyable values intact. (Why: added punctuation breaks copy/paste and changes identifiers.) \[HIGH]
* Decimal separator **MUST** be a dot: 3.1415. (Why: a single convention avoids comma/dot confusion across locales and matches most APIs.)
### 14.2 Units and conventions [#142-units-and-conventions]
* Use binary units (KiB, MiB, GiB) for memory/storage sizes and SI units (kB, MB, Gbps, ms) for network throughput, latency, and timing. Be consistent within each category. (Why: binary vs SI units have different meanings; consistency prevents 2× errors.)
* Currency amounts **MUST** specify the unit (e.g., GRAM, USDT). When precision matters, show decimals explicitly (e.g., 0.000001 GRAM). (Why: omitting units or precision leads to costly misinterpretation.) \[HIGH]
* Address/hash values **MUST NOT** be silently truncated. If truncation aids readability, use a consistent truncation pattern (e.g., first 4 / last 4 with an ellipsis: `EQC…9gA`) and state clearly that the value is truncated. (Why: silent truncation causes copy/paste failures and verification mistakes.) \[HIGH]
### 14.3 Dates and times [#143-dates-and-times]
* Dates **MUST** use ISO-8601 format YYYY-MM-DD (e.g., 2025-02-11). (Why: ISO is unambiguous and sorts correctly.)
* Times **SHOULD** be 24-hour and, where relevant, UTC (e.g., 14:30 UTC). (Why: avoids AM/PM ambiguity and timezone drift.)
* Use UTC for timestamps that might be compared across regions (e.g., transactions, block times, cron examples). (Why: a single timezone ensures consistent ordering and comparison.)
* Ranges **MUST** be explicit: 2025-02-11 14:30–15:00 UTC. (Why: clear start/end with timezone prevents misaligned windows.)
* **MUST NOT** use ambiguous forms like `11/2/2025`. (Why: day/month order varies by locale and leads to errors.)
* Changelogs **SHOULD** include a date stamp in ISO format. (Why: stable, sortable dates aid release tracking.)
### 14.4 Magnitudes and math [#144-magnitudes-and-math]
* Prefer engineering prefixes for readability: 1.2 GiB, 250 ms, 500 kB/s. (Why: normalized units make scale comparisons quick and reduce cognitive load.)
* Inline math **SHOULD** use KaTeX/LaTeX components when formulas help clarity. (Why: consistent rendering and accessibility across themes and locales.)
Rationale: Consistent numeric style reduces misreads and eases localization.
## Accessibility and internationalization [#15-accessibility-and-internationalization]
Objective. Ensure content is usable by all readers and easy to localize. (Why: accessible, localization-ready text works for non-native readers, assistive technologies, and translations without rewrites.)
### 15.1 Language and reading [#151-language-and-reading]
* Content **MUST** use plain, international English; avoid idioms, slang, and culture-specific metaphors. (Why: idioms and slang do not translate well and confuse global readers.)
* Link text and headings **MUST** be descriptive (screen-reader friendly). Avoid “click here” (see [§12](#12-links-and-cross-references)). (Why: descriptive text improves scanning and is meaningful when read aloud by assistive tech.)
* Avoid gendered or ableist terms; use inclusive alternatives (see [Appendix B](#b-banned-and-preferred-terms)). (Why: inclusive language prevents exclusion and avoids unnecessary friction.)
### 15.2 Structure and tables [#152-structure-and-tables]
* Tables **SHOULD** include header rows; keep cell content short and scannable. (Why: headers provide context for readers and screen readers; brief cells are easier to parse.)
* Units **MUST** be shown in headers or cells (e.g., “Latency (ms)”, “Size — MiB”). (Why: explicit units prevent misinterpretation of values.)
* Columns whose cells are primarily numeric values (for example, counts, sizes, fees, percentages, timings) **MUST** be right-aligned so digits line up vertically. (Why: aligned digits make numeric comparisons easier and reduce misreads.) \[HIGH]
* Columns whose cells contain identifiers such as addresses, hashes, transaction IDs, or error codes are not numeric columns and **MAY** remain left-aligned. (Why: identifier strings are scanned, copied, and compared differently than numeric quantities.)
* Cells **SHOULD NOT** contain multi-paragraph text; move extended explanations below the table. (Why: long prose in tables is hard to read and harms accessibility/layout.)
* Long lists inside cells **SHOULD** be converted to bullet lists placed below the table. (Why: lists outside tables are easier to scan and navigate.)
* Provide text alternatives for complex figures when feasible. (Why: alt or adjacent text lets screen-reader users and translators access the content.)
* Keyboard-only navigation **SHOULD** be considered when adding interactive elements. (Why: some users cannot use a mouse; keyboard support is a basic accessibility need.)
* Emojis **MAY** appear in compact tables as secondary indicators only when they follow a widely understood convention (e.g., `✅ Supported`, `❌ Not supported`) and are paired with clear text in the same cell. **MUST NOT** rely on emojis alone to encode meaning or status, and **MUST NOT** use decorative pictograms or one-off icons that do not have a clear, conventional meaning. (Why: paired, conventional indicators remain accessible and understandable when emojis do not render or in translation.)
### 15.3 Localization readiness [#153-localization-readiness]
* Prefer stable terminology from the term bank ([Appendix B](#b-banned-and-preferred-terms) references) to minimize translation drift. (Why: consistent terms reduce rework and inconsistent translations.)
* Dates/times already follow ISO conventions (see [§14.3](#14-3-dates-and-times)), which **SHOULD** simplify localization. (Why: ISO formats are unambiguous across locales and require minimal adaptation.)
Rationale: Clear, inclusive writing and accessible assets improve comprehension for global audiences and translation tools.
## File, navigation, and frontmatter conventions [#16-file-navigation-and-frontmatter-conventions]
Content of this section mostly describes contents of `.mdx` files and `[...](...)` markdown links in `.mdx` files.
### 16.1 Sidebar groups and ordering [#161-sidebar-groups-and-ordering]
Objective. Keep navigation predictable and reduce decision points. (Why: consistent ordering helps readers find the right kind of page without scanning the whole section.)
Rules (binding).
* The onboarding path **SHOULD** be a dedicated “Step by step” group near the top of the sidebar. Keep it linear and link out for depth. (Why: newcomers progress faster with one clear path.)
* Within every topical group (e.g., Ecosystem, Language reference, Standard contracts, TVM, Foundations, Smart-contract patterns, Contribute; Integrate when present), pages **MUST** be ordered: Explanation → How-to → Reference. (Why: readers scan “why” first, then “how”, then exact details.)
* The Explanation page **SHOULD** be the group’s overview (often `overview.mdx`). Keep it conceptual and brief, and link to How-to/Reference as needed. (Why: one conceptual entry frames the section and reduces duplication.)
* Reference pages **MUST** be the canonical source for flags/fields/errors/types. Guides **MUST NOT** duplicate tables; they **SHOULD** deep-link to anchors. (Why: single source of truth stays accurate and reduces maintenance.)
Objective. Keep repository structure and UI labels consistent. (Why: predictable structure speeds editing, improves search/TOC behavior, and reduces merge and build issues.)
### 16.2 Files and titles [#162-files-and-titles]
* Filenames **MUST** use kebab-case.md or kebab-case.mdx (e.g., `validator-setup.mdx`). (Why: kebab-case avoids case-sensitivity bugs, reads well in URLs, and is easy to grep.) \[HIGH]
* Filenames **MUST NOT** have uppercase characters, i.e. `foo-bAR.mdx`. \[HIGH]
* Filenames **MUST NOT** have cyrillic characters, i.e. `сhoice.mdx`. \[HIGH]
### 16.3 Navigation labels [#163-navigation-labels]
* Sidebar and nav labels **SHOULD** be short (2–4 words), unique, and mirror in-page headings. (Why: short, unique labels prevent truncation and speed scanning.)
* Sidebar labels **MAY** be concise aliases of the page title; they **SHOULD** preserve the title’s meaning even if wording is shortened. (Why: sidebars have less space; preserving meaning avoids confusion.)
* Child pages inside a sidebar group **MUST NOT** repeat the group name in `sidebarTitle` when that word adds no new meaning. Rely on the group label as context and choose a short, distinct label instead. (Why: avoiding redundant group nouns keeps nested labels concise and scannable.) \[HIGH]
* Example: in a group `Addresses`, prefer `sidebarTitle: "Overview"` or `sidebarTitle: "Deriving"` over `sidebarTitle: "Addresses overview"` or `sidebarTitle: "Deriving addresses"`.
* Avoid duplicate “Introduction” labels—make them specific (e.g., “Intro to sharding”). (Why: generic labels create indistinguishable TOC items and weak deep links.)
* Frontmatter keys. Use only page metadata supported by Mintlify (see project docs) and `noindex: true` when a page must be excluded from search indexing. **MUST NOT** introduce custom frontmatter keys for internal taxonomy (e.g., `doc_type`, `audience`, custom `status`). Represent such information in the page content or navigation instead. (Why: unsupported keys add maintenance burden, break tooling, and confuse contributors.)
* Length cap. If the frontmatter `title` exceeds 30 characters, the page **MUST** set `sidebarTitle`, and the `sidebarTitle` **MUST** be ≤ 30 characters. If the `title` is ≤ 30 characters, `sidebarTitle` is OPTIONAL; when provided, it **SHOULD** be ≤ 30 characters. Prefer removing non-essential words over truncation; labels **MUST NOT** end with ellipses; preserve meaning and proper-noun/case accuracy. (Why: short, clear labels fit sidebars and remain scannable.)
Example
```mdx
---
title: "How to troubleshoot validator connectivity issues on restrictive firewalls"
sidebarTitle: "Validator connectivity"
---
```
* How-to frontmatter pattern. How-to pages **MUST** set `title: "How to X"` and **MUST** set `sidebarTitle` to either `X` or a shorter alias of X that relies on the sidebar group for context and does not repeat the group name needlessly, where X is the task phrased in sentence case. If X begins with a letter, capitalize its first character; preserve exact casing for proper nouns and code tokens inside X. (Why: consistent titles match “how to …” searches; concise sidebar labels aid scanning while avoiding redundant group nouns and keeping identifiers accurate.) \[HIGH]
* Title vs sidebar semantics. The frontmatter `title` **MUST** be context-free and self-describing for search and deep links; the `sidebarTitle` **SHOULD** be concise and rely on the current navigation context. One-word generic titles (e.g., “Overview”, “Introduction”) **MUST NOT** be used as `title` except on top-level pages (`/the-page`) or when the page is a proper name/term (e.g., “MyTonWallet”, “TON Center”). In those cases, a one-word `title` **MAY** be used. Otherwise, the `title` **SHOULD** replicate or expand the section/folder name (e.g., “Sharding overview”), and the `sidebarTitle` **MAY** be “Overview”. (Why: descriptive titles improve discoverability and stand alone; short sidebar labels read better in context.)
Example
```mdx
---
title: "Sharding overview"
sidebarTitle: "Overview"
---
```
Example
```mdx
---
title: "How to get testnet Gram"
sidebarTitle: "Get testnet Gram"
---
```
### 16.4 Links and anchors [#164-links-and-anchors]
* Internal links **MUST** be root-absolute (start with `/`) and **MUST NOT** include `./` or `../`; ensure anchors are stable. (Why: root-absolute links survive file moves and changes to the information architecture; relative segments break during reorganizations.) \[HIGH]
* Trailing slashes: Follow a single repo-wide policy set by the site generator, and apply it consistently across all internal links. (Why: consistency prevents duplicate routes, cache misses, and SEO issues.)
* Cross-section links **SHOULD** target specific anchors rather than page tops. (Why: deep links land readers directly on the needed detail.)
### 16.5 Status labels [#165-status-labels]
* Pages and features **MAY** declare a status in content at the top of the page using an `` with a clear title (e.g., `title="Deprecated"` or `title="Experimental"`). Do not introduce custom frontmatter keys for status. (Why: status is visible to readers and does not require unsupported metadata.)
* If deprecated, the page **MUST** include the replacement (link to successor) and the removal timeline (date or version) in the callout. You **MAY** set `noindex: true` in frontmatter to exclude the page from search when appropriate. (Why: clear migration guidance reduces breakage; de-indexing avoids surfacing outdated pages.)
* If experimental, briefly state scope and limitations; link to the stable alternative when available. (Why: scope limits misuse and points to the dependable path.)
* Status labels (experimental/deprecated) are independent of safety callouts (see [§11](#11-safety-critical-content-blockchain-specific)). Apply both when applicable. (Why: status communicates lifecycle; safety communicates risk—readers need both.)
### 16.6 Components used in content [#166-components-used-in-content]
* On normal documentation pages, **SHOULD NOT** use `` components; prefer headings, lists, and inline links for navigation and structure. (Why: cards add visual chrome that is rarely needed for comprehension.)
* Existing `` usages **SHOULD** be confined to top-level index or overview pages where the card layout clearly improves navigation. Over time, simplify or remove cards that do not provide a clear navigation benefit. (Why: keeping cards to a few deliberate entry pages avoids fragmenting the visual style.)
* When an index-style page genuinely needs card-like tiles, you **MAY** use ``; keep the content inside each card minimal and avoid duplicating information from the linked pages. (Why: cards should support navigation, not introduce a second layer of prose.)
* More generally, follow the “minimal styling” workflow from [§6.2](#6-2-quotation-marks-and-emphasis): components such as ``, ``, ``, or tab containers **SHOULD** appear only when they improve comprehension or navigation, not as decoration. (Why: reduced decorative chrome makes structure and behavior stand out.)
## Content hygiene and timeless writing [#17-content-hygiene-and-timeless-writing]
Objective. Reduce staleness, duplication, and maintenance costs. (Why: fresh, non-duplicated content is cheaper to maintain and more trustworthy for readers.)
### 17.1 Single source of truth [#171-single-source-of-truth]
* Each fact **MUST** have a canonical home. If you need the same fact elsewhere, link to it (see [§12](#12-links-and-cross-references)). (Why: one source prevents contradictions and simplifies updates.)
* Guides **MUST NOT** replicate reference tables; summarize and link. (Why: duplicated tables drift and become incorrect.)
### 17.2 Timelessness [#172-timelessness]
* You **SHOULD NOT** use words like “currently”, “new”, or “soon”. (Why: time-relative words stale quickly and lose meaning.)
* Prefer durable phrasing: “Since v2.3, X is supported,” not “newly added.” (Why: version-based phrasing stays accurate over time.)
* Remove version qualifiers once they’re no longer useful. (Why: eliminates outdated noise and keeps prose evergreen.)
### 17.3 Freshness and updates [#173-freshness-and-updates]
* When behavior changes, the relevant pages **MUST** be updated promptly. (Why: outdated steps cause failures and support load.)
* Large refactors **SHOULD** include redirects and update cross-links. (Why: preserves deep links and prevents 404s.)
* Avoid re-documenting external tools; link to official docs and focus on TON-specific usage. (Why: external details change often; linking reduces churn.)
### 17.4 Proofread [#174-proofread]
* Read aloud or skim with a “scanner’s eye”; long sentences **SHOULD** be split (see [§8](#8-readability-and-scannability)). (Why: catches awkward phrasing and improves scannability.)
* Check terms against the term bank; enforce casing and spelling consistently. (Why: consistent terminology improves comprehension and search.)
Rationale: “Timeless” style and a canonical home for facts keep the docs trustworthy and maintainable.
## Style exceptions and edge cases [#18-style-exceptions-and-edge-cases]
Objective. Provide a controlled escape hatch without eroding consistency. (Why: limited, trackable exceptions solve real edge cases without letting the style drift.)
* Any deviation from this guide **MUST** document: the rule being overridden, the reason, the scope (pages affected), the owner, and an expiry or review date. (Why: documentation, ownership, and a sunset make exceptions accountable and reversible.)
* Exceptions **SHOULD** be rare, time-boxed, and revisited. (Why: scarcity prevents precedent; time limits force cleanup.)
* For audience-critical reasons (e.g., highly advanced research notes), a page **MAY** relax sentence-length norms ([§8](#8-readability-and-scannability)) or include extra theory in a how-to ([§3](#3-documentation-framework-content-types)), but the page **MUST** clearly state the rationale at the top (e.g., Audience: Advanced). (Why: transparency lets readers self-select and prevents surprise.)
* When quoting external code or configuration verbatim for legal or technical reasons, formatting **MAY** violate some house rules if changing it would misrepresent the original. Such cases **SHOULD** be rare and, for large or recurring examples, **SHOULD** be documented as style exceptions with scope and owner. (Why: fidelity to external sources sometimes takes priority over local formatting rules.)
* A safety requirement ([§11](#11-safety-critical-content-blockchain-specific)) **MUST NOT** be waived. (Why: reader safety outweighs convenience.) \[HIGH]
Rationale: Exceptions exist to serve clarity, not convenience. They are documented so future editors can normalize them later.
## Appendices [#19-appendices]
### A. Admonition levels and usage [#a-admonition-levels-and-usage]
Use the least severe callout that communicates the point; overuse reduces impact. (Why: calibrated severity keeps important warnings noticeable; overuse leads to alert fatigue.)
Implementation. Render callouts with the `` component (see `/src/components/mdx/callout.tsx`). **MUST NOT** use Markdown blockquotes (`>`) to simulate callouts. The only supported `type` values are `note`, `tip`, `caution`, and `danger`. Map levels to types: Note → `type="note"`; Tip → `type="tip"`; Caution → `type="caution"`; Warning → `type="danger"`. Use `title` to set the visible label when needed (e.g., `title="Important"`). (Why: consistent components and a fixed type set keep callouts accessible and visually coherent.) \[HIGH]
* On pages with multiple hazardous actions, combine a page-level safety `` at the top (describing overall risk, scope, rollback/mitigation where feasible, and environment) with short local `` elements near each dangerous step that can refer back to the summary instead of repeating it. (Why: the combination keeps risks visible without duplicating long warnings at every step.)
| Level | When to use | MUST include |
| --------- | -------------------------------------------------------- | ----------------------------------------------- |
| Note | Auxiliary info or minor edge cases | Short, actionable text only |
| Tip | Productivity boosters, shortcuts | A clear benefit (“Saves time by …”) |
| Important | Prerequisites, state assumptions, gotchas | The condition and its effect |
| Caution | Potential data loss or non-recoverable state | Risk + mitigation/rollback |
| Warning | Security, funds/keys/validator risk, chain-affecting ops | Risk + scope + rollback + testnet/mainnet label |
(Why: the “MUST include” fields ensure every callout contains the minimum information a reader needs to act safely.)
Examples
* Important — prerequisite
“This guide requires a funded testnet wallet.”
* Caution — data loss
“`--purge-ledger` removes local data. Back up `` before running.”
* Warning — funds at risk
“Transfers on mainnet are final.”
* Warning — page with many risky steps
“Read the safety note at the top of this page before running any mainnet commands.”
(Admonition usage aligns with the safety requirements in [§11](#11-safety-critical-content-blockchain-specific).)
### B. Banned and preferred terms [#b-banned-and-preferred-terms]
Use this list in combination with the project term bank (see [§13](#13-terminology-and-naming)). Editors **MUST** expand it over time. (Why: the lexicon evolves; keeping it current prevents drift and inconsistency.)
Filler/tone (ban outright) (Why: filler adds no information and can sound condescending.)
* Banned: simply, just, obviously, clearly, please note, super-, ASAP
* Use instead: omit or state the concrete action/effect
Marketing/promotional (ban outright) (Why: marketing language erodes trust, adds no actionable information, and ages poorly.)
* Banned superlatives: blazingly fast, revolutionary, world-class, seamless, best-in-class, powerful, cutting-edge, game-changing, next-generation
* Banned vague adjectives (without measurable criteria): reliable, robust, essential, elegant, intuitive, flexible, comprehensive, scalable, efficient, optimal, superior
* Banned dramatic/emotional words: elusive, challenging (as drama), painful, frustrating, nightmare, perfectly, beautifully, amazing, incredible, stunning
* Banned intensity words: instantly (unless literal), immediately (unless literal), extremely, incredibly, massive, huge (for non-quantified values)
* Banned storytelling openers: "Imagine…", "Picture this…", "Have you ever…", "What if…"
* Use instead: measurable facts, specific numbers, concrete conditions, or omit entirely
Inclusivity (Why: inclusive terms are clearer for everyone and avoid excluding readers.)
* Banned: whitelist/blacklist → Preferred: allowlist/denylist
* Banned: master/slave → Preferred: primary/replica (or leader/follower, depending on context)
* Banned: sanity check → Preferred: basic check / smoke check
* Banned: dummy value → Preferred: sample value / placeholder
* Banned: crazy/insane → Preferred: unexpected / invalid
Clarity (Why: simpler words are read and translated more reliably.)
* Avoid: utilize → Use: use
* Avoid: prior to → Use: before
* Avoid: in order to → Use: to
* Avoid: leverage (as verb) → Use: use/apply
* Avoid: handle → Use: process/manage (be specific)
TON-specific casing (selected; see [§13](#13-terminology-and-naming) for more) (Why: exact casing improves search, recognition, and copy/paste fidelity.)
* Correct: TON, TON Mainnet (or just "mainnet"); smart contract; bag of cells; BoC; accountchain, shardchain, workchain, masterchain, basechain; ZK-proof, ZK-rollup.
* Incorrect: Ton; ton mainnet; Smart Contract; BOC; ShardChain; Shard Chain; WorkChain.
# Documentation style guide (https://docs.ton.org/llms/contribute/style-guide/content.md)
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 `meta.json`-formed 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:
````
Running the next command on mainnet transfers funds irreversibly. Try on the testnet first:
```bash
jetton transfer --to --amount --network testnet
```
On-chain fund transfers on testnet and mainnet are irreversible.
````
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 `public/images/` and reference them with root-absolute paths without the `/public` prefix, 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, Gram, 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).
# Blockchain configuration (https://docs.ton.org/llms/foundations/config/content.md)
TON features a complex configuration comprising many technical parameters, some of which are used by the blockchain itself, while others serve the ecosystem. However, only a limited number of individuals fully understand the significance of these parameters. This article aims to provide users with an overview of configuration parameters, their modification processes, and a straightforward explanation of each parameter and its purpose.
Explore the [config proposals](https://vote.lagus.cooking/) voted on by the validators.
## Prerequisites [#prerequisites]
The parameter values in the [current configuration](https://tonscan.org/config), and the method of writing them into [cells](https://docs.ton.org/llms/foundations/serialization/boc/content.md) are outlined in the [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in [TL-B](https://docs.ton.org/llms/foundations/tlb/overview/content.md) format.
Configuration values are TL-B typed cells serialized into [Bags of Cells (BoC)](https://docs.ton.org/llms/foundations/serialization/boc/content.md).
All parameters are in place, and you won't get lost. For your convenience, please use the right sidebar for quick navigation.
### Overview [#overview]
The **configuration parameters** are specific values that influence the behavior of validators and fundamental smart contracts on the TON blockchain. The current values of all configuration parameters are stored as a distinct part of the masterchain state and are retrieved whenever necessary. Consequently, we can refer to the values of the configuration parameters concerning a particular masterchain block. Each shardchain block includes a reference to the most recently known masterchain block; the values from the corresponding masterchain state are considered active for this shardchain block and are used during its generation and validation.
For masterchain blocks, the state of the previous masterchain block is used to extract the active configuration parameters. Therefore, even if certain configuration parameters are attempted to be modified within a masterchain block, any changes will only take effect in the subsequent masterchain block.
Each configuration parameter is identified by a signed 32-bit integer known as the **configuration parameter index**, or simply the **index**. The value of a configuration parameter is always a `Cell`. In some cases, certain configuration parameters may be absent, and it is generally assumed that the value of these missing parameters is `Null`. Additionally, there is a list of **mandatory** configuration parameters that must always be present. This list is stored in configuration parameter `#9`.
All configuration parameters are combined into a **configuration dictionary** with signed 32-bit keys (the configuration parameter indices) and values that consist of exactly one cell reference. The collection of all configuration parameters is retained in the masterchain state as a value of the TL-B type `ConfigParams`:
```tlb
_ config_addr:bits256 config:^(Hashmap 32 ^Cell) = ConfigParams;
```
In addition to the configuration dictionary, `ConfigParams` contains `config_addr`—the 256-bit address of the configuration smart contract within the masterchain. Further details on the configuration smart contract will be provided later.
The configuration dictionary, which contains the active values of all configuration parameters, is accessible to all smart contracts through a special TVM register called `c7` during the execution of a transaction. Specifically, when a smart contract is executed, `c7` is initialized as a tuple. This tuple consists of a single element, which is another tuple containing several "context" values that are useful for executing the smart contract, such as the current Unix time (as recorded in the block header).
The tenth entry of this inner tuple (i.e., the one indexed with zero-based index 9) contains a `Cell` representing the configuration dictionary. This configuration dictionary can be accessed by using the TVM instructions `PUSH c7; FIRST; INDEX 9` or the equivalent instruction `CONFIGROOT`. Furthermore, special TVM instructions like `CONFIGPARAM` and `CONFIGOPTPARAM` streamline this process by combining the previous actions with a dictionary lookup, allowing smart contracts to retrieve any configuration parameter by its index.
It is important to note that all configuration parameters are readily accessible to all smart contracts, whether they operate on the masterchain or shardchain. As a result, smart contracts can inspect these parameters and utilize them for specific checks. For instance, a smart contract might extract data storage prices for different WorkChains from a configuration parameter in order to calculate the cost of storing a piece of user-provided data.
The values of configuration parameters are not arbitrary. Specifically, if the configuration parameter index `i` is non-negative, then its value must correspond to a valid value of the TL-B type `ConfigParam i`. Validators enforce this restriction and do not accept changes to configuration parameters with non-negative indices unless the values are valid for the corresponding TL-B type.
The structure of these parameters is defined in the source file [`crypto/block/block.tlb`](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/block.tlb), where `ConfigParam i` is specified for different values of `i`. For example:
```tlb
_ config_addr:bits256 = ConfigParam 0;
_ elector_addr:bits256 = ConfigParam 1;
_ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver
capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion;
_ GlobalVersion = ConfigParam 8; // all zero if absent
```
The configuration parameter `#8` includes a `Cell` that has no references and contains exactly 104 data bits. The first eight bits are allocated for `11000100` (`0xc4`), followed by 32 bits that represent the currently enabled "global version". This is followed by a 64-bit integer with flags that correspond to the currently enabled capabilities. A more detailed description of all configuration parameters will be provided in an appendix to the TON blockchain documentation. In the meantime, you can review the TL-B scheme in [`crypto/block/block.tlb`](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/block.tlb) to see how different parameters are utilized in the validator sources.
Unlike configuration parameters with non-negative indices, those with negative indices can hold arbitrary values. Validators do not enforce any restrictions on these values. As a result, they can be used to store essential information, such as the Unix time when specific smart contracts are set to begin operating. This information is not critical for block generation but is necessary for some fundamental smart contracts.
### Changing configuration parameters [#changing-configuration-parameters]
The current values of configuration parameters are stored in a special section of the masterchain state. But how are they changed?
There is a special smart contract known as the **configuration smart contract** that resides in the masterchain. Its address is specified by the `config_addr` field in `ConfigParams`. The first cell reference in its data must contain an up-to-date copy of all configuration parameters. When a new masterchain block is generated, the configuration smart contract is accessed using its address (`config_addr`), and the new configuration dictionary is extracted from the first cell reference of its data.
Following some validity checks—like ensuring that any value with a non-negative 32-bit index `i` is indeed a valid TL-B type (`ConfigParam i`)—the validator copies this new configuration dictionary into the portion of the masterchain that contains `ConfigParams`. This operation occurs after all transactions have been created, meaning only the final version of the new configuration dictionary stored in the smart contract is evaluated.
If the validity checks fail, the existing configuration dictionary remains unchanged, ensuring that the configuration smart contract cannot install invalid parameter values. If the new configuration dictionary is identical to the current one, no checks are performed, and no changes are made.
All changes to configuration parameters are executed by the configuration smart contract, which defines the rules for modifying these parameters. Currently, the contract supports two methods for changing them:
* **External message**: This method involves an external message signed by a specific private key, which corresponds to a public key stored in the configuration smart contract's data. This approach is typically used in the testnet and, possibly, in smaller private test networks controlled by a single entity, as it allows the operator to easily modify any configuration parameter values.
It is important to note that this public key can be changed through a special external message signed by the previous key, and if changed to zero, this mechanism becomes disabled. This means the method can be used for fine-tuning right after launch and then permanently disabled.
* **Configuration proposals**: This method involves creating "configuration proposals" that validators vote on. Generally, a configuration proposal must gather votes from more than 3/4 (75%) of all validators by weight, and this requires approval in multiple rounds (i.e., several consecutive sets of validators must confirm the proposed parameter change). This serves as the distributed governance mechanism for the TON blockchain Mainnet.
## Param 0: config address [#param-0-config-address]
This parameter is the address of a special smart contract that stores the blockchain's configuration. The configuration is stored in the contract to simplify its loading and modification during validator voting.
In the configuration parameter, only the hash portion of the address is recorded, as the contract always resides in the masterchain (workchain -1). Therefore, the full address of the contract will be written as `-1:`.
[Parameter #0 on mainnet](https://tonscan.org/config#0)
## Param 1: elector address [#param-1-elector-address]
This parameter is the address of the [elector smart contract](https://docs.ton.org/llms/foundations/system/content.md), responsible for appointing validators, distributing rewards, and voting on changes to blockchain parameters.
[Parameter #1 on mainnet](https://tonscan.org/config#1)
## Param 2: TON minting address [#param-2-ton-minting-address]
This parameter represents the address of the system, on behalf of which new Gram are minted and sent as rewards for validating the blockchain.
If parameter 2 is missing, parameter 0 is used instead — newly minted Gram come from the configuration smart contract.
[Parameter #2 on mainnet](https://tonscan.org/config#2)
## Param 3: fee collector address [#param-3-fee-collector-address]
This parameter is the address of the transaction fee collector.
If this parameter is missing (for the time being), transaction fees are directed to the elector smart contract (parameter 1).
[Parameter #3 on mainnet](https://tonscan.org/config#3)
## Param 4: root DNS address [#param-4-root-dns-address]
This parameter is the address of the root DNS contract of the TON network.
For details, see the [TON DNS](https://docs.ton.org/llms/foundations/web3/ton-dns/content.md) page and the [original specification](https://github.com/ton-blockchain/TEPs/blob/master/text/0081-dns-standard.md).
This contract is not responsible for selling **.ton** domains.
[Parameter #4 on mainnet](https://tonscan.org/config#4)
## Param 6: extra currency minting prices [#param-6-extra-currency-minting-prices]
This parameter stores the `mint_new_price` and `mint_add_price` values in Gram for extra-currency minting governance. The collator's [minting calculation](https://docs.ton.org/llms/foundations/extra-currencies/content.md) does not use these values.
[Parameter #6 on mainnet](https://tonscan.org/config#6)
## Param 7: extra currency volume [#param-7-extra-currency-volume]
This parameter stores target amounts for [extra-currency minting](https://docs.ton.org/llms/foundations/extra-currencies/content.md). It maps each 32-bit currency ID to a `VarUInteger 32` amount. A masterchain block mints the positive difference between a target and the previous global balance — lowering a target does not burn currency.
[Parameter #7 on mainnet](https://tonscan.org/config#7)
## Param 8: network version [#param-8-network-version]
This parameter indicates the network version and additional capabilities supported by the validators.
Validators are nodes in the TON Blockchain network that are responsible for creating new blocks and verifying transactions.
* `version`: This field specifies the version.
* `capabilities`: This field is a set of flags that are used to indicate the presence or absence of certain features or capabilities.
Thus, when updating the network, validators will vote to change parameter 8. This way, the TON Blockchain network can be updated without downtime.
[Parameter #8 on mainnet](https://tonscan.org/config#8)
## Param 9: mandatory params [#param-9-mandatory-params]
This parameter contains a list (binary tree) of mandatory parameters. It ensures that certain configuration parameters are always present and cannot be removed by a proposal to change the configuration until parameter 9 changes.
[Parameter #9 on mainnet](https://tonscan.org/config#9)
## Param 10: critical params [#param-10-critical-params]
This parameter represents a list (binary tree) of critical TON parameters whose change significantly affects the network, so more voting rounds are held.
[Parameter #10 on mainnet](https://tonscan.org/config#10)
## Param 11: config params [#param-11-config-params]
This parameter indicates under what conditions proposals to change the TON configuration are accepted.
* `min_tot_rounds`: The minimum number of rounds before a proposal can be applied. Currently, this parameter is not used: only `max_tot_round` (when the proposal will be rejected) and `min_wins` (when the proposal will be accepted) matter.
* `max_tot_rounds`: The maximum number of rounds, upon reaching which the proposal will automatically be rejected
* `min_wins`: The required number of wins (3/4 of validators by the sum of the pledges must vote in favor)
* `max_losses`: The maximum number of losses, upon reaching which the proposal will automatically be rejected
* `min_store_sec` and `max_store_sec` determine the possible time interval during which the proposal will be stored
* `bit_price` and `cell_price` indicate the price of storing one bit or one cell of the proposal
[Parameter #11 on mainnet](https://tonscan.org/config#11)
## Param 12: Workchain config [#param-12-workchain-config]
This parameter represents the configuration of a workchain in the TON Blockchain. workchains are designed as independent blockchains that can operate in parallel, allowing TON to scale and process a large number of transactions and smart contracts.
### Workchain configuration parameters [#workchain-configuration-parameters]
* `enabled_since`: A UNIX timestamp of the moment this workchain was enabled.
* `actual_min_split`: The minimum depth of the split (sharding) of this workchain, supported by validators.
* `min_split`: The minimum depth of the split of this workchain, set by the configuration.
* `max_split`: The maximum depth of the split of this workchain.
* `basic`: A boolean flag (1 for true, 0 for false) indicating whether this workchain is basic, i.e., handles Gram values (smart contracts based on the TON Virtual Machine).
* `active`: A boolean flag indicating whether this workchain is active at the moment.
* `accept_msgs`: A boolean flag indicating whether this workchain is accepting messages at the moment.
* `flags`: Additional flags for the workchain (reserved, currently always 0).
* `zerostate_root_hash` and `zerostate_file_hash`: Hashes of the first block of the workchain.
* `version`: Version of the workchain.
* `format`: The format of the workchain, which includes `vm_version` and `vm_mode` - the virtual machine used there.
[Parameter #12 on mainnet](https://tonscan.org/config#12)
## Param 13: complaint cost [#param-13-complaint-cost]
This parameter defines the cost of filing complaints about the incorrect operation of validators in the [elector smart contract](https://docs.ton.org/llms/foundations/system/content.md).
[Parameter #13 on mainnet](https://tonscan.org/config#13)
## Param 14: block reward [#param-14-block-reward]
This parameter indicates the reward for creating a block in the TON Blockchain. Values are in nanograms; therefore, the reward for block creation in the masterchain is 1.7 Gram, while in the basechain, it is 1.0 Gram. In the event of a workchain split, the block reward is also divided: if there are two shardchains within the workchain, then the reward for each shard block will be 0.5 Gram.
[Parameter #14 on mainnet](https://tonscan.org/config#14)
## Param 15: elections timing [#param-15-elections-timing]
This parameter contains the duration of different stages of elections and validators' work in the TON Blockchain.
For each validation period, there is an `election_id` equal to the UNIX-format time at the start of the validation.
You can get the current `election_id` (if elections are ongoing) or the past one by invoking the elector smart contract's respective get-methods `active_election_id` and `past_election_ids`.
### Election and validation timing parameters [#election-and-validation-timing-parameters]
* `validators_elected_for`: The number of seconds the elected validators perform their role (one round).
* `elections_start_before`: The seconds before the end of the current round, when the election process for the next period will start.
* `elections_end_before`: The seconds before the end of the current round, the validators for the next round will be chosen.
* `stake_held_for`: The period for which a validator's stake is held (for handling complaints) after the round expires.
Each value in the arguments is determined by the `uint32` data type.
### Examples [#examples]
In the TON Blockchain, validation periods are typically divided into **even** and **odd** rounds that alternate. Voting for the next round occurs during the previous one, so a validator must allocate their funds into two separate pools to participate in both rounds.
#### Mainnet [#mainnet]
Current values:
```python
constants = {
'validators_elected_for': 65536, # 18.2 hours
'elections_start_before': 32768, # 9.1 hours
'elections_end_before': 8192, # 2.2 hours
'stake_held_for': 32768 # 9.1 hours
}
```
Scheme:
#### How to calculate periods? [#how-to-calculate-periods]
Let `election_id = validation_start = 1600032768`. Then:
```python
election_start = election_id - constants['elections_start_before'] = 1600032768 - 32768 = 1600000000
election_end = delay_start = election_id - constants['elections_end_before'] = 1600032768 - 8192 = 1600024576
hold_start = validation_end = election_id + constants['validators_elected_for'] = 1600032768 + 65536 = 1600098304
hold_end = hold_start + constants['stake_held_for'] = 1600098304 + 32768 = 1600131072
```
Therefore, at this time, the length of one round of one parity is `1600131072 - 1600000000 = 131072 seconds = 36.40888... hours`
#### Testnet [#testnet]
Current values:
```python
constants = {
'validators_elected_for': 7200, # 2 hours
'elections_start_before': 2400, # 40 minutes
'elections_end_before': 180, # 3 minutes
'stake_held_for': 900 # 15 minutes
}
```
Scheme:
#### How to calculate periods? [#how-to-calculate-periods-1]
Let `election_id = validation_start = 160002400`. Then:
```python
election_start = election_id - constants['elections_start_before'] = 160002400 - 2400 = 160000000
election_end = delay_start = election_id - constants['elections_end_before'] = 160002400 - 180 = 160002220
hold_start = validation_end = election_id + constants['validators_elected_for'] = 160002400 + 7200 = 160009600
hold_end = hold_start + constants['stake_held_for'] = 160009600 + 900 = 160010500
```
Therefore, at this time, the length of one round of one parity is `160010500 - 160000000 = 10500 seconds = 175 minutes = 2.91666... hours`
[Parameter #15 on mainnet](https://tonscan.org/config#15)
## Param 16: validators limits [#param-16-validators-limits]
This parameter represents the limits on the number of validators in the TON Blockchain. It is directly used by the elector smart contract.
### Configuration parameters for the number of validators for elections [#configuration-parameters-for-the-number-of-validators-for-elections]
* `max_validators`: This parameter represents the maximum number of validators that can participate in the network operation at any given time.
* `max_main_validators`: This parameter represents the maximum number of masterchain validators.
* `min_validators`: This parameter represents the minimum number of validators that must support the network operation.
#### Notes [#notes]
* The maximum number of validators is greater than or equal to the maximum number of masterchain validators.
* The maximum number of masterchain validators must be greater than or equal to the minimum number of validators.
* The minimum number of validators must be no less than 1.
[Parameter #16 on mainnet](https://tonscan.org/config#16)
## Param 17: stake limits [#param-17-stake-limits]
This parameter represents the stake parameters configuration in the TON Blockchain. In many blockchain systems, especially those using the Proof-of-Stake or Delegated Proof-of-Stake consensus algorithm, cryptocurrency owners native to the network can "stake" their tokens to become validators and earn rewards.
### Configuration parameters [#configuration-parameters]
* `min_stake`: This parameter represents the minimum amount of Gram that an interested party needs to stake to participate in the validation process.
* `max_stake`: This parameter represents the maximum amount of Gram that an interested party can stake.
* `min_total_stake`: This parameter represents the minimum total amount of Gram that the chosen set of validators must hold.
* `max_stake_factor`: This parameter is a multiplier indicating how many times the maximum effective stake (pledge) can exceed the minimum stake sent by any other validator.
Each value in the arguments is determined by the `uint32` data type.
[Parameter #17 on mainnet](https://tonscan.org/config#17)
## Param 18: storage prices [#param-18-storage-prices]
This parameter represents the configuration for determining the prices for data storage on the TON Blockchain. This serves as a measure to prevent spam and encourages network maintenance.
### Dictionary of storage fee parameters [#dictionary-of-storage-fee-parameters]
* `utime_since`: This parameter provides the initial Unix timestamp from which the specified prices apply.
* `bit_price_ps` and `cell_price_ps`: These parameters represent the storage prices for one bit or one cell of information in the main workchains of the TON Blockchain for 65536 seconds.
* `mc_bit_price_ps` and `mc_cell_price_ps`: These parameters represent the storage prices per bit and per cell in the TON masterchain for 65536 seconds.
`utime_since` accepts values in the `uint32` data type.
The rest accept values in the `uint64` data type.
[Parameter #18 on mainnet](https://tonscan.org/config#18)
## Param 20 and 21: gas prices [#param-20-and-21-gas-prices]
These parameters define the cost of computations in the TON network. The complexity of any computation is estimated in gas units.
Note: Param 20 defines gas settings for the masterchain; Param 21 defines gas settings for other workchains.
* `flat_gas_limit` and `flat_gas_price`: A certain starting amount of gas is provided at a price of `flat_gas_price` (to offset the costs of launching the TON Virtual Machine).
* `gas_price`: This parameter reflects the price of gas in the network, in nanograms per 65536 gas units.
* `gas_limit`: This parameter represents the maximum amount of gas that can be consumed per transaction.
* `special_gas_limit`: This parameter represents the limit on the amount of gas that can be consumed per transaction of a special (system) contract.
* `gas_credit`: This parameter represents a credit in gas units provided to transactions to process an external message.
* `block_gas_limit`: This parameter represents the maximum amount of gas that can be consumed within a single block.
* `freeze_due_limit` and `delete_due_limit`: Limits of accumulated storage fees (in nanograms) at which a contract is frozen and deleted, respectively.
You can find more about `gas_credit` and other parameters in the section of external messages [here](https://docs.ton.org/llms/foundations/messages/external-in/content.md).
[Parameter #20 on mainnet](https://tonscan.org/config#20) | [Parameter #21 on mainnet](https://tonscan.org/config#21)
## Param 22 and 23: block limits [#param-22-and-23-block-limits]
These parameters set limits on the block, upon reaching which the block is finalized and the callback of the remaining messages (if any) is carried over to the next block.
### Configuration parameters [#configuration-parameters-1]
* `bytes`: This section sets the limits on the block size in bytes.
* `underload`: Underload is a state when the shard realizes that there is no load and is inclined to merge if a neighboring shard is willing.
* `soft_limit`: Soft limit - when this limit is reached, internal messages stop being processed.
* `hard_limit`: Hard limit - this is the absolute maximum size.
* `gas`: This section sets the limits on the amount of gas that a block can consume. Gas, in the context of blockchain, is an indicator of computational work. The limits on underload, soft and hard limits work the same as for size in bytes.
* `lt_delta`: This section sets the limits on the difference in logical time between the first and last transaction. Logical time is a concept used in the TON Blockchain for ordering events. The limits on underload, soft and hard limits work the same as for size in bytes and gas.
If a shard has insufficient load and there is an intention to merge with a neighboring shard, the `soft_limit` indicates a threshold. When this threshold is exceeded, internal messages will stop being processed, while external messages will still be handled. External messages will continue to be processed until the total reaches a limit that is equal to half the sum of the `soft_limit` and `hard_limit`, or `(soft_limit + hard_limit) / 2`.
[Parameter #22 on mainnet](https://tonscan.org/config#22) | [Parameter #23 on mainnet](https://tonscan.org/config#23)
## Param 24 and 25: message price [#param-24-and-25-message-price]
Parameter 24 represents the configuration for the cost of sending messages in the masterchain of the TON Blockchain.
Parameter 25 represents the configuration for the cost of sending messages in all other cases.
### Configuration parameters defining the costs of forwarding [#configuration-parameters-defining-the-costs-of-forwarding]
* `lump_price`: This parameter means the base price for forwarding a message, regardless of its size or complexity.
* `bit_price`: This parameter represents the cost per bit of message forwarding.
* `cell_price`: This parameter reflects the cost of forwarding a message per cell. A cell is the basic unit of data storage on the TON Blockchain.
* `ihr_price_factor`: This is a factor used to calculate the cost of immediate hypercube routing (IHR).
IHR is a method of message delivery in the TON Blockchain network, where messages are sent directly to the recipient's shardchain.
* `first_frac`: This parameter defines the fraction of the remaining amount that will be used for the first transition along the message route.
* `next_frac`: This parameter defines the fraction of the remaining amount that will be used for subsequent transitions along the message route.
[Parameter #24 on mainnet](https://tonscan.org/config#24) | [Parameter #25 on mainnet](https://tonscan.org/config#25)
## Param 28: catchain config [#param-28-catchain-config]
This parameter provides the configuration for the `Catchain` protocol in the TON Blockchain. `Catchain` is the lowest-level consensus protocol used in the TON to achieve agreement among validators.
### Configuration parameters [#configuration-parameters-2]
* `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set.
* `shuffle_mc_validators`: A Boolean value indicating whether to shuffle the masterchain validators or not. If this parameter is set to 1, the validators will be shuffled; otherwise, they will not.
* `mc_catchain_lifetime`: The lifetime of masterchain's `Catchain` groups in seconds.
* `shard_catchain_lifetime`: The lifetime of shardchain's `Catchain` groups in seconds.
* `shard_validators_lifetime`: The lifetime of a shardchain's validators group in seconds.
* `shard_validators_num`: The number of validators in each shardchain validation group.
[Parameter #28 on mainnet](https://tonscan.org/config#28)
## Param 29: consensus config [#param-29-consensus-config]
This parameter provides the configuration for the consensus protocol above `Catchain` ([Param 28](#param-28-catchain-config)) in the TON Blockchain. The consensus protocol is a crucial component of a blockchain network: it ensures that all nodes agree on the state of the distributed ledger.
`ConfigParam 29` has evolved through several updates. The latest constructor, `consensus_config_v4#d9`, is defined in [`block.tlb`](https://github.com/ton-blockchain/ton/blob/v2026.04/crypto/block/block.tlb#L782). It extends `consensus_config_v3#d8` with a new `use_quic:Bool` field, taking one bit from `flags`, which shrinks from 7 to 6 bits. It also adds `catchain_max_blocks_coeff:uint32` field at the end.
### Configuration parameters [#configuration-parameters-3]
* `flags`: A general field that can be used to set various binary parameters.
* `use_quic`: A Boolean value indicating whether the legacy Catchain consensus path uses QUIC transport instead of RLDP2. Introduced in `consensus_config_v4#d9`; has the same meaning as the `use_quic` field in [Param 30](#param-30-consensus-extension).
* `new_catchain_ids`: A Boolean value indicating whether to generate new `Catchain` identifiers.
* `round_candidates`: The number of candidates to be considered in each round of the consensus protocol.
* `next_candidate_delay_ms`: The delay in milliseconds before the right to generate a block candidate passes to the next validator.
* `consensus_timeout_ms`: The timeout for block consensus in milliseconds.
* `fast_attempts`: The number of "fast" attempts to reach consensus.
* `attempt_duration`: The duration of each attempt at agreement, in seconds.
* `catchain_max_deps`: The maximum number of dependencies of a Catchain block.
* `max_block_bytes`: The maximum size of a block in bytes.
* `max_collated_bytes`: The maximum size of serialized block correctness proofs in bytes.
* `proto_version`: The protocol version.
* `catchain_max_blocks_coeff`: The coefficient limiting the rate of block generation in `Catchain`, [description](https://github.com/ton-blockchain/ton/blob/master/doc/catchain-dos.md).
For up-to-date values, see [Parameter #29 on mainnet](https://tonscan.org/config#29).
### On-chain schema [#on-chain-schema]
`ConfigParam 29` is a tagged union: validators must accept all of its constructors, including legacy ones. This ensures that older serialized configurations continue to be valid while newer on-chain values are written using the latest tag.
The current set defined in [`block.tlb`](https://github.com/ton-blockchain/ton/blob/v2026.04/crypto/block/block.tlb#L782) is:
```tlb
consensus_config#d6 round_candidates:# { round_candidates >= 1 }
next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32
fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32
max_block_bytes:uint32 max_collated_bytes:uint32 = ConsensusConfig;
consensus_config_new#d7 flags:(## 7) { flags = 0 } new_catchain_ids:Bool
round_candidates:(## 8) { round_candidates >= 1 }
next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32
fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32
max_block_bytes:uint32 max_collated_bytes:uint32 = ConsensusConfig;
consensus_config_v3#d8 flags:(## 7) { flags = 0 } new_catchain_ids:Bool
round_candidates:(## 8) { round_candidates >= 1 }
next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32
fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32
max_block_bytes:uint32 max_collated_bytes:uint32
proto_version:uint16 = ConsensusConfig;
consensus_config_v4#d9 flags:(## 6) { flags = 0 } use_quic:Bool new_catchain_ids:Bool
round_candidates:(## 8) { round_candidates >= 1 }
next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32
fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32
max_block_bytes:uint32 max_collated_bytes:uint32
proto_version:uint16 catchain_max_blocks_coeff:uint32 = ConsensusConfig;
_ ConsensusConfig = ConfigParam 29;
```
`consensus_config_v4#d9` was introduced together with the [Catchain 2.0 / Simplex](https://github.com/ton-blockchain/simplex-docs/blob/main/Simplex.md) migration tracked by [Param 30](#param-30-consensus-extension).
The `use_quic` toggle in Param 29 controls the transport for the legacy Catchain path; the `use_quic` toggle in Param 30 controls the transport for the new Simplex path. They are configured independently.
[Parameter #29 on mainnet](https://tonscan.org/config#29)
## Param 30: consensus extension [#param-30-consensus-extension]
* [TON v2026.03](https://github.com/ton-blockchain/ton/releases/tag/v2026.03): `ConfigParam 30` introduced on testnet.
* [TON v2026.04](https://github.com/ton-blockchain/ton/releases/tag/v2026.04): `ConfigParam 30` enabled on mainnet.
This parameter configures [Catchain 2.0](https://github.com/ton-blockchain/simplex-docs/blob/main/Simplex.md) — the Simplex-based consensus protocol that succeeds the original Catchain. The settings are optional and can be supplied independently for each chain. Block-size limits are not duplicated here: the node continues to read `max_block_bytes` and `max_collated_bytes` from [`ConfigParam 29`](https://docs.ton.org/llms/foundations/config/content.md).
The `crypto/block/block.tlb` [defines](https://github.com/ton-blockchain/ton/blob/v2026.04/crypto/block/block.tlb#L782) the following schema:
```tlb
simplex_config#21 flags:(## 7)
use_quic:Bool
target_rate_ms:uint32
slots_per_leader_window:uint32
first_block_timeout_ms:uint32
max_leader_window_desync:uint32
= NewConsensusConfig;
simplex_config_v2#22 flags:(## 7)
use_quic:Bool
slots_per_leader_window:uint32
noncritical_params:(HashmapE 8 uint32)
= NewConsensusConfig;
new_consensus_config_all#10
mc:(Maybe ^NewConsensusConfig)
shard:(Maybe ^NewConsensusConfig)
= NewConsensusConfigAll;
_ NewConsensusConfigAll = ConfigParam 30;
```
The `simplex_config_v2#22` constructor moves noncritical configuration parameters into a sparse dictionary. There are two optional refs in `new_consensus_config_all#10`. If a ref is absent, then the pre-2.0 Catchain config is active for the corresponding class of chains:
| Field | Type | Meaning |
| ------- | --------------------------- | ------------------------------------------------------- |
| `mc` | `Maybe ^NewConsensusConfig` | Config for the masterchain (`workchain = -1`) |
| `shard` | `Maybe ^NewConsensusConfig` | Config for shardchains (all non-masterchain workchains) |
The `NewConsensusConfig` has two constructors:
* `simplex_config#21` is the legacy fixed-layout format; scheduled for removal.
* `simplex_config_v2#22` is the current extensible format, which supports arbitrary `noncritical_params` without changes to the `block.tlb` layout.
### Configuration parameters of `simplex_config_v2` [#configuration-parameters-of-simplex_config_v2]
* `flags`: A general field that can be used to set various binary parameters.
* `use_quic`: Whether the QUIC transport is used instead of RLDP2. Set to `true` on mainnet.
* `slots_per_leader_window`: Number of consecutive slots assigned to one leader. Set to `4` on mainnet.
* `noncritical_params`: A `HashmapE 8 uint32` map from parameter IDs to raw 32-bit values.
Inherited from [Param 29](https://docs.ton.org/llms/foundations/config/content.md):
* `max_block_bytes` — maximum block size.
* `max_collated_bytes` — maximum size of serialized block correctness proofs.
The `noncritical_params` dictionary contains adjustable timing and DoS-protection parameters that can be changed via a config update without altering the `block.tlb` layout:
* The key is an 8-bit parameter ID.
* The value is always a raw 32-bit word.
* Unknown IDs are ignored by the current implementation.
* Missing IDs use default values.
* Duration-like parameters store milliseconds directly.
* Floating-point parameters store `float32` bits according to the [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) standard in a `uint32` value. The loader then reinterprets these bits as a floating-point numeric value.
IDs from `0` through `14` are recognized and supported. On the mainnet, only IDs `0`, `1`, and `13` are explicitly set. All other IDs are normally absent and use defaults.
| ID | Name | Stored as | Default | Meaning |
| ---- | -------------------------------------- | -------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `0` | `target_rate` | `uint32` milliseconds | `2400 ms` | Target slot or block interval; used for leader pacing, block production timing, and skip scheduling. |
| `1` | `first_block_timeout` | `uint32` milliseconds | `1000 ms` | Base timeout before skip voting starts for the first missing block in a leader window. |
| `2` | `first_block_timeout_multiplier` | `float32` bits in `uint32` | `1.2` | Multiplier applied to `first_block_timeout` after a window that had skips. |
| `3` | `first_block_timeout_cap` | `uint32` milliseconds | `100,000 ms` | Cap for the adaptive `first_block_timeout` growth. |
| `4` | `candidate_resolve_timeout` | `uint32` milliseconds | `1000 ms` | Initial timeout for candidate or notarization resolution requests. |
| `5` | `candidate_resolve_timeout_multiplier` | `float32` bits in `uint32` | `1.2` | Backoff multiplier for candidate resolution retries. |
| `6` | `candidate_resolve_timeout_cap` | `uint32` milliseconds | `10,000 ms` | Cap for candidate resolution timeout growth. |
| `7` | `candidate_resolve_cooldown` | `uint32` milliseconds | `10 ms` | Cooldown between candidate resolution attempts. |
| `8` | `standstill_timeout` | `uint32` milliseconds | `10,000 ms` | No-progress timeout before standstill recovery or rebroadcast logic triggers. |
| `9` | `standstill_max_egress_bytes_per_s` | `uint32` | `6,553,600` (`50 << 17`) | Egress rate cap used during standstill rebroadcast. |
| `10` | `max_leader_window_desync` | `uint32` | `250` | Maximum tolerated future leader-window distance for inbound Simplex traffic. |
| `11` | `bad_signature_ban_duration` | `uint32` milliseconds | `5000 ms` | Temporary ban duration after receiving bad signatures from a peer. |
| `12` | `candidate_resolve_rate_limit` | `uint32` | `10` | Per-peer rate limit for candidate resolution requests. |
| `13` | `min_block_interval` | `uint32` milliseconds | `0 ms` | Minimum interval between parent block time and the next locally generated block. |
| `14` | `no_empty_blocks_on_error_timeout` | `uint32` milliseconds | `15,000 ms` | How long empty-block fallback is allowed after the last finalized block when collation fails or times out. |
[Parameter #30 on mainnet](https://tonscan.org/config#30)
## Param 31: fee-exempt contracts [#param-31-fee-exempt-contracts]
This parameter represents the configuration of smart contract addresses from which no fees are charged for either gas or storage, and where **tick-tock** transactions can be created. The list usually includes governance contracts. The parameter is presented as a binary tree structure — a tree (HashMap 256), where the keys are a 256-bit representation of the address. Only addresses in the masterchain can be present in this list.
[Parameter #31 on mainnet](https://tonscan.org/config#31)
## Param 32, 34, and 36: validator lists [#param-32-34-and-36-validator-lists]
Lists of validators from the previous (32), current (34), and next (36) rounds. Parameter 36 is set from the end of the elections until the start of the round.
### Configuration parameters [#configuration-parameters-4]
* `cur_validators`: This is the current list of validators. Validators are typically responsible for verifying transactions in a blockchain network.
* `utime_since` and `utime_until`: These parameters provide the time period during which these validators are active.
* `total` and `main`: These parameters provide the total number of validators and the number of validators validating the masterchain in the network.
* `total_weight`: This adds up the weights of the validators.
* `list`: A list of validators in the tree format `id->validator-data`: `validator_addr`, `public_key`, `weight`, `adnl_addr`: These parameters provide details about each validator - their 256-bit addresses in the masterchain, public key, weight, ADNL address (the address used at the network level of the TON).
[Parameter #32 on mainnet](https://tonscan.org/config#32) | [Parameter #34 on mainnet](https://tonscan.org/config#34) | [Parameter #36 on mainnet](https://tonscan.org/config#36)
## Param 40: misbehavior punishment [#param-40-misbehavior-punishment]
This parameter defines the structure of the configuration for punishment for improper behavior (non-validation). In the absence of the parameter, the default fine size is 101 Gram.
### Configuration parameters [#configuration-parameters-5]
`MisbehaviourPunishmentConfig`: This data structure defines how improper behavior in the system is punished.
It contains several fields:
* `default_flat_fine`: This part of the fine does not depend on the stake size.
* `default_proportional_fine`: This part of the fine is proportional to the validator's stake size.
* `severity_flat_mult`: This is the multiplier applied to the `default_flat_fine` value for significant violations by the validator.
* `severity_proportional_mult`: This is the multiplier applied to the `default_proportional_fine` value for significant violations by the validator.
* `unpunishable_interval`: This parameter represents the period during which offenders are not punished to eliminate temporary network problems or other anomalies.
* `long_interval`, `long_flat_mult`, `long_proportional_mult`: These parameters define a "long" period of time and multipliers for flat and proportional fines for improper behavior.
* `medium_interval`, `medium_flat_mult`, `medium_proportional_mult`: Similarly, they define a "medium" period of time and multipliers for flat and proportional fines for improper behavior.
[Parameter #40 on mainnet](https://tonscan.org/config#40)
## Param 43: account and message limits [#param-43-account-and-message-limits]
This parameter relates to the size limits and other features of accounts and messages.
### Configuration parameters [#configuration-parameters-6]
* `max_msg_bits`: Maximum message size in bits.
* `max_msg_cells`: Maximum number of cells (a form of storage unit) a message can occupy.
* `max_library_cells`: Maximum number of cells that can be used for library cells.
* `max_vm_data_depth`: Maximum cell depth in messages and account state.
* `max_ext_msg_size`: Maximum external message size in bits.
* `max_ext_msg_depth`: Maximum external message depth. This could refer to the depth of the data structure within the message.
* `max_acc_state_cells`: Maximum number of cells that an account state can occupy.
* `max_acc_state_bits`: Maximum account state size in bits.
If absent, the default parameters are taken:
* `max_size` = 65535
* `max_depth` = 512
* `max_msg_bits` = 1 \<\< 21
* `max_msg_cells` = 1 \<\< 13
* `max_library_cells` = 1000
* `max_vm_data_depth` = 512
* `max_acc_state_cells` = 1 \<\< 16
* `max_acc_state_bits` = (1 \<\< 16) \* 1023
You can view more details about the standard parameters [here](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h#L379) in the source code.
[Parameter #43 on mainnet](https://tonscan.org/config#43)
## Param 44: suspended addresses [#param-44-suspended-addresses]
This parameter defines the list of suspended addresses, which cannot be initialized until `suspended_until`. It only applies to yet uninitiated accounts. This is a measure for stabilizing the tokenomics (limiting early miners). If not set, there are no limitations. Each address is represented as an end node in this tree, and the tree-like structure allows efficient checking of whether an address is in the list.
The stabilization of the tokenomics is further described in the [official report](https://t.me/tonblockchain/178) of the `@tonblockchain` Telegram channel.
[Parameter #44 on mainnet](https://tonscan.org/config#44)
## Param 45: precompiled contracts [#param-45-precompiled-contracts]
The list of precompiled contracts is stored in the masterchain config:
```tlb
precompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;
precompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;
_ PrecompiledContractsConfig = ConfigParam 45;
```
More details about precompiled contracts are on [this page](https://docs.ton.org/llms/foundations/precompiled/content.md).
[Parameter #45 on mainnet](https://tonscan.org/config#45)
## Param 71 - 73: outbound bridges [#param-71---73-outbound-bridges]
This parameter pertains to bridges for wrapping Gram in other networks:
* ETH-TON **(71)**
* BNB-TON **(72)**
* Polygon-TON **(73)**
### Configuration parameters [#configuration-parameters-7]
* `bridge_address`: This is the bridge contract address that accepts Grams to issue wrapped Grams in other networks.
* `oracle_multisig_address`: This is the bridge management wallet address. A multisig wallet is a type of digital wallet that requires signatures from multiple parties to authorize a transaction. It is often used to increase security. The oracles act as the parties.
* `oracles`: List of oracles in the form of a tree `id->address`
* `external_chain_address`: This is the bridge contract address in the corresponding external blockchain.
[Parameter #71 on mainnet](https://tonscan.org/config#71) | [Parameter #72 on mainnet](https://tonscan.org/config#72) | [Parameter #73 on mainnet](https://tonscan.org/config#73)
## Param 79, 81, and 82: inbound bridges [#param-79-81-and-82-inbound-bridges]
This parameter relates to bridges for wrapping tokens from other networks into tokens on the TON network:
* ETH-TON **(79)**
* BNB-TON **(81)**
* Polygon-TON **(82)**
### Configuration parameters [#configuration-parameters-8]
* `bridge_address` and `oracles_address`: These are the blockchain addresses of the bridge and the bridge management contract (oracles multisig), respectively.
* `oracles`: List of oracles in the form of a tree `id->address`
* `state_flags`: State flag. This parameter is responsible for enabling/disabling separate bridge functions.
* `prices`: This parameter contains a list or dictionary of prices for different operations or fees associated with the bridge, such as `bridge_burn_fee`, `bridge_mint_fee`, `wallet_min_tons_for_storage`, `wallet_gas_consumption`, `minter_min_tons_for_storage`, `discover_gas_consumption`.
* `external_chain_address`: The bridge contract address in another blockchain.
[Parameter #79 on mainnet](https://tonscan.org/config#79) | [Parameter #81 on mainnet](https://tonscan.org/config#81) | [Parameter #82 on mainnet](https://tonscan.org/config#82)
## Negative parameters [#negative-parameters]
Validators enforce TL-B validity only for configuration parameters with non-negative indices. Values with negative indices are **not** validated against a specific `ConfigParam i` type.
## Next steps [#next-steps]
After thoroughly reviewing this article, it is highly recommended that you dedicate time to a more in-depth study of the following documents:
* The original descriptions are present, but they may be limited, in the documents:
* [The Open Network Whitepaper](https://docs.ton.org/llms/foundations/whitepapers/ton/content.md)
* [Telegram Open Network Blockchain](https://docs.ton.org/llms/foundations/whitepapers/tblkch/content.md)
* Source code:
* [`mc-config.h`](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h)
* [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb)
# Extra currencies (https://docs.ton.org/llms/foundations/extra-currencies/content.md)
TON supports up to $2^{32}$ *extra currencies* besides its native currency — Gram. They are protocol-level fungible assets stored alongside [Gram](https://docs.ton.org/llms/foundations/glossary/content.md) in account balances. Extra currencies can be similarly attached to internal messages, but they cannot be used to pay [transfer fees](#transfers-and-fees) in place of Gram.
Unlike [jettons](https://docs.ton.org/llms/contracts/standard/tokens/jettons/overview/content.md), extra currencies cannot have custom behavior — they can only be stored and transferred. Furthermore, [minting of new extra currencies](#minting) is controlled by the masterchain [config](https://docs.ton.org/llms/foundations/config/content.md).
There are no active extra currencies on the mainnet — use jettons to create new fungible tokens.
## Representation [#representation]
The [`block.tlb` schema](https://docs.ton.org/llms/foundations/tlb/overview/content.md) defines an extra-currency collection as a dictionary, which is then kept in the `CurrencyCollection` structure next to the Gram balance:
```tlb
extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32))
= ExtraCurrencyCollection;
currencies$_ grams:Grams other:ExtraCurrencyCollection
= CurrencyCollection;
```
Each 32-bit dictionary key is a currency ID. Each value is a positive integer of at most 248 bits — zero balances are omitted.
## Transfers and fees [#transfers-and-fees]
A contract reads its remaining `CurrencyCollection` balance through [TVM](https://docs.ton.org/llms/tvm/overview/content.md) and specifies extra-currency amounts in an outbound internal message. The action phase subtracts each amount from the account balance. An insufficient balance produces [action result code 38](https://docs.ton.org/llms/tvm/exit-codes/content.md).
Extra currencies cannot pay storage, computation, or message-forwarding fees. These fees remain denominated in Gram.
Since [global TVM version 10](https://docs.ton.org/llms/foundations/config/content.md), [send modes 64 and 128](https://docs.ton.org/llms/foundations/messages/modes/content.md) change only the Gram component of a message. They do not add extra currencies from the incoming message or account balance.
Incoming and outgoing *external* messages cannot carry any currencies.
## Minting [#minting]
Extra-currency minting is controlled by the masterchain configuration:
* [Parameter 7](https://docs.ton.org/llms/foundations/config/content.md) stores target amounts by currency ID.
* [Parameter 2](https://docs.ton.org/llms/foundations/config/content.md) identifies the minter account. [Parameter 0](https://docs.ton.org/llms/foundations/config/content.md) is the fallback when parameter 2 is absent.
* [Parameter 6](https://docs.ton.org/llms/foundations/config/content.md) stores two Gram price fields intended for minting governance. The collator does not use them to calculate the minted amount.
For each parameter 7 entry, a masterchain collator subtracts the previous masterchain state's global balance from the configured target. A positive difference for a nonzero currency ID is minted in that masterchain block. An equal or lower target mints nothing — lowering the target does not burn currency.
When the difference is positive, the block contains a special internal message from the zero masterchain address to the minter account. Its `CurrencyCollection` carries the minted extra currencies, and its body is empty. Validators recompute the difference and reject a block whose minted value or special message does not match the configuration.
Changing a mint target requires a [configuration update](https://docs.ton.org/llms/foundations/config/content.md). A contract cannot create extra currency through a TVM instruction.
# Transaction fees (https://docs.ton.org/llms/foundations/fees/content.md)
Fees in TON align with the [execution phases](https://docs.ton.org/llms/foundations/phases/content.md) of a transaction:
* Storage fees are charged in the [storage phase](https://docs.ton.org/llms/foundations/phases/content.md).
* Compute fees are charged in the [compute phase](https://docs.ton.org/llms/foundations/phases/content.md).
* Forward and action fees are charged in the [action](https://docs.ton.org/llms/foundations/phases/content.md) and [bounce phases](https://docs.ton.org/llms/foundations/phases/content.md).
* Import fees apply at the start of smart contract execution, not a specific phase.
The total transaction fee is the sum of these components.
Validators set fee levels through voting:
* Storage fees are set in [config parameter 18](https://docs.ton.org/llms/foundations/config/content.md).
* Compute fees are set in [config parameters 20 and 21](https://docs.ton.org/llms/foundations/config/content.md).
* Forward, import, and action fees are set in [config parameters 24 and 25](https://docs.ton.org/llms/foundations/config/content.md).
## Storage fees [#storage-fees]
```cpp
basic_price = (account.bits * bit_price +
account.cells * cell_price)
storage_fee = ceil(basic_price * time_delta / 2^16)
```
The storage fee uses `account.bits` and `account.cells` from `AccountStorage`, excluding `ExtraCurrencyCollection` stored in the `other` field. The `other` field is replaced with a single `0` bit that represents an empty `HashmapE`.
```tlb
extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32))
= ExtraCurrencyCollection;
currencies$_ grams:Grams other:ExtraCurrencyCollection
= CurrencyCollection;
account_storage$_ last_trans_lt:uint64
balance:CurrencyCollection state:AccountState
= AccountStorage;
```
Storage and forward fees treat identical subtrees referenced in multiple branches as one cell. Reused subtrees share a single stored copy and do not accrue additional charges.
## Compute fees [#compute-fees]
All computation is measured in gas units. A TVM operation typically has a fixed gas cost, but that is [not always the case](https://docs.ton.org/llms/tvm/gas/content.md). Network configuration defines gas prices; users cannot override them.
### Flat gas limit [#flat-gas-limit]
A contract invocation pays for at least `flat_gas_limit` gas units. Spending up to that limit costs `flat_gas_price` Gram. If the contract spends `gasUsed` gas units, the fee is:
```ts
const gasUsed = 50_000n;
// 0 = basechain, -1 = masterchain
const prices = getGasPrices(configCell, 0);
const gasFee =
gasUsed <= prices.flat_gas_limit
? prices.flat_gas_price
: prices.flat_gas_price +
(prices.gas_price * (gasUsed - prices.flat_gas_limit)) / 65536n;
```
## Forward fee [#forward-fee]
Forward fee is calculated with this formula:
```
bodyFwdFee = priceForCells * (msgSizeInCells - 1)
+ priceForBits * (msgSizeInBits - bitsInRoot)
fwdFee = lumpPrice + ceil(bodyFwdFee / 2^16)
```
where:
* `lumpPrice` is the fixed value [from config](https://docs.ton.org/llms/foundations/config/content.md) paid once for the message.
* `msgSizeInCells` is the number of cells in the message.
* `msgSizeInBits` is the number of bits in all the cells of the message.
* `bitsInRoot` is the number of bits in the root cell of the message.
The formula excludes the message root cell because it mainly contains headers. `lumpPrice` covers that root cell.
### Action fee [#action-fee]
Action fee is the portion of `fwdFee` granted to the validator of the message's source [shard](https://docs.ton.org/llms/foundations/shards/content.md). The remaining `fwdFee - actionFee` amount goes to the validator of the destination shard.
Action fee exists only for [internal messages](https://docs.ton.org/llms/foundations/messages/internal/content.md).
```cpp
action_fee = floor(fwd_fee * first_frac / 2^16)
```
Starting with Global Version 4, a failed [`SENDMSG` action](https://docs.ton.org/llms/foundations/actions/send/content.md) incurs a penalty proportional to the attempted message size. It is calculated as:
```cpp
fine_per_cell = floor((cell_price >> 16) / 4)
max_cells = floor(remaining_balance / fine_per_cell)
action_fine = fine_per_cell * min(max_cells, cells_in_msg);
```
## Import fee [#import-fee]
Import fee mirrors forward fee for inbound external messages. The root cell and its contents are covered by `lumpPrice` in the same way as internal messages.
## Helper functions (full code) [#helper-functions-full-code]
```ts expandable
import { Cell, Slice, beginCell, Dictionary, Message, DictionaryValue } from '@ton/core';
export type GasPrices = {
flat_gas_limit: bigint,
flat_gas_price: bigint,
gas_price: bigint
};
export type StorageValue = {
utime_since: number,
bit_price_ps: bigint,
cell_price_ps: bigint,
mc_bit_price_ps: bigint,
mc_cell_price_ps: bigint
};
export class StorageStats {
bits: bigint;
cells: bigint;
constructor(bits?: number | bigint, cells?: number | bigint) {
this.bits = bits !== undefined ? BigInt(bits) : 0n;
this.cells = cells !== undefined ? BigInt(cells) : 0n;
}
add(...stats: StorageStats[]) {
let cells = this.cells, bits = this.bits;
for (let stat of stats) {
bits += stat.bits;
cells += stat.cells;
}
return new StorageStats(bits, cells);
}
addBits(bits: number | bigint) {
return new StorageStats(this.bits + BigInt(bits), this.cells);
}
addCells(cells: number | bigint) {
return new StorageStats(this.bits, this.cells + BigInt(cells));
}
}
function shr16ceil(src: bigint) {
const rem = src % 65536n;
let res = src / 65536n;
if (rem !== 0n) res += 1n;
return res;
}
export function collectCellStats(cell: Cell, visited: Array, skipRoot: boolean = false): StorageStats {
let bits = skipRoot ? 0n : BigInt(cell.bits.length);
let cells = skipRoot ? 0n : 1n;
const hash = cell.hash().toString();
if (visited.includes(hash)) {
return new StorageStats();
}
visited.push(hash);
for (const ref of cell.refs) {
const r = collectCellStats(ref, visited);
cells += r.cells;
bits += r.bits;
}
return new StorageStats(bits, cells);
}
export function getGasPrices(configRaw: Cell, workchain: 0 | -1): GasPrices {
const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());
const ds = config.get(21 + workchain)!.beginParse();
if (ds.loadUint(8) !== 0xd1) throw new Error('Invalid flat gas prices tag');
const flat_gas_limit = ds.loadUintBig(64);
const flat_gas_price = ds.loadUintBig(64);
if (ds.loadUint(8) !== 0xde) throw new Error('Invalid gas prices tag');
return { flat_gas_limit, flat_gas_price, gas_price: ds.preloadUintBig(64) };
}
export function computeGasFee(prices: GasPrices, gas: bigint): bigint {
if (gas <= prices.flat_gas_limit) return prices.flat_gas_price;
return prices.flat_gas_price + (prices.gas_price * (gas - prices.flat_gas_limit)) / 65536n;
}
export const storageValue: DictionaryValue = {
serialize: (src, builder) => {
builder
.storeUint(0xcc, 8)
.storeUint(src.utime_since, 32)
.storeUint(src.bit_price_ps, 64)
.storeUint(src.cell_price_ps, 64)
.storeUint(src.mc_bit_price_ps, 64)
.storeUint(src.mc_cell_price_ps, 64);
},
parse: (src) => {
return {
utime_since: src.skip(8).loadUint(32),
bit_price_ps: src.loadUintBig(64),
cell_price_ps: src.loadUintBig(64),
mc_bit_price_ps: src.loadUintBig(64),
mc_cell_price_ps: src.loadUintBig(64)
};
}
};
export function getStoragePrices(configRaw: Cell): StorageValue {
const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());
const storageData = Dictionary.loadDirect(Dictionary.Keys.Uint(32), storageValue, config.get(18)!);
const values = storageData.values();
return values[values.length - 1];
}
export function calcStorageFee(prices: StorageValue, stats: StorageStats, duration: bigint) {
return shr16ceil((stats.bits * prices.bit_price_ps + stats.cells * prices.cell_price_ps) * duration);
}
export const configParseMsgPrices = (sc: Slice) => {
const magic = sc.loadUint(8);
if (magic !== 0xea) throw new Error('Invalid message prices magic number');
return {
lumpPrice: sc.loadUintBig(64),
bitPrice: sc.loadUintBig(64),
cellPrice: sc.loadUintBig(64),
ihrPriceFactor: sc.loadUintBig(32),
firstFrac: sc.loadUintBig(16),
nextFrac: sc.loadUintBig(16)
};
};
export type MsgPrices = ReturnType;
export const getMsgPrices = (configRaw: Cell, workchain: 0 | -1) => {
const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());
const prices = config.get(25 + workchain);
if (prices === undefined) throw new Error('No prices defined in config');
return configParseMsgPrices(prices.beginParse());
};
export function computeDefaultForwardFee(msgPrices: MsgPrices) {
return msgPrices.lumpPrice - ((msgPrices.lumpPrice * msgPrices.firstFrac) >> 16n);
}
export function computeFwdFees(msgPrices: MsgPrices, cells: bigint, bits: bigint) {
return msgPrices.lumpPrice + shr16ceil(msgPrices.bitPrice * bits + msgPrices.cellPrice * cells);
}
export function computeFwdFeesVerbose(msgPrices: MsgPrices, cells: bigint | number, bits: bigint | number) {
const fees = computeFwdFees(msgPrices, BigInt(cells), BigInt(bits));
const res = (fees * msgPrices.firstFrac) >> 16n;
return { total: fees, res, remaining: fees - res };
}
export function computeCellForwardFees(msgPrices: MsgPrices, msg: Cell) {
const storageStats = collectCellStats(msg, [], true);
return computeFwdFees(msgPrices, storageStats.cells, storageStats.bits);
}
export function computeMessageForwardFees(msgPrices: MsgPrices, msg: Message) {
if (msg.info.type !== 'internal') throw new Error('Helper intended for internal messages');
let storageStats = new StorageStats();
const defaultFwd = computeDefaultForwardFee(msgPrices);
if (msg.info.forwardFee === defaultFwd) {
return {
fees: msgPrices.lumpPrice,
res: defaultFwd,
remaining: defaultFwd,
stats: storageStats
};
}
const visited: Array = [];
if (msg.init) {
let addBits = 5n;
let refCount = 0;
if (msg.init.splitDepth) addBits += 5n;
if (msg.init.libraries) {
refCount++;
storageStats = storageStats.add(
collectCellStats(beginCell().storeDictDirect(msg.init.libraries).endCell(), visited, true)
);
}
if (msg.init.code) {
refCount++;
storageStats = storageStats.add(collectCellStats(msg.init.code, visited));
}
if (msg.init.data) {
refCount++;
storageStats = storageStats.add(collectCellStats(msg.init.data, visited));
}
if (refCount >= 2) {
storageStats = storageStats.addCells(1).addBits(addBits);
}
}
const lumpBits = BigInt(msg.body.bits.length);
const bodyStats = collectCellStats(msg.body, visited, true);
storageStats = storageStats.add(bodyStats);
let feesVerbose = computeFwdFeesVerbose(msgPrices, storageStats.cells, storageStats.bits);
if (feesVerbose.remaining < msg.info.forwardFee) {
storageStats = storageStats.addCells(1).addBits(lumpBits);
feesVerbose = computeFwdFeesVerbose(msgPrices, storageStats.cells, storageStats.bits);
}
if (feesVerbose.remaining !== msg.info.forwardFee) {
throw new Error('Forward fee calculation mismatch');
}
return { fees: feesVerbose, stats: storageStats };
}
```
# Glossary (https://docs.ton.org/llms/foundations/glossary/content.md)
## 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.)
### 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](https://docs.ton.org/llms/foundations/serialization/boc/content.md).
### 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](https://docs.ton.org/llms/onboarding/oracles/content.md).
### 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.
### Cryptobot [#cryptobot]
a peer-to-peer (P2P) bot service for buying, trading, and selling Gram 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 Gram.
### 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. Gram 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., Gram 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.
### 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. GRAM or USDT.
### 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.
### Gram [#gram]
the native cryptocurrency of the TON ecosystem, which is used to develop services and pay fees. 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.
# Blockchain limits (https://docs.ton.org/llms/foundations/limits/content.md)
This document contains the current limits and configuration parameters used in the TON blockchain.
There are two sources of network parameter definitions:
1. Blockchain config
2. Node source code
Check blockchain parameters [live in the explorers](https://tonscan.org/config). Parameters defined in the code can be found in the [source code repository](https://github.com/ton-blockchain/ton).
## Message and transaction limits [#message-and-transaction-limits]
| Name | Description | Value | Units | Type | Defined in |
| -------------------------- | ---------------------------------------------------------- | -------- | ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `max_size` | Maximum external message size in bytes | 65535 | bytes | uint32 | [`mc-config.h`:392](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L392) |
| `max_depth` | Maximum external message depth | 512 | levels | uint16 | [`mc-config.h`:393](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L393) |
| `max_msg_bits` | Maximum message size in bits | 2097152 | bits | uint32 | [`mc-config.h`:395](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L395) |
| `max_msg_cells` | Maximum number of cells a message can occupy | 8192 | cells | uint32 | [`mc-config.h`:396](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L396) |
| `max_vm_data_depth` | Maximum cell depth in messages and `c4` and `c5` registers | 512 | levels | uint16 | [`mc-config.h`:398](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L398) |
| `max_actions` | Maximum number of actions | 256 | count | uint32 | [`transaction.h`](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/transaction.h) |
| `max_library_cells` | Maximum number of library cells | 1000 | cells | uint32 | [`mc-config.h`:397](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L397) |
| `max_acc_state_cells` | Maximum number of cells that an account state can occupy | 65536 | cells | uint32 | [`mc-config.h`:400](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L400) |
| `max_acc_state_bits` | Maximum account state size in bits | 67043328 | bits | uint32 | [`mc-config.h`:401](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L401) |
| `max_acc_public_libraries` | Maximum number of public libraries per account | 256 | count | uint32 | [`mc-config.h`:402](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L402) |
## Gas and fee parameters [#gas-and-fee-parameters]
| Name | Description | Value | Units | Type | Defined in |
| ------------------- | ----------------------------------------------------------------------- | -------- | ------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- |
| `free_stack_depth` | Stack depth without gas consumption | 32 | stack entries | enum\_value | [vm.h:120](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/vm/vm.h#L120) |
| `runvm_gas_price` | VM start gas consumption | 40 | gas units | enum\_value | [vm.h:122](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/vm/vm.h#L122) |
| `flat_gas_limit` | Gas below `flat_gas_limit` is provided at the price of `flat_gas_price` | 100 | gas units | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `flat_gas_price` | Costs of launching the TON Virtual Machine | 40000 | nanograms | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_price` | Price of gas in the network in nanograms per 65536 gas units | 26214400 | nanograms | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `special_gas_limit` | Limit on gas for special (system) contract transactions | 1000000 | gas units | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_limit` | Maximum amount of gas per transaction | 1000000 | gas units | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_credit` | Gas credit for checking external messages | 10000 | gas units | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `block_gas_limit` | Maximum gas per block | 10000000 | gas units | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
## Storage fees and limits [#storage-fees-and-limits]
| Name | Description | Value | Units | Type | Defined in |
| ------------------ | ---------------------------------------------- | ---------- | -------------- | ------ | ---------------------------------------------------------- |
| `freeze_due_limit` | Storage fees (nanograms) for contract freezing | 100000000 | nanograms | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `delete_due_limit` | Storage fees (nanograms) for contract deletion | 1000000000 | nanograms | uint64 | [config21](https://docs.ton.org/llms/foundations/config/content.md) |
| `bit_price_ps` | Storage price for one bit for 65536 seconds | 1 | nanograms/bit | uint64 | [config18](https://docs.ton.org/llms/foundations/config/content.md) |
| `cell_price_ps` | Storage price for one cell for 65536 seconds | 500 | nanograms/cell | uint64 | [config18](https://docs.ton.org/llms/foundations/config/content.md) |
## Block size limits [#block-size-limits]
| Name | Description | Value | Units | Type | Defined in |
| --------------------- | -------------------------------------------- | -------- | --------- | ------ | ------------------------------------------------------------ |
| `bytes_underload` | Block size limit for underload state | 131072 | bytes | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `bytes_soft_limit` | Block size soft limit | 524288 | bytes | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `bytes_hard_limit` | Absolute maximum block size in bytes | 1048576 | bytes | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_underload` | Block gas limit for underload state | 2000000 | gas units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_soft_limit` | Block gas soft limit | 10000000 | gas units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `gas_hard_limit` | Absolute maximum block gas | 20000000 | gas units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `lt_delta_underload` | Logical time delta limit for underload state | 1000 | lt units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `lt_delta_soft_limit` | Logical time delta soft limit | 5000 | lt units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
| `lt_delta_hard_limit` | Absolute maximum logical time delta | 10000 | lt units | uint32 | [config23](https://docs.ton.org/llms/foundations/config/content.md) |
## Message forwarding costs [#message-forwarding-costs]
| Name | Description | Value | Units | Type | Defined in |
| ------------ | ---------------------------------------------------- | ---------- | -------------- | ------ | ------------------------------------------------------------- |
| `lump_price` | Base price for message forwarding | 400000 | nanograms | uint64 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
| `bit_price` | Cost per 65536 bits of message forwarding | 26214400 | nanograms/bit | uint64 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
| `cell_price` | Cost per 65536 cells for message forwarding | 2621440000 | nanograms/cell | uint64 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
| `ihr_factor` | Factor for immediate hypercube routing cost | 98304 | factor | uint32 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
| `first_frac` | Fraction for first transition in message route | 21845 | fraction | uint32 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
| `next_frac` | Fraction for subsequent transitions in message route | 21845 | fraction | uint32 | [config25](https://docs.ton.org/llms/foundations/config/content.md) |
## Masterchain specific parameters [#masterchain-specific-parameters]
| Name | Description | Value | Units | Type | Defined in |
| ------------------------ | ----------------------------------------------- | ----------- | -------------- | ------ | ------------------------------------------------------------- |
| `mc_bit_price_ps` | Storage price for one bit for 65536 seconds | 1000 | nanograms/bit | uint64 | [config18](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_cell_price_ps` | Storage price for one cell for 65536 seconds | 500000 | nanograms/cell | uint64 | [config18](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_flat_gas_limit` | Gas below `flat_gas_limit` on masterchain | 100 | gas units | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_flat_gas_price` | VM launch cost on masterchain | 1000000 | nanograms | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_price` | Gas price on masterchain | 655360000 | nanograms | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_special_gas_limit` | Special contract gas limit on masterchain | 70000000 | gas units | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_limit` | Maximum gas per transaction on masterchain | 1000000 | gas units | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_credit` | Gas credit for checking external messages | 10000 | gas units | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_block_gas_limit` | Maximum gas per masterchain block | 2500000 | gas units | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_freeze_due_limit` | Storage fees for contract freezing | 100000000 | nanograms | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_delete_due_limit` | Storage fees for contract deletion | 1000000000 | nanograms | uint64 | [config20](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_bytes_underload` | Block size limit for underload state | 131072 | bytes | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_bytes_soft_limit` | Block size soft limit | 524288 | bytes | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_bytes_hard_limit` | Absolute maximum block size in bytes | 1048576 | bytes | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_underload` | Block gas limit for underload state | 200000 | gas units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_soft_limit` | Block gas soft limit | 1000000 | gas units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_gas_hard_limit` | Absolute maximum block gas | 2500000 | gas units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_lump_price` | Base price for message forwarding | 10000000 | nanograms | uint64 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_bit_price` | Cost per 65536 bits of message forwarding | 655360000 | nanograms/bit | uint64 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_cell_price` | Cost per 65536 cells for message forwarding | 65536000000 | nanograms/cell | uint64 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_ihr_factor` | Factor for immediate hypercube routing cost | 98304 | factor | uint32 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_first_frac` | Fraction for first transition in message route | 21845 | fraction | uint32 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_next_frac` | Fraction for subsequent transitions in route | 21845 | fraction | uint32 | [config24](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_lt_delta_underload` | Logical time delta limit for underload state | 1000 | lt units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_lt_delta_soft_limit` | Logical time delta soft limit | 5000 | lt units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_lt_delta_hard_limit` | Absolute maximum logical time delta | 10000 | lt units | uint32 | [config22](https://docs.ton.org/llms/foundations/config/content.md) |
| `mc_catchain_lifetime` | masterchain catchain groups lifetime in seconds | 250 | seconds | uint32 | [config28](https://docs.ton.org/llms/foundations/config/content.md) |
## Validator parameters [#validator-parameters]
| Name | Description | Value | Units | Type | Defined in |
| --------------------------- | --------------------------------------------------- | ---------- | --------- | ------ | -------------------------------------------------------- |
| `shard_catchain_lifetime` | shardchain catchain groups lifetime in seconds | 250 | seconds | uint32 | [config28](https://docs.ton.org/llms/foundations/config/content.md) |
| `shard_validators_lifetime` | shardchain validators group lifetime in seconds | 1000 | seconds | uint32 | [config28](https://docs.ton.org/llms/foundations/config/content.md) |
| `shard_validators_num` | Number of validators in shardchain validation group | 23 | count | uint32 | [config28](https://docs.ton.org/llms/foundations/config/content.md) |
| `masterchain_block_fee` | Reward for block creation | 1700000000 | nanograms | Grams | [config14](https://docs.ton.org/llms/foundations/config/content.md) |
| `basechain_block_fee` | Basechain block fee | 1000000000 | nanograms | Grams | [config14](https://docs.ton.org/llms/foundations/config/content.md) |
## Time parameters [#time-parameters]
| Name | Description | Value | Units | Type | Defined in |
| ------------- | -------------------------------------------- | ----- | ------- | -------- | ------------------------------------------------------- |
| `utime_since` | Initial Unix timestamp for price application | 0 | seconds | UnixTime | [config18](https://docs.ton.org/llms/foundations/config/content.md) |
# Blockchain foundations overview (https://docs.ton.org/llms/foundations/overview/content.md)
## Data and serialization [#data-and-serialization]
TON stores data as graphs of cells and serializes those graphs for messages, blocks, account state, proofs, and storage.
* [TL-B](https://docs.ton.org/llms/foundations/tlb/overview/content.md): how TON data structures are defined and serialized.
* [Cells](https://docs.ton.org/llms/foundations/serialization/cells/content.md): basic storage units used by TVM, persistent storage, and smart contract code.
* [Library references](https://docs.ton.org/llms/foundations/serialization/library/content.md): cells that point to published library cells by hash.
* [Merkle proofs](https://docs.ton.org/llms/foundations/serialization/merkle/content.md): exotic cells that prove selected data belongs to a larger cell tree.
* [Merkle updates](https://docs.ton.org/llms/foundations/serialization/merkle-update/content.md): exotic cells that describe a verified transition between two cell trees.
* [Pruned branches](https://docs.ton.org/llms/foundations/serialization/pruned/content.md): compact replacements for deleted subtrees.
* [Bag of Cells](https://docs.ton.org/llms/foundations/serialization/boc/content.md): the standard format for transferring or storing cell graphs.
Read about using Merkle cells for the verification of selected blockchain data in smart contracts and off-chain software: [Proofs overview](https://docs.ton.org/llms/foundations/proofs/overview/content.md).
## Accounts and transactions [#accounts-and-transactions]
What happens to accounts before, during, and after transaction execution.
* [Addresses](https://docs.ton.org/llms/foundations/addresses/overview/content.md): how accounts are identified and how smart contracts exchange messages.
* [Messages and transactions](https://docs.ton.org/llms/foundations/messages/overview/content.md): contract execution triggers and records of the resulting account state changes.
* [Actions](https://docs.ton.org/llms/foundations/actions/overview/content.md): how smart contracts queue operations to be performed during the action phase.
* [Account status](https://docs.ton.org/llms/foundations/status/content.md): whether an account can store balance, hold code, or process transactions.
* [Execution phases](https://docs.ton.org/llms/foundations/phases/content.md): the storage, credit, compute, action, and bounce phases that can make up a transaction.
* [Transaction fees](https://docs.ton.org/llms/foundations/fees/content.md): storage, compute, import, forward, and action costs during transaction processing.
* [Traces](https://docs.ton.org/llms/foundations/traces/content.md): causally related messages and transactions grouped into one operation flow.
## Network and configuration [#network-and-configuration]
How TON scales, enforces limits, and stores network parameters.
* [Blockchain sharding](https://docs.ton.org/llms/foundations/shards/content.md): how workchains split into shardchains that process account activity in parallel.
* [Blockchain limits](https://docs.ton.org/llms/foundations/limits/content.md): maximum sizes, depths, gas values, and other network constraints.
* [Blockchain configuration](https://docs.ton.org/llms/foundations/config/content.md): values that influence validator behavior, fees, capabilities, and system contracts.
* [Web3 services](https://docs.ton.org/llms/foundations/web3/overview/content.md): TON Network, TON Storage, TON Proxy, TON DNS, and TON Sites.
* [System contracts](https://docs.ton.org/llms/foundations/system/content.md): contracts that manage validator elections and blockchain configuration.
* [Precompiled contracts](https://docs.ton.org/llms/foundations/precompiled/content.md): contracts with native implementations in validator nodes.
## Consensus [#consensus]
How validators propose blocks and vote on them to reach a consensus: [Catchain 2.0: Simplex Consensus in TON](https://docs.ton.org/llms/foundations/whitepapers/simplex/content.md).
To read about the previous version of the consensus mechanism, see:
* [Catchain 1.0 consensus](https://docs.ton.org/llms/foundations/consensus/catchain-overview/content.md)
* [Catchain 1.0 and BCP visualizer](https://docs.ton.org/llms/foundations/consensus/catchain-visualizer/content.md)
## Whitepapers [#whitepapers]
Original and modern TON whitepapers:
* [Overview](https://docs.ton.org/llms/foundations/whitepapers/overview/content.md)
* [The Open Network (TON)](https://docs.ton.org/llms/foundations/whitepapers/ton/content.md)
* [TON Virtual Machine (TON)](https://docs.ton.org/llms/foundations/whitepapers/tvm/content.md)
* [TON Blockchain](https://docs.ton.org/llms/foundations/whitepapers/tblkch/content.md)
* [Catchain consensus (legacy)](https://docs.ton.org/llms/foundations/whitepapers/catchain/content.md) — previous version of the consensus mechanism in TON
* [Catchain 2.0: Simplex Consensus in TON](https://docs.ton.org/llms/foundations/whitepapers/simplex/content.md) — currently employed consensus mechanism
# Execution phases (https://docs.ton.org/llms/foundations/phases/content.md)
When an event occurs on an account in The Open Network (TON) blockchain, it triggers a **transaction**.
The most common event is receiving a message, but other events like `tick-tock`, `merge`, and `split` can also initiate transactions.
Each transaction consists of up to five phases:
1. **Storage phase**: calculates storage fees for the contract based on the space it occupies in the blockchain state.
2. **Credit phase**: updates the contract balance by accounting for incoming message values and storage fees.
3. **Compute phase**: executes the contract code on the TON Virtual Machine (TVM). The result includes `exit_code`, `actions`, `gas_details`, `new_storage`, and other data.
4. **Action phase**: processes actions from the compute phase if it succeeds.\
Actions may include sending messages, updating contract code, or modifying libraries. If an action fails (for example, due to a lack of funds), the transaction may revert or skip the action, depending on its mode. For example, `mode = 0, flag = 2` means that any errors arising while processing this message during the action phase are ignored.
5. **Bounce phase**: If the compute phase ends with an error and the inbound message has the bounce flag set, this phase generates a bounce message. If the send\_msg action failed and it had the +16 flag set, then the bounce phase will also be triggered.
> Compute, Action and Bounce phases may be skipped
For non-bounceable messages:
Credit → Storage → Compute → Action → Bounce
For bounceable messages:
Storage → Credit → Compute → Action → Bounce
## Fee deduction sequence [#fee-deduction-sequence]
1. Import fee (before the first phase)
2. Storage fee (storage phase)
3. Gas fee (compute phase)
4. Action fee + forward fee (action phase)
5. Additional forward fees (bounce phase)
## Storage phase [#storage-phase]
Cannot be skipped.
In this phase, the blockchain processes fees related to the account's persistent storage. Let's start by looking at the TL-B schema:
```tlb
tr_phase_storage$_ storage_fees_collected:Grams
storage_fees_due:(Maybe Grams)
status_change:AccStatusChange
= TrStoragePhase;
```
The `storage_fees_due` field is of type `Maybe` because it is only present when the account has **insufficient balance** to cover the storage fees. When the account has enough funds, this field is omitted.
> Note: Grams are unsigned integers, so account balances cannot be negative.
The `AccStatusChange` field indicates whether the account's status changed during this phase. For example, see [account status variety](https://docs.ton.org/llms/foundations/status/content.md).
## Credit phase [#credit-phase]
Cannot be skipped.
This phase is relatively small and straightforward.
The main logic of this phase is to **credit the contract’s balance** with the remaining value from the incoming message.
The credit phase is serialized in TL-B as follows:
```tlb
tr_phase_credit$_ due_fees_collected:(Maybe Grams)
credit:CurrencyCollection = TrCreditPhase;
```
This phase consists of the following two fields:
| Field | Type | Description |
| -------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `due_fees_collected` | `Maybe Grams` | Amount of previously due storage fees collected (present only if storage fees were due and collected in this phase). |
| `credit` | `CurrencyCollection` | The amount credited to the account as a result of receiving the incoming message. |
## Compute phase [#compute-phase]
The **compute phase** is one of the most complex stages of a transaction. This is where the smart contract code, stored in the account’s state, is executed.
Unlike previous phases, the TL-B definition for the compute phase includes multiple variants.
```tlb
tr_phase_compute_skipped$0 reason:ComputeSkipReason
= TrComputePhase;
tr_phase_compute_vm$1 success:Bool msg_state_used:Bool
account_activated:Bool gas_fees:Grams
^[ gas_used:(VarUInteger 7)
gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3))
mode:int8 exit_code:int32 exit_arg:(Maybe int32)
vm_steps:uint32
vm_init_state_hash:bits256 vm_final_state_hash:bits256 ]
= TrComputePhase;
cskip_no_state$00 = ComputeSkipReason;
cskip_bad_state$01 = ComputeSkipReason;
cskip_no_gas$10 = ComputeSkipReason;
cskip_suspended$110 = ComputeSkipReason;
```
### When the compute phase is skipped [#when-the-compute-phase-is-skipped]
To start, note that the compute phase can be **skipped** entirely. In that case, the reason for skipping is explicitly recorded and can be one of the following:
| Skip reason | Description |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cskip_no_state` | The smart contract has no [state](https://docs.ton.org/llms/foundations/status/content.md) and, therefore, no code, so execution is not possible. |
| `cskip_bad_state` | Raised in two cases: when the `fixed_prefix_length` [field has an invalid value][fixed_prefix_length] or when the [`StateInit`](https://docs.ton.org/llms/foundations/messages/deploy/content.md) provided in the incoming message [does not match account’s address][account_address]. |
| `cskip_no_gas` | The incoming message did not provide enough Gram to cover the gas required to execute the smart contract. |
| `cskip_suspended` | The address is suspended; execution is disabled (used to limit early miner accounts). |
[fixed_prefix_length]: https://github.com/ton-blockchain/ton/blob/72056a2261cbb11f7cf0f20b389bcbffe018b1a8/crypto/block/transaction.cpp#L1721
[account_address]: https://github.com/ton-blockchain/ton/blob/72056a2261cbb11f7cf0f20b389bcbffe018b1a8/crypto/block/transaction.cpp#L1726
The `fixed_prefix_length` field can be used to specify a fixed prefix for the account address, ensuring that the account resides in a specific shard.
This topic is outside the scope of this guide, but more information is available in [Shards page](https://docs.ton.org/llms/foundations/shards/content.md).
## Action phase [#action-phase]
Once the smart contract code has finished executing, the **Action phase** begins. If any actions were created during the compute phase, they are processed at this stage.
There are precisely 4 types of actions in TON:
```tlb
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;
```
| Type | Description |
| ------------------------- | ------------------------------------------------------------------------------------------ |
| `action_send_msg` | Sends a message. |
| `action_set_code` | Updates the smart contract's code. |
| `action_reserve_currency` | Reserves a portion of the account's balance. This is especially useful for gas management. |
| `action_change_library` | Changes the library used by the smart contract. |
These actions are executed *in the order in which they were created* during code execution.
A total of up to [255 actions](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/transaction.h#L164) can be made.
Here is the TL-B schema, which defines the structure of the action phase:
```tlb
tr_phase_action$_ success:Bool valid:Bool no_funds:Bool
status_change:AccStatusChange
total_fwd_fees:(Maybe Grams) total_action_fees:(Maybe Grams)
result_code:int32 result_arg:(Maybe int32) tot_actions:uint16
spec_actions:uint16 skipped_actions:uint16 msgs_created:uint16
action_list_hash:bits256 tot_msg_size:StorageUsed
= TrActionPhase;
```
## Bounce phase [#bounce-phase]
If the **Compute phase** or **Action phase** ends with an error, and the incoming message has the `bounce` flag set, the system triggers the **Bounce phase**.
For the bounce phase to trigger due to an error in the action phase, the failed action must have **flag 16** set, which enables bounce on error.
```tlb
tr_phase_bounce_negfunds$00 = TrBouncePhase;
tr_phase_bounce_nofunds$01 msg_size:StorageUsed
req_fwd_fees:Grams = TrBouncePhase;
tr_phase_bounce_ok$1 msg_size:StorageUsed
msg_fees:Grams fwd_fees:Grams = TrBouncePhase;
```
The `tr_phase_bounce_negfunds` type is not used in the current version of the blockchain. The other two types function as follows:
| Type | Description |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `tr_phase_bounce_nofunds` | Indicates that the account does not have enough funds to process the message that should be bounced back to the sender. |
| `tr_phase_bounce_ok` | Indicates that the system successfully processes the bounce and sends the message back to the sender. |
In this phase, `msg_fees` and `fwd_fees` are calculated from the `total_fwd_fees`:\
approximately $\frac{1}{3}$ goes to `msg_fees` and $\frac{2}{3}$ go to `fwd_fees`.
> See [Fees → Forward fee](https://docs.ton.org/llms/foundations/fees/content.md) for more info.
### Key points [#key-points]
* If the receiver cannot parse the message and terminates with a non-zero exit code, the message bounces back automatically.
* The bounced message has its `bounce` flag cleared and `bounced` flag set, and contains `0xffffffff` (32-bit) opcode followed by the original message body.
* Always check the `bounced` flag before parsing `op` to avoid treating a bounce as a new query.
# Precompiled contracts (https://docs.ton.org/llms/foundations/precompiled/content.md)
A precompiled smart contract is a contract with a native C++ implementation in the validator node. When a validator processes a transaction for such a contract, it can execute this native implementation instead of TVM. This improves performance and reduces computation fees.
## Config [#config]
The list of precompiled contracts is stored in the blockchain configuration:
```tlb
precompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;
precompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;
_ PrecompiledContractsConfig = ConfigParam 45;
```
The `list:(HashmapE 256 PrecompiledSmc)` represents a mapping of contract code hash to constant gas amount. A contract is considered precompiled if its code hash exists in this map.
View current values on mainnet in [ConfigParam 45](https://tonscan.org/config#45).
## Accessing precompiled gas value [#accessing-precompiled-gas-value]
Contracts can check their precompiled gas value using the [`GETPRECOMPILEDGAS`](https://docs.ton.org/llms/tvm/instructions/content.md) opcode:
* Returns the configured `gas_usage` value if the contract code hash is in `ConfigParam 45`
* Returns `null` if the contract code hash is not in `ConfigParam 45`
The value is also available in the [`c7`](https://docs.ton.org/llms/tvm/registers/content.md) register environment tuple.
## Execution modes [#execution-modes]
When a validator processes a transaction, the execution mode depends on whether the contract code hash is listed in `ConfigParam 45`.
### Contract is not precompiled [#1-contract-is-not-precompiled]
The contract code hash is not in `ConfigParam 45`. TVM executes normally with standard gas accounting.
[`GETPRECOMPILEDGAS`](#accessing-precompiled-gas-value) returns `null`. Transaction result: `gas_used` reflects actual TVM consumption.
### Contract is precompiled [#2-contract-is-precompiled]
The contract code hash exists in `ConfigParam 45`. The validator checks the contract balance against the configured `gas_usage`. If insufficient, the compute phase fails with `cskip_no_gas`.
Otherwise, execution proceeds via one of two paths.
#### Contract has native C++ implementation [#contract-has-native-c-implementation]
The native C++ implementation is available and enabled in the validator node. The validator executes the C++ code directly without invoking TVM.
Transaction [result](https://docs.ton.org/llms/foundations/phases/content.md):
* `gas_used` set to the value from `ConfigParam 45`
* `vm_steps`, `vm_init_state_hash`, `vm_final_state_hash` set to zero
#### Contract has no native C++ implementation [#contract-has-no-native-c-implementation]
The native C++ implementation is disabled or unavailable in the validator node. TVM executes the contract code normally.
[`GETPRECOMPILEDGAS`](#accessing-precompiled-gas-value) returns the configured gas value during execution.
After execution completes, the validator overrides the compute phase values.
Transaction result:
* `gas_used` set to the value from `ConfigParam 45`
* `vm_steps`, `vm_init_state_hash`, `vm_final_state_hash` set to zero
The override ensures that both execution paths produce identical transaction results. This allows validators with and without native C++ implementations to coexist in the network and enables gradual adoption when adding new entries to `ConfigParam 45`.
## Example: Stablecoin jetton wallet [#example-stablecoin-jetton-wallet]
The jetton wallet from the [stablecoin-contract](https://github.com/ton-blockchain/stablecoin-contract) project is the first contract code hash added to `ConfigParam 45` on mainnet. This jetton wallet is optimized as a precompiled contract to reduce computation fees for stablecoin transfers.
The contract implements standard jetton wallet functionality with additional governance features. The precompiled gas logic is implemented in [`gas.fc`](https://github.com/ton-blockchain/stablecoin-contract/blob/5e1d79f4009430f2f7f255c5093a59d9a1628d75/contracts/gas.fc).
# Blockchain sharding (https://docs.ton.org/llms/foundations/shards/content.md)
TON Blockchain is a collection of blockchains that are called *workchains*. Each workchain might have different formats of [account addresses](https://docs.ton.org/llms/foundations/addresses/overview/content.md), formats of [transactions](https://docs.ton.org/llms/foundations/messages/ordinary-tx/content.md), and different virtual machines for smart contracts.
TON Blockchain dynamically splits workchains into halves when the transaction rate is above the threshold, and merges them when it decreases below the threshold. This is called *Infinite Sharding Paradigm*. [Sharding](https://en.wikipedia.org/wiki/Shard_\(database_architecture\)) is the general concept used to split the load into several parts, to ease requirements on a single computing element of some system.
Each account is the sole citizen of its corresponding blockchain, *accountchain*. Each accountchain describes the state and state transitions of only one account. An accountchain is a virtual concept used in explanations.
Regularly creating empty blocks for rarely updated accountchains would be too expensive. To reduce the cost, accountchains are grouped into *shardchains*, where each block is a collection of blocks of accountchains that have been assigned to this shard.
## Sharding process [#sharding-process]
There might be up to `2^32` workchains, identified with `workchain_id`. Each workchain might use its own format for [`account_id`](https://docs.ton.org/llms/foundations/addresses/overview/content.md), but every such ID must be at least 64-bit long. A pair of `workchain_id` and `account_id` uniquely identifies an account.
Each shardchain is identified by a pair `(workchain_id, shard_prefix)`, where `shard_prefix` is a bit string of length at most `60`. Accounts that have `account_id` starting with `shard_prefix` (have `shard_prefix` as the most significant bits) will be assigned to this shardchain.
When the volume of transactions per block exceeds the threshold, validators decide to split shards into halves.
Assume a workchain initially has one shardchain with an empty `shard_prefix`, i.e., it contains all accounts of that workchain. Then the load exceeded the threshold and the validators decide to split this shardchain into two with `shard_prefix` equal to `0` and `1`, respectively. After that, all accounts with an `account_id` starting with bit `0` will be assigned to the first shardchain, and all accounts with `account_id` starting with bit `1` will be assigned to the second shardchain.
If some shardchain with `shard_prefix` equal to `p` needs to be split, then two new shardchains with `shard_prefix` equal to `p0` and `p1` will be created.
When a merge is needed, two shardchains with `shard_prefix` equal to `p0` and `p1` merge into one shardchain with `shard_prefix` equal to `p`. After the merge, all accounts with `account_id` starting with `p` will be assigned to this new single shardchain.
As a result of sharding process, the number of shardchains in each workchain is a power of two, and can vary dynamically from `1` to `2^60`.
## Messages between shardchains [#messages-between-shardchains]
Shardchains can exchange messages with each other. It works both for shardchains of the same and different workchains.
Size of the block sets a limit to how many transactions a shardchain can process in a single block. Every shardchain can do computations asynchronously and in isolation from each other, so due to mismatch in the rate of message processing there might be an congestion: one shard sends messages to another, and it cannot process them at the moment.
During congestion, handling of messages that do not fit into current block is delayed to next blocks. Unprocessed messages are still stored only in blocks of sending shardchains, and receiving shardchain would have to check for all the possible sending shardchains for possible unprocessed messages. In the case of a large number of shardchains, the inspection time for all sending shardchains may be too long. In addition, if a shardchain can receive messages from all other shardchains, then its blocks can fill up very quickly, which will lead to a large delay in outgoing messages in the remaining shardchains.
Minimizing the time it takes to transfer data between different shardchains is crucial for complex protocols, such as token processing and decentralized exchanges (DEX). In these scenarios, different participants may be located in different shardchains, making it essential to optimize the communication process.
To reduce the number of possible sending shardchains to only `16 * 15` *neighboring shardchains*, a *hypercube routing* mechanism is used.
### Hypercube routing [#hypercube-routing]
The set of all shardchains of a given workchain and their connection to neighboring shardchains can be represented as a hypercube. Each vertex of the hypercube corresponds to a shardchain, and two shardchains are connected by an edge if they are neighbors. Omitting the technical details, the neighborhood relation is determined using the differences in the `shard_prefix` of the two shardchains. Finally, messages are routed between shardchains by moving them along the edges of such hypercube.
As a simple example, consider a workchain that has eight shardchains with `shard_prefix` equal to `000`, `001`, `010`, `011`, `100`, `101`, `110`, and `111`. These shardchains can be represented as vertices of a three-dimensional cube, where two shardchains are connected by an edge if their `shard_prefix` differ by exactly one bit. Thus, a message from `001` shardchain to `110` shardchain will be routed along the edges of the cube following the path `001 -> 101 -> 111 -> 110`. Hence, there are three hops between `001` and `110` shardchains.
TON Blockchain uses a more complex version. The hypercube has `15` dimensions, and each shardchain has up to `16` neighboring shardchains (include itself) along each dimension. Hence, each shardchain has up to `16 * 15 = 240` neighboring shardchains in total and the maximum number of hops between any two shardchains in the same workchain is `15`. If the source and destination shardchains belong to different workchains, then an additional hop between workchains is needed.
The hypercube routing mechanism also has some additional features to ensure reliability and efficiency of message delivery, such as preventing double delivery of messages, processing messages in order of their logical time creation, and so on. For a detailed acquaintance with these processes, the reader can refer to the [TON Blockchain whitepaper](https://docs.ton.org/llms/foundations/whitepapers/tblkch/content.md).
# Account status (https://docs.ton.org/llms/foundations/status/content.md)
This article describes the four possible states of an account on TON Blockchain.
Understanding these states is crucial for accurately predicting transaction outcomes and ensuring the correct deployment.
## What is the account status? [#what-is-the-account-status]
The account status is a formal indicator of what actions can occur with an account, what it can store, and whether it contains a contract code. In other words, it is one of the main factors determining the behavior of a given account during a transaction. The account status at the beginning and end of a transaction is recorded in [the corresponding TL-B block](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L285) in the fields `orig_status` and `end_status`. Thus, it allows developers to always view the current status of an account before sending it a message and restore the history of its status changes.
## Status variety [#status-variety]
Each account exists in one of the following statuses:
* **nonexist**: the default status for accounts with no transaction history or that were deleted. Contains no code, data, or balance. All 2256 accounts start in this status.
* **uninit**: holds a balance and metadata, but no code and persistent data. It cannot execute logic but retains funds (and accumulates the storage fee) until the contract code is deployed.
* **active**: contains code, data, and a balance. Fully deployed and operational, capable of processing messages.
* **frozen**: occurs when the storage debt of an active account exceeds 0.1 GRAM. Only the hashes of the previous code and data cells are preserved. While frozen, the contract cannot be executed. To unfreeze, send a message with the valid [`StateInit`](https://docs.ton.org/llms/foundations/messages/deploy/content.md) and sufficient funds for storage fees. Recovery is complex; avoid reaching this state. A project to unfreeze accounts is available [here](https://unfreezer.ton.org/).
### Why exactly these four statuses? [#why-exactly-these-four-statuses]
Although the need for the `active` and `nonexist` statuses is obvious, the purpose of the `uninit` and `frozen` statuses is not immediately clear.
**`nonexist` vs `uninit`**:
As was mentioned above, each account starts in the `nonexist` status. Besides code and persistent data, in this status, an account also has no [metadata](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L258), so it does not accumulate the storage fee. At the same time, the `uninit` status of an account indicates that some actions were performed with it and, possibly, it is prepared for deployment. So, the `uninit` account always has a [positive balance and some additional information](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L259-L260) for which it must pay a storage fee.
Sending an internal message with a valid `state_init` and proper `value` to `nonexist` account results in its deployment and the status changes to `active`. The key point is that the deployment occurs during the compute phase, which requires a suitable number of nanograms to run. But often you want to be able to deploy an account through an **external message**, to which you can also attach `state_init`, but it is impossible to attach `value`! This is also the purpose for which `uninit` exists. You can initially transfer the balance to the account via an internal message, notifying the rest of the blockchain participants of your intention to deploy an account in the future. And only then, including through an external message, to deploy.
**`frozen` vs `uninit`**:
When the active account's storage debt exceeds 0.1 GRAM, it becomes `frozen` or `uninit`. It is possible to restore the account from these statuses by paying off the debt and attaching `state_init`. If the account code and its persistent data have not changed during the lifetime of the account, then there is no problem restoring it from `uninit`. But what if they have changed? Since the `uninit` status does not allow you to store any information about the account's history, its last state will be lost forever. To prevent such situations, the `frozen` status exists.
The main difference between the `uninit` and `frozen` statuses is that in addition to metadata, the `frozen` account contains hash of the [last account state](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L268). Thus, it becomes possible to restore the last state of an account before it was frozen by sending a `state_nint` to it, whose hash matches the one recorded on the account.
## Status transitions [#status-transitions]
We present here a diagram that describes all potential changes in the account status during the receipt of internal or external messages.
### Diagram [#diagram]
In the diagram below, there are four nodes representing the four different account statuses. Each arrow and loop corresponds to a change in the account status at the end of a given transaction. The parameters in the blocks above the arrows (and loops) briefly describe what caused the transaction and also contain some fields that affect the change in the account status.
So, let's look at what changes can occur to a `nonexist` account depending on the messages that come to it.
* **Receiving external messages**: no changes.
* **Receiving internal messages**:
* **With a valid `state_init` and sufficient value**: the contract is deployed on its address that becomes `active` before processing the message.
* **Without/with invalid `state_init` or with insufficient value**: if the message is **bounceable**, then it returns to the sender, and the account status isn't changed. Otherwise, with no `value` in the message, the account status isn't changed. Finally, it becomes `uninit` if it received a valid `state_init` but insufficient nanograms or if `state_init` is absent or invalid.
With the diagram **Legend** below, you can inspect all possible changes in the account status when receiving messages with different parameters.
### Legend [#legend]
* `type`: message type.
* any;
* internal;
* external;
* `bounce`: `bounce` flag of an internal message.
* any;
* true;
* false;
* `value`: an amount of nanograms in a message.
* any;
* 0;
* \> 0.
* `state_init`: [`StateInit`](https://docs.ton.org/llms/foundations/messages/deploy/content.md) structure.
* any;
* none;
* invalid: the address computed from a given `state_init` does not match the recipient address;
* valid: the computed address matches a recipient address;
* valid last state: must be `state_init` of the last successful transaction before the account becomes frozen.
* `balance`: The account balance in nanograms after **Storage phase** of the transaction.
* 0;
* \> 0;
* \< 40000;
* \>= 40000;
* (0, 40000).
* `storage_fees_due`: the number of storage fees that were charged but could not be collected. In the diagram, this field indicates `storage_fees_due` after the **Storage phase**.
* 0;
* \< 0.1;
* \< 1;
* \>= 0.1;
* \>= 1.
* `send_dest_if_zero`: is there any outgoing message with flag 32 in **Action phase**?
* any;
* false;
* true;
* invalid: there was no **Action phase**.
* `zero_bal_after_dest_act`: Whether the account balance became zero when sending some of the messages with the flag 32. This field is meaningful only if there's at least one such message during **Action phase**.
* any;
* false;
* true.
* `action_phase_is_successful`: was **Action phase** successful?
* false;
* true.
* `account_state_changed`: has the account's state changed during its lifetime?
* false;
* true.
### Key points [#key-points]
We additionally review some important points regarding the statuses except `nonexist`.
**Sending to `uninit` account**:
* **Messages of any type without `state_init`**: changes to `nonexist` if its balance becomes zero.
* **Messages of any type with valid `state_init`**: changes to `active` if the balance is at least 40000 nanograms.
**Sending to `frozen` account**:
* **Messages of any type**: Changes to `nonexist` if its `storage_fees_due` exceeds 1 GRAM and the balance is zero.
* **Internal message with valid `state_init` (non-bounceable)**: changes to `active` if its `storage_fees_due` becomes zero.
* **Internal message with valid `state_init` (bounceable)**: changes to `active` with the same debt, and the account balance equals the message's balance minus compute and action fees.
**Sending to `active` account**:
* **Messages of any type**: changes to `frozen` if its `storage_fees_due` exceeds 0.1 GRAM and the account's state has ever changed.
* **Messages of any type**: changes to `uninit` if its `storage_fees_due` exceeds 0.1 GRAM and the account's state has never changed.
* **Messages of any type**: if in the action list there is an outgoing message with the flag 32 but **Action phase** was unsuccessful or the balance after this action is positive, the account status doesn't change.
* **Messages of any type with any `state_init`**: new `state_init` will be ignored and therefore doesn't change the account status.
**Deployment strategy**: The standard practice for deploying a wallet is to first send a non-bounceable message with Gram to its address. This transitions the account to the `uninit` status. The wallet owner can then deploy the contract in a subsequent transaction, using the pre-funded balance.
**Protection against errors**: standard wallets and applications manage these complexities by automatically setting the `bounce` flag based on the status of the destination account. Developers of custom applications must implement similar logic to prevent fund loss.
## Summary [#summary]
* The account status (`nonexist`, `uninit`, `active`, `frozen`) defines behavior.
* Correct handling of `state_init` and the `bounce` flag is crucial for successful deployment and avoiding unintended fund transfers.
* There are many cases when the account status can become `nonexist` or `frozen`. Keep track of the amount of GRAM on the account balance!
* Each new `state_init` is ignored when the account status is active.
# System contracts (https://docs.ton.org/llms/foundations/system/content.md)
These are low-level TON Blockchain internals. You typically do not need to write or deploy these contracts.
System contracts are smart contracts and have on-chain addresses. See [config parameters 1–4](https://tonscan.org/config). The Config account stores the Config contract address. To track changes, review proposals to the Config contract.
In TON, a set of special smart contracts controls consensus parameters for node operation — including TVM, catchain, fees, and chain topology — and how these parameters are stored and updated. Unlike older blockchains that hardcode these parameters, TON enables transparent on-chain governance. The current governance contracts include the **Elector** and **Config** contracts, with expansion plans (for example, the extra-currency **Minter**). Their source code is in the [governance contract repository](https://github.com/ton-blockchain/governance-contract).
## Elector [#elector]
The **Elector** smart contract manages validator elections, validation rounds, and reward distribution. To become a validator and interact with the Elector, follow the [validator instructions](https://ton.org/validator).
### Data storage [#data-storage]
The Elector stores:
* Non-withdrawn Gram in the `credits` hashmap.
* New validator applications in the `elect` hashmap.
* Past election data in the `past_elections` hashmap (including complaints and `frozen` stakes held for `stake_held_for` periods, defined in [**ConfigParam 15**](https://tonscan.org/config#15)).
### Key functions [#key-functions]
1. **Process validator applications**
2. **Conduct elections**
3. **Handle validator misbehavior reports**
4. **Distribute validation rewards**
#### Processing applications [#processing-applications]
To apply, a validator must:
1. Send a message to the Elector with their Abstract Datagram Network Layer (ADNL) address, public key, `max_factor`, and stake (GRAM amount).
2. The Elector validates the parameters and either registers the application or refunds the stake.
*Note:* Only masterchain addresses can apply.
### Conducting elections [#conducting-elections]
The Elector is a special smart contract triggered by **Tick and Tock transactions** (forced executions at the start and end of each block). It checks whether it’s time to conduct a new election during each block.
**Process details:**
* Take applications with stake ≥ `min_stake` ([**ConfigParam 17**](https://tonscan.org/config#17)).
* Arrange candidates by stake in descending order.
* If applicants exceed `max_validators` ([**ConfigParam 16**](https://tonscan.org/config#16)), discard the lowest-staked candidates.
* For each subset size `i` (from 1 to remaining candidates):
* Assume the `i`-th candidate (lowest in the subset) defines the baseline.
* Calculate effective stake (`true_stake`) for each `j`-th candidate (`j < i`) as:
```python title="Not runnable"
min(stake[i] * max_factor[j], stake[j])
```
* Track the subset with the highest **total effective stake (TES)**.
* Submit the winning validator set to the **Config** contract.
* Return unused stakes and excess amounts (e.g., `stake[j] - min(stake[i] * max_factor[j], stake[j])`) to `credits`.
**Example breakdown**:
* **Case 1**: 9 candidates stake 100,000 GRAM (`max_factor=2.7`), 1 candidate stakes 10,000.
* *Without the 10,000-stake candidate*: TES = 900,000.
* *With the 10,000-stake candidate*: TES = 9 \* 27,000 + 10,000 = 253,000.
* **Result**: 10,000-stake candidate are excluded.
* **Case 2**: 1 candidate stakes 100,000-stake (`max_factor=2.7`), 9 stake 10,000.
* Effective stake for the 100,000-stake candidate: `10,000 * 2.7 = 27,000`.
* Excess: `100,000 - 27,000 = 73,000` → sent to `credits`.
* **Result**: All 10 participate.
**Election constraints**:
* `min_validators` ≤ participants ≤ `max_validators` (**ConfigParam 16**).
* Stakes must satisfy:
* `min_stake` ≤ stake ≤ `max_stake`
* `min_total_stake` ≤ total stake ≤ `max_total_stake`
* Stake ratios ≤ `max_stake_factor` (**ConfigParam 17**).
* If conditions aren’t met, elections are **postponed**.
### Report validator misbehavior [#report-validator-misbehavior]
Each validator is periodically assigned the duty to create new blocks, with the frequency of assignments determined by their weight. After a validation round, anyone can audit the blocks to check whether the actual number of blocks produced by a validator significantly deviates from the expected number (based on their weight). A statistically significant underperformance (e.g., fewer blocks created than expected) constitutes misbehavior.
To report misbehavior, a user must:
1. Generate a **Merkle proof** demonstrating the validator's failure to produce the expected blocks.
2. Propose a fine proportional to the severity of the offense.
3. Submit the proof and fine proposal to the Elector contract, covering the associated storage costs.
The Elector registers the complaint in the `past_elections` hashmap. Current round validators then verify the complaint. If the proof is valid and the proposed fine aligns with the severity of the misbehavior, validators vote on the complaint. Approval requires agreement from over **two-thirds of the total validator weight** (not just a majority of participants).
The fine is deducted from the validator's `frozen` stake in the relevant `past_elections` record if approved. These funds stay locked for the period defined by [**ConfigParam 15**](https://tonscan.org/config#15) (`stake_held_for`).
#### Distributing rewards [#distributing-rewards]
The Elector releases `frozen` stakes and rewards (gas fees plus block rewards) proportionally to past validators. Funds move to `credits`, and the election record clears from `past_elections`.
## Config [#config]
The **Config** contract manages TON’s configuration parameters, validator set updates, and proposal voting.
### Validator set updates [#validator-set-updates]
1. The **Elector** notifies **Config** of a new validator set.
2. **Config** stores it in `ConfigParam 36` (*next validators*).
3. At the scheduled time (`utime_since`), **Config**:
* Moves the old set to `ConfigParam 32` (*previous validators*).
* Promotes `ConfigParam 36` to `ConfigParam 34` (*current validators*).
### Proposal/voting mechanism [#proposalvoting-mechanism]
1. **Submit a proposal**: Pay storage fees to propose parameter changes.
2. **Vote**: Validators (from **ConfigParam 34**) sign approval messages.
3. **Outcome**:
* **Approved**: After `min_wins` rounds (**ConfigParam 11**) with ≥3/4 weighted votes.
* **Rejected**: After `max_losses` rounds.
* *Critical parameters* (**ConfigParam 10**) require more rounds.
#### Emergency updates [#emergency-updates]
* Reserved indexes (`-999`, `-1000`, `-1001`) allow urgent updates to **Config**/**Elector** code.
* A temporary emergency key (assigned to the TON Foundation in 2021) accelerated fixes but couldn't alter contracts.
* **Key retired** on Nov 22, 2023 (**block 34312810**), replaced with zeros.
* Later patched to a fixed byte sequence (`sha256("Not a valid curve point")`) to prevent exploits.
**Historical uses**:
* **Apr 2022**: Increased gas limits (**blocks 19880281/19880300**) to unblock elections.
* **Mar 2023**: Raised `special_gas_limit` to 25M (**block 27747086**) for election throughput.
# Traces (https://docs.ton.org/llms/foundations/traces/content.md)
A trace is a partially ordered set of messages. This set includes all dependent messages. In other words, if message B was sent while message A was being processed, then both of these messages belong to exactly one trace. Strictly speaking, this set is partially ordered according to the causal relation “A is sent as a result of processing B.”
When drawing a trace, messages are usually drawn on the edges, and the addresses of the accounts to which the messages are sent are drawn at the vertices. Transactions that occurred on the account at that moment in time are also usually signed at the vertex.
### Start of the trace [#start-of-the-trace]
Most often, a trace begins with an [external message](https://docs.ton.org/llms/foundations/messages/external-in/content.md). It is the first one, since there is no message that could generate an external-in. However, trace may be started not only by external messages but also by [tick-tock transactions](https://docs.ton.org/llms/foundations/messages/overview/content.md), commonly used within TON Blockchain [system contracts](https://docs.ton.org/llms/foundations/system/content.md). Traces can also start with split and merge transactions, but since they are not currently implemented, this will not occur in a real network.
As a result, messages in the trace are partially ordered by their [logical time (lt)](https://docs.ton.org/llms/foundations/whitepapers/tblkch/content.md), reflecting their logical dependencies. The diagram shows transactions on independent accounts, each triggered by an incoming message, with `lt` values indicated for every message. It is important to note that in the network in general, lt is formed as follows:
* lt transactions = lt incoming message + 1
* lt outgoing message = lt transaction + outgoing message index
This scheme is not applicable to the first vertex if the trace is started by special transactions mentioned above, as in that case there is no `incoming message` for the first vertex.
## Representation in explorers [#representation-in-explorers]
In explorers, traces are visualized as [directed acyclic graphs (DAGs)](https://en.wikipedia.org/wiki/Directed_acyclic_graph), where *transactions are nodes* and *messages are edges*, showing the full sequence of account state changes.
## Examples [#examples]
The NFT transfer illustrates a single operation that consists of multiple messages.
This trace is started with an external message and [can be inspected](https://tonscan.org/tx/47d0989633fc03ff3fdca05880ab5760d0321c196501a6a4cbb5578dea2624cb#details):
Here is the [example](https://tonscan.org/tx/9effb91e18be732033fe6aa8c39941f26f5e9566848bc487aa7c6bfecdd9d89d#details) of the trace that started with tick-tock transaction:
## Access using API [#access-using-api]
To fetch traces data, use the [`GET /traces`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-traces/content.md) endpoint. This method allows finding a trace if any of its parameters are known.
# Blockchain nodes overview (https://docs.ton.org/llms/nodes/overview/content.md)
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. |
Learn more about the [staking in TON](https://docs.ton.org/llms/nodes/staking/overview/content.md).
## 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](https://docs.ton.org/llms/api/overview/content.md) or other [RPC providers](https://docs.ton.org/llms/api/overview/content.md) 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](https://docs.ton.org/llms/nodes/cpp/setup-mytonctrl/content.md) 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](https://docs.ton.org/llms/nodes/cpp/setup-mytonctrl/content.md) with liteserver option (and archive mode if needed) to expose API for applications. |
| An isolated development network | [Setting up a local blockchain using MyLocalTon](https://docs.ton.org/llms/nodes/cpp/setup-mylocalton/content.md) to spin up a local shard, explorer, and APIs for rapid iterations with no mainnet impact. |
## 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 GRAM for successful participation in the validation process.
To be entitled to propose and validate blocks, other participants elect validators based on the amount of GRAM they hold — in other words, their *stake*. The more GRAM 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 GRAM 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](https://docs.ton.org/llms/nodes/cpp/setup-mytonctrl/content.md).
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](https://docs.ton.org/llms/applications/sdks/content.md), 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](https://docs.ton.org/llms/api/overview/content.md) is an official HTTP API provider, and its API endpoints can be used directly or [self-hosted](https://docs.ton.org/llms/api/overview/content.md). In the [SDK table](https://docs.ton.org/llms/applications/sdks/content.md), libraries that use these endpoints or other HTTP providers have a mark in the HTTP column.
# Network status (https://docs.ton.org/llms/nodes/status/content.md)
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. |
# Analytics and data providers (https://docs.ton.org/llms/onboarding/analytics/content.md)
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, one needs 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 getting 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 working 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/re-doubt/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](https://docs.ton.org/llms/foundations/serialization/cells/content.md) 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 when building an estimation of assets denominated in GRAM 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 GRAM 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 GRAM and Jettons.
All tables mentioned above are updated daily.
### Getting started with Dune [#getting-started-with-dune]
To get started, read:
* [Quick start with TON data on Dune](https://dune.com/ton_foundation/ton-quick-start)
* [Official Dune documentation](https://docs.dune.com/)
For inspiration for custom dashboards, check out these examples:
* [Application activity](https://dune.com/ton_foundation/application-activity)
* [TON & Ethena Boost Rewards Campaign](https://dune.com/ton_foundation/tonandethena-staking-rewards-campaign)
* [Telegram Gifts dashboard](https://dune.com/rdmcd/telegram-gifts)
## 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.
Deploy it on the personal 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, one cannot rely on the opcode alone since anyone can generate messages with that 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, prepare a relevant PR on GitHub [to TON-ETL's repo](https://github.com/re-doubt/ton-etl). Use those past PRs as a reference: [186](https://github.com/re-doubt/ton-etl/pull/186), [171](https://github.com/re-doubt/ton-etl/pull/171), [144](https://github.com/re-doubt/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/re-doubt/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, deploy the infrastructure by:
1. Running a [TON node](https://docs.ton.org/llms/nodes/overview/content.md)
2. Launching [TON-ETL](https://github.com/re-doubt/ton-etl/blob/main/README.md)
3. Setting up [`ton-index-worker`](https://github.com/toncenter/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.
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]
* [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 (https://docs.ton.org/llms/onboarding/bridges/content.md)
In the TON ecosystem, bridges allow users to transfer assets and data between TON and other major blockchains like Ethereum, BNB Chain, and Polygon.
## 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]
#### 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
#### 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 Gram into other networks:
* **ETH-TON Bridge** ([Config Parameter 71](https://docs.ton.org/llms/foundations/config/content.md))
* **BNB-TON Bridge** ([Config Parameter 72](https://docs.ton.org/llms/foundations/config/content.md))
* **Polygon-TON Bridge** ([Config Parameter 73](https://docs.ton.org/llms/foundations/config/content.md))
#### Inbound bridges (config parameters 79, 81-82) [#inbound-bridges-config-parameters-79-81-82]
These bridges wrap tokens from other networks into Gram:
* **ETH-TON Bridge** ([Config Parameter 79](https://docs.ton.org/llms/foundations/config/content.md))
* **BNB-TON Bridge** ([Config Parameter 81](https://docs.ton.org/llms/foundations/config/content.md))
* **Polygon-TON Bridge** ([Config Parameter 82](https://docs.ton.org/llms/foundations/config/content.md))
You can read more about these bridge configuration parameters on the [TON Config page](https://docs.ton.org/llms/foundations/config/content.md).
### Third-party bridge ecosystem [#third-party-bridge-ecosystem]
The TON ecosystem features multiple bridge providers offering different features and supported networks. Look up statistics for existing bridges on the [Bridge Dashboard](https://dune.com/ton_foundation/bridges).
# Explorers overview (https://docs.ton.org/llms/onboarding/explorers/content.md)
Explorers are web tools designed for reading blockchain data, allowing users to look up accounts, transactions, blocks, and smart contracts. They provide a searchable user interface (UI) that indexes on-chain data, making it easy to verify activity and debug issues.
## What explorers show [#what-explorers-show]
In TON, explorers typically display account balances, transactions, tokens, contract code and state, as well as links to related blocks and messages.
More precisely, explorers show:
* Balances and assets: Grams, jettons (FTs), and NFTs held by an address
* Transactions and messages: history, fees, phases, and traces
* Blocks and validators: block contents, masterchain and shardchain details
* Smart contracts: code, state, disassembly, and known contract type
* Analytics: top entities, volumes, gas, fees, and network health
## Indexers [#indexers]
Indexers such as [TON Center API v3](https://docs.ton.org/llms/api/v3/overview/content.md) continuously read blocks from nodes, parse messages and transactions, and store them in a database optimized for queries. Explorers rely on these indexers to provide fast search, traces, higher-level events, and historical views beyond what a single node exposes by default.
## Examples [#examples]
[TON explorer](https://explorer.toncoin.org/) is a low-level developer-oriented explorer that displays transactions and blocks. It works on [mainnet](https://explorer.toncoin.org/) and [testnet](https://test-explorer.toncoin.org).
Discover other [TON explorers](https://duckduckgo.com/?q=ton+explorer).
# Oracles overview (https://docs.ton.org/llms/onboarding/oracles/content.md)
Blockchain oracles are entities that connect the blockchain to external systems, allowing smart contracts to be executed based on real-world inputs.
## How blockchain oracles work [#how-blockchain-oracles-work]
Blockchain oracles are specialized services that act as bridges between the real world and blockchain technology. They provide smart contracts with relevant and necessary information from the outside world, such as exchange rates, payment statuses, or even weather conditions. This data helps to automate and fulfill the terms of contracts without direct human intervention.
The basic principle behind oracles is their ability to function outside of the blockchain by connecting to various online sources to collect data. Although oracles are not part of the blockchain itself, they play a key role in making it functional by acting as a trusted intermediary that reliably feeds external data into the system.
Most oracles tend to be decentralized, avoiding the risks associated with dependence on a single source of data. This provides greater security and reliability to the system as data is verified and validated through a network of nodes before it is used in smart contracts. This approach minimizes the risk of manipulation and errors, ensuring that the information provided is accurate and up-to-date.
## Varieties of blockchain oracles [#varieties-of-blockchain-oracles]
Blockchain oracles are categorized according to various aspects: mechanism of operation, data sources, data direction, and governance structure.
### Push and pull oracles [#push-and-pull-oracles]
Push and pull oracles differ in how they deliver data to an on-chain smart contract.
For push oracle, the data provider constantly updates info, *pushing* the newest data to the centralized trusted contract.
Read more about oracle model differences: [ChainLink - Pull vs Push oracles](https://chain.link/education-hub/pull-oracles-vs-push-oracles).
For pull oracle, users should retrieve the latest data from the off-chain data provider themselves, then verify it using the oracle contract. [Learn more](#oracles-in-ton) about data verification flow with pull model oracles.
Given TON actor-model, pull oracles prove to be more suited for real world applications.
### Centralized and decentralized oracles [#centralized-and-decentralized-oracles]
Centralized oracles are controlled by a single party, which creates security and reliability risks. Decentralized oracles use multiple nodes to verify data, making them more secure and reliable.
### Cross-chain oracles [#cross-chain-oracles]
These oracles are used to transfer data between different blockchains and are a critical component of bridges. They are used for decentralized applications that use cross-chain transactions, such as cross-chain transfer of crypto assets from one network to another.
## Application of blockchain oracles [#application-of-blockchain-oracles]
Blockchain oracles build bridges between the digital world of blockchains and real life, opening up a wide range of applications. Let's take a look at some of the most popular uses of oracles.
### DeFi (decentralized finance) [#defi-decentralized-finance]
Oracles play a critical role in the DeFi ecosystem by providing market price and cryptocurrency data. Price oracles allow DeFi platforms to link token values to real assets, which is essential for controlling liquidity and securing users' positions. Additionally, oracles are vital for lending platforms, where accurate price data ensures proper collateral valuation and risk management, safeguarding both lenders and borrowers. This makes transactions more transparent and secure, contributing to the stability and reliability of financial transactions.
### Prediction markets [#prediction-markets]
Oracles can automatically read and analyze data from a variety of sources to determine the occurrence of real-life events. This enables prediction and insurance contracts to automatically pay claims, reducing the need for manual processing of each case and speeding up response times to events.
### Random number generation [#random-number-generation]
It is difficult to generate random numbers in smart contracts because all operations must be reproducible and predictable, which contradicts the concept of randomness. Computational oracles solve this problem by bringing data from the outside world into contracts. They can generate verifiable random numbers for games and lotteries, ensuring fairness and transparency of results.
Read more: [Randomness in TON](https://docs.ton.org/llms/contracts/techniques/random/content.md)
## Oracles in TON [#oracles-in-ton]
Since the TON execution model is asynchronous, the classic ways to interact with oracles, e.g., get methods during a transaction, [cannot be applied here](https://docs.ton.org/llms/from-ethereum/content.md). The best pattern to retrieve data from an oracle on TON is the Request-Response pattern - you send an internal message to the oracle contract and verify the response, getting the needed data.
This model works well with pull oracles, since one can always guarantee the lowest possible latency for real-world data. If you use a push oracle, you will still need to process two internal messages (request and response) to retrieve data. However, data relevance is limited by the data provider's uptime and pushing intervals. If the data provider pushes updates every 10 minutes, you will commonly receive information that is 5 minutes outdated. But using pull oracle, you can ensure pushes as often as your service needs by updating the data yourself.
### Push oracle flow [#push-oracle-flow]
0. Data provider pushes the latest data on-chain
1. The user contract, which needs prices on-chain, sends a request message to the trusted oracle contract
2. Oracle contract replies to the sender address with a response internal message, containing the requested data
3. User contract receives oracle response, verifies sender address, and then is ready to use the provided data
### Pull oracle flow [#pull-oracle-flow]
1. Users' off-chain backend calls the API method on the data provider
2. Provider responds with signed price data (including timestamp till this data is valid)
3-4. User sends a message to his on-chain contract that will need prices (and the rest of the business logic)
5. User contract sends "Verify that this price is correctly signed and valid" internal message to the oracle contract
6. Oracle contract verifies signature, timestamp, and price feed ID. If everything is okay, it sends a response with the prices back
7. User contract receives a response from the oracle contract, checks if the sender is really the oracle, and then can use the provided data
# Basic syntax (https://docs.ton.org/llms/tolk/basic-syntax/content.md)
## Imports [#imports]
[Imports](https://docs.ton.org/llms/tolk/syntax/imports/content.md) must appear at the top of the file:
```tolk
import "another-file"
// Symbols from `another-file.tolk` become available in this file.
```
In most workflows, the IDE adds imports automatically. For example, when selecting an item from auto-completion.
The entire file is imported. There are no modules or exports; all symbols must have unique names within the project.
## Structures [#structures]
A [struct](https://docs.ton.org/llms/tolk/syntax/structures-fields/content.md) `Point` holding two 8-bit integers:
```tolk
struct Point {
x: int8
y: int8
}
fun demo() {
// create an object
val p1: Point = { x: 10, y: 20 };
// the same, type of p2 is auto-inferred
val p2 = Point { x: 10, y: 20 };
}
```
* Methods are declared as `fun Point.method(self)`.
* Fields can use any [types](https://docs.ton.org/llms/tolk/types/list-of-types/content.md): numeric, cell, union, and others.
* Fields can define default values: `x: int8 = 0`.
* Fields can be `private` and `readonly`.
* Structs can be generic: `struct Wrapper { ... }`.
If all fields are serializable, a struct can be [automatically serialized](https://docs.ton.org/llms/tolk/features/auto-serialization/content.md):
```tolk
// makes a cell containing hex "0A14"
val c = p1.toCell();
// back to { x: 10, y: 20 }
val p3 = Point.fromCell(c);
```
## Functions [#functions]
A [function](https://docs.ton.org/llms/tolk/syntax/functions-methods/content.md) that returns the sum of two integers:
```tolk
fun sum(a: int, b: int): int {
return a + b;
}
```
* Parameter types are mandatory.
* The return type can be omitted: it is auto-inferred.
* Parameters can define default values: `fun f(b: int = 0)`
* Statements in a block are separated by semicolons `;`.
* Generic functions are supported: `fun f(value: T) { ... }`
* Assembler functions are supported: `fun f(...): int asm "..."`
## Methods [#methods]
A function declared as `fun .name(...)` is a [method](https://docs.ton.org/llms/tolk/syntax/functions-methods/content.md).
* If the first parameter is `self`, it's an instance method.
* If the first parameter is not `self`, it's a static method.
```tolk
// `self` — instance method (invoked on a value)
fun Point.sumCoords(self) {
return sum(self.x, self.y);
}
// not `self` — static method
fun Point.createZero(): Point {
return { x: 0, y: 0 };
}
fun demo() {
val p = Point.createZero(); // { 0, 0 }
return p.sumCoords(); // 0
}
```
By default, `self` is immutable; `mutate self` allows modifying the object.
Methods can be declared for any type, including primitives:
```tolk
fun int.isNegative(self) {
return self < 0
}
```
## Variables [#variables]
Within functions, [variables](https://docs.ton.org/llms/tolk/syntax/variables/content.md) are declared with `val` or `var` keywords. The `val` keyword declares an immutable variable that can be assigned only once:
```tolk
val coeff = 5;
// cannot change its value, `coeff += 1` is an error
```
The `var` keyword declares a variable that can be reassigned:
```tolk
var x = 5;
x += 1; // now 6
```
A variable’s type can be specified after its name:
```tolk
var x: int8 = 5;
```
Declaring variables at the top level, outside functions, is supported using the `global` keyword.
## Constants [#constants]
Constants can be declared only at the top level, not inside functions:
```tolk
const ONE = 1
const MAX_AMOUNT = grams("0.05")
const ADMIN_ADDRESS = address("EQ...")
```
To group integer constants, [enums](https://docs.ton.org/llms/tolk/types/enums/content.md) are useful.
## Value semantics [#value-semantics]
Tolk follows value semantics: assignments create independent copies, and function calls do not [mutate](https://docs.ton.org/llms/tolk/syntax/mutability/content.md) arguments unless explicitly specified.
```tolk
var a = Point { x: 1, y: 2 };
var b = a; // `b` is a copy
b.x = 99; // `a.x` remains 1
someFn(a); // pass a copy; `a` will not change
// but there can be mutating functions, called this way:
anotherFn(mutate a);
```
## Semicolons [#semicolons]
* Semicolons are optional at the top level, after imports, aliases, etc.
* Semicolons are required between statements in a function.
* After the last statement in a block, a semicolon is optional.
```tolk
// optional at the top-level
const ONE = 1
type UserId = int
// required inside functions
fun demo() {
val x = 5;
val y = 6;
return x + y // optional after the last statement
}
```
## Comments [#comments]
Tolk supports single-line or end-of-line and multi-line or block comments:
```tolk
// This is a single-line comment
/* This is a block comment
across multiple lines. */
const TWO = 1 /* + 100 */ + 1 // 2
```
## Conditional operators [#conditional-operators]
In [conditions](https://docs.ton.org/llms/tolk/syntax/conditions-loops/content.md), `if` is a statement. `else if` and `else` blocks are optional.
```tolk
fun sortNumbers(a: int, b: int) {
if (a > b) {
return (b, a)
} else {
return (a, b)
}
}
```
A ternary operator is also available:
```tolk
val sign = a > 0 ? 1 : a < 0 ? -1 : 0;
```
## Union types and matching [#union-types-and-matching]
[Union types](https://docs.ton.org/llms/tolk/types/unions/content.md) allow a variable to hold one of possible types. They are typically handled by `match`:
```tolk
fun processValue(value: int | slice) {
match (value) {
int => {
value * 2
}
slice => {
value.loadUint(8)
}
}
}
```
Alternatively, test a union with `is` or `!is` operators:
```tolk
fun processValue(value: int | slice) {
if (value is slice) {
// call methods for `slice`
return;
}
// value is `int`
return value * 2;
}
```
Union types are commonly used when [handling incoming messages](https://docs.ton.org/llms/tolk/features/message-handling/content.md).
## While loop [#while-loop]
Tolk does not have a `for` loop; use [`while` loop](https://docs.ton.org/llms/tolk/syntax/conditions-loops/content.md) for repeated execution.
```tolk
while (i > 0) {
// ...
i -= 1;
}
```
## Assert and throw [#assert-and-throw]
The `try-catch` statement is supported for [exceptions](https://docs.ton.org/llms/tolk/syntax/exceptions/content.md), although it is not commonly used in contracts.
```tolk
const ERROR_NO_BALANCE = 403;
// in some function
throw ERROR_NO_BALANCE;
// or conditional throw
assert (balance > 0) throw ERROR_NO_BALANCE;
```
## Arrays [#arrays]
[Arrays](https://docs.ton.org/llms/tolk/types/tuples/content.md) are dynamically sized containers created with `[...]`:
```tolk
var numbers = [1, 2, 3]; // array
numbers.push(4);
numbers.get(0); // 1
```
## Iterate over a map [#iterate-over-a-map]
To iterate, [maps](https://docs.ton.org/llms/tolk/types/maps/content.md) can be used:
```tolk
fun iterateOverMap(m: map) {
var r = m.findFirst();
while (r.isFound) {
// ...
r = m.iterateNext(r);
}
}
```
## Send a message to another contract [#send-a-message-to-another-contract]
To [construct and send a message](https://docs.ton.org/llms/tolk/features/message-sending/content.md), a message body is typically represented by a structure. For example, `RequestedInfo`:
```tolk
val reply = createMessage({
bounce: BounceMode.NoBounce,
value: grams("0.05"),
dest: someAddress,
body: RequestedInfo { ... }
});
reply.send(SEND_MODE_REGULAR);
```
## Contract getters [#contract-getters]
[Contract getters](https://docs.ton.org/llms/tolk/features/contract-getters/content.md) or get-methods are declared with `get fun`:
```tolk
get fun currentOwner() {
val storage = lazy Storage.load();
return storage.ownerAddress;
}
```
# Changelog (https://docs.ton.org/llms/tolk/changelog/content.md)
## [v1.4](https://github.com/ton-blockchain/ton/pull/2357) [#v14]
1. ABI export — for toolchain, explorers, UI
2. TypeScript wrappers for Tolk contracts
3. Source maps that map TVM execution back to Tolk source, variables, stack layout, and call frames
4. Debugger marks that enable step-by-step debugging of fully-optimized production contracts
5. Several language enhancements (continue the direction of a general-purpose language)
## [v1.3](https://github.com/ton-blockchain/ton/pull/2234) [#v13]
1. Introduced `array` — dynamically sized arrays backed by TVM tuples.
2. Introduced the `unknown` type — a TVM primitive with unknown contents.
3. Introduced `lisp_list` — nested two-element tuples (FunC-style).
4. Introduced the `string` type — a dedicated string type backed by snaked cells, with `StringBuilder` for concatenation.
5. Compile-time string functions became methods: `"str".crc32()`, `"str".sha256()`, etc.
6. Allowed `[]` to create empty maps, deprecating `createEmptyMap`.
7. Added the null coalescing operator `??`.
8. Added import path mappings (`@alias` → directory).
9. Added compile-time reflection via `@stdlib/reflection`.
10. Extended custom serializers (`packToBuilder`/`unpackFromSlice`) to structures and generics.
11. The compiler can now report multiple errors at once.
## [v1.2](https://github.com/ton-blockchain/ton/pull/1886) [#v12]
1. Introduced `address` as "internal only".
2. Delivered rich bounces: return the full body instead of 256 bits.
3. Provided low-cost builder-to-slice, `StateInit`, and address composition.
4. Improved compilation errors.
5. Added support for anonymous functions.
6. Added the borrow checker and related undefined-behavior checks.
## [v1.1](https://github.com/ton-blockchain/ton/pull/1795) [#v11]
1. Added `map` — a wrapper over TVM dictionaries.
2. Added `enum` — group numeric constants into a distinct type.
3. Added `private` and `readonly` fields in structures.
4. Enhanced overload resolution and partial specialization.
## [v1.0](https://github.com/ton-blockchain/ton/pull/1741) [#v10]
1. Added the `lazy` keyword.
2. Added auto-detect and inline functions at the compiler level.
3. Added various peephole optimizations for gas efficiency.
4. Added `onInternalMessage` and `onBouncedMessage`, TVM 11 support.
5. Added custom pack and unpack serializers for custom types.
## [v0.99](https://github.com/ton-blockchain/ton/pull/1707) [#v099]
1. Added `createMessage`.
2. Added `createExternalLogMessage`.
3. Added sharding support for calculating addresses "close to another contract".
## [v0.13](https://github.com/ton-blockchain/ton/pull/1694) [#v013]
1. Added auto-packing `to` and `from` `cells`, `builders`, and `slices`.
2. Added type `address`.
3. Added Lateinit variables.
4. Added defaults for parameters.
## [v0.12](https://github.com/ton-blockchain/ton/pull/1645) [#v012]
1. Added structures `struct A { ... }`.
2. Added generics `struct` and `type`.
3. Added methods `fun Point.getX(self)`.
4. Renamed stdlib functions to short methods.
## [v0.11](https://github.com/ton-blockchain/ton/pull/1610) [#v011]
1. Added type aliases `type NewName = `.
2. Added union types `T1 | T2 | ...`.
3. Added pattern matching for types.
4. Added the `is` and `!is` operators.
5. Added pattern matching for expressions.
6. Allowed the semicolon to be omitted for the last statement in a block.
## [v0.10](https://github.com/ton-blockchain/ton/pull/1559) [#v010]
1. Added fixed-width integers such as `int32` and `uint64`.
2. Added the `coins` type and the `ton("0.05")` function.
3. Added `bytesN` and `bitsN` types backed by slices at the TVM level.
4. Replaced `"..."c` postfixes with `stringCrc32("...")` functions.
5. Added support `0b...` number literals in addition to `0x...`.
6. Added support trailing commas.
## [v0.9](https://github.com/ton-blockchain/ton/pull/1545) [#v09]
1. Added nullable types `int?`, `cell?`, and others; introduce null safety.
2. Updated the standard library, including`asm` definitions, to support nullability.
3. Introduced smart casts, like in TypeScript and Kotlin.
4. Added the `!` operator (non-null assertion).
5. Treated code after `throw` as unreachable.
6. Added the `never` type.
## [v0.8](https://github.com/ton-blockchain/ton/pull/1503) [#v08]
1. Introduced syntax `tensorVar.0` and `tupleVar.0` for reading and writing.
2. Allowed `cell`, `slice`, and similar terms to be used as valid identifiers rather than keywords.
## [v0.7](https://github.com/ton-blockchain/ton/pull/1477) [#v07]
1. Refactored compiler internals and introduce an AST-level semantic analysis kernel.
2. Changed the type system to static typing.
3. Provided clear and readable error messages for type mismatch.
4. Added generic functions `fun f(...)` and instantiations such as `f(...)`.
5. Added `bool` type and type casting through `value as T`.
## [v0.6](https://github.com/ton-blockchain/ton/pull/1345) [#v06]
The first public release.
Tolk is a fork of FunC with iterative improvements. In 2024, a pull request for [FunC v0.5.0](https://github.com/ton-blockchain/ton/pull/1026) was submitted together with a roadmap for further development. Instead of merging it, it was forked.
Tolk was first announced at [TON Gateway](https://www.youtube.com/watch?v=Frq-HUYGdbI) in 2024.
The released version was marked v0.6, indicating its relation to the FunC v0.5.
# Tolk contract examples (https://docs.ton.org/llms/tolk/examples/content.md)
Basic jetton and NFT contract examples from [`ton-blockchain/tolk-bench`](https://github.com/ton-blockchain/tolk-bench), extracted from commit [`cb9648b`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9), appear here as accordions by source file.
All examples are given for educational purposes only. Never apply them directly in production without prior testing.
For reference-grade Tolk contracts, see the [`ton-blockchain/acton-contracts`](https://github.com/ton-blockchain/acton-contracts) repository.
## Jetton [#jetton]
Source directory: [`contracts_Tolk/01_jetton`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9/contracts_Tolk/01_jetton).
Some files in the source directory are not runnable on their own and depend on others. Keep all the listed files together.
```tolk
const ERR_INVALID_OP = 709
const ERR_NOT_FROM_ADMIN = 73
const ERR_UNAUTHORIZED_BURN = 74
const ERR_NOT_ENOUGH_AMOUNT_TO_RESPOND = 75
const ERR_NOT_FROM_OWNER = 705
const ERR_NOT_ENOUGH_TON = 709
const ERR_NOT_ENOUGH_GAS = 707
const ERR_INVALID_WALLET = 707
const ERR_WRONG_WORKCHAIN = 333
const ERR_NOT_ENOUGH_BALANCE = 706
const ERR_INVALID_PAYLOAD = 708
```
```tolk
// 6905(computational_gas_price) * 1000(cur_gas_price) = 6905000 ~= 0.01 GRAM
const MINIMAL_MESSAGE_VALUE_BOUND = grams("0.01")
const MIN_GRAMS_FOR_STORAGE = grams("0.01")
const JETTON_WALLET_GAS_CONSUMPTION = grams("0.015")
```
```tolk
struct WalletStorage {
jettonBalance: coins
ownerAddress: address
minterAddress: address
}
struct MinterStorage {
totalSupply: coins
adminAddress: address
content: cell
jettonWalletCode: cell
}
fun MinterStorage.load() {
return MinterStorage.fromCell(contract.getData())
}
fun MinterStorage.save(self) {
contract.setData(self.toCell())
}
fun WalletStorage.load() {
return WalletStorage.fromCell(contract.getData())
}
fun WalletStorage.save(self) {
contract.setData(self.toCell())
}
```
```tolk
type ForwardPayloadRemainder = RemainingBitsAndRefs
struct (0x0f8a7ea5) AskToTransfer {
queryId: uint64
jettonAmount: coins
transferRecipient: address
sendExcessesTo: address?
customPayload: cell?
forwardGrams: coins
forwardPayload: ForwardPayloadRemainder
}
struct (0x7362d09c) TransferNotificationForRecipient {
queryId: uint64
jettonAmount: coins
transferInitiator: address?
forwardPayload: ForwardPayloadRemainder
}
struct (0x178d4519) InternalTransferStep {
queryId: uint64
jettonAmount: coins
// is null when minting (not initiated by another wallet)
transferInitiator: address?
sendExcessesTo: address?
forwardGrams: coins
forwardPayload: ForwardPayloadRemainder
}
struct (0xd53276db) ReturnExcessesBack {
queryId: uint64
}
struct (0x595f07bc) AskToBurn {
queryId: uint64
jettonAmount: coins
sendExcessesTo: address?
customPayload: cell?
}
struct (0x7bdd97de) BurnNotificationForMinter {
queryId: uint64
jettonAmount: coins
burnInitiator: address
sendExcessesTo: address?
}
struct (0x2c76b973) RequestWalletAddress {
queryId: uint64
ownerAddress: address
includeOwnerAddress: bool
}
struct (0xd1735400) ResponseWalletAddress {
queryId: uint64
jettonWalletAddress: address?
ownerAddress: Cell?
}
struct (0x00000015) MintNewJettons {
queryId: uint64
mintRecipient: address
gramAmount: coins
internalTransferMsg: Cell
}
struct (0x00000003) ChangeMinterAdmin {
queryId: uint64
newAdminAddress: address
}
struct (0x00000004) ChangeMinterContent {
queryId: uint64
newContent: cell
}
```
```tolk
import "storage"
fun calcDeployedJettonWallet(
ownerAddress: address,
minterAddress: address,
jettonWalletCode: cell,
): AutoDeployAddress {
val emptyWalletStorage: WalletStorage = {
jettonBalance: 0,
ownerAddress,
minterAddress,
};
return {
stateInit: {
code: jettonWalletCode,
data: emptyWalletStorage.toCell(),
}
}
}
fun calcAddressOfJettonWallet(
ownerAddress: address,
minterAddress: address,
jettonWalletCode: cell,
) {
val jwDeployed = calcDeployedJettonWallet(
ownerAddress,
minterAddress,
jettonWalletCode,
);
return jwDeployed.calculateAddress()
}
```
```tolk
import "@stdlib/gas-payments"
import "errors"
import "jetton-utils"
import "messages"
import "storage"
import "fees-management"
type AllowedMessageToMinter =
| MintNewJettons
| BurnNotificationForMinter
| RequestWalletAddress
| ChangeMinterAdmin
| ChangeMinterContent
fun onInternalMessage(in: InMessage) {
val msg = lazy AllowedMessageToMinter.fromSlice(in.body);
match (msg) {
BurnNotificationForMinter => {
var storage = lazy MinterStorage.load();
assert (in.senderAddress ==
calcAddressOfJettonWallet(
msg.burnInitiator,
contract.getAddress(),
storage.jettonWalletCode,
)) throw ERR_UNAUTHORIZED_BURN;
storage.totalSupply -= msg.jettonAmount;
storage.save();
if (msg.sendExcessesTo == null) {
return;
}
val excessesMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: msg.sendExcessesTo,
value: 0,
body: ReturnExcessesBack {
queryId: msg.queryId
}
});
excessesMsg.send(
SEND_MODE_IGNORE_ERRORS +
SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE
);
}
RequestWalletAddress => {
assert (in.valueCoins >
in.originalForwardFee + MINIMAL_MESSAGE_VALUE_BOUND)
throw ERR_NOT_ENOUGH_AMOUNT_TO_RESPOND;
var respondOwnerAddress: Cell? = msg.includeOwnerAddress
? msg.ownerAddress.toCell()
: null;
var walletAddress: address? = null;
if (msg.ownerAddress.getWorkchain() == BASECHAIN) {
var storage = lazy MinterStorage.load();
walletAddress = calcAddressOfJettonWallet(
msg.ownerAddress,
contract.getAddress(),
storage.jettonWalletCode,
);
}
val respondMsg = createMessage({
bounce: BounceMode.Only256BitsOfBody,
dest: in.senderAddress,
value: 0,
body: ResponseWalletAddress {
queryId: msg.queryId,
jettonWalletAddress: walletAddress,
ownerAddress: respondOwnerAddress,
}
});
respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}
MintNewJettons => {
var storage = lazy MinterStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERR_NOT_FROM_ADMIN;
var internalTransferMsg = lazy msg.internalTransferMsg.load();
storage.totalSupply += internalTransferMsg.jettonAmount;
storage.save();
val deployMsg = createMessage({
bounce: BounceMode.Only256BitsOfBody,
dest: calcDeployedJettonWallet(
msg.mintRecipient,
contract.getAddress(),
storage.jettonWalletCode,
),
value: msg.gramAmount,
// a newly-deployed wallet contract will immediately handle it
body: msg.internalTransferMsg,
});
deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}
ChangeMinterAdmin => {
var storage = lazy MinterStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERR_NOT_FROM_ADMIN;
storage.adminAddress = msg.newAdminAddress;
storage.save();
}
ChangeMinterContent => {
var storage = lazy MinterStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERR_NOT_FROM_ADMIN;
storage.content = msg.newContent;
storage.save();
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
}
}
}
struct JettonDataReply {
totalSupply: int
mintable: bool
adminAddress: address
jettonContent: cell
jettonWalletCode: cell
}
get fun get_jetton_data(): JettonDataReply {
val storage = lazy MinterStorage.load();
return {
totalSupply: storage.totalSupply,
mintable: true,
adminAddress: storage.adminAddress,
jettonContent: storage.content,
jettonWalletCode: storage.jettonWalletCode,
}
}
get fun get_wallet_address(ownerAddress: address): address {
val storage = lazy MinterStorage.load();
return calcAddressOfJettonWallet(
ownerAddress,
contract.getAddress(),
storage.jettonWalletCode,
);
}
```
```tolk
import "@stdlib/gas-payments"
import "errors"
import "jetton-utils"
import "messages"
import "fees-management"
import "storage"
type AllowedMessageToWallet =
| AskToTransfer
| AskToBurn
| InternalTransferStep
type BounceOpToHandle = InternalTransferStep | BurnNotificationForMinter
fun onBouncedMessage(in: InMessageBounced) {
in.bouncedBody.skipBouncedPrefix();
val msg = lazy BounceOpToHandle.fromSlice(in.bouncedBody);
val restoreAmount = match (msg) {
// fetching jettonAmount is safe because
// it is at the beginning of the message body
InternalTransferStep => msg.jettonAmount,
BurnNotificationForMinter => msg.jettonAmount,
};
var storage = lazy WalletStorage.load();
storage.jettonBalance += restoreAmount;
storage.save();
}
fun onInternalMessage(in: InMessage) {
val msg = lazy AllowedMessageToWallet.fromSlice(in.body);
match (msg) {
InternalTransferStep => {
var storage = lazy WalletStorage.load();
if (in.senderAddress != storage.minterAddress) {
assert (in.senderAddress ==
calcAddressOfJettonWallet(
msg.transferInitiator!,
storage.minterAddress,
contract.getCode(),
)) throw ERR_INVALID_WALLET;
}
storage.jettonBalance += msg.jettonAmount;
storage.save();
var msgValue = in.valueCoins;
var tonBalanceBeforeMsg = contract.getOriginalBalance() - msgValue;
var storageFee = MIN_GRAMS_FOR_STORAGE - min(
tonBalanceBeforeMsg,
MIN_GRAMS_FOR_STORAGE,
);
msgValue -= (storageFee + JETTON_WALLET_GAS_CONSUMPTION);
if (msg.forwardGrams) {
msgValue -= (msg.forwardGrams + in.originalForwardFee);
val notifyOwnerMsg = createMessage({
// cause receiver can have uninitialized contract
bounce: BounceMode.NoBounce,
dest: storage.ownerAddress,
value: msg.forwardGrams,
body: TransferNotificationForRecipient {
queryId: msg.queryId,
jettonAmount: msg.jettonAmount,
transferInitiator: msg.transferInitiator,
forwardPayload: msg.forwardPayload
}
});
notifyOwnerMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}
if (msg.sendExcessesTo != null & (msgValue > 0)) {
val excessesMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: msg.sendExcessesTo!,
value: msgValue,
body: ReturnExcessesBack {
queryId: msg.queryId
}
});
excessesMsg.send(SEND_MODE_IGNORE_ERRORS);
}
}
AskToTransfer => {
assert (msg.forwardPayload.remainingBitsCount())
throw ERR_INVALID_PAYLOAD;
assert (msg.transferRecipient.getWorkchain() == BASECHAIN)
throw ERR_WRONG_WORKCHAIN;
var storage = lazy WalletStorage.load();
assert (in.senderAddress == storage.ownerAddress)
throw ERR_NOT_FROM_OWNER;
assert (storage.jettonBalance >= msg.jettonAmount)
throw ERR_NOT_ENOUGH_BALANCE;
storage.jettonBalance -= msg.jettonAmount;
storage.save();
var forwardedMessagesCount = msg.forwardGrams ? 2 : 1;
assert (in.valueCoins >
msg.forwardGrams +
// 3 messages: wal1->wal2, wal2->owner, wal2->response
// but last one is optional (it is ok if it fails)
forwardedMessagesCount * in.originalForwardFee +
(2 * JETTON_WALLET_GAS_CONSUMPTION + MIN_GRAMS_FOR_STORAGE)
) throw ERR_NOT_ENOUGH_TON;
val deployMsg = createMessage({
bounce: BounceMode.Only256BitsOfBody,
dest: calcDeployedJettonWallet(
msg.transferRecipient,
storage.minterAddress,
contract.getCode(),
),
value: 0,
body: InternalTransferStep {
queryId: msg.queryId,
jettonAmount: msg.jettonAmount,
transferInitiator: storage.ownerAddress,
sendExcessesTo: msg.sendExcessesTo,
forwardGrams: msg.forwardGrams,
forwardPayload: msg.forwardPayload,
}
});
deployMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}
AskToBurn => {
var storage = lazy WalletStorage.load();
assert (in.senderAddress == storage.ownerAddress)
throw ERR_NOT_FROM_OWNER;
assert (storage.jettonBalance >= msg.jettonAmount)
throw ERR_NOT_ENOUGH_BALANCE;
storage.jettonBalance -= msg.jettonAmount;
storage.save();
val notifyMinterMsg = createMessage({
bounce: BounceMode.Only256BitsOfBody,
dest: storage.minterAddress,
value: 0,
body: BurnNotificationForMinter {
queryId: msg.queryId,
jettonAmount: msg.jettonAmount,
burnInitiator: storage.ownerAddress,
sendExcessesTo: msg.sendExcessesTo,
}
});
notifyMinterMsg.send(
SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE
| SEND_MODE_BOUNCE_ON_ACTION_FAIL
);
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
}
}
}
struct JettonWalletDataReply {
jettonBalance: coins
ownerAddress: address
minterAddress: address
jettonWalletCode: cell
}
get fun get_wallet_data(): JettonWalletDataReply {
val storage = lazy WalletStorage.load();
return {
jettonBalance: storage.jettonBalance,
ownerAddress: storage.ownerAddress,
minterAddress: storage.minterAddress,
jettonWalletCode: contract.getCode(),
}
}
```
## NFT [#nft]
Source directory: [`contracts_Tolk/02_nft`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9/contracts_Tolk/02_nft).
Some files in the source directory are not runnable on their own and depend on others. Keep all the listed files together.
```tolk
const ERROR_NOT_FROM_ADMIN = 401
const ERROR_NOT_FROM_OWNER = 401
const ERROR_NOT_FROM_COLLECTION = 405
const ERROR_BATCH_LIMIT_EXCEEDED = 399
const ERROR_INVALID_ITEM_INDEX = 402
const ERROR_INCORRECT_FORWARD_PAYLOAD = 708
const ERROR_INVALID_WORKCHAIN = 333
const ERROR_TOO_SMALL_REST_AMOUNT = 402
```
```tolk
const MIN_GRAMS_FOR_STORAGE = grams("0.05")
```
```tolk
// SnakeString describes a (potentially long) string inside a cell;
// short strings are stored as-is, like "my-picture.png";
// long strings are nested refs, like "xxxx".ref("yyyy".ref("zzzz"))
type SnakeString = slice
fun SnakeString.unpackFromSlice(mutate s: slice) {
// SnakeString can be only the last — it's just the remainder;
// For correctness, it's better to validate it has no more refs:
// assert (s.remainingRefsCount() <= 1) throw 5;
// Since it is matching the original FunC implementation,
// checks are not kept
val snakeRemainder = s;
s = createEmptySlice(); // no more left to read
return snakeRemainder
}
fun SnakeString.packToBuilder(self, mutate b: builder) {
b.storeSlice(self)
}
struct RoyaltyParams {
numerator: uint16
denominator: uint16
royaltyAddress: address
}
struct NftCollectionStorage {
adminAddress: address
nextItemIndex: uint64
content: Cell
nftItemCode: cell
royaltyParams: Cell
}
struct CollectionContent {
collectionMetadata: cell
commonContent: Cell
}
struct NftItemStorage {
itemIndex: uint64
collectionAddress: address
ownerAddress: address
content: Cell
}
struct NftItemStorageNotInitialized {
itemIndex: uint64
collectionAddress: address
}
fun NftCollectionStorage.load() {
return NftCollectionStorage.fromCell(contract.getData())
}
fun NftCollectionStorage.save(self) {
contract.setData(self.toCell())
}
// Actual storage of an NFT item is tricky: it's either initialized or not;
// After NFT has been inited, it's represented as `NftItemStorage`;
// Before initialization, it has only itemIndex and collectionAddress;
// Hence, detect whether it's inited or not during parsing.
struct NftItemStorageMaybeNotInitialized {
contractData: slice
}
// how do we detect whether it's initialized or not?
// the answer: when "inited", we store `content` (cell),
// so, we have a ref, and for uninited, we don't have a ref
fun NftItemStorageMaybeNotInitialized.isInitialized(self) {
val hasContent = self.contractData.remainingRefsCount();
return hasContent
}
fun NftItemStorageMaybeNotInitialized.parseNotInitialized(self) {
return NftItemStorageNotInitialized.fromSlice(self.contractData)
}
fun NftItemStorageMaybeNotInitialized.parseInitialized(self) {
return NftItemStorage.fromSlice(self.contractData)
}
fun startLoadingNftItemStorage(): NftItemStorageMaybeNotInitialized {
return {
contractData: contract.getData().beginParse()
}
}
fun NftItemStorage.save(self) {
contract.setData(self.toCell())
}
fun calcDeployedNftItem(
itemIndex: uint64,
collectionAddress: address,
nftItemCode: cell,
): AutoDeployAddress {
val emptyNftItemStorage: NftItemStorageNotInitialized = {
itemIndex,
collectionAddress,
};
return {
stateInit: {
code: nftItemCode,
data: emptyNftItemStorage.toCell()
}
}
}
```
```tolk
import "storage"
struct NftItemInitAtDeployment {
ownerAddress: address
content: Cell
}
struct (0x693d3950) RequestRoyaltyParams {
queryId: uint64
}
struct (0xa8cb00ad) ResponseRoyaltyParams {
queryId: uint64
royaltyParams: RoyaltyParams
}
struct (0x00000001) DeployNft {
queryId: uint64
itemIndex: uint64
attachGrams: coins
initParams: Cell
}
struct (0x00000002) BatchDeployNfts {
queryId: uint64
deployList: map
}
struct BatchDeployDictItem {
attachGrams: coins
initParams: Cell
}
struct (0x00000003) ChangeCollectionAdmin {
queryId: uint64
newAdminAddress: address
}
struct (0x2fcb26a2) RequestStaticData {
queryId: uint64
}
struct (0x8b771735) ResponseStaticData {
queryId: uint64
itemIndex: uint256
collectionAddress: address
}
struct (0x05138d91) NotificationForNewOwner {
queryId: uint64
oldOwnerAddress: address
payload: RemainingBitsAndRefs
}
struct (0xd53276db) ReturnExcessesBack {
queryId: uint64
}
struct (0x5fcc3d14) AskToChangeOwnership {
queryId: uint64
newOwnerAddress: address
sendExcessesTo: address?
customPayload: dict
forwardGrams: coins
forwardPayload: RemainingBitsAndRefs
}
```
```tolk
import "errors"
import "storage"
import "messages"
fun deployNftItem(
itemIndex: int,
nftItemCode: cell,
attachGrams: coins,
initParams: Cell,
) {
val deployMsg = createMessage({
bounce: BounceMode.Only256BitsOfBody,
dest: calcDeployedNftItem(
itemIndex,
contract.getAddress(),
nftItemCode,
),
value: attachGrams,
body: initParams,
});
deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}
type AllowedMessageToNftCollection =
| RequestRoyaltyParams
| DeployNft
| BatchDeployNfts
| ChangeCollectionAdmin
fun onInternalMessage(in: InMessage) {
val msg = lazy AllowedMessageToNftCollection.fromSlice(in.body);
match (msg) {
DeployNft => {
var storage = lazy NftCollectionStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERROR_NOT_FROM_ADMIN;
assert (msg.itemIndex <= storage.nextItemIndex)
throw ERROR_INVALID_ITEM_INDEX;
var isLast = msg.itemIndex == storage.nextItemIndex;
deployNftItem(
msg.itemIndex,
storage.nftItemCode,
msg.attachGrams,
msg.initParams,
);
if (isLast) {
storage.nextItemIndex += 1;
storage.save();
}
}
RequestRoyaltyParams => {
val storage = lazy NftCollectionStorage.load();
val respondMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: in.senderAddress,
value: 0,
body: ResponseRoyaltyParams {
queryId: msg.queryId,
royaltyParams: storage.royaltyParams.load(),
}
});
respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}
BatchDeployNfts => {
var storage = lazy NftCollectionStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERROR_NOT_FROM_ADMIN;
var counter = 0;
var r = msg.deployList.findFirst();
while (r.isFound) {
counter += 1;
// due to limits of action list size
assert (counter < 250) throw ERROR_BATCH_LIMIT_EXCEEDED;
val itemIndex = r.getKey();
assert (itemIndex <= storage.nextItemIndex)
throw ERROR_NOT_FROM_ADMIN + counter;
val dictItem = r.loadValue();
deployNftItem(
itemIndex,
storage.nftItemCode,
dictItem.attachGrams,
dictItem.initParams,
);
if (itemIndex == storage.nextItemIndex) {
storage.nextItemIndex += 1;
}
r = msg.deployList.iterateNext(r);
}
storage.save();
}
ChangeCollectionAdmin => {
var storage = lazy NftCollectionStorage.load();
assert (in.senderAddress == storage.adminAddress)
throw ERROR_NOT_FROM_ADMIN;
storage.adminAddress = msg.newAdminAddress;
storage.save();
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
}
}
}
struct CollectionDataReply {
nextItemIndex: int
collectionMetadata: cell
adminAddress: address
}
struct (0x01) OffchainMetadataReply {
string: SnakeString
}
get fun get_collection_data(): CollectionDataReply {
val storage = lazy NftCollectionStorage.load();
val content = lazy storage.content.load();
return {
nextItemIndex: storage.nextItemIndex,
collectionMetadata: content.collectionMetadata,
adminAddress: storage.adminAddress,
}
}
get fun get_nft_address_by_index(itemIndex: int): address {
val storage = lazy NftCollectionStorage.load();
val nftDeployed = calcDeployedNftItem(
itemIndex,
contract.getAddress(),
storage.nftItemCode,
);
return nftDeployed.calculateAddress();
}
get fun royalty_params(): RoyaltyParams {
val storage = lazy NftCollectionStorage.load();
return storage.royaltyParams.load();
}
get fun get_nft_content(
itemIndex: int,
individualNftContent: Cell,
): Cell {
val storage = lazy NftCollectionStorage.load();
val content = lazy storage.content.load();
// construct a responce from "common content" and "individual content";
// for example:
// common content = "https://site.org/my-collection/"
// individual nft = "my-picture-123.png" (a long, snake-encoded string)
return OffchainMetadataReply {
string: beginCell()
// assume it's short (no refs)
.storeSlice(content.commonContent.load())
// so, it's the first ref (snake encoding)
.storeRef(individualNftContent)
.endCell().beginParse()
}.toCell()
}
```
```tolk
import "@stdlib/gas-payments"
import "errors"
import "storage"
import "messages"
import "fees-management"
type AllowedMessageToNftItem =
| AskToChangeOwnership
| RequestStaticData
fun onInternalMessage(in: InMessage) {
var loadingStorage = startLoadingNftItemStorage();
if (!loadingStorage.isInitialized()) {
val uninitedSt = loadingStorage.parseNotInitialized();
assert (in.senderAddress == uninitedSt.collectionAddress)
throw ERROR_NOT_FROM_COLLECTION;
// using a message from collection,
// convert "uninitialized" to "initialized" state
val initParams = NftItemInitAtDeployment.fromSlice(in.body);
val storage: NftItemStorage = {
itemIndex: uninitedSt.itemIndex,
collectionAddress: uninitedSt.collectionAddress,
ownerAddress: initParams.ownerAddress,
content: initParams.content,
};
storage.save();
return;
}
var storage = loadingStorage.parseInitialized();
val msg = lazy AllowedMessageToNftItem.fromSlice(in.body);
match (msg) {
AskToChangeOwnership => {
assert (in.senderAddress == storage.ownerAddress)
throw ERROR_NOT_FROM_OWNER;
assert (msg.forwardPayload.remainingBitsCount())
throw ERROR_INCORRECT_FORWARD_PAYLOAD;
assert (msg.newOwnerAddress.getWorkchain() == BASECHAIN)
throw ERROR_INVALID_WORKCHAIN;
val fwdFee = in.originalForwardFee;
var restAmount = contract.getOriginalBalance() - MIN_GRAMS_FOR_STORAGE;
if (msg.forwardGrams) {
restAmount -= (msg.forwardGrams + fwdFee);
}
if (msg.sendExcessesTo != null) {
assert (msg.sendExcessesTo.getWorkchain() == BASECHAIN)
throw ERROR_INVALID_WORKCHAIN;
restAmount -= fwdFee;
}
// base nft spends fixed amount of gas, will not check for response
assert (restAmount >= 0) throw ERROR_TOO_SMALL_REST_AMOUNT;
if (msg.forwardGrams) {
val ownershipMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: msg.newOwnerAddress,
value: msg.forwardGrams,
body: NotificationForNewOwner {
queryId: msg.queryId,
oldOwnerAddress: storage.ownerAddress,
payload: msg.forwardPayload,
}
});
ownershipMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}
if (msg.sendExcessesTo != null) {
val excessesMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: msg.sendExcessesTo,
value: restAmount,
body: ReturnExcessesBack {
queryId: msg.queryId,
}
});
excessesMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
}
storage.ownerAddress = msg.newOwnerAddress;
storage.save();
}
RequestStaticData => {
val respondMsg = createMessage({
bounce: BounceMode.NoBounce,
dest: in.senderAddress,
value: 0,
// The `itemIndex` was encoded as 256-bit in FunC implementation,
// we do the same here to pass FunC tests;
// As such, response becomes too long (64 + 256 + address),
// and the compiler will create a ref;
// To circumvent that, let's force the compiler to inline the body,
// since it is guaranteed that with value (coins) = 0,
// it will always fit into a message cell directly.
body: UnsafeBodyNoRef {
forceInline: ResponseStaticData {
queryId: msg.queryId,
itemIndex: storage.itemIndex as uint256,
collectionAddress: storage.collectionAddress,
}
}
});
respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);
}
else => {
// ignore empty messages, "wrong opcode" for others
assert (in.body.isEmpty()) throw 0xFFFF
}
}
}
struct NftDataReply {
isInitialized: bool
itemIndex: int
collectionAddress: address
ownerAddress: address? = null
content: Cell? = null
}
get fun get_nft_data(): NftDataReply {
var loadingStorage = startLoadingNftItemStorage();
if (!loadingStorage.isInitialized()) {
val uninitedSt = loadingStorage.parseNotInitialized();
return {
isInitialized: false,
itemIndex: uninitedSt.itemIndex,
collectionAddress: uninitedSt.collectionAddress,
}
}
val storage = loadingStorage.parseInitialized();
return {
isInitialized: true,
itemIndex: storage.itemIndex,
collectionAddress: storage.collectionAddress,
ownerAddress: storage.ownerAddress,
content: storage.content,
}
}
```
## See also [#see-also]
* [Tolk language overview](https://docs.ton.org/llms/tolk/overview/content.md)
* [Tolk vs FunC](https://docs.ton.org/llms/tolk/from-func/tolk-vs-func/content.md)
# Idioms and conventions (https://docs.ton.org/llms/tolk/idioms-conventions/content.md)
After learning of [basic syntax](https://docs.ton.org/llms/tolk/basic-syntax/content.md), study the common patterns, conventions, and best practices to write idiomatic Tolk code.
## Declare each contract with a `contract` directive [#declare-each-contract-with-a-contract-directive]
Place a [`contract` declaration](https://docs.ton.org/llms/tolk/features/contract-abi/content.md) at the top of every entrypoint file. It names the contract and lists its public shapes — at minimum, the storage struct and the union of accepted incoming messages. The compiler uses this information to emit a machine-readable ABI, which in turn powers TypeScript wrappers, explorers, the step-by-step debugger, and other client-side tooling.
```tolk
contract JettonWallet {
storage: WalletStorage
incomingMessages: WalletMessages
}
```
Use the contract's PascalCase name as the file name: `JettonWallet.tolk`, `JettonMinter.tolk`. All `get fun` and entrypoints must live in the same file as the `contract` declaration.
## Prefer automatic serialization to manual one [#prefer-automatic-serialization-to-manual-one]
Manual work with slices and builders is error-prone and tedious. By comparison, [auto-serialization](https://docs.ton.org/llms/tolk/features/auto-serialization/content.md) with structures helps express data with types and prevents many related bugs.
```tolk
struct Holder {
owner: address
lastUpdated: uint32
extra: Cell
}
fun demo(data: Holder) {
// make a cell with 299 bits and 1 ref
val c = data.toCell();
// unpack it back
val holder = Holder.fromCell(c);
}
```
## Prefer typed cells with `Cell` [#prefer-typed-cells-with-cellt]
All data in TON is stored in cells. To express data relation clearly and to aid in [serialization](https://docs.ton.org/llms/tolk/features/auto-serialization/content.md), use cells with well-typed contents: `Cell`.
```tolk
struct Holder {
// ...
extra: Cell
}
struct ExtraInfo {
someField: int8
// ...
}
fun getDeepData(value: Holder) {
// `value.extra` is a reference
// use `load()` to access its contents
val data = value.extra.load();
return data.someField;
}
```
## Use lazy data loading [#use-lazy-data-loading]
When reading data from cells, add the [`lazy` keyword](https://docs.ton.org/llms/tolk/features/lazy-loading/content.md):
* `lazy SomeStruct.fromCell(c)` over `SomeStruct.fromCell(c)`
* `lazy typedCell.load()` over `typedCell.load()`
With `lazy`, the compiler loads only the requested fields, skipping the rest. This reduces gas consumption and bytecode size:
```tolk
get fun publicKey() {
val st = lazy Storage.load();
// <-- here, "skip 65 bits, preload uint256" is inserted
return st.publicKey
}
```
## Use type aliases to express custom serialization logic [#use-type-aliases-to-express-custom-serialization-logic]
Serialization may require custom rules which are not covered by existing types. Tolk allows defining custom [serialization rules for type aliases](https://docs.ton.org/llms/tolk/types/overall-serialization/content.md):
```tolk
// The custom type alias over a regular, untyped slice
type MyString = slice
// The function that is called when composing a new cell with a builder
fun MyString.packToBuilder(self, mutate b: builder) {
// ...custom logic for MyString serialization
}
// The function that is called when loading data from the cell with a slice
fun MyString.unpackFromSlice(mutate s: slice) {
// ...custom logic for MyString deserialization
}
// With those two functions implemented, MyString becomes
// a type with clear serialization rules and can be used anywhere
struct Everywhere {
tokenName: MyString
fullDomain: Cell
}
```
Consider a structure that holds a signature hash of the data in its tail:
```tolk
struct SignedRequest {
signature: uint256
// hash of all data below is signed
field1: int32
field2: address?
// ...
}
```
The task is to parse the structure and check the signature of the fields below `signature` against it. A manual approach would be to read `uint256`, calculate the hash of the remaining slice, then read other fields and compare the signatures.
However, a better solution is to continue using auto-serialization by introducing a synthetic field populated only when loading a slice and never when composing a cell with a builder:
```tolk
type HashOfRemainder = uint256
struct SignedRequest {
signature: uint256
restHash: HashOfRemainder // populated on load
field1: int32
field2: address?
// ...
}
fun HashOfRemainder.unpackFromSlice(mutate s: slice) {
// In this case, `s` is a slice remainder after loading `signature`,
// while the `restHash` field has to contain the hash of that remainder:
return s.hash()
}
// Now, assert that signatures match
fun demo(input: slice) {
val req = SignedRequest.fromSlice(input);
assert (req.signature == req.restHash) throw XXX;
}
```
## Use contract storage as a structure [#use-contract-storage-as-a-structure]
[Contract storage](https://docs.ton.org/llms/tolk/features/contract-storage/content.md) is a regular `struct`, serialized into persistent on-chain data.
Add `load` and `store` methods for convenience:
```tolk
struct Storage {
counterValue: int64
}
fun Storage.load() {
return Storage.fromCell(contract.getData())
}
fun Storage.save(self) {
contract.setData(self.toCell())
}
```
## Express messages as structs with 32-bit prefixes [#express-messages-as-structs-with-32-bit-prefixes]
By convention, every message in TON has an *opcode*: a unique 32-bit number. In Tolk, every [`struct`](https://docs.ton.org/llms/tolk/syntax/structures-fields/content.md) can have a serialization prefix of arbitrary length. Use 32-bit prefixes to express message opcodes.
```tolk
struct (0x12345678) CounterIncrement {
// ...message body fields...
}
```
When implementing [Jettons](https://docs.ton.org/llms/contracts/standard/tokens/jettons/overview/content.md), [NFTs](https://docs.ton.org/llms/contracts/standard/tokens/nft/overview/content.md), or other standard contracts, use predefined opcodes according to the specification. Otherwise, opcodes are ad hoc.
## Use unions to handle incoming messages [#use-unions-to-handle-incoming-messages]
The suggested pattern:
1. Each [incoming message](https://docs.ton.org/llms/tolk/features/message-handling/content.md) is made a struct with an opcode.
2. Structs are combined into a union type.
3. Union is used to lazily load data from the message body slice.
4. Finally, result is [pattern matched](https://docs.ton.org/llms/tolk/syntax/pattern-matching/content.md) over union variants.
```tolk
struct (0x12345678) CounterIncrement {
incBy: uint32
}
struct (0x23456789) CounterReset {
initialValue: int64
}
type AllowedMessage = CounterIncrement | CounterReset
contract Counter {
storage: Storage
incomingMessages: AllowedMessage
}
fun onInternalMessage(in: InMessage) {
val msg = lazy AllowedMessage.fromSlice(in.body);
match (msg) {
CounterIncrement => {
// use `msg.incBy`
}
CounterReset => {
// use `msg.initialValue`
}
else => {
// invalid input; a typical reaction is:
// ignore empty messages, "wrong opcode" if not
assert (in.body.isEmpty()) throw 0xFFFF
}
}
}
```
The `lazy` keyword works with unions and performs a lazy match by the slice prefix: a message opcode. This approach is more efficient than manual opcode parsing and branching via a series of `if (op == TRANSFER_OP)` statements.
## Use structs to send messages [#use-structs-to-send-messages]
To send a message from contract A to contract B:
1. Declare a struct with an opcode and fields expected by the receiver.
2. Use the `createMessage()` function to compose a message, and the `send()` method to send it.
```tolk
struct (0x98765432) RequestedInfo {
// ...
}
fun respond(/* ... */) {
val reply = createMessage({
bounce: BounceMode.NoBounce,
value: grams("0.05"),
dest: addressOfB,
body: RequestedInfo {
// ... initialize fields
}
});
reply.send(SEND_MODE_REGULAR);
}
```
When both contracts share the same codebase, a struct serves as an outgoing message for A and an incoming message for B.
## Attach initial code and data to a message to deploy another contract [#attach-initial-code-and-data-to-a-message-to-deploy-another-contract]
Contract deployment is performed by attaching the code and data of the future contract to a message sent to its soon-to-be-initialized address. That address is deterministically calculated from the attached code and data.
A common case is when the jetton minter contract deploys a jetton wallet contract per user, knowing the future wallet's initial state: code and data.
```tolk
val msgThatDeploys = createMessage({
// address auto-calculated, code+data auto-attached
dest: {
// initial state
stateInit: {
code: jettonWalletCode,
data: emptyWalletStorage.toCell(),
}
}
});
```
Since one cannot synchronously check whether a contract is already deployed, the standard approach is always to attach the initial state needed for deployment whenever the contract's logic requires it.
To calculate or validate resulting addresses in addition to sending messages to them, always extract the `StateInit` generation to a separate function:
```tolk
fun calcDeployedJettonWallet(/* ... */): AutoDeployAddress {
val emptyWalletStorage: WalletStorage = {
// ... initialize fields from parameters
};
return {
stateInit: {
code: jettonWalletCode,
data: emptyWalletStorage.toCell()
}
}
}
fun demoDeploy() {
val deployMsg = createMessage({
// address auto-calculated, code+data auto-attached
dest: calcDeployedJettonWallet(...),
// ...
});
deployMsg.send(mode);
}
```
See the [Tolk contract examples](https://docs.ton.org/llms/tolk/examples/content.md) page for selected contracts from the [`tolk-bench`](https://github.com/ton-blockchain/tolk-bench).
## Target certain shards when deploying sibling contracts [#target-certain-shards-when-deploying-sibling-contracts]
Specify the prefix length and the contract address to aim for the [same shard](https://docs.ton.org/llms/tolk/features/message-sending/content.md). For example, sharded jetton wallet must be deployed to the same shard as the owner's wallet.
```tolk
val deployMsg = createMessage({
dest: {
stateInit: { code, data },
toShard: {
closeTo: ownerAddress,
fixedPrefixLength: 8
}
}
});
```
## Emit events and logs to off-chain world during development [#emit-events-and-logs-to-off-chain-world-during-development]
[External messages](https://docs.ton.org/llms/tolk/features/message-sending/content.md) with a special address `none` are used to emit events and logs to the outer world. Indexers catch such messages and provide a picture of on-chain activity.
External messages cost less gas than internal ones and help track events during contract development. They provide a simple way to emit structured logs that indexers and debugging tools can consume.
To send an external log message:
1. Create a `struct` to represent the message body.
2. Use `createExternalLogMessage()` to compose a message and the `send()` method to send it.
```tolk
struct DepositEvent {
// ...fields...
}
fun demo() {
val emitMsg = createExternalLogMessage({
dest: createAddressNone(),
body: DepositEvent {
// ...field values...
}
});
emitMsg.send(SEND_MODE_REGULAR);
}
```
## Return several state values as a structure from a get method [#return-several-state-values-as-a-structure-from-a-get-method]
When a [contract getter](https://docs.ton.org/llms/tolk/features/contract-getters/content.md) needs to return several values, introduce a structure. Avoid returning unnamed tensors like `(int, int, int)`. Field names provide clear metadata for client wrappers and human readers.
```tolk
struct JettonWalletDataReply {
jettonBalance: coins
ownerAddress: address
minterAddress: address
jettonWalletCode: cell
}
get fun get_wallet_data(): JettonWalletDataReply {
return {
jettonBalance: ...,
ownerAddress: ...,
minterAddress: ...,
jettonWalletCode: ..,
}
}
```
## Validate user input with assertions [#validate-user-input-with-assertions]
After parsing an incoming message, validate required fields with [`assert`](https://docs.ton.org/llms/tolk/syntax/exceptions/content.md):
```tolk
assert (msg.seqno == storage.seqno) throw E_INVALID_SEQNO;
assert (msg.validUntil > blockchain.now()) throw E_EXPIRED;
```
If a condition is violated, execution terminates with the specified error code. Otherwise, a contract remains ready to serve the next request. This is the standard mechanism for reacting to invalid input.
## Organize a project into several files [#organize-a-project-into-several-files]
Consistent file structure across projects simplifies navigation:
* Supply `errors.tolk` with constants or enums.
* Supply `storage.tolk` with storage and helper methods.
* Supply `messages.tolk` with incoming and outgoing messages.
* Have `MyContract.tolk` as an entrypoint, named after the contract in PascalCase. Place a [`contract` declaration](https://docs.ton.org/llms/tolk/features/contract-abi/content.md) at the top of the file and keep all `get fun` and entrypoint functions within it; use [imports](https://docs.ton.org/llms/tolk/syntax/imports/content.md) to bring in shared code.
When developing several related contracts simultaneously, keep them in the same codebase. A contract file can `import` another contract — its types are exposed to the importer, while its `onInternalMessage` and `get fun` stay private to the original contract. For instance, struct `SomeMessage` outgoing for contract A can be incoming for contract B; or contract A may need to know B's storage to compute the deploy address.
## Prefer methods to functions [#prefer-methods-to-functions]
All symbols across different files share the same namespace and must have unique names project-wide. There are no modules or exports.
Use [methods](https://docs.ton.org/llms/tolk/syntax/functions-methods/content.md) to avoid name collisions:
```tolk
fun Struct1.validate(self) { /* ... */ }
fun Struct2.validate(self) { /* ... */ }
```
Methods are also more convenient: `obj.someMethod()` reads better than `someFunction(obj)`.
```tolk
struct AuctionConfig {
// ...fields...
}
// Prefer this:
fun AuctionConfig.isInvalid(self) {
// ...
}
// Over this:
// fun isAuctionConfigInvalid(config: AuctionConfig) {}
```
Static methods follow the same pattern: `Auction.createFrom(...)` reads better than `createAuctionFrom(...)`.
A method without a `self` parameter is static:
```tolk
fun Auction.createFrom(config: cell, minBid: coins) {
// ...
}
```
Static methods also group utility functions. For example, standard functions like `blockchain.now()` are static methods on an empty struct. This technique emulates namespaces:
```tolk
struct blockchain
fun blockchain.now(): int /* ... */;
fun blockchain.logicalTime(): int /* ... */;
```
## Use optional addresses to have address defaults [#use-optional-addresses-to-have-address-defaults]
A nullable [address](https://docs.ton.org/llms/tolk/types/address/content.md) `address?` is a pattern for an optional address, sometimes called *"maybe address"*:
* `null` represents the address `none`.
* `address` represents an internal address.
## Calculate CRC32 or SHA256 at compile-time [#calculate-crc32-or-sha256-at-compile-time]
Several [compile-time methods](https://docs.ton.org/llms/tolk/types/strings/content.md) operate on constant [strings](https://docs.ton.org/llms/tolk/types/strings/content.md):
```tolk
// Calculates CRC32 of a string
const crc32 = "some_str".crc32()
// Calculates SHA256 of a string as a 256-bit integer
const hash = "some_crypto_key".sha256()
```
## Work with strings [#work-with-strings]
Tolk provides a dedicated [`string` type](https://docs.ton.org/llms/tolk/types/strings/content.md) backed by snake-encoded cells. Use the [`StringBuilder`](https://docs.ton.org/llms/tolk/types/strings/content.md) for concatenation:
```tolk
import "@stdlib/strings"
var str = StringBuilder.create()
.append("hello ")
.append("world")
.build();
```
For fixed-size binary data, use [`bitsN` or `bytesN` types](https://docs.ton.org/llms/tolk/types/cells/content.md).
## Avoid micro-optimization [#avoid-micro-optimization]
The [compiler applies many optimizations](https://docs.ton.org/llms/tolk/features/compiler-optimizations/content.md): it automatically inlines functions, reduces stack allocations, and handles the underlying work. Attempts to outsmart the compiler yield negligible effects, either positive or negative.
Prefer readability over manual optimizations:
* Use one-line methods freely as they are auto-inlined.
* Use flat structures: they are as efficient as raw stack values.
* Extract standalone values into constants and variables.
* Avoid assembler functions unless necessary.
# Tolk language (https://docs.ton.org/llms/tolk/overview/content.md)
Tolk is a statically typed language for writing smart contracts on TON. It provides declarative data structures, automatic cell serialization, and message handling primitives.
The language compiles to [TVM](https://docs.ton.org/llms/tvm/overview/content.md) and provides direct control over execution.
```tolk
type AllowedMessage = CounterIncrement | CounterReset
contract Counter {
storage: Storage
incomingMessages: AllowedMessage
}
fun onInternalMessage(in: InMessage) {
val msg = lazy AllowedMessage.fromSlice(in.body);
match (msg) {
CounterIncrement => { ... }
CounterReset => { ... }
}
}
get fun currentCounter() {
val storage = lazy Storage.load();
return storage.counter;
}
```
Tolk is compatible with existing [TON standards](https://docs.ton.org/llms/from-ethereum/content.md).
## Key features [#key-features]
Tolk provides high-level readability while preserving low-level control:
* a type system for describing [cell](https://docs.ton.org/llms/foundations/serialization/cells/content.md) layouts;
* [`lazy` loading](https://docs.ton.org/llms/tolk/features/lazy-loading/content.md) that skips unused fields;
* unified message composition and deployment;
* a [`contract` declaration](https://docs.ton.org/llms/tolk/features/contract-abi/content.md) that drives ABI export, TypeScript wrappers, source maps, and debugging;
* a compiler targeting the Fift assembler;
* tooling with IDE integration.
## From FunC to Tolk [#from-func-to-tolk]
Tolk evolved from FunC and is now the recommended language for TON smart contracts. To migrate from FunC:
* see [Tolk contract examples](https://docs.ton.org/llms/tolk/examples/content.md) for embedded jetton and NFT examples;
* check [gas benchmarks](https://github.com/ton-blockchain/tolk-bench);
* study [reference contracts](https://github.com/ton-blockchain/acton-contracts);
* read [Tolk vs FunC](https://docs.ton.org/llms/tolk/from-func/tolk-vs-func/content.md) for an overview;
* use the [FunC-to-Tolk converter](https://docs.ton.org/llms/tolk/from-func/converter/content.md) to migrate existing projects.
## Quick start [#quick-start]
Follow the [quickstart page in the Acton documentation](https://ton-blockchain.github.io/acton/docs/quickstart).
## IDE support [#ide-support]
1. [JetBrains IDEs plugin](https://docs.ton.org/llms/contracts/ide/jetbrains/content.md) provides syntax highlighting and code navigation.
2. [VSCode extension](https://docs.ton.org/llms/contracts/ide/vscode/content.md) adds syntax highlighting, code navigation, and other language features for VS Code and VS Code-based editors such as VSCodium, Cursor, and Windsurf.
3. [Language server](https://github.com/ton-blockchain/ton-language-server#other-editors) supports (Neo)Vim, Helix, and other editors with LSP support.
## Start with [#start-with]
* [Basic syntax](https://docs.ton.org/llms/tolk/basic-syntax/content.md)
* [Idioms and conventions](https://docs.ton.org/llms/tolk/idioms-conventions/content.md)
* [Contract examples](https://docs.ton.org/llms/tolk/examples/content.md)
* [Type system](https://docs.ton.org/llms/tolk/types/list-of-types/content.md)
* [Message handling](https://docs.ton.org/llms/tolk/features/message-handling/content.md)
# `ACCEPT` and gas credit (https://docs.ton.org/llms/tvm/accept/content.md)
The [`ACCEPT`](https://docs.ton.org/llms/tvm/instructions/content.md) instruction changes the gas available to the [TVM](https://docs.ton.org/llms/tvm/overview/content.md). For an incoming external message, this change also makes the contract pay for computation and allows the message to produce a transaction.
`ACCEPT` does **not** validate a message, guarantee successful execution, or commit contract state.
Tolk exposes the `ACCEPT` instruction as the `acceptExternalMessage()` function from the [`@stdlib/gas-payments` module](https://docs.ton.org/llms/tolk/features/standard-library/content.md).
Calling `ACCEPT` before authentication allows invalid external messages to charge the contract balance on testnet and mainnet. Check authentication and replay fields before `ACCEPT`, and test all failure paths on testnet before deployment.
## External message flow [#external-message-flow]
As described in [`GasLimits`](https://docs.ton.org/llms/tvm/gas/content.md), an incoming external message starts with gas credit because it cannot carry Gram. This credit lets the contract inspect the message before agreeing to pay for its execution.
Process an external message in this order:
1. Verify its signature or other authentication data.
2. Reject expired or replayed messages.
3. Call `ACCEPT` or `SETGASLIMIT`.
4. Update and commit replay state before operations that can fail.
If execution ends before acceptance, TON records no transaction and discards state changes and actions. After acceptance, the contract pays for all compute gas, including gas spent from the initial credit.
See the [external-message security guidance](https://docs.ton.org/llms/contracts/techniques/security/content.md) for Tolk examples.
## `ACCEPT` and `SETGASLIMIT` [#accept-and-setgaslimit]
`ACCEPT` makes the maximum available gas payable by the contract. [`SETGASLIMIT`](https://docs.ton.org/llms/tvm/instructions/content.md) accepts the message with a lower limit when its argument is below that maximum.
`SETGASLIMIT` throws an out-of-gas exception before changing the limit if execution has already consumed more gas than the requested limit. The [`GasLimits` reference](https://docs.ton.org/llms/tvm/gas/content.md) defines the exact updates made by both instructions.
Tolk exposes the `SETGASLIMIT` instruction as the `setGasLimit(limit)` function from the [`@stdlib/gas-payments` module](https://docs.ton.org/llms/tolk/features/standard-library/content.md).
## Failures after acceptance [#failures-after-acceptance]
Acceptance creates fee liability but does not guarantee success:
| Possible outcomes after successful `ACCEPT` | Compute gas | State and actions |
| -------------------------------------------------------------------------- | ----------- | ------------------------------------------------- |
| Compute phase succeeds as well | Charged | Final data and actions enter the action phase |
| Compute phase fails without `COMMIT` | Charged | Discarded |
| [`COMMIT`](https://docs.ton.org/llms/tvm/instructions/content.md) precedes a later compute failure | Charged | Committed data and actions enter the action phase |
Commit the replay-state update before later operations and actions that are allowed to fail. In Tolk, [`commitContractDataAndActions()`](https://docs.ton.org/llms/tolk/features/standard-library/content.md) snapshots persistent data and the current action list.
Without a committed replay-state update, validators can deliver the same valid external message again. Each attempt that reaches `ACCEPT` can charge the contract.
The [execution phases](https://docs.ton.org/llms/foundations/phases/content.md) determine whether state changes and actions take effect. Incoming external messages cannot bounce because they have no on-chain sender — there is no one to receive the bounced message.
## Internal messages [#internal-messages]
An [internal message](https://docs.ton.org/llms/foundations/messages/internal/content.md) starts without gas credit and does not require explicit acceptance. `ACCEPT` raises its gas limit to the maximum available to the contract, which can spend balance held before the message arrived. `SETGASLIMIT` can apply a lower limit.
Neither `ACCEPT` nor `SETGASLIMIT` changes the [bounce behavior](https://docs.ton.org/llms/foundations/messages/internal/content.md) of internal messages.
# Builders and Slices (https://docs.ton.org/llms/tvm/builders-and-slices/content.md)
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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md):
```fift title="Fift"
NEWC // returns empty builder x{}
```
Then, put a number on the stack:
```fift title="Fift"
1 INT // stack: x{} 1
```
And call [`STU`](https://docs.ton.org/llms/tvm/instructions/content.md) ("STore Unsigned integer") to store integer into builder (swapping builder and value to meet `STU` input order):
```fift title="Fift"
SWAP // stack: 1 x{}
4 STU // stack: x{0001}
```
Then, store the other two numbers:
```fift title="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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) ("Cell TO Slice") loads a `Cell` to a `Slice`.
```fift title="Fift"
// assume a cell with bitstring x{0001001011111111} is on the stack
CTOS // x{0001001011111111}
```
Then, call [`LDU`](https://docs.ton.org/llms/tvm/instructions/content.md) ("LoaD Unsigned integer") to read first value (`uint4`).
```fift title="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 title="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`](https://docs.ton.org/llms/tvm/instructions/content.md).
# Continuations (https://docs.ton.org/llms/tvm/continuations/content.md)
[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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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 title="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`](https://docs.ton.org/llms/tvm/instructions/content.md) works.
```fift title="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](https://docs.ton.org/llms/tvm/initialization/content.md), `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](https://docs.ton.org/llms/tvm/initialization/content.md), `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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) and variants.
# Exit codes (https://docs.ton.org/llms/tvm/exit-codes/content.md)
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-phase) or [action](#action-phase) 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-phase). Exit (or [result](#action-phase)) code 0 indicates normal (successful) execution of the [action phase](#action-phase). 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-phase)) 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-integer-out-of-expected-range). This is done intentionally to prevent some exit codes from being produced artificially, such as [exit code -14](#14-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-normal-termination) | [Compute][c] and [action][a] phases | Standard successful execution exit code. |
| [1](#1-alternative-termination) | [Compute phase][c] | Alternative successful execution exit code. Reserved, but does not occur. |
| [2](#2-stack-underflow) | [Compute phase][c] | Stack underflow. |
| [3](#3-stack-overflow) | [Compute phase][c] | Stack overflow. |
| [4](#4-integer-overflow) | [Compute phase][c] | Integer overflow. |
| [5](#5-integer-out-of-expected-range) | [Compute phase][c] | Range check error — an integer is out of its expected range. |
| [6](#6-invalid-opcode) | [Compute phase][c] | Invalid [TVM][tvm] opcode. |
| [7](#7-type-check-error) | [Compute phase][c] | Type check error. |
| [8](#8-cell-overflow) | [Compute phase][c] | Cell overflow. |
| [9](#9-cell-underflow) | [Compute phase][c] | Cell underflow. |
| [10](#10-dictionary-error) | [Compute phase][c] | Dictionary error. |
| [11](#11-%22unknown%22-error) | [Compute phase][c] | Described in [TVM][tvm] docs as "Unknown error, may be thrown by user programs." |
| [12](#12-fatal-error) | [Compute phase][c] | Fatal error. Thrown by [TVM][tvm] in situations deemed impossible. |
| [13](#13-out-of-gas-error) | [Compute phase][c] | Out of gas error. |
| [-14](#14-out-of-gas-error) | [Compute phase][c] | Same as 13. Negative, so that it [cannot be faked](#13-out-of-gas-error). |
| [14](#14-virtualization-error) | [Compute phase][c] | VM virtualization error. Reserved, but never thrown. |
| [32](#32-action-list-is-invalid) | [Action phase][a] | Action list is invalid. |
| [33](#33-action-list-is-too-long) | [Action phase][a] | Action list is too long. |
| [34](#34-invalid-or-unsupported-action) | [Action phase][a] | Action is invalid or not supported. |
| [35](#35-invalid-source-address-in-outbound-message) | [Action phase][a] | Invalid source address in outbound message. |
| [36](#36-invalid-destination-address-in-outbound-message) | [Action phase][a] | Invalid destination address in outbound message. |
| [37](#37-not-enough-grams) | [Action phase][a] | Not enough GRAMs. |
| [38](#38-not-enough-extra-currencies) | [Action phase][a] | Not enough extra currencies. |
| [39](#39-outbound-message-does-not-fit-into-cell) | [Action phase][a] | Outbound message does not fit into a cell after rewriting. |
| [40](#40-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-library-reference-is-null) | [Action phase][a] | Library reference is null during library change action. |
| [42](#42-library-change-action-error) | [Action phase][a] | Library change action error. |
| [43](#43-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-account-state-size-exceeded-limits) | [Action phase][a] | Account state size exceeded limits. |
Often enough, you might encounter the exit code 65535 (or `0xffff`), which usually means that the received opcode is unknown to the contract, as no handlers were expecting it. The exit code 65535 is set in the smart contract code and not by [TVM][tvm] or the Tolk compiler.
[c]: https://docs.ton.org/llms/tvm/overview/content.md
[a]: https://docs.ton.org/llms/tvm/overview/content.md
## Exit codes in Blueprint projects [#exit-codes-in-blueprint-projects]
In [Blueprint][bp] tests, exit codes from the [compute phase](#compute-phase) are specified in the `exitCode` field of the object argument for the `toHaveTransaction()` method of the `expect()` matcher. The field for the [result](#action-phase) codes (exit codes from the [action phase](#action-phase)) in the same `toHaveTransaction()` method is called `actionResultCode`.
Read more about expecting specific exit codes: [Explore TVM logs](https://docs.ton.org/llms/contracts/blueprint/debug/content.md).
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-phase) (or [action phase](#action-phase)).
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-phase)) code indicates the successful completion of the [compute phase](#compute-phase) (or [action phase](#action-phase)) 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-normal-termination) nor [1](#1-alternative-termination)), the transaction skips the [action phase](#action-phase) 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-phase). 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;
}
}
```
[TVM overview][tvm].
### 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](https://docs.ton.org/llms/languages/fift/fift-and-tvm-assembly/content.md) 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;
}
}
```
[TVM overview][tvm].
### 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-phase), 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](https://docs.ton.org/llms/languages/func/dictionaries/content.md).
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](https://docs.ton.org/llms/languages/fift/fift-and-tvm-assembly/content.md) 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-phase), 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-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-phase). 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-phase), 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](#exit-codes-in-blueprint-projects). 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-phase) 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 nanograms
// This won't fail in the compute phase, but will result in exit code 33 in the action phase
repeat (256) {
reserveGramsOnBalance(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 nanograms, 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 GRAMs [#37-not-enough-grams]
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 GRAMs`.
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]
When the account lacks a requested [extra-currency](https://docs.ton.org/llms/foundations/extra-currencies/content.md) amount to send in an outbound internal message, an error with exit code 38 is thrown: `Not enough extra currencies`.
If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.
### 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](https://docs.ton.org/llms/foundations/config/content.md) by the end of the [action phase](#action-phase), 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).
## Tolk compiler [#tolk-compiler]
Tolk utilizes exit codes below 128. 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-phase), not during compilation.
* **0:** When the `onBouncedMessage()` handler is not defined, all bounced messages are rejected with an [exit code 0](#0-normal-termination), which is considered a normal termination.
* **5:** If there is an exhaustive enum `match` fallthrough or an enum deserialization range or membership check, an [exit code 5: integer out of expected range](#5-integer-out-of-expected-range) is thrown.
* **9:** If there is a slice or array deserialization invalidation, an [exit code 9: cell underflow](#9-cell-underflow) is thrown.
* **63:** If there is an opcode (or prefix) mismatch when unpacking a struct, a Tolk-specific exit code 63 is thrown. Additionally, it is the default exit code for `throwIfOpcodeDoesNotMatch()` function, which can be overridden.
[tlb]: https://docs.ton.org/llms/foundations/tlb/overview/content.md
[tvm]: https://docs.ton.org/llms/tvm/overview/content.md
[bp]: https://docs.ton.org/llms/contracts/blueprint/overview/content.md
[sb]: https://github.com/ton-org/sandbox
[jest]: https://jestjs.io
# Gas (https://docs.ton.org/llms/tvm/gas/content.md)
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`](https://docs.ton.org/llms/tvm/instructions/content.md) | `#C8` | `18` | 8-bit prefix without operands |
| [`STU`](https://docs.ton.org/llms/tvm/instructions/content.md) | `#CB` `cc:uint8` | `26` | 8-bit prefix, 8-bit operand |
| [`PUSHINT_LONG`](https://docs.ton.org/llms/tvm/instructions/content.md) | `#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`](https://docs.ton.org/llms/tvm/instructions/content.md) | `#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`](https://docs.ton.org/llms/tvm/instructions/content.md)-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`](https://docs.ton.org/llms/tvm/instructions/content.md), [`TUPLEVAR`](https://docs.ton.org/llms/tvm/instructions/content.md), [`UNTUPLE`](https://docs.ton.org/llms/tvm/instructions/content.md), [`UNTUPLEVAR`](https://docs.ton.org/llms/tvm/instructions/content.md), [`UNPACKFIRST`](https://docs.ton.org/llms/tvm/instructions/content.md), [`UNPACKFIRSTVAR`](https://docs.ton.org/llms/tvm/instructions/content.md), [`EXPLODE`](https://docs.ton.org/llms/tvm/instructions/content.md), [`EXPLODEVAR`](https://docs.ton.org/llms/tvm/instructions/content.md) consumes `1` gas for each entry been pushed or popped into a tuple. [`TPUSH`](https://docs.ton.org/llms/tvm/instructions/content.md), [`TPOP`](https://docs.ton.org/llms/tvm/instructions/content.md), [`SETINDEX`](https://docs.ton.org/llms/tvm/instructions/content.md), [`SETINDEXVAR`](https://docs.ton.org/llms/tvm/instructions/content.md), [`SETINDEXQ`](https://docs.ton.org/llms/tvm/instructions/content.md)/[`SETINDEXVARQ`](https://docs.ton.org/llms/tvm/instructions/content.md) consumes `len(tuple)` gas for the resulting tuple size after push/pop/set. Same applies to instructions operating with `c7`: [`SETGLOB`](https://docs.ton.org/llms/tvm/instructions/content.md)/[`SETGLOBVAR`](https://docs.ton.org/llms/tvm/instructions/content.md), [`RANDU256`](https://docs.ton.org/llms/tvm/instructions/content.md)/[`RAND`](https://docs.ton.org/llms/tvm/instructions/content.md), [`SETRAND`](https://docs.ton.org/llms/tvm/instructions/content.md), [`ADDRAND`](https://docs.ton.org/llms/tvm/instructions/content.md).
## 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`](https://docs.ton.org/llms/tvm/instructions/content.md) and similar instructions, when using [`RUNVM`](https://docs.ton.org/llms/tvm/instructions/content.md) (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`](https://docs.ton.org/llms/tvm/instructions/content.md) and [`RUNVMX`](https://docs.ton.org/llms/tvm/instructions/content.md) consume `40` extra gas before starting a VM.
## Cryptography [#cryptography]
### CHKSIGNS/CHKSIGNU [#chksignschksignu]
[`CHKSIGNS`](https://docs.ton.org/llms/tvm/instructions/content.md) and [`CHKSIGNU`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) | 600 |
| [`RIST255_VALIDATE`](https://docs.ton.org/llms/tvm/instructions/content.md) | 200 |
| [`RIST255_ADD`](https://docs.ton.org/llms/tvm/instructions/content.md) | 600 |
| [`RIST255_MUL`](https://docs.ton.org/llms/tvm/instructions/content.md) | 2000 |
| [`RIST255_MULBASE`](https://docs.ton.org/llms/tvm/instructions/content.md) | 750 |
### Other instructions [#other-instructions]
[`ECRECOVER`](https://docs.ton.org/llms/tvm/instructions/content.md) consumes 1500 extra gas.
`SECP256K1_XONLY_PUBKEY_TWEAK_ADD` consumes 1250 extra gas.
[`P256_CHKSIGNU`](https://docs.ton.org/llms/tvm/instructions/content.md) and [`P256_CHKSIGNS`](https://docs.ton.org/llms/tvm/instructions/content.md) consume 3500 extra gas.
### BLS [#bls]
#### Signature verification and aggregation [#signature-verification-and-aggregation]
| Instruction | Gas consumed | Notes |
| ----------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------- |
| [`BLS_VERIFY`](https://docs.ton.org/llms/tvm/instructions/content.md) | `61000` | |
| [`BLS_AGGREGATE`](https://docs.ton.org/llms/tvm/instructions/content.md) | `-2650 + 4350 * n` | `n` is the number of signatures aggregated. |
| [`BLS_FASTAGGREGATEVERIFY`](https://docs.ton.org/llms/tvm/instructions/content.md) | `58000 + 3000 * n` | `n` is the number of public keys verified against one message/signature pair. |
| [`BLS_AGGREGATEVERIFY`](https://docs.ton.org/llms/tvm/instructions/content.md) | `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`](https://docs.ton.org/llms/tvm/instructions/content.md) / [`BLS_G1_SUB`](https://docs.ton.org/llms/tvm/instructions/content.md) | `3900` |
| [`BLS_G1_NEG`](https://docs.ton.org/llms/tvm/instructions/content.md) | `750` |
| [`BLS_G1_MUL`](https://docs.ton.org/llms/tvm/instructions/content.md) | `5200` |
| [`BLS_MAP_TO_G1`](https://docs.ton.org/llms/tvm/instructions/content.md) | `2350` |
| [`BLS_G1_INGROUP`](https://docs.ton.org/llms/tvm/instructions/content.md) | `2950` |
[`BLS_G1_MULTIEXP`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md) and [`BLS_G1_ISZERO`](https://docs.ton.org/llms/tvm/instructions/content.md) do not charge additional gas.
#### G2 group helpers [#g2-group-helpers]
| Instruction | Gas consumed |
| --------------------------------------------------------------------------------------------------------- | ------------ |
| [`BLS_G2_ADD`](https://docs.ton.org/llms/tvm/instructions/content.md) / [`BLS_G2_SUB`](https://docs.ton.org/llms/tvm/instructions/content.md) | `6100` |
| [`BLS_G2_NEG`](https://docs.ton.org/llms/tvm/instructions/content.md) | `1550` |
| [`BLS_G2_MUL`](https://docs.ton.org/llms/tvm/instructions/content.md) | `10550` |
| [`BLS_MAP_TO_G2`](https://docs.ton.org/llms/tvm/instructions/content.md) | `7950` |
| [`BLS_G2_INGROUP`](https://docs.ton.org/llms/tvm/instructions/content.md) | `4250` |
[`BLS_G2_MULTIEXP`](https://docs.ton.org/llms/tvm/instructions/content.md) consumes `30388 + 1280 * n + (22840 * n) / max(log₂ n, 4)` gas, where `n` is the number of `(point, scalar)` pairs.
Instructions [`BLS_G2_ZERO`](https://docs.ton.org/llms/tvm/instructions/content.md) and [`BLS_G2_ISZERO`](https://docs.ton.org/llms/tvm/instructions/content.md) do not charge additional gas.
#### Pairing and constants [#pairing-and-constants]
| Instruction | Gas consumed | Notes |
| ----------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------- |
| [`BLS_PAIRING`](https://docs.ton.org/llms/tvm/instructions/content.md) | `20000 + 11800 * n` | `n` is the number of `(G1, G2)` pairs supplied for the pairing product check. |
[`BLS_PUSHR`](https://docs.ton.org/llms/tvm/instructions/content.md) 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 GRAM 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 (https://docs.ton.org/llms/tvm/get-method/content.md)
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](https://docs.ton.org/llms/contracts/standard/tokens/nft/nft-reference/content.md)), 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](https://docs.ton.org/llms/contracts/standard/tokens/nft/nft-reference/content.md)). 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](https://docs.ton.org/llms/tvm/registers/content.md). 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](https://docs.ton.org/llms/tvm/registers/content.md) 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](https://docs.ton.org/llms/tvm/registers/content.md).
### Decentralized way [#decentralized-way]
The process of fetching the actual contract state and initializing c7 can be handled by [liteserver](https://docs.ton.org/llms/nodes/overview/content.md) 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](https://docs.ton.org/llms/foundations/serialization/boc/content.md) 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](https://docs.ton.org/llms/api/overview/content.md). It has a [`/api/v3/runGetMethod`](https://docs.ton.org/llms/api/v3/api-v2/run-get-method/content.md) 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 (https://docs.ton.org/llms/tvm/initialization/content.md)
## 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](https://docs.ton.org/llms/foundations/phases/content.md).
## Registers initialization [#registers-initialization]
For more info about registers, take a look at [Registers](https://docs.ton.org/llms/tvm/registers/content.md)
* `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)](https://docs.ton.org/llms/tvm/get-method/content.md)
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 nanograms (`0` for externals). |
| `s4` | Contract balance | `Integer` | Current account balance in nanograms. |
### Tick-tock [#tick-tock]
| 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 nanograms. |
### Split/merge events [#splitmerge-events]
These events are not implemented yet. Possible stack layout for split/merge events is described in [TON Blockchain](https://docs.ton.org/llms/foundations/whitepapers/tblkch/content.md) whitepaper. However, it is subject to change.
# Instructions (https://docs.ton.org/llms/tvm/instructions/content.md)
The [notation](#notation) section below explains how the table encodes TVM instruction opcodes and immediate arguments in binary.
## Notation [#notation]
### Opcodes [#opcodes]
TVM instructions are encoded as variable-length bit sequences, with each instruction being a multiple of a byte. The immediate arguments form a part of the instruction and have no special demarcation in a bitstream. This leads to some instructions sharing the same opcode *prefix*.
For instance, the `NOP` instruction has the full opcode `0x00`, which represents 8 consecutive zero bits (a null byte). At the same time, the `XCHG_0I` family of instructions starts with `0x0`, which is 4 consecutive zero bits, then continues with a 4-bit immediate argument ranging from `0x1` to `0xF`.
The `opcode` column lists instruction prefixes without arguments in hexadecimal, representing the corresponding bit sequences that are always multiples of 4. Yet, the `opcode` *box* on an instruction card shows the full [TL-B](https://docs.ton.org/llms/foundations/tlb/overview/content.md) schema for the instruction, including immediate arguments.
### Stack slots [#stack-slots]
The `s[i]` notation refers to the `i`-th stack slot counting from the top, and the top being the `0`-th slot. Particular stack slots are referenced directly as `s0`, `s1` and so forth in TASM, Fift and documentation, and are encoded simply by index in the binary.
### Bracket formulas [#bracket-formulas]
The `[32(c+1)] PLDUZ` notation means a value for `c` should be chosen, the calculation performed, and the result substituted. For example, with `c = 2`, the instruction is written as `96 PLDUZ` in Fift. The value `96` is the actual number of bits to read, while the bitstream stores only the value for `c`, and the TVM performs the calculation on its own.
#### `00` NOP [#00-nop]
Does nothing.
**Category:** Stack Basic (stack\_basic)
```fift title="Fift"
NOP
```
#### `0i` XCHG\_0I [#0i-xchg_0i]
Interchanges `s0` with `s[i]`, `1 <= i <= 15`.
**Category:** Stack Basic (stack\_basic)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
s[i] s[j] XCHG2
```
#### `51ij` XCPU [#51ij-xcpu]
Equivalent to `s[i] XCHG0` `s[j] PUSH`.
**Category:** Stack Complex (stack\_complex)
```fift title="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 title="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 title="Fift"
s[i] s[j] PUSH2
```
#### `540ijk` XCHG3\_ALT [#540ijk-xchg3_alt]
Long form of `XCHG3`.
**Category:** Stack Complex (stack\_complex)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
[ii] s() POP
```
#### `58` ROT [#58-rot]
Equivalent to `1 2 BLKSWAP` or to `s2 s1 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
ROT
```
#### `59` ROTREV [#59-rotrev]
Equivalent to `2 1 BLKSWAP` or to `s2 s2 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
ROTREV
-ROT
```
#### `5A` SWAP2 [#5a-swap2]
Equivalent to `2 2 BLKSWAP` or to `s3 s2 XCHG2`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
SWAP2
2SWAP
```
#### `5B` DROP2 [#5b-drop2]
Equivalent to `DROP` `DROP`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
DROP2
2DROP
```
#### `5C` DUP2 [#5c-dup2]
Equivalent to `s1 s0 PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
DUP2
2DUP
```
#### `5D` OVER2 [#5d-over2]
Equivalent to `s3 s2 PUSH2`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
OVER2
2OVER
```
#### `5Eij` REVERSE [#5eij-reverse]
Reverses the order of `s[j+i+1] ... s[j]`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
[i+2] [j] REVERSE
```
#### `5F0i` BLKDROP [#5f0i-blkdrop]
Equivalent to `DROP` performed `i` times.
**Category:** Stack Complex (stack\_complex)
```fift title="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 title="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 title="Fift"
PICK
PUSHX
```
#### `61` ROLLX [#61-rollx]
Pops integer `i` from the stack, then performs `1 [i] BLKSWAP`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
ROLLX
```
#### `62` -ROLLX [#62--rollx]
Pops integer `i` from the stack, then performs `[i] 1 BLKSWAP`.
**Category:** Stack Complex (stack\_complex)
```fift title="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 title="Fift"
BLKSWX
```
#### `64` REVX [#64-revx]
Pops integers `i`,`j` from the stack, then performs `[i] [j] REVERSE`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
REVX
```
#### `65` DROPX [#65-dropx]
Pops integer `i` from the stack, then performs `[i] BLKDROP`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
DROPX
```
#### `66` TUCK [#66-tuck]
Equivalent to `SWAP` `OVER` or to `s1 s1 XCPU`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
TUCK
```
#### `67` XCHGX [#67-xchgx]
Pops integer `i` from the stack, then performs `s[i] XCHG`.
**Category:** Stack Complex (stack\_complex)
```fift title="Fift"
XCHGX
```
#### `68` DEPTH [#68-depth]
Pushes the current depth of the stack.
**Category:** Stack Complex (stack\_complex)
```fift title="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 title="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 title="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 title="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 title="Fift"
[i] [j] BLKDROP2
```
#### `6D` NULL [#6d-null]
Pushes the only value of type *Null*.
**Category:** Tuple (tuple)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
TUPLEVAR
```
#### `6F81` INDEXVAR [#6f81-indexvar]
Similar to `k INDEX`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
INDEXVAR
```
#### `6F82` UNTUPLEVAR [#6f82-untuplevar]
Similar to `n UNTUPLE`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
UNTUPLEVAR
```
#### `6F83` UNPACKFIRSTVAR [#6f83-unpackfirstvar]
Similar to `n UNPACKFIRST`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
UNPACKFIRSTVAR
```
#### `6F84` EXPLODEVAR [#6f84-explodevar]
Similar to `n EXPLODE`, but with `0 <= n <= 255` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
EXPLODEVAR
```
#### `6F85` SETINDEXVAR [#6f85-setindexvar]
Similar to `k SETINDEX`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
SETINDEXVAR
```
#### `6F86` INDEXVARQ [#6f86-indexvarq]
Similar to `n INDEXQ`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
INDEXVARQ
```
#### `6F87` SETINDEXVARQ [#6f87-setindexvarq]
Similar to `k SETINDEXQ`, but with `0 <= k <= 254` taken from the stack.
**Category:** Tuple (tuple)
```fift title="Fift"
SETINDEXVARQ
```
#### `6F88` TLEN [#6f88-tlen]
Returns the length of a *Tuple*.
**Category:** Tuple (tuple)
```fift title="Fift"
TLEN
```
#### `6F89` QTLEN [#6f89-qtlen]
Similar to `TLEN`, but returns `-1` if `t` is not a *Tuple*.
**Category:** Tuple (tuple)
```fift title="Fift"
QTLEN
```
#### `6F8A` ISTUPLE [#6f8a-istuple]
Returns `-1` or `0` depending on whether `t` is a *Tuple*.
**Category:** Tuple (tuple)
```fift title="Fift"
ISTUPLE
```
#### `6F8B` LAST [#6f8b-last]
Returns the last element of a non-empty *Tuple* `t`.
**Category:** Tuple (tuple)
```fift title="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 title="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 title="Fift"
TPOP
```
#### `6FA0` NULLSWAPIF [#6fa0-nullswapif]
Pushes a *Null* under the topmost *Integer* `x`, but only if `x!=0`.
**Category:** Tuple (tuple)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
[xx+1] PUSHPOW2
```
#### `83FF` PUSHNAN [#83ff-pushnan]
Pushes a `NaN`.
**Category:** Const Int (const\_int)
```fift title="Fift"
PUSHNAN
```
#### `84xx` PUSHPOW2DEC [#84xx-pushpow2dec]
Pushes `2^(xx+1)-1` for `0 <= xx <= 255`.
**Category:** Const Int (const\_int)
```fift title="Fift"
[xx+1] PUSHPOW2DEC
```
#### `85xx` PUSHNEGPOW2 [#85xx-pushnegpow2]
Pushes `-2^(xx+1)` for `0 <= xx <= 255`.
**Category:** Const Int (const\_int)
```fift title="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 title="Fift"
[ref] PUSHREF
```
#### `89` PUSHREFSLICE [#89-pushrefslice]
Similar to `PUSHREF`, but converts the cell into a *Slice*.
**Category:** Const Data (const\_data)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
[builder] PUSHCONT
[builder] CONT
```
#### `A0` ADD [#a0-add]
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
ADD
```
#### `A1` SUB [#a1-sub]
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
SUB
```
#### `A2` SUBR [#a2-subr]
Equivalent to `SWAP` `SUB`.
**Category:** Arithm Basic (arithm\_basic)
```fift title="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 title="Fift"
NEGATE
```
#### `A4` INC [#a4-inc]
Equivalent to `1 ADDCONST`.
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
INC
```
#### `A5` DEC [#a5-dec]
Equivalent to `-1 ADDCONST`.
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
DEC
```
#### `A6cc` ADDCONST [#a6cc-addconst]
`-128 <= cc <= 127`.
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
[cc] ADDCONST
[cc] ADDINT
[-cc] SUBCONST
[-cc] SUBINT
```
#### `A7cc` MULCONST [#a7cc-mulconst]
`-128 <= cc <= 127`.
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
[cc] MULCONST
[cc] MULINT
```
#### `A8` MUL [#a8-mul]
**Category:** Arithm Basic (arithm\_basic)
```fift title="Fift"
MUL
```
#### `A900` ADDDIVMOD [#a900-adddivmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDDIVMOD
```
#### `A901` ADDDIVMODR [#a901-adddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDDIVMODR
```
#### `A902` ADDDIVMODC [#a902-adddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDDIVMODC
```
#### `A904` DIV [#a904-div]
`q=floor(x/y)`, `r=x-y*q`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIV
```
#### `A905` DIVR [#a905-divr]
`q'=round(x/y)`, `r'=x-y*q'`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIVR
```
#### `A906` DIVC [#a906-divc]
`q''=ceil(x/y)`, `r''=x-y*q''`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIVC
```
#### `A908` MOD [#a908-mod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MOD
```
#### `A909` MODR [#a909-modr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MODR
```
#### `A90A` MODC [#a90a-modc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MODC
```
#### `A90C` DIVMOD [#a90c-divmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIVMOD
```
#### `A90D` DIVMODR [#a90d-divmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIVMODR
```
#### `A90E` DIVMODC [#a90e-divmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
DIVMODC
```
#### `A920` ADDRSHIFTMOD\_VAR [#a920-addrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDRSHIFTMOD
```
#### `A921` ADDRSHIFTMODR [#a921-addrshiftmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDRSHIFTMODR
```
#### `A922` ADDRSHIFTMODC [#a922-addrshiftmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
ADDRSHIFTMODC
```
#### `A925` RSHIFTR\_VAR [#a925-rshiftr_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
RSHIFTR
```
#### `A926` RSHIFTC\_VAR [#a926-rshiftc_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
RSHIFTC
```
#### `A928` MODPOW2\_VAR [#a928-modpow2_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MODPOW2
```
#### `A929` MODPOW2R\_VAR [#a929-modpow2r_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MODPOW2R
```
#### `A92A` MODPOW2C\_VAR [#a92a-modpow2c_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MODPOW2C
```
#### `A92C` RSHIFTMOD\_VAR [#a92c-rshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
RSHIFTMOD
```
#### `A92D` RSHIFTMODR\_VAR [#a92d-rshiftmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
RSHIFTMODR
```
#### `A92E` RSHIFTMODC\_VAR [#a92e-rshiftmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
RSHIFTMODC
```
#### `A930tt` ADDRSHIFTMOD [#a930tt-addrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] ADDRSHIFT#MOD
```
#### `A931tt` ADDRSHIFTRMOD [#a931tt-addrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] ADDRSHIFTR#MOD
```
#### `A932tt` ADDRSHIFTCMOD [#a932tt-addrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] ADDRSHIFTC#MOD
```
#### `A935tt` RSHIFTR [#a935tt-rshiftr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] RSHIFTR#
```
#### `A936tt` RSHIFTC [#a936tt-rshiftc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] RSHIFTC#
```
#### `A938tt` MODPOW2 [#a938tt-modpow2]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MODPOW2#
```
#### `A939tt` MODPOW2R [#a939tt-modpow2r]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MODPOW2R#
```
#### `A93Att` MODPOW2C [#a93att-modpow2c]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MODPOW2C#
```
#### `A93Ctt` RSHIFTMOD [#a93ctt-rshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] RSHIFT#MOD
```
#### `A93Dtt` RSHIFTRMOD [#a93dtt-rshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] RSHIFTR#MOD
```
#### `A93Ett` RSHIFTCMOD [#a93ett-rshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] RSHIFTC#MOD
```
#### `A980` MULADDDIVMOD [#a980-muladddivmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDDIVMOD
```
#### `A981` MULADDDIVMODR [#a981-muladddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDDIVMODR
```
#### `A982` MULADDDIVMODC [#a982-muladddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDDIVMODC
```
#### `A984` MULDIV [#a984-muldiv]
`q=floor(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIV
```
#### `A985` MULDIVR [#a985-muldivr]
`q'=round(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIVR
```
#### `A986` MULDIVC [#a986-muldivc]
`q'=ceil(x*y/z)`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIVC
```
#### `A988` MULMOD [#a988-mulmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMOD
```
#### `A989` MULMODR [#a989-mulmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMODR
```
#### `A98A` MULMODC [#a98a-mulmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMODC
```
#### `A98C` MULDIVMOD [#a98c-muldivmod]
`q=floor(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIVMOD
```
#### `A98D` MULDIVMODR [#a98d-muldivmodr]
`q=round(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIVMODR
```
#### `A98E` MULDIVMODC [#a98e-muldivmodc]
`q=ceil(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULDIVMODC
```
#### `A9A0` MULADDRSHIFTMOD\_VAR [#a9a0-muladdrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDRSHIFTMOD
```
#### `A9A1` MULADDRSHIFTRMOD\_VAR [#a9a1-muladdrshiftrmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDRSHIFTRMOD
```
#### `A9A2` MULADDRSHIFTCMOD\_VAR [#a9a2-muladdrshiftcmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULADDRSHIFTCMOD
```
#### `A9A4` MULRSHIFT\_VAR [#a9a4-mulrshift_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFT
```
#### `A9A5` MULRSHIFTR\_VAR [#a9a5-mulrshiftr_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTR
```
#### `A9A6` MULRSHIFTC\_VAR [#a9a6-mulrshiftc_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTC
```
#### `A9A8` MULMODPOW2\_VAR [#a9a8-mulmodpow2_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMODPOW2_VAR
```
#### `A9A9` MULMODPOW2R\_VAR [#a9a9-mulmodpow2r_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMODPOW2R_VAR
```
#### `A9AA` MULMODPOW2C\_VAR [#a9aa-mulmodpow2c_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULMODPOW2C_VAR
```
#### `A9AC` MULRSHIFTMOD\_VAR [#a9ac-mulrshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTMOD_VAR
```
#### `A9AD` MULRSHIFTRMOD\_VAR [#a9ad-mulrshiftrmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTRMOD_VAR
```
#### `A9AE` MULRSHIFTCMOD\_VAR [#a9ae-mulrshiftcmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTCMOD_VAR
```
#### `A9B0tt` MULADDRSHIFTMOD [#a9b0tt-muladdrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULADDRSHIFT#MOD
```
#### `A9B1tt` MULADDRSHIFTRMOD [#a9b1tt-muladdrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULADDRSHIFTR#MOD
```
#### `A9B2tt` MULADDRSHIFTCMOD [#a9b2tt-muladdrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULADDRSHIFTC#MOD
```
#### `A9B4tt` MULRSHIFT [#a9b4tt-mulrshift]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULRSHIFT#
```
#### `A9B5tt` MULRSHIFTR [#a9b5tt-mulrshiftr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULRSHIFTR#
```
#### `A9B6tt` MULRSHIFTC [#a9b6tt-mulrshiftc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULRSHIFTC#
```
#### `A9B8tt` MULMODPOW2 [#a9b8tt-mulmodpow2]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULMODPOW2#
```
#### `A9B9tt` MULMODPOW2R [#a9b9tt-mulmodpow2r]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULMODPOW2R#
```
#### `A9BAtt` MULMODPOW2C [#a9batt-mulmodpow2c]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] MULMODPOW2C#
```
#### `A9BC` MULRSHIFTMOD [#a9bc-mulrshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFT#MOD
```
#### `A9BD` MULRSHIFTRMOD [#a9bd-mulrshiftrmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTR#MOD
```
#### `A9BE` MULRSHIFTCMOD [#a9be-mulrshiftcmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
MULRSHIFTC#MOD
```
#### `A9C0` LSHIFTADDDIVMOD\_VAR [#a9c0-lshiftadddivmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTADDDIVMOD
```
#### `A9C1` LSHIFTADDDIVMODR\_VAR [#a9c1-lshiftadddivmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTADDDIVMODR
```
#### `A9C2` LSHIFTADDDIVMODC\_VAR [#a9c2-lshiftadddivmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTADDDIVMODC
```
#### `A9C4` LSHIFTDIV\_VAR [#a9c4-lshiftdiv_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIV
```
#### `A9C5` LSHIFTDIVR\_VAR [#a9c5-lshiftdivr_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIVR
```
#### `A9C6` LSHIFTDIVC\_VAR [#a9c6-lshiftdivc_var]
`0 <= z <= 256`
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIVC
```
#### `A9C8` LSHIFTMOD\_VAR [#a9c8-lshiftmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTMOD
```
#### `A9C9` LSHIFTMODR\_VAR [#a9c9-lshiftmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTMODR
```
#### `A9CA` LSHIFTMODC\_VAR [#a9ca-lshiftmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTMODC
```
#### `A9CC` LSHIFTDIVMOD\_VAR [#a9cc-lshiftdivmod_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIVMOD
```
#### `A9CD` LSHIFTDIVMODR\_VAR [#a9cd-lshiftdivmodr_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIVMODR
```
#### `A9CE` LSHIFTDIVMODC\_VAR [#a9ce-lshiftdivmodc_var]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
LSHIFTDIVMODC
```
#### `A9D0tt` LSHIFTADDDIVMOD [#a9d0tt-lshiftadddivmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#ADDDIVMOD
```
#### `A9D1tt` LSHIFTADDDIVMODR [#a9d1tt-lshiftadddivmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#ADDDIVMODR
```
#### `A9D2tt` LSHIFTADDDIVMODC [#a9d2tt-lshiftadddivmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#ADDDIVMODC
```
#### `A9D4tt` LSHIFTDIV [#a9d4tt-lshiftdiv]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIV
```
#### `A9D5tt` LSHIFTDIVR [#a9d5tt-lshiftdivr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIVR
```
#### `A9D6tt` LSHIFTDIVC [#a9d6tt-lshiftdivc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIVC
```
#### `A9D8tt` LSHIFTMOD [#a9d8tt-lshiftmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#MOD
```
#### `A9D9tt` LSHIFTMODR [#a9d9tt-lshiftmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#MODR
```
#### `A9DAtt` LSHIFTMODC [#a9datt-lshiftmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#MODC
```
#### `A9DCtt` LSHIFTDIVMOD [#a9dctt-lshiftdivmod]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIVMOD
```
#### `A9DDtt` LSHIFTDIVMODR [#a9ddtt-lshiftdivmodr]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIVMODR
```
#### `A9DEtt` LSHIFTDIVMODC [#a9dett-lshiftdivmodc]
**Category:** Arithm Div (arithm\_div)
```fift title="Fift"
[tt+1] LSHIFT#DIVMODC
```
#### `AAcc` LSHIFT [#aacc-lshift]
`0 <= cc <= 255`
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
[cc+1] LSHIFT#
```
#### `ABcc` RSHIFT [#abcc-rshift]
`0 <= cc <= 255`
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
[cc+1] RSHIFT#
```
#### `AC` LSHIFT\_VAR [#ac-lshift_var]
`0 <= y <= 1023`
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
LSHIFT
```
#### `AD` RSHIFT\_VAR [#ad-rshift_var]
`0 <= y <= 1023`
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
RSHIFT
```
#### `AE` POW2 [#ae-pow2]
`0 <= y <= 1023` Equivalent to `ONE` `SWAP` `LSHIFT`.
**Category:** Arithm Logical (arithm\_logical)
```fift title="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 title="Fift"
AND
```
#### `B1` OR [#b1-or]
Bitwise or of two integers.
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
OR
```
#### `B2` XOR [#b2-xor]
Bitwise xor of two integers.
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
XOR
```
#### `B3` NOT [#b3-not]
Bitwise not of an integer.
**Category:** Arithm Logical (arithm\_logical)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
UBITSIZE
```
#### `B608` MIN [#b608-min]
Computes the minimum of two integers `x` and `y`.
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
MIN
```
#### `B609` MAX [#b609-max]
Computes the maximum of two integers `x` and `y`.
**Category:** Arithm Logical (arithm\_logical)
```fift title="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 title="Fift"
MINMAX
INTSORT2
```
#### `B60B` ABS [#b60b-abs]
Computes the absolute value of an integer `x`.
**Category:** Arithm Logical (arithm\_logical)
```fift title="Fift"
ABS
```
#### `B7A0` QADD [#b7a0-qadd]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADD
```
#### `B7A1` QSUB [#b7a1-qsub]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QSUB
```
#### `B7A2` QSUBR [#b7a2-qsubr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QSUBR
```
#### `B7A3` QNEGATE [#b7a3-qnegate]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QNEGATE
```
#### `B7A4` QINC [#b7a4-qinc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QINC
```
#### `B7A5` QDEC [#b7a5-qdec]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDEC
```
#### `B7A8` QMUL [#b7a8-qmul]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMUL
```
#### `B7A900` QADDDIVMOD [#b7a900-qadddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDDIVMOD
```
#### `B7A901` QADDDIVMODR [#b7a901-qadddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDDIVMODR
```
#### `B7A902` QADDDIVMODC [#b7a902-qadddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDDIVMODC
```
#### `B7A904` QDIV [#b7a904-qdiv]
Division returns `NaN` if `y=0`.
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIV
```
#### `B7A905` QDIVR [#b7a905-qdivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIVR
```
#### `B7A906` QDIVC [#b7a906-qdivc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIVC
```
#### `B7A908` QMOD [#b7a908-qmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMOD
```
#### `B7A909` QMODR [#b7a909-qmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMODR
```
#### `B7A90A` QMODC [#b7a90a-qmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMODC
```
#### `B7A90C` QDIVMOD [#b7a90c-qdivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIVMOD
```
#### `B7A90D` QDIVMODR [#b7a90d-qdivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIVMODR
```
#### `B7A90E` QDIVMODC [#b7a90e-qdivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QDIVMODC
```
#### `B7A920` QADDRSHIFTMOD [#b7a920-qaddrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDRSHIFTMOD
```
#### `B7A921` QADDRSHIFTMODR [#b7a921-qaddrshiftmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDRSHIFTMODR
```
#### `B7A922` QADDRSHIFTMODC [#b7a922-qaddrshiftmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QADDRSHIFTMODC
```
#### `B7A925` QRSHIFTR\_VAR [#b7a925-qrshiftr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFTR
```
#### `B7A926` QRSHIFTC\_VAR [#b7a926-qrshiftc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFTC
```
#### `B7A928` QMODPOW2\_VAR [#b7a928-qmodpow2_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMODPOW2
```
#### `B7A929` QMODPOW2R\_VAR [#b7a929-qmodpow2r_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMODPOW2R
```
#### `B7A92A` QMODPOW2C\_VAR [#b7a92a-qmodpow2c_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMODPOW2C
```
#### `B7A92C` QRSHIFTMOD\_VAR [#b7a92c-qrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFTMOD
```
#### `B7A92D` QRSHIFTMODR\_VAR [#b7a92d-qrshiftmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFTMODR
```
#### `B7A92E` QRSHIFTMODC\_VAR [#b7a92e-qrshiftmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFTMODC
```
#### `B7A930tt` QADDRSHIFTMOD [#b7a930tt-qaddrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QADDRSHIFT#MOD
```
#### `B7A931tt` QADDRSHIFTRMOD [#b7a931tt-qaddrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QADDRSHIFTR#MOD
```
#### `B7A932tt` QADDRSHIFTCMOD [#b7a932tt-qaddrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QADDRSHIFTC#MOD
```
#### `B7A935tt` QRSHIFTR [#b7a935tt-qrshiftr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QRSHIFTR#
```
#### `B7A936tt` QRSHIFTC [#b7a936tt-qrshiftc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QRSHIFTC#
```
#### `B7A938tt` QMODPOW2 [#b7a938tt-qmodpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMODPOW2#
```
#### `B7A939tt` QMODPOW2R [#b7a939tt-qmodpow2r]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMODPOW2R#
```
#### `B7A93Att` QMODPOW2C [#b7a93att-qmodpow2c]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMODPOW2C#
```
#### `B7A93Ctt` QRSHIFTMOD [#b7a93ctt-qrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QRSHIFT#MOD
```
#### `B7A93Dtt` QRSHIFTRMOD [#b7a93dtt-qrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QRSHIFTR#MOD
```
#### `B7A93Ett` QRSHIFTCMOD [#b7a93ett-qrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QRSHIFTC#MOD
```
#### `B7A980` QMULADDDIVMOD [#b7a980-qmuladddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDDIVMOD
```
#### `B7A981` QMULADDDIVMODR [#b7a981-qmuladddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDDIVMODR
```
#### `B7A982` QMULADDDIVMODC [#b7a982-qmuladddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDDIVMODC
```
#### `B7A984` QMULDIV [#b7a984-qmuldiv]
`q=floor(x*y/z)`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIV
```
#### `B7A985` QMULDIVR [#b7a985-qmuldivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIVR
```
#### `B7A986` QMULDIVC [#b7a986-qmuldivc]
`q'=ceil(x*y/z)`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIVC
```
#### `B7A988` QMULMOD [#b7a988-qmulmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMOD
```
#### `B7A989` QMULMODR [#b7a989-qmulmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMODR
```
#### `B7A98A` QMULMODC [#b7a98a-qmulmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMODC
```
#### `B7A98C` QMULDIVMOD [#b7a98c-qmuldivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIVMOD
```
#### `B7A98D` QMULDIVMODR [#b7a98d-qmuldivmodr]
`q=round(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIVMODR
```
#### `B7A98E` QMULDIVMODC [#b7a98e-qmuldivmodc]
`q=ceil(x*y/z)`, `r=x*y-z*q`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULDIVMODC
```
#### `B7A9A0` QMULADDRSHIFTMOD\_VAR [#b7a9a0-qmuladdrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDRSHIFTMOD
```
#### `B7A9A1` QMULADDRSHIFTRMOD\_VAR [#b7a9a1-qmuladdrshiftrmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDRSHIFTRMOD
```
#### `B7A9A2` QMULADDRSHIFTCMOD\_VAR [#b7a9a2-qmuladdrshiftcmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULADDRSHIFTCMOD
```
#### `B7A9A4` QMULRSHIFT\_VAR [#b7a9a4-qmulrshift_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFT
```
#### `B7A9A5` QMULRSHIFTR\_VAR [#b7a9a5-qmulrshiftr_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTR
```
#### `B7A9A6` QMULRSHIFTC\_VAR [#b7a9a6-qmulrshiftc_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTC
```
#### `B7A9A8` QMULMODPOW2\_VAR [#b7a9a8-qmulmodpow2_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMODPOW2_VAR
```
#### `B7A9A9` QMULMODPOW2R\_VAR [#b7a9a9-qmulmodpow2r_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMODPOW2R_VAR
```
#### `B7A9AA` QMULMODPOW2C\_VAR [#b7a9aa-qmulmodpow2c_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULMODPOW2C_VAR
```
#### `B7A9AC` QMULRSHIFTMOD\_VAR [#b7a9ac-qmulrshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTMOD_VAR
```
#### `B7A9AD` QMULRSHIFTRMOD\_VAR [#b7a9ad-qmulrshiftrmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTRMOD_VAR
```
#### `B7A9AE` QMULRSHIFTCMOD\_VAR [#b7a9ae-qmulrshiftcmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTCMOD_VAR
```
#### `B7A9B0tt` QMULADDRSHIFTMOD [#b7a9b0tt-qmuladdrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULADDRSHIFT#MOD
```
#### `B7A9B1tt` QMULADDRSHIFTRMOD [#b7a9b1tt-qmuladdrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULADDRSHIFTR#MOD
```
#### `B7A9B2tt` QMULADDRSHIFTCMOD [#b7a9b2tt-qmuladdrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULADDRSHIFTC#MOD
```
#### `B7A9B4tt` QMULRSHIFT [#b7a9b4tt-qmulrshift]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULRSHIFT#
```
#### `B7A9B5tt` QMULRSHIFTR [#b7a9b5tt-qmulrshiftr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULRSHIFTR#
```
#### `B7A9B6tt` QMULRSHIFTC [#b7a9b6tt-qmulrshiftc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULRSHIFTC#
```
#### `B7A9B8tt` QMULMODPOW2 [#b7a9b8tt-qmulmodpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULMODPOW2#
```
#### `B7A9B9tt` QMULMODPOW2R [#b7a9b9tt-qmulmodpow2r]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULMODPOW2R#
```
#### `B7A9BAtt` QMULMODPOW2C [#b7a9batt-qmulmodpow2c]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QMULMODPOW2C#
```
#### `B7A9BC` QMULRSHIFTMOD [#b7a9bc-qmulrshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFT#MOD
```
#### `B7A9BD` QMULRSHIFTRMOD [#b7a9bd-qmulrshiftrmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTR#MOD
```
#### `B7A9BE` QMULRSHIFTCMOD [#b7a9be-qmulrshiftcmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QMULRSHIFTC#MOD
```
#### `B7A9C0` QLSHIFTADDDIVMOD\_VAR [#b7a9c0-qlshiftadddivmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTADDDIVMOD
```
#### `B7A9C1` QLSHIFTADDDIVMODR\_VAR [#b7a9c1-qlshiftadddivmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTADDDIVMODR
```
#### `B7A9C2` QLSHIFTADDDIVMODC\_VAR [#b7a9c2-qlshiftadddivmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTADDDIVMODC
```
#### `B7A9C4` QLSHIFTDIV\_VAR [#b7a9c4-qlshiftdiv_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIV
```
#### `B7A9C5` QLSHIFTDIVR\_VAR [#b7a9c5-qlshiftdivr_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIVR
```
#### `B7A9C6` QLSHIFTDIVC\_VAR [#b7a9c6-qlshiftdivc_var]
`0 <= z <= 256`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIVC
```
#### `B7A9C8` QLSHIFTMOD\_VAR [#b7a9c8-qlshiftmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTMOD
```
#### `B7A9C9` QLSHIFTMODR\_VAR [#b7a9c9-qlshiftmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTMODR
```
#### `B7A9CA` QLSHIFTMODC\_VAR [#b7a9ca-qlshiftmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTMODC
```
#### `B7A9CC` QLSHIFTDIVMOD\_VAR [#b7a9cc-qlshiftdivmod_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIVMOD
```
#### `B7A9CD` QLSHIFTDIVMODR\_VAR [#b7a9cd-qlshiftdivmodr_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIVMODR
```
#### `B7A9CE` QLSHIFTDIVMODC\_VAR [#b7a9ce-qlshiftdivmodc_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFTDIVMODC
```
#### `B7A9D0tt` QLSHIFTADDDIVMOD [#b7a9d0tt-qlshiftadddivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#ADDDIVMOD
```
#### `B7A9D1tt` QLSHIFTADDDIVMODR [#b7a9d1tt-qlshiftadddivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#ADDDIVMODR
```
#### `B7A9D2tt` QLSHIFTADDDIVMODC [#b7a9d2tt-qlshiftadddivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#ADDDIVMODC
```
#### `B7A9D4tt` QLSHIFTDIV [#b7a9d4tt-qlshiftdiv]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIV
```
#### `B7A9D5tt` QLSHIFTDIVR [#b7a9d5tt-qlshiftdivr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIVR
```
#### `B7A9D6tt` QLSHIFTDIVC [#b7a9d6tt-qlshiftdivc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIVC
```
#### `B7A9D8tt` QLSHIFTMOD [#b7a9d8tt-qlshiftmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#MOD
```
#### `B7A9D9tt` QLSHIFTMODR [#b7a9d9tt-qlshiftmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#MODR
```
#### `B7A9DAtt` QLSHIFTMODC [#b7a9datt-qlshiftmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#MODC
```
#### `B7A9DCtt` QLSHIFTDIVMOD [#b7a9dctt-qlshiftdivmod]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIVMOD
```
#### `B7A9DDtt` QLSHIFTDIVMODR [#b7a9ddtt-qlshiftdivmodr]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIVMODR
```
#### `B7A9DEtt` QLSHIFTDIVMODC [#b7a9dett-qlshiftdivmodc]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[tt+1] QLSHIFT#DIVMODC
```
#### `B7AAcc` QLSHIFT [#b7aacc-qlshift]
`0 <= cc <= 255`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[cc+1] QLSHIFT#
```
#### `B7ABcc` QRSHIFT [#b7abcc-qrshift]
`0 <= cc <= 255`
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
[cc+1] QRSHIFT#
```
#### `B7AC` QLSHIFT\_VAR [#b7ac-qlshift_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QLSHIFT
```
#### `B7AD` QRSHIFT\_VAR [#b7ad-qrshift_var]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QRSHIFT
```
#### `B7AE` QPOW2 [#b7ae-qpow2]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QPOW2
```
#### `B7B0` QAND [#b7b0-qand]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QAND
```
#### `B7B1` QOR [#b7b1-qor]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QOR
```
#### `B7B2` QXOR [#b7b2-qxor]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="Fift"
QXOR
```
#### `B7B3` QNOT [#b7b3-qnot]
**Category:** Arithm Quiet (arithm\_quiet)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
SGN
```
#### `B9` LESS [#b9-less]
Returns `-1` if `x
**Category:** Compare Int (compare\_int)
```fift title="Fift"
LESS
```
#### `BA` EQUAL [#ba-equal]
Returns `-1` if `x=y`, `0` otherwise.
**Category:** Compare Int (compare\_int)
```fift title="Fift"
EQUAL
```
#### `BB` LEQ [#bb-leq]
**Category:** Compare Int (compare\_int)
```fift title="Fift"
LEQ
```
#### `BC` GREATER [#bc-greater]
**Category:** Compare Int (compare\_int)
```fift title="Fift"
GREATER
```
#### `BD` NEQ [#bd-neq]
Equivalent to `EQUAL` `NOT`.
**Category:** Compare Int (compare\_int)
```fift title="Fift"
NEQ
```
#### `BE` GEQ [#be-geq]
Equivalent to `LESS` `NOT`.
**Category:** Compare Int (compare\_int)
```fift title="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 title="Fift"
CMP
```
#### `C0yy` EQINT [#c0yy-eqint]
Returns `-1` if `x=yy`, `0` otherwise. `-2^7 <= yy < 2^7`.
**Category:** Compare Int (compare\_int)
```fift title="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 title="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 title="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 title="Fift"
[yy] NEQINT
```
#### `C4` ISNAN [#c4-isnan]
Checks whether `x` is a `NaN`.
**Category:** Compare Int (compare\_int)
```fift title="Fift"
ISNAN
```
#### `C5` CHKNAN [#c5-chknan]
Throws an arithmetic overflow exception if `x` is a `NaN`.
**Category:** Compare Int (compare\_int)
```fift title="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 title="Fift"
SEMPTY
```
#### `C701` SDEMPTY [#c701-sdempty]
Checks whether *Slice* `s` has no bits of data.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDEMPTY
```
#### `C702` SREMPTY [#c702-srempty]
Checks whether *Slice* `s` has no references.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SREMPTY
```
#### `C703` SDFIRST [#c703-sdfirst]
Checks whether the first bit of *Slice* `s` is a one.
**Category:** Compare Other (compare\_other)
```fift title="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 title="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 title="Fift"
SDEQ
```
#### `C708` SDPFX [#c708-sdpfx]
Checks whether `s` is a prefix of `s'`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDPFX
```
#### `C709` SDPFXREV [#c709-sdpfxrev]
Checks whether `s'` is a prefix of `s`, equivalent to `SWAP` `SDPFX`.
**Category:** Compare Other (compare\_other)
```fift title="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 title="Fift"
SDPPFX
```
#### `C70B` SDPPFXREV [#c70b-sdppfxrev]
Checks whether `s'` is a proper prefix of `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDPPFXREV
```
#### `C70C` SDSFX [#c70c-sdsfx]
Checks whether `s` is a suffix of `s'`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDSFX
```
#### `C70D` SDSFXREV [#c70d-sdsfxrev]
Checks whether `s'` is a suffix of `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDSFXREV
```
#### `C70E` SDPSFX [#c70e-sdpsfx]
Checks whether `s` is a proper suffix of `s'`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDPSFX
```
#### `C70F` SDPSFXREV [#c70f-sdpsfxrev]
Checks whether `s'` is a proper suffix of `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDPSFXREV
```
#### `C710` SDCNTLEAD0 [#c710-sdcntlead0]
Returns the number of leading zeroes in `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDCNTLEAD0
```
#### `C711` SDCNTLEAD1 [#c711-sdcntlead1]
Returns the number of leading ones in `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDCNTLEAD1
```
#### `C712` SDCNTTRAIL0 [#c712-sdcnttrail0]
Returns the number of trailing zeroes in `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDCNTTRAIL0
```
#### `C713` SDCNTTRAIL1 [#c713-sdcnttrail1]
Returns the number of trailing ones in `s`.
**Category:** Compare Other (compare\_other)
```fift title="Fift"
SDCNTTRAIL1
```
#### `C8` NEWC [#c8-newc]
Creates a new empty *Builder*.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
NEWC
```
#### `C9` ENDC [#c9-endc]
Converts a *Builder* into an ordinary *Cell*.
**Category:** Cell Build (cell\_build)
```fift title="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 title="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 title="Fift"
[cc+1] STU
```
#### `CC` STREF [#cc-stref]
Stores a reference to *Cell* `c` into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STREF
```
#### `CD` STBREFR [#cd-stbrefr]
Equivalent to `ENDC` `SWAP` `STREF`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBREFR
ENDCST
```
#### `CE` STSLICE [#ce-stslice]
Stores *Slice* `s` into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="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 title="Fift"
STUX
```
#### `CF02` STIXR [#cf02-stixr]
Similar to `STIX`, but with arguments in a different order.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STIXR
```
#### `CF03` STUXR [#cf03-stuxr]
Similar to `STUX`, but with arguments in a different order.
**Category:** Cell Build (cell\_build)
```fift title="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 title="Fift"
STIXQ
```
#### `CF05` STUXQ [#cf05-stuxq]
A quiet version of `STUX`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STUXQ
```
#### `CF06` STIXRQ [#cf06-stixrq]
A quiet version of `STIXR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STIXRQ
```
#### `CF07` STUXRQ [#cf07-stuxrq]
A quiet version of `STUXR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STUXRQ
```
#### `CF08cc` STI\_ALT [#cf08cc-sti_alt]
A longer version of `[cc+1] STI`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STI_l
```
#### `CF09cc` STU\_ALT [#cf09cc-stu_alt]
A longer version of `[cc+1] STU`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STU_l
```
#### `CF0Acc` STIR [#cf0acc-stir]
Equivalent to `SWAP` `[cc+1] STI`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STIR
```
#### `CF0Bcc` STUR [#cf0bcc-stur]
Equivalent to `SWAP` `[cc+1] STU`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STUR
```
#### `CF0Ccc` STIQ [#cf0ccc-stiq]
A quiet version of `STI`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STIQ
```
#### `CF0Dcc` STUQ [#cf0dcc-stuq]
A quiet version of `STU`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STUQ
```
#### `CF0Ecc` STIRQ [#cf0ecc-stirq]
A quiet version of `STIR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STIRQ
```
#### `CF0Fcc` STURQ [#cf0fcc-sturq]
A quiet version of `STUR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[cc+1] STURQ
```
#### `CF10` STREF\_ALT [#cf10-stref_alt]
A longer version of `STREF`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STREF_l
```
#### `CF11` STBREF [#cf11-stbref]
Equivalent to `SWAP` `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBREF
```
#### `CF12` STSLICE\_ALT [#cf12-stslice_alt]
A longer version of `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STSLICE_l
```
#### `CF13` STB [#cf13-stb]
Appends all data from *Builder* `b'` to *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STB
```
#### `CF14` STREFR [#cf14-strefr]
Equivalent to `SWAP` `STREF`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STREFR
```
#### `CF15` STBREFR\_ALT [#cf15-stbrefr_alt]
A longer encoding of `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBREFR_l
```
#### `CF16` STSLICER [#cf16-stslicer]
Equivalent to `SWAP` `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STSLICER
```
#### `CF17` STBR [#cf17-stbr]
Concatenates two builders. Equivalent to `SWAP` `STB`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBR
BCONCAT
```
#### `CF18` STREFQ [#cf18-strefq]
Quiet version of `STREF`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STREFQ
```
#### `CF19` STBREFQ [#cf19-stbrefq]
Quiet version of `STBREF`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBREFQ
```
#### `CF1A` STSLICEQ [#cf1a-stsliceq]
Quiet version of `STSLICE`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STSLICEQ
```
#### `CF1B` STBQ [#cf1b-stbq]
Quiet version of `STB`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBQ
```
#### `CF1C` STREFRQ [#cf1c-strefrq]
Quiet version of `STREFR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STREFRQ
```
#### `CF1D` STBREFRQ [#cf1d-stbrefrq]
Quiet version of `STBREFR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBREFRQ
```
#### `CF1E` STSLICERQ [#cf1e-stslicerq]
Quiet version of `STSLICER`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STSLICERQ
```
#### `CF1F` STBRQ [#cf1f-stbrq]
Quiet version of `STBR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STBRQ
BCONCATQ
```
#### `CF20` STREFCONST [#cf20-strefconst]
Equivalent to `PUSHREF` `STREFR`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
[ref] STREFCONST
```
#### `CF21` STREF2CONST [#cf21-stref2const]
Equivalent to `STREFCONST` `STREFCONST`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="Fift"
ENDXC
```
#### `CF28` STILE4 [#cf28-stile4]
Stores a little-endian signed 32-bit integer.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STILE4
```
#### `CF29` STULE4 [#cf29-stule4]
Stores a little-endian unsigned 32-bit integer.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STULE4
```
#### `CF2A` STILE8 [#cf2a-stile8]
Stores a little-endian signed 64-bit integer.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STILE8
```
#### `CF2B` STULE8 [#cf2b-stule8]
Stores a little-endian unsigned 64-bit integer.
**Category:** Cell Build (cell\_build)
```fift title="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 title="Fift"
BDEPTH
```
#### `CF31` BBITS [#cf31-bbits]
Returns the number of data bits already stored in *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
BBITS
```
#### `CF32` BREFS [#cf32-brefs]
Returns the number of cell references already stored in `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
BREFS
```
#### `CF33` BBITREFS [#cf33-bbitrefs]
Returns the numbers of both data bits and cell references in `b`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="Fift"
BREMBITS
```
#### `CF36` BREMREFS [#cf36-bremrefs]
Returns the number of references that can still be stored in `b`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="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 title="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 title="Fift"
BCHKBITS
```
#### `CF3A` BCHKREFS [#cf3a-bchkrefs]
Checks whether `y` references can be stored into `b`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="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 title="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 title="Fift"
BCHKBITSQ
```
#### `CF3E` BCHKREFSQ [#cf3e-bchkrefsq]
Checks whether `y` references can be stored into `b`, `0 <= y <= 7`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="Fift"
BCHKBITREFSQ
```
#### `CF40` STZEROES [#cf40-stzeroes]
Stores `n` binary zeroes into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STZEROES
```
#### `CF41` STONES [#cf41-stones]
Stores `n` binary ones into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="Fift"
STONES
```
#### `CF42` STSAME [#cf42-stsame]
Stores `n` binary `x`es (`0 <= x <= 1`) into *Builder* `b`.
**Category:** Cell Build (cell\_build)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
[cc+1] LDU
```
#### `D4` LDREF [#d4-ldref]
Loads a cell reference `c` from `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDREF
```
#### `D5` LDREFRTOS [#d5-ldrefrtos]
Equivalent to `LDREF` `SWAP` `CTOS`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="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 title="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 title="Fift"
PLDIX
```
#### `D703` PLDUX [#d703-pldux]
Preloads an unsigned `l`-bit integer from `s`, for `0 <= l <= 256`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="Fift"
LDIXQ
```
#### `D705` LDUXQ [#d705-lduxq]
Quiet version of `LDUX`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDUXQ
```
#### `D706` PLDIXQ [#d706-pldixq]
Quiet version of `PLDIX`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDIXQ
```
#### `D707` PLDUXQ [#d707-plduxq]
Quiet version of `PLDUX`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDUXQ
```
#### `D708cc` LDI\_ALT [#d708cc-ldi_alt]
A longer encoding for `LDI`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] LDI_l
```
#### `D709cc` LDU\_ALT [#d709cc-ldu_alt]
A longer encoding for `LDU`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="Fift"
[cc+1] PLDI
```
#### `D70Bcc` PLDU [#d70bcc-pldu]
Preloads an unsigned `cc+1`-bit integer from `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] PLDU
```
#### `D70Ccc` LDIQ [#d70ccc-ldiq]
A quiet version of `LDI`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] LDIQ
```
#### `D70Dcc` LDUQ [#d70dcc-lduq]
A quiet version of `LDU`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] LDUQ
```
#### `D70Ecc` PLDIQ [#d70ecc-pldiq]
A quiet version of `PLDI`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] PLDIQ
```
#### `D70Fcc` PLDUQ [#d70fcc-plduq]
A quiet version of `PLDU`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="Fift"
LDSLICEX
```
#### `D719` PLDSLICEX [#d719-pldslicex]
Returns the first `0 <= l <= 1023` bits of `s` as `s''`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDSLICEX
```
#### `D71A` LDSLICEXQ [#d71a-ldslicexq]
A quiet version of `LDSLICEX`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDSLICEXQ
```
#### `D71B` PLDSLICEXQ [#d71b-pldslicexq]
A quiet version of `LDSLICEXQ`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDSLICEXQ
```
#### `D71Ccc` LDSLICE\_ALT [#d71ccc-ldslice_alt]
A longer encoding for `LDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="Fift"
[cc+1] PLDSLICE
```
#### `D71Ecc` LDSLICEQ [#d71ecc-ldsliceq]
A quiet version of `LDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[cc+1] LDSLICEQ
```
#### `D71Fcc` PLDSLICEQ [#d71fcc-pldsliceq]
A quiet version of `PLDSLICE`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="Fift"
SDSKIPFIRST
```
#### `D722` SDCUTLAST [#d722-sdcutlast]
Returns the last `0 <= l <= 1023` bits of `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
SDCUTLAST
```
#### `D723` SDSKIPLAST [#d723-sdskiplast]
Returns all but the last `0 <= l <= 1023` bits of `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="Fift"
SDBEGINSX
```
#### `D727` SDBEGINSXQ [#d727-sdbeginsxq]
A quiet version of `SDBEGINSX`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="Fift"
[slice] SDBEGINS
```
#### `D72E_xsss` SDBEGINSQ [#d72e_xsss-sdbeginsq]
A quiet version of `SDBEGINS`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
SPLIT
```
#### `D737` SPLITQ [#d737-splitq]
A quiet version of `SPLIT`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="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 title="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 title="Fift"
SCHKBITS
```
#### `D742` SCHKREFS [#d742-schkrefs]
Checks whether there are at least `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="Fift"
SCHKBITREFS
```
#### `D745` SCHKBITSQ [#d745-schkbitsq]
Checks whether there are at least `l` data bits in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
SCHKBITSQ
```
#### `D746` SCHKREFSQ [#d746-schkrefsq]
Checks whether there are at least `r` references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="Fift"
PLDREFVAR
```
#### `D749` SBITS [#d749-sbits]
Returns the number of data bits in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
SBITS
```
#### `D74A` SREFS [#d74a-srefs]
Returns the number of references in *Slice* `s`.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="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 title="Fift"
LDILE4
```
#### `D751` LDULE4 [#d751-ldule4]
Loads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDULE4
```
#### `D752` LDILE8 [#d752-ldile8]
Loads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDILE8
```
#### `D753` LDULE8 [#d753-ldule8]
Loads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDULE8
```
#### `D754` PLDILE4 [#d754-pldile4]
Preloads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDILE4
```
#### `D755` PLDULE4 [#d755-pldule4]
Preloads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDULE4
```
#### `D756` PLDILE8 [#d756-pldile8]
Preloads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDILE8
```
#### `D757` PLDULE8 [#d757-pldule8]
Preloads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDULE8
```
#### `D758` LDILE4Q [#d758-ldile4q]
Quietly loads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDILE4Q
```
#### `D759` LDULE4Q [#d759-ldule4q]
Quietly loads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDULE4Q
```
#### `D75A` LDILE8Q [#d75a-ldile8q]
Quietly loads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDILE8Q
```
#### `D75B` LDULE8Q [#d75b-ldule8q]
Quietly loads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
LDULE8Q
```
#### `D75C` PLDILE4Q [#d75c-pldile4q]
Quietly preloads a little-endian signed 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDILE4Q
```
#### `D75D` PLDULE4Q [#d75d-pldule4q]
Quietly preloads a little-endian unsigned 32-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDULE4Q
```
#### `D75E` PLDILE8Q [#d75e-pldile8q]
Quietly preloads a little-endian signed 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
PLDILE8Q
```
#### `D75F` PLDULE8Q [#d75f-pldule8q]
Quietly preloads a little-endian unsigned 64-bit integer.
**Category:** Cell Parse (cell\_parse)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
CDEPTH
```
#### `D766` CLEVEL [#d766-clevel]
Returns level of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
CLEVEL
```
#### `D767` CLEVELMASK [#d767-clevelmask]
Returns level mask of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
CLEVELMASK
```
#### `D76A_` CHASHI [#d76a_-chashi]
Returns `i`th hash of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[i] CHASHI
```
#### `D76E_` CDEPTHI [#d76e_-cdepthi]
Returns `i`th depth of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
[i] CDEPTHI
```
#### `D770` CHASHIX [#d770-chashix]
Returns `i`th hash of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
CHASHIX
```
#### `D771` CDEPTHIX [#d771-cdepthix]
Returns `i`th depth of the cell.
**Category:** Cell Parse (cell\_parse)
```fift title="Fift"
CDEPTHIX
```
#### `D8` EXECUTE [#d8-execute]
*Calls*, or *executes*, continuation `c`.
**Category:** Cont Basic (cont\_basic)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
RETALT
RETFALSE
```
#### `DB32` BRANCH [#db32-branch]
Performs `RETTRUE` if integer `f!=0`, or `RETFALSE` if `f=0`.
**Category:** Cont Basic (cont\_basic)
```fift title="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 title="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 title="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 title="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 title="Fift"
CALLXVARARGS
```
#### `DB39` RETVARARGS [#db39-retvarargs]
Similar to `RETARGS`.
**Category:** Cont Basic (cont\_basic)
```fift title="Fift"
RETVARARGS
```
#### `DB3A` JMPXVARARGS [#db3a-jmpxvarargs]
Similar to `JMPXARGS`.
**Category:** Cont Basic (cont\_basic)
```fift title="Fift"
JMPXVARARGS
```
#### `DB3B` CALLCCVARARGS [#db3b-callccvarargs]
Similar to `CALLCCARGS`.
**Category:** Cont Basic (cont\_basic)
```fift title="Fift"
CALLCCVARARGS
```
#### `DB3C` CALLREF [#db3c-callref]
Equivalent to `PUSHREFCONT` `CALLX`.
**Category:** Cont Basic (cont\_basic)
```fift title="Fift"
[ref] CALLREF
```
#### `DB3D` JMPREF [#db3d-jmpref]
Equivalent to `PUSHREFCONT` `JMPX`.
**Category:** Cont Basic (cont\_basic)
```fift title="Fift"
[ref] JMPREF
```
#### `DB3E` JMPREFDATA [#db3e-jmprefdata]
Equivalent to `PUSHREFCONT` `JMPXDATA`.
**Category:** Cont Basic (cont\_basic)
```fift title="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 title="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 title="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 title="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 title="Fift"
IFRET
IFNOT:
```
#### `DD` IFNOTRET [#dd-ifnotret]
Performs a `RET`, but only if integer `f` is zero.
**Category:** Cont Conditional (cont\_conditional)
```fift title="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 title="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 title="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 title="Fift"
IFJMP
```
#### `E1` IFNOTJMP [#e1-ifnotjmp]
Jumps to `c` (similarly to `JMPX`), but only if `f` is zero.
**Category:** Cont Conditional (cont\_conditional)
```fift title="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 title="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 title="Fift"
[ref] IFREF
```
#### `E301` IFNOTREF [#e301-ifnotref]
Equivalent to `PUSHREFCONT` `IFNOT`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="Fift"
[ref] IFNOTREF
```
#### `E302` IFJMPREF [#e302-ifjmpref]
Equivalent to `PUSHREFCONT` `IFJMP`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="Fift"
[ref] IFJMPREF
```
#### `E303` IFNOTJMPREF [#e303-ifnotjmpref]
Equivalent to `PUSHREFCONT` `IFNOTJMP`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="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 title="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 title="Fift"
CONDSELCHK
```
#### `E308` IFRETALT [#e308-ifretalt]
Performs `RETALT` if integer `f!=0`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="Fift"
IFRETALT
```
#### `E309` IFNOTRETALT [#e309-ifnotretalt]
Performs `RETALT` if integer `f=0`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="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 title="Fift"
[ref] IFREFELSE
```
#### `E30E` IFELSEREF [#e30e-ifelseref]
Equivalent to `PUSHREFCONT` `IFELSE`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="Fift"
[ref] IFELSEREF
```
#### `E30F` IFREFELSEREF [#e30f-ifrefelseref]
Equivalent to `PUSHREFCONT` `PUSHREFCONT` `IFELSE`.
**Category:** Cont Conditional (cont\_conditional)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
REPEAT
```
#### `E5` REPEATEND [#e5-repeatend]
Similar to `REPEAT`, but it is applied to the current continuation `cc`.
**Category:** Cont Loops (cont\_loops)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
AGAIN
```
#### `EB` AGAINEND [#eb-againend]
Similar to `AGAIN`, but performed with respect to the current continuation `cc`.
**Category:** Cont Loops (cont\_loops)
```fift title="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 title="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 title="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 title="Fift"
UNTILBRK
```
#### `E317` UNTILENDBRK [#e317-untilendbrk]
Equivalent to `SAMEALTSAVE` `UNTILEND`.
**Category:** Cont Loops (cont\_loops)
```fift title="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 title="Fift"
WHILEBRK
```
#### `E319` WHILEENDBRK [#e319-whileendbrk]
Equivalent to `SAMEALTSAVE` `WHILEEND`.
**Category:** Cont Loops (cont\_loops)
```fift title="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 title="Fift"
AGAINBRK
```
#### `E31B` AGAINENDBRK [#e31b-againendbrk]
Equivalent to `SAMEALTSAVE` `AGAINEND`.
**Category:** Cont Loops (cont\_loops)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
BLESS
```
#### `ED1F` BLESSVARARGS [#ed1f-blessvarargs]
Equivalent to `ROT` `BLESS` `ROTREV` `SETCONTVARARGS`.
**Category:** Cont Create (cont\_create)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
c[i] SETRETCTR
```
#### `ED8i` SETALTCTR [#ed8i-setaltctr]
Equivalent to `c1 PUSHCTR` `c[i] SETCONTCTR` `c1 POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
SETEXITALT
```
#### `EDF6` THENRET [#edf6-thenret]
Computes `compose0(c, c0)`.
**Category:** Cont Registers (cont\_registers)
```fift title="Fift"
THENRET
```
#### `EDF7` THENRETALT [#edf7-thenretalt]
Computes `compose0(c, c1)`
**Category:** Cont Registers (cont\_registers)
```fift title="Fift"
THENRETALT
```
#### `EDF8` INVERT [#edf8-invert]
Interchanges `c0` and `c1`.
**Category:** Cont Registers (cont\_registers)
```fift title="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 title="Fift"
BOOLEVAL
```
#### `EDFA` SAMEALT [#edfa-samealt]
Sets `c1` to `c0`. Equivalent to `c0 PUSHCTR` `c1 POPCTR`.
**Category:** Cont Registers (cont\_registers)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
THROWARGANY
```
#### `F2F2` THROWANYIF [#f2f2-throwanyif]
Throws exception `0 <= n < 2^16` with parameter zero only if `f!=0`.
**Category:** Exceptions (exceptions)
```fift title="Fift"
THROWANYIF
```
#### `F2F3` THROWARGANYIF [#f2f3-throwarganyif]
Throws exception `0 <= n<2^16` with parameter `x` only if `f!=0`.
**Category:** Exceptions (exceptions)
```fift title="Fift"
THROWARGANYIF
```
#### `F2F4` THROWANYIFNOT [#f2f4-throwanyifnot]
Throws exception `0 <= n<2^16` with parameter zero only if `f=0`.
**Category:** Exceptions (exceptions)
```fift title="Fift"
THROWANYIFNOT
```
#### `F2F5` THROWARGANYIFNOT [#f2f5-throwarganyifnot]
Throws exception `0 <= n<2^16` with parameter `x` only if `f=0`.
**Category:** Exceptions (exceptions)
```fift title="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 title="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 title="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 title="Fift"
STDICT
STOPTREF
```
#### `F401` SKIPDICT [#f401-skipdict]
Equivalent to `LDDICT` `NIP`.
**Category:** Dict Serial (dict\_serial)
```fift title="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 title="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 title="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 title="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 title="Fift"
PLDDICT
PLDOPTREF
```
#### `F406` LDDICTQ [#f406-lddictq]
A quiet version of `LDDICT`.
**Category:** Dict Serial (dict\_serial)
```fift title="Fift"
LDDICTQ
```
#### `F407` PLDDICTQ [#f407-plddictq]
A quiet version of `PLDDICT`.
**Category:** Dict Serial (dict\_serial)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
DICTUGET
```
#### `F40F` DICTUGETREF [#f40f-dictugetref]
Similar to `DICTIGETREF`, but with an unsigned `n`-bit *Integer* key `i`.
**Category:** Dict Get (dict\_get)
```fift title="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 title="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 title="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 title="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 title="Fift"
DICTISETREF
```
#### `F416` DICTUSET [#f416-dictuset]
Similar to `DICTISET`, but with `i` an *unsigned* `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUSET
```
#### `F417` DICTUSETREF [#f417-dictusetref]
Similar to `DICTISETREF`, but with `i` unsigned.
**Category:** Dict Set (dict\_set)
```fift title="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 title="Fift"
DICTSETGET
```
#### `F41B` DICTSETGETREF [#f41b-dictsetgetref]
Combines `DICTSETREF` with `DICTGETREF` similarly to `DICTSETGET`.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTSETGETREF
```
#### `F41C` DICTISETGET [#f41c-dictisetget]
`DICTISETGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTISETGET
```
#### `F41D` DICTISETGETREF [#f41d-dictisetgetref]
`DICTISETGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTISETGETREF
```
#### `F41E` DICTUSETGET [#f41e-dictusetget]
`DICTISETGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUSETGET
```
#### `F41F` DICTUSETGETREF [#f41f-dictusetgetref]
`DICTISETGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="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 title="Fift"
DICTREPLACE
```
#### `F423` DICTREPLACEREF [#f423-dictreplaceref]
A *Replace* counterpart of `DICTSETREF`.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTREPLACEREF
```
#### `F424` DICTIREPLACE [#f424-dictireplace]
`DICTREPLACE`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIREPLACE
```
#### `F425` DICTIREPLACEREF [#f425-dictireplaceref]
`DICTREPLACEREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIREPLACEREF
```
#### `F426` DICTUREPLACE [#f426-dictureplace]
`DICTREPLACE`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUREPLACE
```
#### `F427` DICTUREPLACEREF [#f427-dictureplaceref]
`DICTREPLACEREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="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 title="Fift"
DICTREPLACEGET
```
#### `F42B` DICTREPLACEGETREF [#f42b-dictreplacegetref]
A *Replace* counterpart of `DICTSETGETREF`.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTREPLACEGETREF
```
#### `F42C` DICTIREPLACEGET [#f42c-dictireplaceget]
`DICTREPLACEGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIREPLACEGET
```
#### `F42D` DICTIREPLACEGETREF [#f42d-dictireplacegetref]
`DICTREPLACEGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIREPLACEGETREF
```
#### `F42E` DICTUREPLACEGET [#f42e-dictureplaceget]
`DICTREPLACEGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUREPLACEGET
```
#### `F42F` DICTUREPLACEGETREF [#f42f-dictureplacegetref]
`DICTREPLACEGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="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 title="Fift"
DICTADD
```
#### `F433` DICTADDREF [#f433-dictaddref]
An *Add* counterpart of `DICTSETREF`.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTADDREF
```
#### `F434` DICTIADD [#f434-dictiadd]
`DICTADD`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIADD
```
#### `F435` DICTIADDREF [#f435-dictiaddref]
`DICTADDREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIADDREF
```
#### `F436` DICTUADD [#f436-dictuadd]
`DICTADD`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUADD
```
#### `F437` DICTUADDREF [#f437-dictuaddref]
`DICTADDREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="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 title="Fift"
DICTADDGET
```
#### `F43B` DICTADDGETREF [#f43b-dictaddgetref]
An *Add* counterpart of `DICTSETGETREF`.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTADDGETREF
```
#### `F43C` DICTIADDGET [#f43c-dictiaddget]
`DICTADDGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIADDGET
```
#### `F43D` DICTIADDGETREF [#f43d-dictiaddgetref]
`DICTADDGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTIADDGETREF
```
#### `F43E` DICTUADDGET [#f43e-dictuaddget]
`DICTADDGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUADDGET
```
#### `F43F` DICTUADDGETREF [#f43f-dictuaddgetref]
`DICTADDGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Set (dict\_set)
```fift title="Fift"
DICTUADDGETREF
```
#### `F441` DICTSETB [#f441-dictsetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTSETB
```
#### `F442` DICTISETB [#f442-dictisetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTISETB
```
#### `F443` DICTUSETB [#f443-dictusetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTUSETB
```
#### `F445` DICTSETGETB [#f445-dictsetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTSETGETB
```
#### `F446` DICTISETGETB [#f446-dictisetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTISETGETB
```
#### `F447` DICTUSETGETB [#f447-dictusetgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTUSETGETB
```
#### `F449` DICTREPLACEB [#f449-dictreplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTREPLACEB
```
#### `F44A` DICTIREPLACEB [#f44a-dictireplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTIREPLACEB
```
#### `F44B` DICTUREPLACEB [#f44b-dictureplaceb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTUREPLACEB
```
#### `F44D` DICTREPLACEGETB [#f44d-dictreplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTREPLACEGETB
```
#### `F44E` DICTIREPLACEGETB [#f44e-dictireplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTIREPLACEGETB
```
#### `F44F` DICTUREPLACEGETB [#f44f-dictureplacegetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTUREPLACEGETB
```
#### `F451` DICTADDB [#f451-dictaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTADDB
```
#### `F452` DICTIADDB [#f452-dictiaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTIADDB
```
#### `F453` DICTUADDB [#f453-dictuaddb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTUADDB
```
#### `F455` DICTADDGETB [#f455-dictaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTADDGETB
```
#### `F456` DICTIADDGETB [#f456-dictiaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="Fift"
DICTIADDGETB
```
#### `F457` DICTUADDGETB [#f457-dictuaddgetb]
**Category:** Dict Set Builder (dict\_set\_builder)
```fift title="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 title="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 title="Fift"
DICTIDEL
```
#### `F45B` DICTUDEL [#f45b-dictudel]
Similar to `DICTIDEL`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift title="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 title="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 title="Fift"
DICTDELGETREF
```
#### `F464` DICTIDELGET [#f464-dictidelget]
`DICTDELGET`, but with `i` a signed `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift title="Fift"
DICTIDELGET
```
#### `F465` DICTIDELGETREF [#f465-dictidelgetref]
`DICTDELGETREF`, but with `i` a signed `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift title="Fift"
DICTIDELGETREF
```
#### `F466` DICTUDELGET [#f466-dictudelget]
`DICTDELGET`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift title="Fift"
DICTUDELGET
```
#### `F467` DICTUDELGETREF [#f467-dictudelgetref]
`DICTDELGETREF`, but with `i` an unsigned `n`-bit integer.
**Category:** Dict Delete (dict\_delete)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
DICTUSETGETOPTREF
```
#### `F470` PFXDICTSET [#f470-pfxdictset]
**Category:** Dict Prefix (dict\_prefix)
```fift title="Fift"
PFXDICTSET
```
#### `F471` PFXDICTREPLACE [#f471-pfxdictreplace]
**Category:** Dict Prefix (dict\_prefix)
```fift title="Fift"
PFXDICTREPLACE
```
#### `F472` PFXDICTADD [#f472-pfxdictadd]
**Category:** Dict Prefix (dict\_prefix)
```fift title="Fift"
PFXDICTADD
```
#### `F473` PFXDICTDEL [#f473-pfxdictdel]
**Category:** Dict Prefix (dict\_prefix)
```fift title="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 title="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 title="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 title="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 title="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 title="Fift"
DICTIGETNEXT
```
#### `F479` DICTIGETNEXTEQ [#f479-dictigetnexteq]
Similar to `DICTGETNEXTEQ`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="Fift"
DICTIGETNEXTEQ
```
#### `F47A` DICTIGETPREV [#f47a-dictigetprev]
Similar to `DICTGETPREV`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="Fift"
DICTIGETPREV
```
#### `F47B` DICTIGETPREVEQ [#f47b-dictigetpreveq]
Similar to `DICTGETPREVEQ`, but interprets keys as signed `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="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 title="Fift"
DICTUGETNEXT
```
#### `F47D` DICTUGETNEXTEQ [#f47d-dictugetnexteq]
Similar to `DICTGETNEXTEQ`, but interprets keys as unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="Fift"
DICTUGETNEXTEQ
```
#### `F47E` DICTUGETPREV [#f47e-dictugetprev]
Similar to `DICTGETPREV`, but interprets keys as unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="Fift"
DICTUGETPREV
```
#### `F47F` DICTUGETPREVEQ [#f47f-dictugetpreveq]
Similar to `DICTGETPREVEQ`, but interprets keys a unsigned `n`-bit integers.
**Category:** Dict Next (dict\_next)
```fift title="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 title="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 title="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 title="Fift"
DICTIMIN
```
#### `F485` DICTIMINREF [#f485-dictiminref]
Similar to `DICTIMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTUMIN
```
#### `F487` DICTUMINREF [#f487-dictuminref]
Similar to `DICTUMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTMAX
```
#### `F48B` DICTMAXREF [#f48b-dictmaxref]
Similar to `DICTMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTIMAX
```
#### `F48D` DICTIMAXREF [#f48d-dictimaxref]
Similar to `DICTIMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTUMAX
```
#### `F48F` DICTUMAXREF [#f48f-dictumaxref]
Similar to `DICTUMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="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 title="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 title="Fift"
DICTIREMMIN
```
#### `F495` DICTIREMMINREF [#f495-dictiremminref]
Similar to `DICTIREMMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTUREMMIN
```
#### `F497` DICTUREMMINREF [#f497-dicturemminref]
Similar to `DICTUREMMIN`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="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 title="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 title="Fift"
DICTIREMMAX
```
#### `F49D` DICTIREMMAXREF [#f49d-dictiremmaxref]
Similar to `DICTIREMMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTUREMMAX
```
#### `F49F` DICTUREMMAXREF [#f49f-dicturemmaxref]
Similar to `DICTUREMMAX`, but returns the only reference in the value.
**Category:** Dict Min (dict\_min)
```fift title="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 title="Fift"
DICTIGETJMP
```
#### `F4A1` DICTUGETJMP [#f4a1-dictugetjmp]
Similar to `DICTIGETJMP`, but performs `DICTUGET` instead of `DICTIGET`.
**Category:** Dict Special (dict\_special)
```fift title="Fift"
DICTUGETJMP
```
#### `F4A2` DICTIGETEXEC [#f4a2-dictigetexec]
Similar to `DICTIGETJMP`, but with `EXECUTE` instead of `JMPX`.
**Category:** Dict Special (dict\_special)
```fift title="Fift"
DICTIGETEXEC
```
#### `F4A3` DICTUGETEXEC [#f4a3-dictugetexec]
Similar to `DICTUGETJMP`, but with `EXECUTE` instead of `JMPX`.
**Category:** Dict Special (dict\_special)
```fift title="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 title="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 title="Fift"
PFXDICTGETQ
```
#### `F4A9` PFXDICTGET [#f4a9-pfxdictget]
Similar to `PFXDICTGET`, but throws a cell deserialization failure exception on failure.
**Category:** Dict Special (dict\_special)
```fift title="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 title="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 title="Fift"
PFXDICTGETEXEC
```
#### `F4AE_n` PFXDICTCONSTGETJMP [#f4ae_n-pfxdictconstgetjmp]
Combines `[n] DICTPUSHCONST` for `0 <= n <= 1023` with `PFXDICTGETJMP`.
**Category:** Dict Special (dict\_special)
```fift title="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 title="Fift"
DICTIGETJMPZ
```
#### `F4BD` DICTUGETJMPZ [#f4bd-dictugetjmpz]
A variant of `DICTUGETJMP` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift title="Fift"
DICTUGETJMPZ
```
#### `F4BE` DICTIGETEXECZ [#f4be-dictigetexecz]
A variant of `DICTIGETEXEC` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift title="Fift"
DICTIGETEXECZ
```
#### `F4BF` DICTUGETEXECZ [#f4bf-dictugetexecz]
A variant of `DICTUGETEXEC` that returns index `i` on failure.
**Category:** Dict Special (dict\_special)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
SETGASLIMIT
```
#### `F807` GASCONSUMED [#f807-gasconsumed]
Returns gas consumed by VM so far (including this instruction).
**Category:** App Gas (app\_gas)
```fift title="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 title="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 title="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 title="Fift"
RAND
```
#### `F814` SETRAND [#f814-setrand]
Sets the random seed to unsigned 256-bit *Integer* `x`.
**Category:** App Rnd (app\_rnd)
```fift title="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 title="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 title="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 (nanograms).
#### `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 title="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 title="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 title="Fift"
CONFIGOPTPARAM
```
#### `F83400` PREVMCBLOCKS [#f83400-prevmcblocks]
Retrives `last_mc_blocks` part of PrevBlocksInfo from c7 (parameter 13).
**Category:** App Config (app\_config)
```fift title="Fift"
PREVMCBLOCKS
```
#### `F83401` PREVKEYBLOCK [#f83401-prevkeyblock]
Retrives `prev_key_block` part of PrevBlocksInfo from c7 (parameter 13).
**Category:** App Config (app\_config)
```fift title="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 title="Fift"
PREVMCBLOCKS_100
```
#### `F835` GLOBALID [#f835-globalid]
Retrieves `global_id` from 19 network config.
**Category:** App Config (app\_config)
```fift title="Fift"
GLOBALID
```
#### `F836` GETGASFEE [#f836-getgasfee]
Calculates gas fee
**Category:** App Config (app\_config)
```fift title="Fift"
GETGASFEE
```
#### `F837` GETSTORAGEFEE [#f837-getstoragefee]
Calculates storage fees (only current StoragePrices entry is used).
**Category:** App Config (app\_config)
```fift title="Fift"
GETSTORAGEFEE
```
#### `F838` GETFORWARDFEE [#f838-getforwardfee]
Calculates forward fee.
**Category:** App Config (app\_config)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
[i] GETPARAMLONG
```
#### `F89i` INMSGPARAM [#f89i-inmsgparam]
Equivalent to `INMSGPARAMS` `i INDEX`
**Category:** App Config (app\_config)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
P256_CHKSIGNS
```
#### `F916` HASHBU [#f916-hashbu]
Same as `ENDC HASHCU`, but without gas cost for cell creation.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="Fift"
RIST255_VALIDATE
```
#### `F922` RIST255\_ADD [#f922-rist255_add]
Addition of two points on a curve.
**Category:** App Crypto (app\_crypto)
```fift title="Fift"
RIST255_ADD
```
#### `F923` RIST255\_SUB [#f923-rist255_sub]
Subtraction of two points on curve.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
RIST255_QMULBASE
```
#### `F93000` BLS\_VERIFY [#f93000-bls_verify]
Checks BLS signature, return true on success, false otherwise.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="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 title="Fift"
BLS_AGGREGATEVERIFY
```
#### `F93010` BLS\_G1\_ADD [#f93010-bls_g1_add]
Addition on G1.
**Category:** App Crypto (app\_crypto)
```fift title="Fift"
BLS_G1_ADD
```
#### `F93011` BLS\_G1\_SUB [#f93011-bls_g1_sub]
Subtraction on G1.
**Category:** App Crypto (app\_crypto)
```fift title="Fift"
BLS_G1_SUB
```
#### `F93012` BLS\_G1\_NEG [#f93012-bls_g1_neg]
Negation on G1.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="Fift"
BLS_G1_MULTIEXP
```
#### `F93015` BLS\_G1\_ZERO [#f93015-bls_g1_zero]
Pushes zero point in G1.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="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 title="Fift"
BLS_G1_ISZERO
```
#### `F93020` BLS\_G2\_ADD [#f93020-bls_g2_add]
Addition on G2.
**Category:** App Crypto (app\_crypto)
```fift title="Fift"
BLS_G2_ADD
```
#### `F93021` BLS\_G2\_SUB [#f93021-bls_g2_sub]
Subtraction on G2.
**Category:** App Crypto (app\_crypto)
```fift title="Fift"
BLS_G2_SUB
```
#### `F93022` BLS\_G2\_NEG [#f93022-bls_g2_neg]
Negation on G2.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="Fift"
BLS_G2_MULTIEXP
```
#### `F93025` BLS\_G2\_ZERO [#f93025-bls_g2_zero]
Pushes zero point in G2.
**Category:** App Crypto (app\_crypto)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
REWRITESTDADDR
```
#### `FA45` REWRITESTDADDRQ [#fa45-rewritestdaddrq]
A quiet version of primitive `REWRITESTDADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="Fift"
REWRITEVARADDR
```
#### `FA47` REWRITEVARADDRQ [#fa47-rewritevaraddrq]
A quiet version of primitive `REWRITEVARADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="Fift"
LDSTDADDR
```
#### `FA49` LDSTDADDRQ [#fa49-ldstdaddrq]
A quiet version of primitive `LDSTDADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="Fift"
LDOPTSTDADDR
```
#### `FA51` LDOPTSTDADDRQ [#fa51-ldoptstdaddrq]
A quiet version of primitive `LDOPTSTDADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="Fift"
STSTDADDR
```
#### `FA53` STSTDADDRQ [#fa53-ststdaddrq]
A quiet version of primitive `STSTDADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="Fift"
STOPTSTDADDR
```
#### `FA55` STOPTSTDADDRQ [#fa55-stoptstdaddrq]
A quiet version of primitive `STOPTSTDADDR`.
**Category:** App Addr (app\_addr)
```fift title="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 title="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 title="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 title="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 title="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 title="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 title="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 title="Fift"
SENDMSG
```
#### `FEij` DEBUG [#feij-debug]
**Category:** Debug (debug)
```fift title="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 title="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 title="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 title="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 title="Fift"
SETCPX
```
# TVM overview (https://docs.ton.org/llms/tvm/overview/content.md)
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](https://docs.ton.org/llms/tvm/initialization/content.md).
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](https://docs.ton.org/llms/tvm/gas/content.md). 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](https://docs.ton.org/llms/foundations/serialization/cells/content.md).
* Reading and writing of cells is done with [slices and builders](https://docs.ton.org/llms/tvm/builders-and-slices/content.md).
* There are no function addresses or function pointers. Code is executed from bitcode inside [continuations](https://docs.ton.org/llms/tvm/continuations/content.md).
## 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](https://docs.ton.org/llms/tvm/initialization/content.md).
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**](https://docs.ton.org/llms/tvm/registers/content.md). A small fixed set of special registers, denoted as `c0`, `c1`, ..., `c5`, and `c7` (`c6` does not exist).
* [**Gas counter**](https://docs.ton.org/llms/tvm/gas/content.md). 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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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](https://docs.ton.org/llms/languages/fift/overview/content.md). 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](https://docs.ton.org/llms/tvm/initialization/content.md) 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](https://docs.ton.org/llms/tvm/initialization/content.md) 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 title="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)
}>
```
# TVM registers (https://docs.ton.org/llms/tvm/registers/content.md)
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`](https://docs.ton.org/llms/tvm/instructions/content.md) 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`](https://docs.ton.org/llms/tvm/instructions/content.md), [`IFRETALT`](https://docs.ton.org/llms/tvm/instructions/content.md), 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`](https://docs.ton.org/llms/tvm/instructions/content.md)-like instructions. To set a custom exception handler, use [TRY](https://docs.ton.org/llms/tvm/instructions/content.md).
## `c3` — function selector [#c3--function-selector]
**Type**: Continuation
**Initial value**: Root cell of code currently executing in TVM.
Invoked by [`CALLDICT`](https://docs.ton.org/llms/tvm/instructions/content.md) 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 title=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`](https://docs.ton.org/llms/tvm/instructions/content.md) modifies `c7`, inserting an element with index `i`, [`[i] GETGLOB`](https://docs.ton.org/llms/tvm/instructions/content.md) 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 (GRAM 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 (GRAM 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
* 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 nanograms
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`.
# Streaming API overview (https://docs.ton.org/llms/api/streaming/overview/content.md)
The TON Center **Streaming API** (v2) provides developer access to TON Blockchain through [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) and [WebSockets](https://en.wikipedia.org/wiki/WebSocket). It delivers low-latency, real-time updates on transactions and actions observed on the TON blockchain. Clients can subscribe to updates for monitoring a wallet, some contract addresses, or a specific trace of transactions.
Streaming API serves as a real-time, streaming version of the [indexed access layer (API v3)](https://docs.ton.org/llms/api/v3/overview/content.md). Use it when building wallets, explorers, monitoring systems, or automation tools.
The Streaming API does not recover past events; it only tracks current ones. As such, network interruptions, client restarts, or brief service downtime can cause missed events.
When application state or business logic depends on a complete event sequence, resynchronize with historical data by polling [API v3](https://docs.ton.org/llms/api/v3/overview/content.md) after reconnecting.
The [API v2](https://docs.ton.org/llms/api/v2/overview/content.md) and [API v3](https://docs.ton.org/llms/api/v3/overview/content.md) include their major version numbers in their product names. For the Streaming API, `v2` means the current protocol version and doesn't refer to different APIs.
## Event groups [#event-groups]
The Streaming API emits the following event groups:
* Trace-based events: `transactions`, `actions`, `trace`
* State updates: `account_state_change` and `jettons_change`
* Invalidation signal: `trace_invalidated`
The [event types section](https://docs.ton.org/llms/api/streaming/reference/content.md) and [notification schemas section](https://docs.ton.org/llms/api/streaming/reference/content.md) provide the exact payload structure for each event.
## Finality model [#finality-model]
Trace-based events carry a `finality` field according to their finality level:
```json
"finality": "pending" | "confirmed" | "finalized"
```
Each trace moves through the following monotonic lifecycle:
* `pending` — result of emulation or speculative execution. This state can be invalidated (`trace_invalidated`).
* `confirmed` — trace or transactions are included in a candidate shard block. Rollback chance is very small, but still possible.
* `finalized` — committed in the masterchain and will not be updated nor invalidated.
Non-trace events behave differently:
* `account_state_change` and `jettons_change` are emitted only when `finality` field is set to either `confirmed` or `finalized`.
* `trace_invalidated` applies to previously emitted trace-based data and is not emitted after `finalized`.
## Delivery behavior [#delivery-behavior]
The `min_finality` field is used to control how early the server emits trace-based updates:
* `pending` — receive every trace snapshot as it moves from `pending` to `confirmed` to `finalized`.
* `confirmed` — skip pure emulation results and start at `confirmed` or later.
* `finalized` — receive only finalized trace-based events.
Choose the setting based on the tolerance for speculative data:
* Use `pending` for the lowest latency.
* Use `confirmed` for lower rollback risk with near-real-time delivery.
* Use `finalized` when only settled data is acceptable.
The [delivery semantics section](https://docs.ton.org/llms/api/streaming/reference/content.md) and [event invalidation section](https://docs.ton.org/llms/api/streaming/reference/content.md) document the exact behavior for each event type.
## Supported interfaces [#supported-interfaces]
The Streaming API exposes two transports: SSE and a WebSocket. Choose either of the transports to proceed with its usage:
Recommended for browser environments or clients that prefer HTTP streaming and a fixed subscription.
Preferred for persistent, bidirectional communication with dynamic subscription patterns.
## See also [#see-also]
* [Notification reference](https://docs.ton.org/llms/api/streaming/reference/content.md)
* [API key](https://docs.ton.org/llms/api/get-api-key/content.md)
* [API authentication](https://docs.ton.org/llms/api/v3/authentication/content.md)
# Streaming API notification reference (https://docs.ton.org/llms/api/streaming/reference/content.md)
## Event types [#event-types]
Once a subscription is established, the server sends event messages (notifications) matching the selected `types` and `min_finality`. Each message is a JSON object representing a single event.
The `type` field in each notification identifies the notification schema:
* `"transactions"` — subscribe to transactions and their finality levels.
* `"actions"` — subscribe to certain actions by setting `action_types`.
* `"trace"` — subscribe to a transaction trace.
* `"account_state_change"` — emitted for each matching confirmed or finalized account transaction.
* `"jettons_change"` — emitted for each matching confirmed or finalized jetton wallet transaction.
* `"trace_invalidated"` — emitted when earlier trace data becomes invalid.
## Notification schemas [#notification-schemas]
Trace-related notifications, such as `"transactions"`, `"actions"`, and `"trace"` are grouped by the trace. They use the same `trace_external_hash_norm` value across all events generated from one external message.
Transactions and actions in the same trace are ordered by logical time (LT) in descending order. The `"trace"` event includes the full trace tree and a map of all transactions in that trace.
### `"transactions"` [#transactions]
Subscriptions that include `"transactions"` can receive multiple notifications for the same trace as finality increases.
Trace is determined by its `trace_external_hash_norm`.
| Field | Type | Description |
| -------------------------- | --------------- | ------------------------------------------------------------------------ |
| `type` | `string` | Always `"transactions"`. |
| `finality` | `string` | `"pending"`, `"confirmed"`, or `"finalized"`. |
| `trace_external_hash_norm` | `string` | Normalized external message hash for the trace. |
| `transactions` | `Transaction[]` | Transactions in the trace, ordered by descending logical time. |
| `address_book` | `object` | Optional mapping of addresses to a friendly format and a TON DNS domain. |
| `metadata` | `object` | Optional mapping of token addresses to metadata (jetton or NFT). |
```jsonc title="Notification example"
{
"type": "transactions",
"finality": "pending",
"trace_external_hash_norm": "E7...NORMALIZED_EXTERNAL_MSG_HASH",
"transactions": [ /* transaction objects */ ],
"address_book": { /* mapping of known addresses */ },
"metadata": { /* mapping of known token addresses to metadata */ }
}
```
### `"actions"` [#actions]
Subscriptions that include `"actions"` can receive multiple notifications for the same trace as finality increases.
Unlike [traces](#trace) and [transactions](#transactions), actions do not exist on-chain and in blockchain history. Instead, actions are aggregated based on the internal logic of TON Center's [API v3](https://docs.ton.org/llms/api/v3/overview/content.md).
Trace is determined by its `trace_external_hash_norm`.
| Field | Type | Description |
| -------------------------- | ---------- | ------------------------------------------------------------------------ |
| `type` | `string` | Always `"actions"`. |
| `finality` | `string` | `"pending"`, `"confirmed"`, or `"finalized"`. |
| `trace_external_hash_norm` | `string` | Normalized external message hash for the trace. |
| `actions` | `Action[]` | Classified actions for the trace. |
| `address_book` | `object` | Optional mapping of addresses to a friendly format and a TON DNS domain. |
| `metadata` | `object` | Optional mapping of token addresses to metadata (jetton or NFT). |
Use `action_types` when subscribing via [SSE](https://docs.ton.org/llms/api/streaming/sse/content.md) or a [WebSocket](https://docs.ton.org/llms/api/streaming/wss/content.md) to filter received `actions`. Refer to a list of [available action types in API v3](https://docs.ton.org/llms/api/v3/actions-and-traces/get-actions/content.md).
```jsonc title="Notification example"
{
"type": "actions",
"finality": "confirmed",
"trace_external_hash_norm": "E7...NORMALIZED_EXTERNAL_MSG_HASH",
"actions": [ /* action objects */ ],
"address_book": { /* mapping of known addresses */ },
"metadata": { /* mapping of known token addresses to metadata */ }
}
```
### `"trace"` [#trace]
Subscriptions that include `"trace"` receive trace-wide payloads. These payloads are not filtered by account address and include all transactions and actions in the trace.
Trace is determined by its `trace_external_hash_norm`.
| Field | Type | Description |
| -------------------------- | ----------- | ------------------------------------------------------------------------ |
| `type` | `string` | Always `"trace"`. |
| `finality` | `string` | `"pending"`, `"confirmed"`, or `"finalized"`. |
| `trace_external_hash_norm` | `string` | Normalized external message hash for the trace. |
| `trace` | `TraceNode` | Trace tree. |
| `transactions` | `object` | Map of transaction hash to transaction object. |
| `actions` | `Action[]` | Optional classified actions for the trace. |
| `address_book` | `object` | Optional mapping of addresses to a friendly format and a TON DNS domain. |
| `metadata` | `object` | Optional mapping of token addresses to metadata (jetton or NFT). |
```jsonc title="Notification example"
{
"type": "trace",
"finality": "confirmed",
"trace_external_hash_norm": "E7...NORMALIZED_EXTERNAL_MSG_HASH",
"trace": {},
"transactions": { /* mappings */ },
"actions": [ /* action objects */ ],
"address_book": { /* mapping of known addresses */ },
"metadata": { /* mapping of known token addresses to metadata */ }
}
```
### `"account_state_change"` [#account_state_change]
Subscriptions that include `"account_state_change"` receive notifications for each transaction executed on a subscribed account address.
This event is emitted only for `"confirmed"` and `"finalized"` finality levels.
| Field | Type | Description |
| ---------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | Always `"account_state_change"`. |
| `finality` | `string` | `"confirmed"` or `"finalized"`. |
| `account` | `string` | Account address in raw format, e.g., `0:abc...RAW_ADDRESS`. |
| `state` | `AccountState` | Account state without full code and data [BoCs](https://docs.ton.org/llms/foundations/serialization/boc/content.md). Includes state hash, nanograms balance, [account status](https://docs.ton.org/llms/foundations/status/content.md), data and code hashes. All hashes are given in the Base64 format. |
```jsonc title="Notification example"
{
"type": "account_state_change",
"finality": "finalized",
"account": "0:18AA...RAW_ADDRESS",
"state": {
"hash": "P0Gc...BASE64_HASH",
"balance": "42...NANOTON_BALANCE",
"account_status": "active",
"data_hash": "7qNe...BASE64_HASH",
"code_hash": "ow8E...BASE64_HASH"
}
}
```
### `"jettons_change"` [#jettons_change]
Subscriptions that include `"jettons_change"` receive notifications for each transaction on a jetton wallet contract when the subscribed address is its own address or its owner's TON wallet address.
This event is emitted only for `"confirmed"` and `"finalized"` finality levels.
| Field | Type | Description |
| -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | Always `"jettons_change"`. |
| `finality` | `string` | `"confirmed"` or `"finalized"`. |
| `jetton` | `JettonWallet` | Jetton wallet data. Includes its raw address, jetton balance, owner's raw address, jetton master (minter) raw address, and logical time of its last transaction. |
| `address_book` | `object` | Optional mapping of addresses to a friendly format and a TON DNS domain. |
| `metadata` | `object` | Optional mapping of token addresses to metadata (jetton or NFT). |
```jsonc title="Notification example"
{
"type": "jettons_change",
"finality": "finalized",
"jetton": {
"address": "0:88DA...RAW_ADDRESS",
"balance": "42...JETTON_BALANCE",
"owner": "0:18AA...RAW_ADDRESS",
"jetton": "0:B113...RAW_ADDRESS",
"last_transaction_lt": "61664...LT_UNIX_TIME",
},
"address_book": { /* mapping of known addresses */ },
"metadata": { /* mapping of known token addresses to metadata */ }
}
```
### `"trace_invalidated"` [#trace_invalidated]
The `"trace_invalidated"` notification signals that previously emitted speculative or intermediate trace data is no longer valid.
Typical causes include:
* external message was not accepted by the blockchain;
* later state change invalidated previous emulation result;
* confirmed shard block was replaced by another block, and the trace did not end up in the finalized block.
Trace in the notification is determined by its `trace_external_hash_norm`.
| Field | Type | Description |
| -------------------------- | -------- | ----------------------------------------------------------- |
| `type` | `string` | Always `"trace_invalidated"`. |
| `trace_external_hash_norm` | `string` | Normalized external message hash for the invalidated trace. |
```jsonc title="Notification example"
{
"type": "trace_invalidated",
"trace_external_hash_norm": "E7...NORMALIZED_EXTERNAL_MSG_HASH"
}
```
Upon receiving this notification, remove any stored `"trace"`, `"transactions"`, and `"actions"` data for the affected `trace_external_hash_norm`.
The `"trace_invalidated"` notification cannot be sent for the `"finalized"` finality level of the trace.
## Delivery semantics [#delivery-semantics]
| Type | Finality values | Delivery behavior |
| ---------------------- | ----------------------------------------- | ----------------------------------------------------------------------------- |
| `transactions` | `"pending"`, `"confirmed"`, `"finalized"` | Emitted per trace as finality increases. |
| `actions` | `"pending"`, `"confirmed"`, `"finalized"` | Emitted per trace as action classification and finality progress. |
| `trace` | `"pending"`, `"confirmed"`, `"finalized"` | Emitted per trace with the full trace payload. |
| `account_state_change` | `"confirmed"`, `"finalized"` | Emitted for each matching confirmed or finalized account transaction. |
| `jettons_change` | `"confirmed"`, `"finalized"` | Emitted for each matching confirmed or finalized jetton wallet transaction. |
| `trace_invalidated` | Not applicable | Emitted when earlier trace-based data [becomes invalid](#event-invalidation). |
### `min_finality` behavior [#min_finality-behavior]
For trace-based events:
* `min_finality = "pending"` returns `"pending"`, `"confirmed"`, and `"finalized"` snapshots.
* `min_finality = "confirmed"` skips pure emulation and starts at `"confirmed"` or later.
* `min_finality = "finalized"` returns only finalized trace-based events.
For non-trace events:
* `"account_state_change"` and `"jettons_change"` are emitted only with `"confirmed"` and `"finalized"` finality levels.
## Event invalidation [#event-invalidation]
Subscriptions that allow speculative states can later receive `"trace_invalidated"`. If the finality level reaches `"finalized"`, the server is guaranteed not to emit `"trace_invalidated"` for the trace.
The current API does not expose a separate invalidation signal for `"account_state_change"` or `"jettons_change"` emitted at the `"confirmed"` finality level.
## See also [#see-also]
* [Streaming API overview](https://docs.ton.org/llms/api/streaming/overview/content.md)
* [SSE](https://docs.ton.org/llms/api/streaming/sse/content.md)
* [WebSocket](https://docs.ton.org/llms/api/streaming/wss/content.md)
* [API key](https://docs.ton.org/llms/api/get-api-key/content.md)
* [API authentication](https://docs.ton.org/llms/api/v3/authentication/content.md)
# Streaming API: Server-Sent Events (https://docs.ton.org/llms/api/streaming/sse/content.md)
[Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) transport of the [Streaming API](https://docs.ton.org/llms/api/streaming/overview/content.md) uses a single `POST` request to establish the connection and specify the subscription. No further messages are sent by the client on this connection.
## Usage [#usage]
Send one `POST` request to the SSE endpoint with a JSON body that defines the subscription.
### Endpoints [#endpoints]
* Mainnet: `https://toncenter.com/api/streaming/v2/sse`
* Testnet: `https://testnet.toncenter.com/api/streaming/v2/sse`
Some API support the same WebSocket subscription format on different endpoints:
* Mainnet: `https://tonapi.io/streaming/v2/sse`
* Testnet: `https://testnet.tonapi.io/streaming/v2/sse`
Authentication uses an [API key](https://tonconsole.com/tonapi/api-keys).
### Request fields [#request-fields]
One or more event types to receive: `transactions`, `actions`, `trace`, `trace_invalidated`, `account_state_change`, `jettons_change`. The [event types section](https://docs.ton.org/llms/api/streaming/reference/content.md) and [notification schemas section](https://docs.ton.org/llms/api/streaming/reference/content.md) provide the exact payload structure for each event.
Wallet or contract addresses to monitor. Accepts [valid TON address formats](https://docs.ton.org/llms/foundations/addresses/formats/content.md). Optional when subscribing only to a `"trace"`, otherwise required.
Optional list of normalized external message hashes to monitor. Required when subscribing to a `"trace"`.
Optional minimum finality: `"pending"`, `"confirmed"`, or `"finalized"`. Defaults to `"finalized"`.
Optional. If `true`, includes address book data in supported notifications.
Optional. If `true`, includes token metadata (jetton or NFT) in supported notifications.
Optional action type filter. Applies only to `"actions"`. Refer to a list of [available action types in API v3](https://docs.ton.org/llms/api/v3/actions-and-traces/get-actions/content.md).
Optional list of action classification types supported by the client. Defaults to `["latest"]`.
Streaming API does not expose separate `"pending_transactions"` or `"pending_actions"` event types. Subscribe to `"transactions"` or `"actions"`, then use `min_finality` to control delivery timing.
* Include `"trace"` in `types` and provide `trace_external_hash_norms` to subscribe to a specific trace.
* Omit `addresses` when subscribing only to a `"trace"`.
### Examples [#examples]
Lowest-latency stream of `"pending"` → `"confirmed"` → `"finalized"` finality levels:
```http
POST https://toncenter.com/api/streaming/v2/sse
Content-Type: application/json
Accept: text/event-stream
{
"types": ["transactions", "actions"],
"addresses": ["EQC...ACCOUNT_ADDRESS", "0:abc...RAW_ADDRESS"],
"min_finality": "pending",
"include_address_book": true,
"include_metadata": false,
"action_types": ["jetton_transfer", "ton_transfer"]
}
```
Subscribing to a specific trace:
```http
POST https://toncenter.com/api/streaming/v2/sse
Content-Type: application/json
Accept: text/event-stream
{
"types": ["trace"],
"trace_external_hash_norms": ["E7...NORMALIZED_EXTERNAL_MSG_HASH"],
"min_finality": "pending",
"include_address_book": true,
"include_metadata": true
}
```
Successful SSE subscriptions receive the following message from the server:
```json
{"status": "subscribed"}
```
To keep the subscription alive, the server sends the following `keepalive` line every 15 seconds:
```text
: keepalive\n\n
```
Ignore SSE lines that begin with `:`.
## Known limitations [#known-limitations]
### Rate limit on reconnect (429 error) [#rate-limit-on-reconnect-429-error]
If a client reconnects immediately after a disconnect, the previous connection may still be open for \~1 minute. The reconnect attempt receives a 429 error. Use exponential backoff or [an enterprise plan API key](https://docs.ton.org/llms/api/get-api-key/content.md).
### POST-only subscription [#post-only-subscription]
Despite SSE typically using `GET` requests, Streaming API endpoints require a `POST` with the subscription JSON in the request body.
`GET` requests are not supported yet.
### No invalidation signal for `account_state_change` or `jettons_change` [#no-invalidation-signal-for-account_state_change-or-jettons_change]
If a `"confirmed"` account state or jetton balance update is later rolled back, no `"trace_invalidated"` notification is sent for these event types.
When using `"account_state_change"` or `"jettons_change"` at `"confirmed"` finality, consider waiting for `"finalized"` for balance-critical flows.
## Next steps [#next-steps]
* Skim the server [notification reference](https://docs.ton.org/llms/api/streaming/reference/content.md)
* [Get an API key](https://docs.ton.org/llms/api/get-api-key/content.md)
# Streaming API: WebSocket (https://docs.ton.org/llms/api/streaming/wss/content.md)
[WebSocket](https://en.wikipedia.org/wiki/WebSocket) transport of the [Streaming API](https://docs.ton.org/llms/api/streaming/overview/content.md) is the preferred interface for persistent and bidirectional communication with dynamic subscription patterns.
## Usage [#usage]
Connect to the WebSocket endpoint, then send JSON messages for `subscribe`, `unsubscribe`, and `ping` operations.
Each request may include an optional `id` field for request and response correlation.
### Endpoints [#endpoints]
* Mainnet: `wss://toncenter.com/api/streaming/v2/ws`
* Testnet: `wss://testnet.toncenter.com/api/streaming/v2/ws`
Some API support the same WebSocket subscription format on different endpoints:
* Mainnet: `wss://tonapi.io/streaming/v2/ws`
* Testnet: `wss://testnet.tonapi.io/streaming/v2/ws`
Authentication uses an [API key](https://tonconsole.com/tonapi/api-keys).
### Operations [#operations]
#### `subscribe` [#subscribe]
Subscribe operation replaces the entire subscription snapshot for the current connection.
Must be `"subscribe"`.
One or more event types to receive: `transactions`, `actions`, `trace`, `trace_invalidated`, `account_state_change`, `jettons_change`. The [event types section](https://docs.ton.org/llms/api/streaming/reference/content.md) and [notification schemas section](https://docs.ton.org/llms/api/streaming/reference/content.md) provide the exact payload structure for each event.
Wallet or contract addresses to monitor. Accepts [valid TON address formats](https://docs.ton.org/llms/foundations/addresses/formats/content.md). May be left empty when subscribing only to a `"trace"`, otherwise required for non-trace event types.
Optional list of normalized external message hashes to monitor. Required when subscribing to a `"trace"`.
Optional minimum finality: `"pending"`, `"confirmed"`, or `"finalized"`. Defaults to `"finalized"`.
Optional. If `true`, includes address book data in supported notifications.
Optional. If `true`, includes token metadata (jetton or NFT) in supported notifications.
Optional action type filter. Applies only to `"actions"`. Refer to a list of [available action types in API v3](https://docs.ton.org/llms/api/v3/actions-and-traces/get-actions/content.md).
Optional list of action classification types supported by the client. Defaults to `["latest"]`.
Optional request identifier to match responses with requests.
```json title="Request example"
{
"operation": "subscribe",
"types": ["transactions", "actions", "account_state_change", "jettons_change", "trace"],
"addresses": [""],
"trace_external_hash_norms": ["E7...NORMALIZED_EXTERNAL_MSG_HASH"],
"min_finality": "pending",
"include_address_book": true,
"include_metadata": false,
"action_types": ["jetton_transfer", "ton_transfer"],
"id": "1"
}
```
```json title="Successful response"
{"id": "1", "status": "subscribed"}
```
#### `unsubscribe` [#unsubscribe]
Unsubscribe operation removes one or more addresses or trace hashes from the active subscription.
Must be `"unsubscribe"`.
Wallet or contract addresses to remove from monitoring. Accepts [valid TON address formats](https://docs.ton.org/llms/foundations/addresses/formats/content.md).
List of normalized external message hashes to remove from monitoring.
Optional request identifier to match responses with requests.
```json title="Request example"
{
"operation": "unsubscribe",
"addresses": [""],
"trace_external_hash_norms": ["E7...NORMALIZED_EXTERNAL_MSG_HASH"],
"id": "2"
}
```
```json title="Successful response"
{"id": "2", "status": "unsubscribed"}
```
#### `ping` [#ping]
Ping operation serves as a `keepalive` or a connection health check.
Must be `"ping"`.
Optional request identifier to match responses with requests.
It is recommended to send `ping` request every 15 seconds to keep the connection active.
```json title="Request example"
{
"operation": "ping",
"id": "ping-42"
}
```
```json title="Successful response"
{"id": "ping-42", "status": "pong"}
```
## Next steps [#next-steps]
* Skim the server [notification reference](https://docs.ton.org/llms/api/streaming/reference/content.md)
* [Get an API key](https://docs.ton.org/llms/api/get-api-key/content.md)
# API v2 authentication (https://docs.ton.org/llms/api/v2/authentication/content.md)
## 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](https://docs.ton.org/llms/api/get-api-key/content.md).
| 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 v2 error codes (https://docs.ton.org/llms/api/v2/errors/content.md)
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.
# TON Center API v2 overview (https://docs.ton.org/llms/api/v2/overview/content.md)
The TON Center API v2 provides developer access to the TON blockchain through [REST](https://en.wikipedia.org/wiki/REST) and [JSON-RPC](https://en.wikipedia.org/wiki/JSON-RPC) endpoints. It allows applications to read blockchain data, run smart contract methods, and send transactions.
API v2 serves as the non-indexed access layer.
Applications interact with the TON blockchain by connecting to a TON node. Since nodes communicate through the binary ADNL protocol, an intermediate layer is needed for web-based access. API v2 provides this bridge by using [`tonlib`](https://github.com/ton-blockchain/ton/tree/master/tonlib/tonlib) to query data from liteservers and exposes it through a standard REST interface.
Refer to the [Streaming API v2](https://docs.ton.org/llms/api/streaming/overview/content.md) page for an API that uses Server-Sent Events (SSE) and exposes WebSocket interfaces.
## Base URLs [#base-urls]
| API | Mainnet | Testnet |
| ------ | ------------------------------ | -------------------------------------- |
| API v2 | `https://toncenter.com/api/v2` | `https://testnet.toncenter.com/api/v2` |
## Versioning [#versioning]
API v2 uses semantic versioning in the format `a.b.c` (for example, `2.1.1`):
| Segment | Example | Meaning |
| ------- | ------- | ------------------------------------------------------------------- |
| Major | `2.x.x` | Fixed at `2` to avoid confusion ("API v2 v3.x.x"). Will not change. |
| Minor | `2.1.x` | Implementation variant: `0` = Python version, `1` = C++ version. |
| Patch | `2.1.1` | Bumped with every release on GitHub. |
## Typical use cases [#typical-use-cases]
* Query account balances and state
* Run get-methods on smart contracts
* Send or broadcast messages
* Retrieve latest transactions and block information
## Endpoints [#endpoints]
| Category | Method | Description |
| ----------------- | ----------------------------------------------------------------------------------------- | --------------------------------- |
| **Accounts** | [`GET /getAddressInformation`](https://docs.ton.org/llms/api/v2/accounts/get-address-information/content.md) | Get address information |
| **Accounts** | [`GET /getExtendedAddressInformation`](https://docs.ton.org/llms/api/v2/accounts/get-extended-address-information/content.md) | Get extended address information |
| **Accounts** | [`GET /getWalletInformation`](https://docs.ton.org/llms/api/v2/accounts/get-wallet-information/content.md) | Get wallet information |
| **Accounts** | [`GET /getAddressBalance`](https://docs.ton.org/llms/api/v2/accounts/get-address-balance/content.md) | Get address balance |
| **Accounts** | [`GET /getAddressState`](https://docs.ton.org/llms/api/v2/accounts/get-address-state/content.md) | Get address state |
| **Accounts** | [`GET /getTokenData`](https://docs.ton.org/llms/api/v2/accounts/get-token-data/content.md) | Get token data |
| **Blocks** | [`GET /getMasterchainInfo`](https://docs.ton.org/llms/api/v2/blocks/get-masterchain-info/content.md) | Get masterchain info |
| **Blocks** | [`GET /getMasterchainBlockSignatures`](https://docs.ton.org/llms/api/v2/blocks/get-masterchain-block-signatures/content.md) | Get masterchain block signatures |
| **Blocks** | [`GET /getShardBlockProof`](https://docs.ton.org/llms/api/v2/blocks/get-shard-block-proof/content.md) | Get shard block proof |
| **Blocks** | [`GET /getConsensusBlock`](https://docs.ton.org/llms/api/v2/blocks/get-consensus-block/content.md) | Get consensus block |
| **Blocks** | [`GET /lookupBlock`](https://docs.ton.org/llms/api/v2/blocks/lookup-block/content.md) | Lookup block |
| **Blocks** | [`GET /getShards`](https://docs.ton.org/llms/api/v2/blocks/get-shards/content.md) | Get shards |
| **Blocks** | [`GET /getBlockHeader`](https://docs.ton.org/llms/api/v2/blocks/get-block-header/content.md) | Get block header |
| **Blocks** | [`GET /getOutMsgQueueSize`](https://docs.ton.org/llms/api/v2/blocks/get-outbound-message-queue-size/content.md) | Get outbound message queue size |
| **Transactions** | [`GET /getBlockTransactions`](https://docs.ton.org/llms/api/v2/transactions/get-block-transactions/content.md) | Get block transactions |
| **Transactions** | [`GET /getBlockTransactionsExt`](https://docs.ton.org/llms/api/v2/transactions/get-block-transactions-extended/content.md) | Get block transactions (extended) |
| **Transactions** | [`GET /getTransactions`](https://docs.ton.org/llms/api/v2/transactions/get-transactions/content.md) | Get transactions |
| **Transactions** | [`GET /getTransactionsStd`](https://docs.ton.org/llms/api/v2/transactions/get-transactions-standard/content.md) | Get transactions (standard) |
| **Transactions** | [`GET /tryLocateTx`](https://docs.ton.org/llms/api/v2/transactions/try-locate-transaction/content.md) | Try locate transaction |
| **Transactions** | [`GET /tryLocateResultTx`](https://docs.ton.org/llms/api/v2/transactions/try-locate-result-transaction/content.md) | Try locate result transaction |
| **Transactions** | [`GET /tryLocateSourceTx`](https://docs.ton.org/llms/api/v2/transactions/try-locate-source-transaction/content.md) | Try locate source transaction |
| **Send** | [`POST /sendBoc`](https://docs.ton.org/llms/api/v2/send/send-boc/content.md) | Send BoC |
| **Send** | [`POST /sendBocReturnHash`](https://docs.ton.org/llms/api/v2/send/send-boc-return-hash/content.md) | Send BoC (return hash) |
| **Send** | [`POST /estimateFee`](https://docs.ton.org/llms/api/v2/send/estimate-fee/content.md) | Estimate fee |
| **Run method** | [`POST /runGetMethod`](https://docs.ton.org/llms/api/v2/run-method/run-get-method/content.md) | Run get method |
| **Run method** | [`POST /runGetMethodStd`](https://docs.ton.org/llms/api/v2/run-method/run-get-method-standard/content.md) | Run get method (standard) |
| **Utils** | [`GET /detectAddress`](https://docs.ton.org/llms/api/v2/utils/detect-address/content.md) | Detect address |
| **Utils** | [`GET /detectHash`](https://docs.ton.org/llms/api/v2/utils/detect-hash/content.md) | Detect hash |
| **Utils** | [`GET /packAddress`](https://docs.ton.org/llms/api/v2/utils/pack-address/content.md) | Pack address |
| **Utils** | [`GET /unpackAddress`](https://docs.ton.org/llms/api/v2/utils/unpack-address/content.md) | Unpack address |
| **Configuration** | [`GET /getConfigParam`](https://docs.ton.org/llms/api/v2/configuration/get-config-parameter/content.md) | Get config parameter |
| **Configuration** | [`GET /getConfigAll`](https://docs.ton.org/llms/api/v2/configuration/get-all-config-parameters/content.md) | Get all config parameters |
| **Configuration** | [`GET /getLibraries`](https://docs.ton.org/llms/api/v2/configuration/get-libraries/content.md) | Get libraries |
| **RPC** | [`POST /jsonRPC`](https://docs.ton.org/llms/api/v2/rpc/json-rpc-endpoint/content.md) | JSON-RPC endpoint |
## How to access the API [#how-to-access-the-api]
Developers can access API v2 either through hosted infrastructure managed by TON Center or by running a self-hosted instance.
### Managed service [#managed-service]
Hosted access uses TON Center’s managed infrastructure instead of running a personal node. This approach enables immediate network access without setup or maintenance.
Requests without an API key are limited to a default rate of 1 request per second. To increase this limit or access private liteservers, generate an [API key](https://docs.ton.org/llms/api/get-api-key/content.md) and [choose a plan](https://docs.ton.org/llms/api/rate-limit/content.md).
### Self-hosted service [#self-hosted-service]
Run a self-hosted TON Center API v2 infrastructure for full control over performance and data retention. See the [API v2](https://github.com/toncenter/ton-http-api-cpp) repository for setup instructions.
# API v2 TonLib type identifiers (https://docs.ton.org/llms/api/v2/tonlib-types/content.md)
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-GRAM 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](https://docs.ton.org/llms/foundations/tlb/overview/content.md).
Types prefixed with `ext.` are TON Center extensions not present in the upstream TL schema.
# API authentication (https://docs.ton.org/llms/api/v3/authentication/content.md)
## 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](https://docs.ton.org/llms/api/get-api-key/content.md).
| 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 (https://docs.ton.org/llms/api/v3/errors/content.md)
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.
# TON Center API v3 overview (https://docs.ton.org/llms/api/v3/overview/content.md)
The TON Center **API v3** provides developer access to TON Blockchain through an indexed data layer. It allows applications to read blockchain data, run analytical queries, retrieve historical information, and decode Jetton, NFT, and action data.
API v3 serves as the indexed access layer.
It reads raw data from a node's RocksDB storage, parses and decodes it, and stores it in PostgreSQL.
Refer to the [Streaming API v2](https://docs.ton.org/llms/api/streaming/overview/content.md) page for an API that uses Server-Sent Events (SSE) and exposes WebSocket interfaces.
## Base URLs [#base-urls]
| API | Mainnet | Testnet |
| ------ | ------------------------------ | -------------------------------------- |
| API v3 | `https://toncenter.com/api/v3` | `https://testnet.toncenter.com/api/v3` |
## Typical use cases [#typical-use-cases]
* Query historical transactions and traces
* Retrieve decoded Jetton and NFT data
* Run analytical or filtered searches across multiple accounts
* Power explorers or reporting tools
## Endpoints [#endpoints]
| Category | Method | Description |
| ------------------ | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| Accounts | [`GET /accountStates`](https://docs.ton.org/llms/api/v3/accounts/get-account-states/content.md) | Get account states |
| Accounts | [`GET /addressBook`](https://docs.ton.org/llms/api/v3/accounts/address-book/content.md) | Address book |
| Accounts | [`GET /metadata`](https://docs.ton.org/llms/api/v3/accounts/metadata/content.md) | Metadata |
| Accounts | [`GET /walletStates`](https://docs.ton.org/llms/api/v3/accounts/get-wallet-states/content.md) | Get wallet states |
| Actions and traces | [`GET /actions`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-actions/content.md) | Get actions |
| Actions and traces | [`GET /pendingActions`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-pending-actions/content.md) | Get pending actions |
| Actions and traces | [`GET /pendingTraces`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-pending-traces/content.md) | Get pending traces |
| Actions and traces | [`GET /traces`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-traces/content.md) | Get traces |
| Blockchain data | [`GET /adjacentTransactions`](https://docs.ton.org/llms/api/v3/blockchain-data/get-adjacent-transactions/content.md) | Get adjacent transactions |
| Blockchain data | [`GET /blocks`](https://docs.ton.org/llms/api/v3/blockchain-data/get-blocks/content.md) | Get blocks |
| Blockchain data | [`GET /masterchainBlockShardState`](https://docs.ton.org/llms/api/v3/blockchain-data/get-masterchain-block-shard-state/content.md) | Get masterchain block shard state |
| Blockchain data | [`GET /masterchainBlockShards`](https://docs.ton.org/llms/api/v3/blockchain-data/get-masterchain-block-shards/content.md) | Get masterchain block shards |
| Blockchain data | [`GET /masterchainInfo`](https://docs.ton.org/llms/api/v3/blockchain-data/get-masterchain-info/content.md) | Get masterchain info |
| Blockchain data | [`GET /messages`](https://docs.ton.org/llms/api/v3/blockchain-data/get-messages/content.md) | Get messages |
| Blockchain data | [`GET /pendingTransactions`](https://docs.ton.org/llms/api/v3/blockchain-data/get-pending-transactions/content.md) | Get pending transactions |
| Blockchain data | [`GET /transactions`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions/content.md) | Get transactions |
| Blockchain data | [`GET /transactionsByMasterchainBlock`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions-by-masterchain-block/content.md) | Get transactions by masterchain block |
| Blockchain data | [`GET /transactionsByMessage`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions-by-message/content.md) | Get transactions by message |
| Jettons | [`GET /jetton/burns`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-burns/content.md) | Get jetton burns |
| Jettons | [`GET /jetton/masters`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-masters/content.md) | Get jetton masters |
| Jettons | [`GET /jetton/transfers`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-transfers/content.md) | Get jetton transfers |
| Jettons | [`GET /jetton/wallets`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-wallets/content.md) | Get jetton wallets |
| NFTs | [`GET /nft/collections`](https://docs.ton.org/llms/api/v3/nfts/get-nft-collections/content.md) | Get NFT collections |
| NFTs | [`GET /nft/items`](https://docs.ton.org/llms/api/v3/nfts/get-nft-items/content.md) | Get NFT items |
| NFTs | [`GET /nft/sales`](https://docs.ton.org/llms/api/v3/nfts/get-nft-sales-and-auctions/content.md) | Get NFT sales and auctions |
| NFTs | [`GET /nft/transfers`](https://docs.ton.org/llms/api/v3/nfts/get-nft-transfers/content.md) | Get NFT transfers |
| DNS | [`GET /dns/records`](https://docs.ton.org/llms/api/v3/dns/get-dns-records/content.md) | Get DNS records |
| DNS | [`GET /dns/activeAuctions`](https://docs.ton.org/llms/api/v3/dns/get-dns-auctions-by-bidder/content.md) | Get DNS auctions by bidder |
| Staking | [`GET /staking/nominatorPools/pool`](https://docs.ton.org/llms/api/v3/staking/get-nominator-pool/content.md) | Get nominator pool |
| Staking | [`GET /staking/nominatorPools/nominator`](https://docs.ton.org/llms/api/v3/staking/get-nominator-positions-in-nominator-pools/content.md) | Get nominator positions in nominator pools |
| Staking | [`GET /staking/nominatorPools/nominatorEvents`](https://docs.ton.org/llms/api/v3/staking/get-nominator-events-from-nominator-pools/content.md) | Get nominator events from nominator pools |
| Staking | [`GET /staking/nominatorPools/nominatorRewards`](https://docs.ton.org/llms/api/v3/staking/get-nominator-rewards-from-a-nominator-pool/content.md) | Get nominator rewards from a nominator pool |
| Staking | [`GET /staking/nominatorPools/validatorEvents`](https://docs.ton.org/llms/api/v3/staking/get-validator-accounting-events-from-nominator-pools/content.md) | Get validator accounting events from nominator pools |
| Staking | [`GET /staking/nominatorPools/validatorRewards`](https://docs.ton.org/llms/api/v3/staking/get-validator-rewards-from-a-nominator-pool/content.md) | Get validator rewards from a nominator pool |
| Validators | [`GET /validators/events`](https://docs.ton.org/llms/api/v3/validators/get-validator-stake-and-recover-events/content.md) | Get validator stake and recover events |
| Validators | [`GET /validators/elections`](https://docs.ton.org/llms/api/v3/validators/get-validator-elections/content.md) | Get validator elections |
| Validators | [`GET /validators/cycles`](https://docs.ton.org/llms/api/v3/validators/get-validator-cycles/content.md) | Get validator cycles |
| Validators | [`GET /validators/complaints`](https://docs.ton.org/llms/api/v3/validators/get-validator-complaints/content.md) | Get validator complaints |
| Multisig | [`GET /multisig/orders`](https://docs.ton.org/llms/api/v3/multisig/get-multisig-orders/content.md) | Get multisig orders |
| Multisig | [`GET /multisig/wallets`](https://docs.ton.org/llms/api/v3/multisig/get-multisig-wallets/content.md) | Get multisig wallets |
| Vesting | [`GET /vesting`](https://docs.ton.org/llms/api/v3/vesting/get-vesting-contracts/content.md) | Get vesting contracts |
| Stats | [`GET /topAccountsByBalance`](https://docs.ton.org/llms/api/v3/stats/get-top-accounts-by-balance/content.md) | Get top accounts by balance |
| Utils | [`GET /decode`](https://docs.ton.org/llms/api/v3/utils/decode-opcodes-and-bodies-get/content.md) | Decode opcodes and bodies (GET) |
| Utils | [`POST /decode`](https://docs.ton.org/llms/api/v3/utils/decode-opcodes-and-bodies-post/content.md) | Decode opcodes and bodies (POST) |
| Legacy (v2) | [`GET /addressInformation`](https://docs.ton.org/llms/api/v3/api-v2/get-address-information/content.md) | Get address information |
| Legacy (v2) | [`POST /estimateFee`](https://docs.ton.org/llms/api/v3/api-v2/estimate-fee/content.md) | Estimate fee |
| Legacy (v2) | [`POST /message`](https://docs.ton.org/llms/api/v3/api-v2/send-message/content.md) | Send message |
| Legacy (v2) | [`POST /runGetMethod`](https://docs.ton.org/llms/api/v3/api-v2/run-get-method/content.md) | Run get method |
| Legacy (v2) | [`GET /walletInformation`](https://docs.ton.org/llms/api/v3/api-v2/get-wallet-information/content.md) | Get wallet information |
## How to access the API [#how-to-access-the-api]
Developers can access TON Center API v3 either through hosted infrastructure or by running a self-hosted instance.
### Managed service [#managed-service]
Hosted access uses TON Center’s indexed infrastructure. Requests without an API key are rate-limited to a default value.
To increase limits, generate an [API key](https://docs.ton.org/llms/api/get-api-key/content.md) and select a [plan](https://docs.ton.org/llms/api/rate-limit/content.md).
### Self-hosted service [#self-hosted-service]
Run a self-hosted API v3 setup for full control over performance and data retention. For setup instructions, use the [ton-indexer](https://github.com/toncenter/ton-indexer) repository.
# Pagination (https://docs.ton.org/llms/api/v3/pagination/content.md)
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`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions/content.md) | 10 | 1000 | Yes |
| [`actions`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-actions/content.md) | 10 | 1000 | Yes |
| [`blocks`](https://docs.ton.org/llms/api/v3/blockchain-data/get-blocks/content.md) | 10 | 1000 | Yes |
| [`messages`](https://docs.ton.org/llms/api/v3/blockchain-data/get-messages/content.md) | 10 | 1000 | Yes |
| [`traces`](https://docs.ton.org/llms/api/v3/actions-and-traces/get-traces/content.md) | 10 | 1000 | Yes |
| [`jetton/burns`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-burns/content.md) | 10 | 1000 | Yes |
| [`jetton/transfers`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-transfers/content.md) | 10 | 1000 | Yes |
| [`jetton/wallets`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-wallets/content.md) | 10 | 1000 | Yes |
| [`nft/items`](https://docs.ton.org/llms/api/v3/nfts/get-nft-items/content.md) | 10 | 1000 | Yes |
| [`nft/transfers`](https://docs.ton.org/llms/api/v3/nfts/get-nft-transfers/content.md) | 10 | 1000 | Yes |
| [`multisig/orders`](https://docs.ton.org/llms/api/v3/multisig/get-multisig-orders/content.md) | 10 | 1000 | Yes |
| [`multisig/wallets`](https://docs.ton.org/llms/api/v3/multisig/get-multisig-wallets/content.md) | 10 | 1000 | Yes |
| [`transactionsByMasterchainBlock`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions-by-masterchain-block/content.md) | 10 | 1000 | Yes |
| [`jetton/masters`](https://docs.ton.org/llms/api/v3/jettons/get-jetton-masters/content.md) | 10 | 1000 | No |
| [`nft/collections`](https://docs.ton.org/llms/api/v3/nfts/get-nft-collections/content.md) | 10 | 1000 | No |
| [`dns/records`](https://docs.ton.org/llms/api/v3/dns/get-dns-records/content.md) | 100 | 1000 | No |
| [`masterchainBlockShards`](https://docs.ton.org/llms/api/v3/blockchain-data/get-masterchain-block-shards/content.md) | 10 | 1000 | No |
| [`topAccountsByBalance`](https://docs.ton.org/llms/api/v3/stats/get-top-accounts-by-balance/content.md) | 10 | 1024 | No |
| [`transactionsByMessage`](https://docs.ton.org/llms/api/v3/blockchain-data/get-transactions-by-message/content.md) | 10 | 1000 | No |
| [`vesting`](https://docs.ton.org/llms/api/v3/vesting/get-vesting-contracts/content.md) | 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.
### Fetch the first page [#fetch-the-first-page]
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).
### Fetch the next page [#fetch-the-next-page]
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.
### Repeat until the last page [#repeat-until-the-last-page]
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.
# Gram payments processing (https://docs.ton.org/llms/applications/payments/gram/content.md)
Processing Gram payments requires choosing between two architectural approaches:
* invoice-based deposits to a single address, common to all users
* unique deposit addresses per user.
Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](https://docs.ton.org/llms/from-ethereum/content.md). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
Do not send funds to a wallet address that you cannot initialize. Derive addresses deterministically based on contracts [initial state](https://docs.ton.org/llms/foundations/addresses/overview/content.md).
## Deposit methods comparison [#deposit-methods-comparison]
**Invoice-based flow**
**Unique deposit address flow**
**Comparison table**
| Criteria | Invoice-based deposits | Unique deposit addresses |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](https://docs.ton.org/llms/foundations/fees/content.md) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](https://docs.ton.org/llms/api/overview/content.md) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
| Withdrawal handling | [Highload wallet](https://docs.ton.org/llms/contracts/standard/wallets/highload/overview/content.md) can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
| Sharding behavior | All activity hits [one shard](https://docs.ton.org/llms/foundations/shards/content.md); throughput limited by that shard | Wallets are distributed across shards; helps spread load |
## Invoice-based deposits [#invoice-based-deposits]
Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
The implementation deploys one wallet contract (typically [Highload](https://docs.ton.org/llms/contracts/standard/wallets/highload/overview/content.md)) and generates unique invoice identifiers for each deposit. Users send Gram to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
Transaction comments in TON use the text message format; read more in [How TON wallets work](https://docs.ton.org/llms/contracts/standard/wallets/how-it-works/content.md).
Risk: deposits without the correct invoice identifier may be lost.
Scope: incoming transfers to the shared deposit address.
Mitigation: enforce invoice format; reject or hold unmatched deposits; provide a recovery workflow; document comment entry in the UI.
Environment: validate the full flow on testnet before enabling mainnet.
**Advantages**:
* Single wallet simplifies key management
* Reduced gas costs for deployments
* Withdrawals can batch multiple user requests into one transaction using a Highload wallet
**Disadvantages**:
* Access leak to the single hot wallet could lead to all user funds loss
* Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
* Comment parsing adds complexity
* Some user wallet applications don't support comments, limiting accessibility
* Single wallet network load [won't be sharded](https://docs.ton.org/llms/foundations/shards/content.md)
Use the following TypeScript implementation for educational purposes only: [invoice-based Gram deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/toncoin-processing/src/deposits/invoices.ts).
## Unique deposit addresses [#unique-deposit-addresses]
Unique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](https://docs.ton.org/llms/contracts/standard/wallets/mnemonics/content.md) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [`subwallet_id`](https://docs.ton.org/llms/contracts/standard/wallets/how-it-works/content.md) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
Funds sent to a [non-existent or wrong address](https://docs.ton.org/llms/foundations/addresses/overview/content.md) are irrecoverable. Derive addresses deterministically and double check.
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the not deployed address, send the transaction in [non-bounceable mode](https://docs.ton.org/llms/foundations/messages/overview/content.md). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
Sending non-bounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
Risk: leaked or mishandled private keys enable wallet takeover and fund loss.
Scope: generation, storage, and access to per-user wallet keys and deployment workflow.
Mitigation: encrypt keys at rest; restrict access; rotate keys; monitor deployment status; verify destination addresses before crediting deposits.
Environment: validate key management and deployment flow on testnet before mainnet.
Withdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.
**Advantages**:
* No comment parsing removes a major source of user error
* Better security since each user has a unique keypair
* Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
**Disadvantages**:
* Higher operational complexity managing multiple wallets
* Deployment costs multiply by the number of users
* Withdrawal processing requires coordination across wallets
* Storage fees apply to each deployed contract (currently \~0.001 GRAM per year per contract)
Use the following TypeScript implementation for educational purposes only: [unique address Gram deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/toncoin-processing/src/deposits/unique-addresses.ts).
## Withdrawal batching [#withdrawal-batching]
When withdrawing, do not send funds to a wallet address that you cannot initialize later, based on contracts [initial state](https://docs.ton.org/llms/foundations/addresses/overview/content.md).
[Highload wallets](https://docs.ton.org/llms/contracts/standard/wallets/highload/overview/content.md) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
## Common abuse patterns [#common-abuse-patterns]
* Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after the first use.
* Changing the Gram amount but leaving the original invoice identifier to obtain services at a lower price if expected amounts are not enforced.
* Crafting comments that mimic another users invoice identifier in order to hijack their pending credit.
* Submitting large numbers of dust payments to inflate processing costs or exhaust rate limits on transaction polling.
## Monitoring best practices [#monitoring-best-practices]
Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [`getTransactions`](https://docs.ton.org/llms/api/v2/transactions/get-transactions/content.md) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
Store transaction state persistently. Record the last processed `lt` value (`lt` here is logical time) and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
Use multiple RPC endpoints for reliability. TON has several public API providers and liteserver networks. Implement fallback logic to switch endpoints if the primary becomes unavailable. Compare results across endpoints to detect potential inconsistencies.
Log all processing decisions including deposit credits, withdrawal submissions, and failed transactions. These logs are essential for debugging user reports and auditing system behavior. Include transaction hashes, logical times, amounts, and user identifiers in logs.
# Jettons payments processing (https://docs.ton.org/llms/applications/payments/jettons/content.md)
Processing jetton payments requires understanding TON's sharded token architecture. Unlike single-contract token systems, each jetton type consists of a master contract and individual wallet contracts for each holder.
For example, USDT on TON is implemented as a jetton, and its master (minter) contract address is `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`.
Jettons are fungible tokens on TON. Each jetton has a master contract (minter) and separate wallet contracts for every holder. Read more in [How Jettons Work](https://docs.ton.org/llms/contracts/standard/tokens/jettons/how-it-works/content.md).
Jetton processing is security-critical. Incorrect validation of jetton wallet addresses or transfer notifications can lead to accepting fake tokens or crediting wrong amounts.
## Key concepts [#key-concepts]
Before implementing jetton payment processing, understand these core concepts:
**Jetton architecture**: Each jetton type has one master contract that stores metadata and total supply. Each address holding the jetton has a separate jetton wallet contract at a deterministic address derived from the master contract and owner address.
**Transfer flow**: Jetton transfers involve multiple messages. A user sends a `transfer` message to their jetton wallet, which sends an `internal_transfer` to the recipient's jetton wallet, which then sends a `transfer_notification` to the recipient's address if `forward_ton_amount > 0`.
Jetton transfers are considered successful only when the recipient receives `transfer_notification`. Services must set `forward_ton_amount` to at least 0.000000001 Gram (1 nanogram) when sending tokens to trigger notifications. Without this, transfers won't be compliant and may not be processed by exchanges and other services.
**Security model**: Always validate that jetton wallets belong to the expected master contract. Anyone can deploy fake jetton wallet contracts with arbitrary balances.
This article covers processing jetton deposits using transfer notifications. All approaches require maintaining an allowlist of trusted jetton master contracts.
For architectural patterns and deposit methods comparison, see [Gram processing](https://docs.ton.org/llms/applications/payments/gram/content.md).
## Processing deposits [#processing-deposits]
Skipping any validation step or changing their order can lead to incorrect deposit processing and potential loss of funds.
### Setup [#setup]
Processing jetton deposits requires:
* **Allowlist of trusted jetton masters**: List of jetton master contract addresses to accept
* **Deposit wallet address**: Service wallet (e.g., wallet v4 or v5)
### Initial configuration [#initial-configuration]
1. For each allowlisted jetton master, derive the jetton wallet address for the deposit wallet using the master contract's `get_wallet_address()` method
2. Store the mapping of `jetton master` → `jetton wallet` → `deposit wallet` in the database
3. Begin monitoring transactions to the deposit wallet address
### Processing incoming transactions [#processing-incoming-transactions]
When a transaction arrives at the deposit wallet:
1. Check that `tx.in_msg.source` matches a known jetton wallet for this deposit wallet
2. Verify the master → jetton wallet relationship:
* Call `get_wallet_address(deposit-wallet)` on the master contract
* Confirm the returned address matches the sender
3. Verify there are no outgoing messages (`tx.out_msgs.length === 0`)
4. Parse the message body:
* Check the opcode (first 32 bits of `tx.in_msg.body`) equals `0x7362d09c` (transfer\_notification)
* Extract `query_id`, `amount`, `sender`, and `forward_payload` [according to TL-B](https://docs.ton.org/llms/contracts/standard/tokens/jettons/api/content.md)
5. Verify the amount matches the expected value
### Crediting user accounts [#crediting-user-accounts]
After validation, extract deposit information:
* For [invoice-based deposits][inv-dep]: Parse the invoice ID from `forward_payload`, match it against the database, and credit the corresponding user account.
* For [address-based deposits][add-dep]: Match the `deposit-wallet` address against the database and credit the user account.
Not production-ready code, use only for educational purposes:
* [Invoice-based jetton deposits][inv-dep]
* [Unique address jetton deposits][add-dep]
[inv-dep]: https://github.com/ton-org/docs-examples/blob/jetton-processing-only/guidebook/jetton-processing/src/deposits/jetton-invoices.ts
[add-dep]: https://github.com/ton-org/docs-examples/blob/jetton-processing-only/guidebook/jetton-processing/src/deposits/jetton-unique-addresses.ts
## Security considerations [#security-considerations]
### Master-wallet verification [#master-wallet-verification]
Never trust jetton wallet addresses without verification. Always perform these checks:
1. Get the jetton master address from the allowlist
2. Call `jetton_master.get_wallet_address(owner_address)`
3. Verify the returned address matches the jetton wallet that sent the notification
### Transfer notification validation [#transfer-notification-validation]
When processing deposits via `transfer_notification`:
* Verify the opcode is exactly `0x7362d09c`
* Check the sender address is an expected jetton wallet
* Extract `amount` in base units (not decimal)
* Validate the `sender` field against expected user addresses
* Parse `forward_payload` carefully—it may be malformed
* Check for bounce indicators (single outgoing message back to sender)
### Fake jetton detection [#fake-jetton-detection]
Attackers can deploy jettons with identical names, symbols, and images:
* Always verify the jetton master address against the allowlist
* Never trust metadata (name, symbol, image) for authentication
* Display the master contract address in admin interfaces
* Implement a manual approval workflow for adding new jettons
## Common attack patterns [#common-attack-patterns]
### Fake jetton wallets [#fake-jetton-wallets]
**Attack**: Attacker deploys a contract claiming to be a jetton wallet with an inflated balance.
**Mitigation**: Verify the master-wallet relationship by calling `get_wallet_address()` on the master contract.
### Invoice ID reuse [#invoice-id-reuse]
**Attack**: User attempts to reuse a settled invoice identifier.
**Mitigation**: Mark invoices as used after the first successful deposit.
### Master contract spoofing [#master-contract-spoofing]
**Attack**: Deploying a fake master contract that validates the attacker's fake jetton wallets.
**Mitigation**: Maintain a strict allowlist of trusted master contracts and verify all jetton wallets against it.
## Implementation checklist [#implementation-checklist]
Before enabling jetton processing in production:
### Testing [#testing]
1. Deploy and test on testnet with real user scenarios
2. Verify master-wallet relationships for all allowlisted jettons
3. Test with fake jetton wallets to confirm rejection
4. Validate transfer notification parsing with various payload formats
5. Test bounce detection and handling
6. Test invoice ID collision and reuse scenarios
7. Test full flow: deposit → credit → withdrawal → confirmation
# Payment processing overview (https://docs.ton.org/llms/applications/payments/overview/content.md)
Payment processing on TON refers to monitoring and handling blockchain transactions for business applications. While simple use cases can rely entirely on smart contracts, most real-world payment systems require off-chain processing to track deposits, manage user balances, send confirmations, and integrate with existing business logic.
See how to set up an example [self-hosted payment processor](https://docs.ton.org/llms/applications/payments/setup/content.md) for Gram and USDT (on TON) deposits and withdrawals.
## On-chain vs off-chain processing [#on-chain-vs-off-chain-processing]
On-chain processing executes all payment logic within smart contracts. When a user sends Grams or Jettons (including USDT on TON mainnet) to a contract, the contract immediately processes the payment and updates state. This works for simple scenarios like direct peer-to-peer transfers or automated market makers, but becomes impractical when you need user accounts, payment history, refunds, or integration with external systems.
Off-chain processing monitors blockchain state changes from outside the network. Your application observes transactions, verifies their validity, updates internal databases, and triggers business logic. Exchanges, merchants, and payment processors use this approach because it provides flexibility to implement complex workflows, maintain user data, and integrate with traditional systems.
## Transaction finality [#transaction-finality]
TON achieves transaction [finality](https://en.wikipedia.org/wiki/Blockchain#Finality) after a single masterchain block confirmation, typically within 1 second. Once a transaction from a shardchain appears in a masterchain block, it becomes irreversible. This differs from blockchains like Ethereum where merchants wait for multiple confirmations (usually 12-15 blocks, taking 2-3 minutes) or Bitcoin where 6 confirmations are standard (about 60 minutes).
Since the [Catchain 2.0 update](https://docs.ton.org/llms/subsecond/content.md), the masterchain coordinates all workchain activity and produces blocks approximately every 400 milliseconds. When monitoring payments, you need to verify that the transaction was included in a masterchain block rather than just in a shardchain. Most TON APIs provide methods to check whether a transaction has achieved masterchain finality or, better yet, only consider a transaction included in the masterchain as finalized by the network.
## Supported assets [#supported-assets]
TON supports several asset types for payment processing:
**Gram** is the native currency of the network. Every wallet can receive Gram directly without additional setup. Transfers are simple value transfers between addresses, making Gram the easiest asset to process.
[**Jettons**](https://docs.ton.org/llms/contracts/standard/tokens/jettons/overview/content.md) are fungible tokens following the TON Enhancement Proposal 74 (TEP-74) standard. Each Jetton type has a master contract and individual wallet contracts for each holder. When processing Jetton payments, you monitor the Jetton wallet contract associated with your deposit address. Transfer notifications include sender information and transfer amounts.
Read more about [how Jettons work](https://docs.ton.org/llms/contracts/standard/tokens/jettons/how-it-works/content.md).
* [Gram processing](https://docs.ton.org/llms/applications/payments/gram/content.md)
* [Jetton processing](https://docs.ton.org/llms/applications/payments/jettons/content.md)
## Implementation approaches [#implementation-approaches]
Three main approaches exist for implementing payment processing on TON:
* **Self-built solution**: You run your own service that connects to some TON API or [liteserver](https://docs.ton.org/llms/api/overview/content.md), monitors blocks for relevant transactions, and maintains a database of payment events. This requires building infrastructure to fetch blocks, parse transactions, handle reconnections, and manage state. The advantage is complete control over the implementation and no dependency on external services. The disadvantage is significant development and maintenance effort.
* **Self-hosted payment processor**: Open-source payment processors like [Bicycle](https://docs.ton.org/llms/applications/payments/bicycle/content.md) and [Spice harvester](https://github.com/txsociety/spice-harvester) provide ready-to-deploy solutions that handle blockchain monitoring and expose APIs for your application. You deploy the processor on your infrastructure, configure it for your wallet addresses and asset types, and consume its API to track payments. This balances control with reduced development effort, though you still manage the infrastructure.
* **Third-party payment processor**: External services handle all blockchain interaction and provide simple APIs or webhooks for payment notifications. You integrate their SDK or API, and they manage infrastructure, monitoring, and maintenance. This is fastest to implement but introduces dependency on the service provider and typically involves transaction fees.
The choice depends on your requirements for control, development resources, and operational complexity. High-volume applications often build custom solutions, while smaller merchants prefer third-party services.
## Monitoring payments [#monitoring-payments]
Payment monitoring requires polling for new blocks and filtering transactions that affect your addresses. For Gram, you check for incoming messages to your wallet address. For Jettons, you monitor the Jetton wallet contract associated with your address for transfer notifications.
The typical monitoring flow involves fetching the latest workchain blocks, retrieving all transactions from them, filtering for transactions involving your addresses, parsing transaction data to extract amounts and metadata, verifying the transaction reached finality, and updating your internal payment records.
Most applications poll for new blocks every few seconds. More sophisticated systems use multiple strategies: polling for recent data, webhooks from indexing services for real-time notifications, and periodic reconciliation to catch any missed transactions.
# How to set up a self-hosted payment processor using Bicycle (https://docs.ton.org/llms/applications/payments/setup/content.md)
This guide shows one of the possible ways to set up Gram and USDT (on TON) payments in business applications. For more info and alternative approaches, see the [payment processing overview](https://docs.ton.org/llms/applications/payments/overview/content.md).
[Bicycle](https://github.com/gobicycle/bicycle) is a self-hosted payment processor for TON. It runs next to an exchange, custodial wallet, merchant backend, or payment service and provides a REST API for:
* Reusable per-user deposit addresses
* Gram deposits and withdrawals
* Jetton deposits and withdrawals, including USDT on TON
* Hot-wallet aggregation and optional cold-wallet sweeps
* Webhooks or RabbitMQ notifications
Use Bicycle to show one deposit address per user and currency, credit deposits automatically, and submit withdrawals through one backend API.
Bicycle controls a hot wallet from `SEED`. Do **not** withdraw manually from this hot wallet outside Bicycle. The processor tracks balances, internal sweeps, and withdrawal state in its database — bypassing it can make the service state inconsistent.
## Architecture [#architecture]
Bicycle creates deposit addresses from the hot-wallet seed and stores the mapping to an application `user_id`. For Gram, users deposit to a TON wallet address. For USDT, users deposit to a proxy owner address that owns the user's USDT jetton wallet. Bicycle scans the relevant shard blocks, records deposits, sweeps balances to the hot wallet when thresholds are met, and sends withdrawals from the hot wallet.
The application does not need to parse comments, generate wallet contracts, scan blocks, or build jetton transfer messages. The backend calls Bicycle and stores Bicycle IDs in the application ledger.
## Prerequisites [#prerequisites]
* Linux-based OS with `jq` and `curl` installed
* [Docker Engine](https://docs.docker.com/engine/install/) 24 or later with Docker Compose v2
* A 24-word seed phrase for the Bicycle hot wallet
* Enough Gram on the hot wallet to pay fees and deploy/sweep deposit wallets
* A cold wallet address for automatic cold-wallet sweeps
Test the full flow on testnet first. Note that `IS_TESTNET=true` only controls address validation inside Bicycle — it does **not** prove that the liteserver is testnet.
## Clone and build Bicycle [#1-clone-and-build-bicycle]
```bash
git clone https://github.com/gobicycle/bicycle.git
cd bicycle
make -f Makefile
```
The existing Bicycle `docker-compose.yml` can start PostgreSQL, the processor, Grafana, Prometheus, and RabbitMQ. For a minimal production-like setup, start only PostgreSQL and `payment-processor`.
## Choose a liteserver [#2-choose-a-liteserver]
Bicycle connects to a liteserver over Abstract Datagram Network Layer (ADNL). Either use a [public liteserver with proof verification enabled](#option-a-public-liteserver-with-proofs), or run a [self-hosted liteserver](#option-b-local-liteserver-with-official-docker-image) next to Bicycle.
### Option A: Public liteserver with proofs [#option-a-public-liteserver-with-proofs]
Use this path for a short setup. Fetch the current public liteserver list from the network config and extract one endpoint into the Bicycle `.env` file:
```bash
curl -fsSL https://ton-blockchain.github.io/global.config.json \
| jq -r '
def ntoa:
(if . < 0 then . + 4294967296 else . end) as $ip
| [($ip / 16777216 | floor) % 256,
($ip / 65536 | floor) % 256,
($ip / 256 | floor) % 256,
$ip % 256]
| join(".");
.liteservers[0]
| "LITESERVER=\(.ip | ntoa):\(.port)\nLITESERVER_KEY='\''\(.id.key)'\''"
' >> .env
```
Then enable proof checking:
```bash
cat >> .env <<'EOF'
PROOF_CHECK_ENABLED=true
NETWORK_CONFIG_URL=https://ton-blockchain.github.io/global.config.json
EOF
```
For testnet, use `https://ton-blockchain.github.io/testnet-global.config.json` and set `IS_TESTNET=true`.
Public liteservers are shared infrastructure. Keep `PROOF_CHECK_ENABLED=true` and set a conservative `LITESERVER_RATE_LIMIT`.
Consider setting up a [dedicated liteserver](#option-b-local-liteserver-with-official-docker-image) for production payment volume.
### Option B: Local liteserver with official Docker image [#option-b-local-liteserver-with-official-docker-image]
Ensure the server meets the [minimal hardware requirements](https://docs.ton.org/llms/nodes/cpp/run-liteserver/content.md) for running a liteserver node.
Use this path to run Bicycle and the liteserver on the same host. Put this compose file next to Bicycle's `docker-compose.yml`:
```yaml title="docker-compose.liteserver.yml"
services:
ton-node:
image: ghcr.io/ton-blockchain/ton:latest
container_name: ton_liteserver
restart: unless-stopped
network_mode: host
volumes:
- /var/ton-work/db:/var/ton-work/db
environment:
PUBLIC_IP: ${PUBLIC_IP}
GLOBAL_CONFIG_URL: https://ton-blockchain.github.io/global.config.json
DUMP_URL: https://dump.ton.org/dumps/latest.tar.lz
LITESERVER: "true"
LITE_PORT: "30003"
VALIDATOR_PORT: "30001"
QUIC_PORT: "31001"
CONSOLE_PORT: "30002"
STATE_TTL: "86400"
ARCHIVE_TTL: "2592000"
```
Start it:
```bash
# One of the ways to check the public IP of the server.
# If it is known ahead of time, manually specify it here.
export PUBLIC_IP=$(curl -4 -fsSL ifconfig.me)
docker compose -f docker-compose.liteserver.yml up -d ton-node
# Follow the logs to check the status.
docker logs -f ton_liteserver
```
After `/var/ton-work/db/config.json` is created, append the local liteserver endpoint to Bicycle's `.env`:
```bash
jq -r '
.liteservers[0]
| "LITESERVER=host.docker.internal:\(.port)\nLITESERVER_KEY='\''\(.id.key)'\''"
' /var/ton-work/db/config.json >> .env
```
Add host access to the `payment-processor` service in Bicycle's compose file when Bicycle uses Docker's bridge network:
```yaml title="docker-compose.yml"
services:
payment-processor:
extra_hosts:
- "host.docker.internal:host-gateway"
```
For node setup, hardware requirements, firewall, sync, and maintenance details, see [Run a liteserver](https://docs.ton.org/llms/nodes/cpp/run-liteserver/content.md). The official Docker image uses the same node software. The key settings above are `LITESERVER=true`, `LITE_PORT`, a public `PUBLIC_IP`, and persistent `/var/ton-work/db` storage.
## Configure assets [#3-configure-assets]
Create `.env` file in the Bicycle directory:
```bash title=".env"
# PostgreSQL setup
POSTGRES_DB=payment_processor
POSTGRES_USER=payment_processor
POSTGRES_PASSWORD=
POSTGRES_READONLY_PASSWORD=
DB_URI=postgres://payment_processor:@payment_processor_db:5432/payment_processor
# Bicycle's REST API port
API_PORT=8081
# Bicycle's Bearer token for REST API
API_TOKEN=
# Seed phrase for the main hot wallet, 12 or 24 word mnemonic compatible with standard TON wallets
SEED=
# TON address of the cold wallet
COLD_WALLET=
# Cutoffs in nanograms format:
# hot_wallet_min_balance:hot_wallet_max_balance:min_withdrawal_amount:hot_wallet_residual_balance
TON_CUTOFFS=1000000000:100000000000:1000000000:95000000000
# List of jettons to be processed by the service; set to USDTs only
JETTONS=USDT:EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs:100000000000:10000000:95000000000
# USDTs only exist on mainnet!
IS_TESTNET=false
# Miscellaneous, refer to Bicycle's README.md for details
DEPOSIT_SIDE_BALANCE=true
FORWARD_TON_AMOUNT=1
LITESERVER_RATE_LIMIT=25
LITESERVER_MAX_RETRIES=10
LITESERVER_BASE_RETRY_DELAY=100
ALLOWABLE_LAG=40
```
Configure the processor container to receive all Bicycle `.env` vars, not only the variables already listed in the upstream compose file:
```yaml title="docker-compose.yml"
services:
payment-processor:
env_file:
- .env
```
`TON_CUTOFFS` uses nanograms:
| Position | Meaning |
| ----------------------------- | --------------------------------------------------------- |
| `hot_wallet_min_balance` | Minimum hot-wallet Gram balance required on startup |
| `hot_wallet_max_balance` | Balance that triggers a cold-wallet sweep |
| `minimum_withdrawal_amount` | Minimum deposit-wallet balance to sweep to the hot wallet |
| `hot_wallet_residual_balance` | Balance left after a cold-wallet sweep |
`JETTONS` uses jetton base units. USDT on TON has 6 decimals, so `1000000` means 1 USDT:
| Position | Meaning |
| -------------------- | ------------------------------------------------------- |
| `USDT` | Currency code used in Bicycle API requests |
| [`EQCx...sDs`][usdt] | [USDT jetton master address][usdt] on mainnet |
| `100000000000` | Sweep hot-wallet excess above 100,000 USDT |
| `10000000` | Sweep a deposit wallet after it holds more than 10 USDT |
| `95000000000` | Leave 95,000 USDT after a cold-wallet sweep |
Never accept jettons by symbol or metadata alone — only accept an allow-listed master contract address. Verify the USDT jetton master address before mainnet launch.
USDTs only exist on the mainnet.
For information about the other environment variables, refer to the Bicycle's `README.md` file.
## Start Bicycle [#4-start-bicycle]
For a minimal production setup, start only `payment-postgres` (PostgreSQL) and `payment-processor` (Bicycle itself):
```bash
docker compose up -d payment-postgres
docker compose up -d payment-processor
```
Optional available services include: `payment-grafana` (Grafana), `payment-prometheus` (Prometheus), and `payment-rabbitmq` (RabbitMQ).
Check sync:
```bash
curl -sS http://127.0.0.1:8081/v1/system/sync | jq
```
Example of an expected response when Bicycle is caught up:
```json
{
"is_synced": true,
"last_block_gen_utime": 1719306580
}
```
## Create deposit addresses [#5-create-deposit-addresses]
Create one Gram deposit address for a user:
```bash
curl -sS http://127.0.0.1:8081/v1/address/new \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id":"user-1001","currency":"TON"}' | jq
```
Create one USDT deposit address for the same user:
```bash
curl -sS http://127.0.0.1:8081/v1/address/new \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id":"user-1001","currency":"USDT"}' | jq
```
Store the returned address in the application database and show it to the user. Users do not need to enter comments or invoice IDs.
To list all addresses later:
```bash
curl -sS "http://127.0.0.1:8081/v1/address/all?user_id=user-1001" \
-H "Authorization: Bearer $API_TOKEN" | jq
```
## Credit deposits [#6-credit-deposits]
If `DEPOSIT_SIDE_BALANCE=true`, Bicycle credits deposits when it observes income on the deposit address. Query the user's total credited income:
```bash
curl -sS "http://127.0.0.1:8081/v1/income?user_id=user-1001" \
-H "Authorization: Bearer $API_TOKEN" | jq
```
Fetch deposit history for reconciliation:
```bash
curl -sS "http://127.0.0.1:8081/v1/deposit/history?user_id=user-1001¤cy=USDT&limit=20&offset=0&sort_order=desc" \
-H "Authorization: Bearer $API_TOKEN" | jq
```
Look up a deposit by transaction hash when handling support tickets:
```bash
curl -sS "http://127.0.0.1:8081/v1/deposit/income?tx_hash=" \
-H "Authorization: Bearer $API_TOKEN" | jq
```
## Send manual withdrawals [#7-send-manual-withdrawals]
Bicycle controls a hot wallet from `SEED`. Do **not** withdraw manually from this hot wallet **outside** Bicycle. The processor tracks balances, internal sweeps, and withdrawal state in its database — bypassing it can make the service state inconsistent.
Use a unique `query_id` per user withdrawal. Bicycle rejects duplicate `(user_id, query_id)` pairs.
Withdraw 1 Gram:
```bash
# Replace with desired TON wallet address
curl -sS http://127.0.0.1:8081/v1/withdrawal/send \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user-1001",
"query_id": "wd-ton-000001",
"currency": "TON",
"amount": 1000000000,
"destination": "",
"comment": "withdrawal wd-ton-000001"
}' | jq
```
Withdraw 25 USDT:
```bash
# Replace with desired TON wallet address
curl -sS http://127.0.0.1:8081/v1/withdrawal/send \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user-1001",
"query_id": "wd-usdt-000001",
"currency": "USDT",
"amount": 25000000,
"destination": "",
"comment": "withdrawal wd-usdt-000001"
}' | jq
```
Check the withdrawal status:
```bash
# Replace with the `query_id` previously submitted to `/v1/withdrawal/send`
curl -sS "http://127.0.0.1:8081/v1/withdrawal/status?id=" \
-H "Authorization: Bearer $API_TOKEN" | jq
```
Statuses are `pending`, `processing`, `processed`, and `failed`. Treat `processed` as the terminal success state in the application ledger.
## Enable notifications [#8-enable-notifications]
### Option A: Webhook endpoint [#option-a-webhook-endpoint]
Extend the `.env` file with webhook variables before starting the `payment-processor` service:
```bash
cat >> .env <<'EOF'
# When set, Bicycle will send webhooks to the specified endpoint
WEBHOOK_ENDPOINT=https://payments.example.com/ton/bicycle/webhook
# Bearer token for the webhook requests — leave unset when unused
# WEBHOOK_TOKEN=
EOF
```
Start or restart the service:
```bash
docker compose up -d payment-processor
```
Bicycle sends deposit notifications as JSON:
```json
{
"deposit_address": "",
"time": 1719306580,
"amount": "25000000",
"source_address": "",
"comment": "optional comment",
"tx_hash": "f9b9e7efd3a38da318a894576499f0b6af5ca2da97ccd15c5f1d291a808a0ebf",
"user_id": "user-1001"
}
```
The webhook handler should be idempotent by `tx_hash`, verify `user_id` and `deposit_address` against application records, credit the internal ledger once, and return HTTP `200` with an empty body. Bicycle stops after repeated unsuccessful webhook delivery, so monitor processor logs and alerts.
### Option B: RabbitMQ [#option-b-rabbitmq]
Extend the `.env` file with RabbitMQ variables and start the `payment-rabbitmq` service before starting the `payment-processor`:
```bash
cat >> .env <<'EOF'
# When true, Bicycle will send incoming notiications to the RabbitMQ queue
QUEUE_ENABLED=true
# URI for client connections to the queue
QUEUE_URI=amqp://guest:guest@payment_rabbitmq:5672/
# Name of the exchange
QUEUE_NAME=
EOF
```
Start or restart the services:
```bash
docker compose up -d payment-rabbitmq
docker compose up -d payment-processor
```
## Operational checklist [#operational-checklist]
* Keep `SEED`, `API_TOKEN`, database credentials, and webhook tokens in a secret manager.
* Expose Bicycle's API **only** to the application backend, not to the public Internet.
* Keep enough Gram on the hot wallet for fees, jetton notifications, and deposit sweeps.
* Keep a separate cold wallet whose seed is **never** loaded into Bicycle.
* Always use `PROOF_CHECK_ENABLED=true` for public or rented liteservers.
* Monitor `/v1/system/sync`, `/metrics`, hot-wallet balances, failed withdrawals, and webhook delivery.
* Reconcile the application ledger with `/v1/deposit/history` and `/v1/withdrawal/status`.
* Test mistaken-transfer recovery with `/v1/withdrawal/service/ton` and `/v1/withdrawal/service/jetton` before production.
## See also [#see-also]
* [Payment processing overview](https://docs.ton.org/llms/applications/payments/overview/content.md)
* [Gram payments processing](https://docs.ton.org/llms/applications/payments/gram/content.md)
* [Jetton payments processing](https://docs.ton.org/llms/applications/payments/jettons/content.md)
* [Guide for running a liteserver](https://docs.ton.org/llms/nodes/cpp/run-liteserver/content.md)
* [Liteserver proof verification](https://docs.ton.org/llms/foundations/proofs/verifying-liteserver-proofs/content.md)
[usdt]: https://tonscan.org/jetton/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs
# Core concepts of TON Connect (https://docs.ton.org/llms/applications/ton-connect/core-concepts/content.md)
TON Connect is a protocol that links dApps to wallets. This page introduces the main building blocks — architecture, bridges, sessions, links, manifests, the wallet registry, feature negotiation, and the security model. Each section gives you enough context to work with the SDK; the full protocol details live in the [protocol specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/overview.md).
## Architecture [#architecture]
TON Connect has three roles: the **app**, the **wallet**, and the **bridge**.
* The **app** runs in the user's browser, native app, or inside the wallet's webview.
* The **wallet** holds the user's keys and signs on the user's behalf.
* The **bridge** relays encrypted messages between the two. It is operated by the wallet provider and is not trusted with plaintext.
Two transports carry the protocol:
* The **HTTP bridge** — used when the app and the wallet are on different devices or in different browsers. Messages are end-to-end encrypted; the bridge sees only ciphertext.
* The **JS bridge** — used when the app runs inside the wallet's webview, or the wallet is a browser extension. Both sides share the device, so messages are exchanged in plaintext.
### Connect, request, disconnect over the HTTP bridge [#connect-request-disconnect-over-the-http-bridge]
Only the `ConnectRequest` embedded in the universal link travels in clear; once the wallet generates its keypair `(b, B)`, every bridge message — starting with the wallet's `ConnectEvent` reply — is encrypted with `nacl.box` under the session keys.
### Connect over the JS bridge [#connect-over-the-js-bridge]
For wire-level details, see the [protocol specification overview](https://github.com/ton-blockchain/ton-connect/blob/main/spec/overview.md), the [Bridge specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/bridge.md), the [Session specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/session.md), and the [Connect specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/connect.md).
## Bridges [#bridges]
A bridge is the transport that carries TON Connect messages between an app and a wallet. The protocol defines two types.
| Type | When it is used | Encryption |
| ----------- | -------------------------------------------------------------------------- | ------------------------ |
| HTTP bridge | App and wallet on different devices or in different browsers | End-to-end (NaCl) |
| JS bridge | App runs inside the wallet's webview, or the wallet is a browser extension | Not needed (same device) |
Both bridges deliver the same protocol messages — `ConnectRequest`, `ConnectEvent`, `AppRequest`, `WalletResponse`, `WalletEvent`. The transport is invisible to most dApp code thanks to the SDK.
The **HTTP bridge** is operated by the wallet provider and published in the wallet's [`wallets-list`](https://github.com/ton-connect/wallets-list) entry. It exposes two endpoints — `GET /events` (SSE stream) and `POST /message` — and buffers messages until the recipient picks them up or the TTL expires. Because the bridge is untrusted, every message after the initial connect is encrypted with NaCl `crypto_box`.
The **JS bridge** is injected by the wallet as `window..tonconnect` when the dApp runs inside the wallet's webview or as a browser extension. The `` comes from the wallet's `bridge[]` entry of `type: "js"` in the wallets-list. The JS bridge does not use the session encryption keys — the webview and the wallet share a device, so the channel is already trusted and the SDK works directly with plaintext.
The SDK picks the JS bridge when available, otherwise falls back to the HTTP bridge. A wallet may list both.
Bridge endpoints and the `BridgeMessage` envelope accept an optional `trace_id` (UUID, UUIDv7 recommended) for analytics correlation. Tracing-aware bridges echo it back to the recipient, so the dApp, bridge, and wallet share one ID per user-visible operation. The SDK auto-generates a `traceId`; signing-action results expose it, while connect and disconnect use it only for correlation.
Spec reference: [Bridge specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/bridge.md).
## Sessions and keypairs [#sessions-and-keypairs]
A TON Connect session is the agreement between one app and one wallet account. Each side generates an X25519 keypair on first contact (NaCl `crypto_box`). The 32-byte public key becomes that side's `client_id`. The session is the pair of those two `client_id`s: the dApp's `A` and the wallet's `B`.
Session keys do two jobs:
* **Routing.** The HTTP bridge keeps a per-`client_id` queue. Each side subscribes to its own queue and posts to the other side's.
* **Encryption.** Every message after the initial connect is encrypted with `nacl.box`. Each message carries a fresh 24-byte random nonce. The bridge sees only ciphertext, the sender's `client_id`, and the TTL.
The JS bridge does not use these keys — see [Bridges](#bridges).
### What is persisted [#what-is-persisted]
| Persisted (dApp side) | Not persisted |
| ------------------------------------------------------------------------ | ------------------- |
| Session keypair (`a`, `A`) | RPC request bodies |
| Wallet's `client_id` (`B`) | RPC response bodies |
| Wallet's bridge URL | Encryption nonces |
| `DeviceInfo` from the connect event | Connect modal state |
| Wallet account info (`address`, `chain`, `walletStateInit`, `publicKey`) | |
| Last SSE event ID (`lastWalletEventId`) for resumable reconnects | |
| Next outgoing RPC request ID (`nextRpcRequestId`) | |
The wallet keeps the corresponding state on its side: its keypair `(b, B)`, the dApp's `client_id` `A`, the manifest URL it approved, and any per-session UI state. Browser SDKs default to `localStorage`; headless or server-side flows pass an `IStorage` implementation.
Treat the stored values like session secrets. The `client_id` is semi-private — anyone who knows it can fetch ciphertext or remove queued bridge messages.
### Lifetime [#lifetime]
The dApp persists its keypair, the wallet's `client_id`, the bridge URL, and the last SSE event ID. On reload the SDK calls `restoreConnection()`:
* **Restored.** Both sides reconnect to their bridge queues and the SDK continues. The wallet sees no new connect prompt.
* **Revoked.** The wallet has dropped the session. The SDK returns `UNKNOWN_APP_ERROR` (code `100`) and clears local state.
* **Bridge unreachable.** The SDK retries at a fixed interval; the connection stays in a "restoring" state until the bridge responds.
A session is not bound to a single browser tab — reloads and cross-tab sharing work as long as storage persists.
### Multi-device behavior [#multi-device-behavior]
A session is bound to wherever its keypair lives. The protocol does not synchronize keypairs across devices.
* **Tabs in the same browser.** Same origin, same `localStorage`, one shared session.
* **Different browsers, profiles, or devices.** Distinct storage means a distinct keypair. The user goes through the connect flow on each, producing separate sessions.
* **Custom storage backends.** A headless app injects an `IStorage` (IndexedDB, encrypted file, server database). One keypair per logical session — keyed per user on a multi-tenant server, not shared globally.
* **Do not copy session state to another device.** Anyone holding the dApp's secret key `a` and `client_id` `B` can decrypt every message in the session. To "share" a connection across devices, do a fresh connect on each.
For cross-device continuity, use `ton_proof` with a server-issued token — the user reconnects on each device, the backend verifies the proof, and the token follows the user. See [Authenticate with `ton_proof`](https://docs.ton.org/llms/applications/ton-connect/how-to/connect/content.md).
Spec reference: [Session specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/session.md). See also [Disconnect a session](https://docs.ton.org/llms/applications/ton-connect/how-to/disconnect/content.md).
## Universal links [#universal-links]
A TON Connect connection starts with a deep link from the dApp to the wallet — as a tap on mobile, a QR code on desktop, or a click inside a webview. The link comes in three forms:
* **Wallet universal link** — an HTTPS link specific to one wallet, listed as `universal_url` in [`wallets-list`](https://github.com/ton-connect/wallets-list). Used when the user has picked a wallet from the picker.
```
https://?v=2&id=&r=&ret=back
```
* **Unified `tc://`** — the protocol-level scheme every wallet supports. A single QR code connects to any installed TON Connect wallet.
```
tc://?v=2&id=&r=&ret=back
```
* **Custom-scheme deep link** — a wallet-specific scheme like `mytonwallet-tc://`, published as `deepLink` in the wallets-list.
### Parameters [#parameters]
| Param | Required | Meaning |
| ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `v` | yes | Protocol version (`2`). |
| `id` | yes | dApp's `client_id` as hex (no `0x` prefix). |
| `r` | yes | URL-safe JSON of `ConnectRequest`. |
| `ret` | no | Return strategy: `back` (default), `none`, or a URL. |
| `e` | no | Embedded RPC request, base64-URL JSON. Requires `EmbeddedRequest` feature. |
| `trace_id` | no | UUID (UUIDv7 recommended) for end-to-end analytics correlation across dApp, bridge, and wallet. Echoed by tracing-aware bridges in the `BridgeMessage` envelope, and reused by tracing-aware wallets on their reply. |
The `e` parameter packs an RPC request into the connect URL so the wallet handles connection and action in a single tap. The UI SDK attaches it only for wallets that advertise `EmbeddedRequest`. If no embedded response arrives, the SDK reports that outcome and the dApp decides whether retrying is safe. See [Connect-and-act in one tap](https://docs.ton.org/llms/applications/ton-connect/how-to/embedded-request/content.md).
Spec reference: [Deep links specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/deeplinks.md).
## Manifest [#manifest]
The app manifest is a JSON file the wallet fetches before showing the connect prompt. It carries metadata the wallet displays to the user — app name, icon, and optional legal links.
The dApp passes the URL as `manifestUrl` in the connect request. By convention the file is named `tonconnect-manifest.json` and hosted at the root of the dApp's domain.
### Fields [#fields]
| Field | Required | Description |
| ------------------ | -------- | -------------------------------------------------------------------- |
| `url` | yes | App URL. Used as the dApp identifier. No trailing slash. |
| `name` | yes | Display name shown to the user. |
| `iconUrl` | yes | App icon URL. PNG or ICO, 180×180 px recommended. SVG not supported. |
| `termsOfUseUrl` | no | URL to terms of use. |
| `privacyPolicyUrl` | no | URL to privacy policy. |
The manifest must be reachable with a `GET` from any origin, without CORS restrictions, without auth and without a proxy challenge. It must be served over HTTPS — wallets do not guarantee they will fetch a manifest served over plain HTTP. If the wallet cannot fetch it, the connect flow returns `MANIFEST_NOT_FOUND_ERROR` (code 2) or `MANIFEST_CONTENT_ERROR` (code 3). See [Manifest 404 and CORS](https://docs.ton.org/llms/applications/ton-connect/troubleshooting/content.md).
Spec reference: [App manifest specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/manifest.md). Schema: [Manifest JSON schema](https://github.com/ton-blockchain/ton-connect/blob/main/schemas/manifest.schema.json).
## Wallets list registry [#wallets-list-registry]
The wallets list is a public JSON registry of TON Connect-compatible wallets. Its source repository is [`ton-connect/wallets-list`](https://github.com/ton-connect/wallets-list). Every entry tells the SDK how to open and communicate with a wallet — bridge transports, universal link, supported platforms, advertised features, and the injected JS bridge key when available.
The SDK fetches [`wallets-v2.json`](https://config.ton.org/wallets-v2.json) at runtime and falls back to a bundled copy if the fetch fails.
### Entry shape [#entry-shape]
Each entry carries identity and branding (`app_name`, `name`, `image`, `about_url`), one or two bridge transports (`sse` URL and/or `js` key), link forms (`universal_url`, `deepLink`), the `platforms` it runs on, and `features` it supports.
For example:
```json
{
"app_name": "mytonwallet",
"name": "My Wallet",
"image": "https://config.ton.org/assets/mytonwallet.png",
"about_url": "https://mywallet.io",
"universal_url": "https://connect.mytonwallet.org",
"deepLink": "mytonwallet-tc://",
"bridge": [
{
"type": "js",
"key": "mytonwallet"
},
{
"type": "sse",
"url": "https://tonconnectbridge.mytonwallet.org/bridge/"
}
],
"platforms": [
"chrome",
"windows",
"macos",
"linux",
"ios",
"android",
"firefox"
],
"features": [
{
"name": "SendTransaction",
"maxMessages": 255,
"extraCurrencySupported": false
},
{
"name": "SignData",
"types": [
"text",
"binary",
"cell"
]
}
]
}
```
### How dApps consume it [#how-dapps-consume-it]
The SDK loads `wallets-v2.json` and prepares the list before rendering the modal:
1. **Platform handling.** The UI uses `platforms` as a display and connection hint. Mobile views show `ios`/`android` wallets; desktop views can still show mobile wallets because QR-code connection is a desktop flow.
2. **Feature handling.** When the dApp declares required capabilities via [`walletsRequiredFeatures`](https://docs.ton.org/llms/applications/ton-connect/how-to/filter-wallets/content.md), the UI checks each entry's `features` array. Once a session opens, the SDK checks the runtime `DeviceInfo.features`, which is authoritative.
3. **Injected detection.** For entries that list a `js` bridge, the SDK probes `window[]`. If present, that wallet is marked as injected.
### How a wallet gets listed [#how-a-wallet-gets-listed]
1. Implement TON Connect — at minimum the connect handshake and `sendTransaction`. See the [wallet developer guide](https://github.com/ton-blockchain/ton-connect/blob/main/guides/wallet-guidelines.md).
2. Deploy an HTTP bridge according to the [bridge spec](https://github.com/ton-blockchain/ton-connect/blob/main/spec/bridge.md), expose a JS bridge, or both.
3. Open a pull request against [`ton-connect/wallets-list`](https://github.com/ton-connect/wallets-list) with your entry appended to `wallets-v2.json`.
4. CI validates the entry against the [wallets list JSON schema](https://github.com/ton-connect/wallets-list/blob/main/wallets-v2.schema.json).
dApps may also add wallets directly through the SDK, bypassing the registry — useful for staging or partner integrations.
Spec reference: [Wallets list specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/wallets-list.md). Schema: [Wallets list JSON schema](https://github.com/ton-blockchain/ton-connect/blob/main/schemas/wallets-v2.schema.json).
## Features and protocol negotiation [#features-and-protocol-negotiation]
TON Connect uses explicit feature flags. When a wallet sends a `ConnectEvent`, it includes a `features` array inside `DeviceInfo`. The dApp reads it to decide which RPC methods are safe to call.
### Feature entries [#feature-entries]
| Feature | Meaning |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| `SendTransaction` | The wallet accepts `sendTransaction`. Includes `maxMessages` and optional `itemTypes`, `extraCurrencySupported`. |
| `SignData` | The wallet accepts `signData` for the listed payload `types` (`text`, `binary`, `cell`). |
| `SignMessage` | The wallet accepts `signMessage` (sign without broadcast). Same shape as `SendTransaction`. |
| `EmbeddedRequest` | The wallet processes the `e` URL parameter for one-tap connect-and-act. |
The `features` in the registry are static (what the binary supports). The runtime `DeviceInfo.features` from the connect event is authoritative — the SDK refuses methods not in the runtime list, even if the registry entry claims support.
## Security model [#security-model]
* **The bridge is untrusted.** Every message after the initial connect is end-to-end encrypted. The bridge sees only ciphertext, `client_id`s, and TTL. A malicious bridge can drop messages or measure timing, but cannot decrypt or impersonate either side.
* **The dApp's domain is bound to the connection.** The wallet displays the manifest's domain at connect time. `ton_proof` signatures bind the domain so one dApp cannot replay another's proof.
* **Replay protection** is layered: per-message nonces, monotonic request and event `id`s, and `valid_until` timestamps. For login, `ton_proof` adds a server-issued nonce with an expiry.
* **What the protocol does not protect against:** a compromised wallet device, phishing manifests on typo-domains, or smart contract bugs. The wallet signs the bytes the dApp provides — on-chain logic is out of scope.
Spec reference:
* [Session specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/session.md)
* [`ton_proof` signature specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/connect.md#address-proof-signature-ton_proof)
* [Bridge specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/bridge.md)
# TON Connect FAQ (https://docs.ton.org/llms/applications/ton-connect/faq/content.md)
## How do I tell if the user is on mainnet or testnet? [#how-do-i-tell-if-the-user-is-on-mainnet-or-testnet]
Read `wallet.account.chain` after connect. Values: `'-239'` (mainnet) or `'-3'` (testnet).
The protocol does not emit a `NetworkChanged` event. If your dApp targets mainnet, set `network: '-239'` on every `sendTransaction` and `signMessage` request — the wallet refuses mismatched networks and shows an alert.
If you need separate testnet and mainnet experiences, run two instances of the dApp on different domains (`app.com` and `testnet.app.com`) rather than switching networks at runtime.
## How do I make my own bridge? [#how-do-i-make-my-own-bridge]
Most dApp developers should not need to. The wallet provider operates the bridge; you connect to whichever bridge the user's wallet lists in [`wallets-list`](https://github.com/ton-connect/wallets-list).
If you are building a wallet, you do need a bridge. Options:
* Use the common bridge at `https://connect.ton.org/bridge` for a quick start.
* Run the Go reference implementation: [`ton-connect/bridge`](https://github.com/ton-connect/bridge).
* Implement the `/events` and `/message` endpoints from the [Bridge specification](https://github.com/ton-blockchain/ton-connect/blob/main/spec/bridge.md) yourself.
The wallet side of the bridge API is not mandated — you can add wallet-specific routes (admin, monitoring) freely.
## How do I add my wallet to the list? [#how-do-i-add-my-wallet-to-the-list]
Submit a pull request to [`ton-connect/wallets-list`](https://github.com/ton-connect/wallets-list) that adds your entry to `wallets-v2.json`. The PR runs schema validation against `wallets-v2.schema.json` — make your entry match.
Apps may also add wallets directly through the SDK without the registry — useful for staging or partner integrations.
For the full implementer guide, see the [Wallet Guidelines](https://github.com/ton-blockchain/ton-connect/blob/main/guides/wallet-guidelines.md).
## How do I implement backend authentication with TON Connect? [#how-do-i-implement-backend-authentication-with-ton-connect]
Use the `ton_proof` connect item. The wallet returns a signature that binds the user's address, your domain, a timestamp, and a server-issued nonce. The backend verifies the signature against the user's public key (extracted from `walletStateInit` or fetched via the on-chain `get_public_key` method) and issues a session token.
Walkthrough: [Connect a wallet → Authenticate with `ton_proof`](https://docs.ton.org/llms/applications/ton-connect/how-to/connect/content.md). Reference example: [`ton-connect/demo-dapp-backend`](https://github.com/ton-connect/demo-dapp-backend).
## Why is there no `accountChanged` event? [#why-is-there-no-accountchanged-event]
By design. TON Connect treats the wallet like a physical wallet that holds many "bank cards" (accounts). The user picks one account at connect time, and the dApp continues working with that account regardless of which account the user later browses in the wallet.
To switch accounts the user disconnects (logs out) and reconnects (logs in) inside the dApp UI. See the [wallet developer guide](https://github.com/ton-blockchain/ton-connect/blob/main/guides/wallet-guidelines.md).
## Why is there no `networkChanged` event? [#why-is-there-no-networkchanged-event]
Same philosophy. Mainnet and testnet are distinct deployments — dApps target one or the other and refuse cross-network requests. There is no expected runtime network switch. Hosting separate instances on separate domains is the recommended pattern.
## How big can a transaction batch be? [#how-big-can-a-transaction-batch-be]
Bounded by the wallet's `maxMessages` field in its `SendTransaction` feature. Common values are 4 (older wallets) to 255 (newer wallets). Read it from `wallet.device.features` and split larger batches.
## See also [#see-also]
* [Troubleshooting](https://docs.ton.org/llms/applications/ton-connect/troubleshooting/content.md) — error codes and manifest fetch failures.
# Get started with TON Connect (https://docs.ton.org/llms/applications/ton-connect/get-started/content.md)
This page walks you through every supported integration path.
Start with [What you need](#what-you-need) and then select the section for your stack:
* [What you need](#what-you-need)
* [Build a dApp with React](#build-a-dapp-with-react)
* [Build a dApp with Next.js](#build-a-dapp-with-nextjs)
* [Build a dApp with vanilla JS](#build-a-dapp-with-vanilla-js)
* [Build without a UI (`@tonconnect/sdk`)](#build-without-a-ui-tonconnectsdk)
## What you need [#what-you-need]
Before you start integrating, prepare the manifest file and pick a TON Connect SDK.
### Prepare the manifest [#1-prepare-the-manifest]
Prepare `tonconnect-manifest.json` — the JSON file the wallet fetches to learn your app's name, icon, and policy URLs. The wallet shows this metadata to the user before approving the connection.
The minimum:
```json
{
"url": "https://yourapp.com",
"name": "Your App",
"iconUrl": "https://yourapp.com/icon-180.png"
}
```
Optional:
```json
{
"termsOfUseUrl": "https://yourapp.com/terms",
"privacyPolicyUrl": "https://yourapp.com/privacy"
}
```
#### Hosting requirements: [#hosting-requirements]
The manifest must be publicly accessible by the time wallets connect to your app:
* The file must be reachable with a `GET` from any origin, without CORS restrictions, without auth and without a Cloudflare-style proxy challenge.
* The icon at the URL listed in `iconUrl` must be PNG or ICO. SVG is not supported. Use a 180×180 px PNG.
* The manifest must be served over HTTPS. Wallets do not guarantee they will fetch a manifest served over plain HTTP.
* Any reachable HTTPS URL is valid. Hosting the manifest at the root of your domain (e.g. `https://yourapp.com/tonconnect-manifest.json`) keeps access simple.
If the wallet cannot fetch the manifest, the connect flow returns `MANIFEST_NOT_FOUND_ERROR` (code 2) or `MANIFEST_CONTENT_ERROR` (code 3). See [Manifest 404 and CORS](https://docs.ton.org/llms/applications/ton-connect/troubleshooting/content.md).
For the full field reference, see [Manifest](https://docs.ton.org/llms/applications/ton-connect/core-concepts/content.md).
### Pick an SDK [#2-pick-an-sdk]
There are three dApp-facing packages, all published from [`ton-connect/sdk`](https://github.com/ton-connect/sdk):
| Package | When to use |
| ---------------------- | ---------------------------------------------------------------------------- |
| `@tonconnect/ui-react` | React or Next.js dApps. **Recommended.** Hooks, prebuilt button, modal. |
| `@tonconnect/ui` | Vanilla JS or non-React frameworks. Same UI components, no React bindings. |
| `@tonconnect/sdk` | Headless integrations — server-side flows, custom UI from scratch. |
Pick `ui-react` if your app is React. Pick `ui` if it is not. Reach for `sdk` only when you need low-level control.
## Build a dApp with React [#build-a-dapp-with-react]
Install the UI kit, host the manifest, mount the provider, add a connect button, and send a test transaction.
For Next.js-specific notes (App Router, `'use client'`, SSR), see [Build a dApp with Next.js](#build-a-dapp-with-nextjs).
### Install [#1-install]
```bash
npm i @tonconnect/ui-react
```
### Host the manifest [#2-host-the-manifest]
Place `tonconnect-manifest.json` at the root of your app's domain. See [What you need](#1-prepare-the-manifest) for the full requirements.
### Wrap the app in `TonConnectUIProvider` [#3-wrap-the-app-in-tonconnectuiprovider]
```tsx
import { TonConnectUIProvider } from '@tonconnect/ui-react';
export function App() {
return (
);
}
```
### Add the connect button [#4-add-the-connect-button]
```tsx
import { TonConnectButton } from '@tonconnect/ui-react';
export function Header() {
return (
);
}
```
The button toggles between "Connect Wallet" and the connected account state automatically.
You can pass a `className` or `style` prop:
```tsx
```
### Read connection state [#5-read-connection-state]
```tsx
import {
useIsConnectionRestored,
useTonAddress,
useTonWallet,
} from '@tonconnect/ui-react';
function Status() {
const address = useTonAddress();
const wallet = useTonWallet();
const restored = useIsConnectionRestored();
if (!restored) return Restoring…;
if (!wallet) return Not connected;
return Connected as {address};
}
```
### Send a transaction [#6-send-a-transaction]
The destination here is the connected wallet's own address, returned by `useTonAddress()` in user-friendly form. Replace it with your recipient.
```tsx
import { useTonAddress, useTonConnectUI, useTonWallet } from '@tonconnect/ui-react';
function PayButton() {
const [tonConnectUi] = useTonConnectUI();
const wallet = useTonWallet();
const address = useTonAddress();
const handlePay = async () => {
if (!address) return;
try {
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300,
network: '-239', // mainnet
messages: [
{ address, amount: '100000000' }, // 0.1 Gram
],
});
} catch (e) {
console.error(e);
}
};
return (
);
}
```
`address` must be in user-friendly format (base64url with the bounce flag — `EQ…` for bounceable, `UQ…` for non-bounceable). Wallets reject raw `0:` addresses. To convert one, use `toUserFriendlyAddress` from `@tonconnect/ui-react`. Each `message` also accepts optional `payload`, `stateInit`, and `extraCurrency` fields. Amounts use **nanograms**: `1 Gram = 10⁹ nanogram`. Send `100000000` for 0.1 Gram.
### Open the modal manually [#open-the-modal-manually]
```tsx
const [tonConnectUi] = useTonConnectUI();
```
### Customize the UI [#customize-the-ui]
```tsx
import { useTonConnectUI, THEME } from '@tonconnect/ui-react';
const [tonConnectUi] = useTonConnectUI();
tonConnectUi.uiOptions = {
language: 'ru',
uiPreferences: { theme: THEME.DARK },
};
```
`uiOptions` is a setter, not a plain object. Assigning to it runs the merge, theme switch, and re-render logic; mutating a nested property (e.g. `tonConnectUi.uiOptions.uiPreferences.theme = ...`) bypasses the setter and has no effect. Always reassign the whole object.
## Build a dApp with Next.js [#build-a-dapp-with-nextjs]
Next.js needs two adjustments on top of the [React tutorial](#build-a-dapp-with-react): `TonConnectUIProvider` must run on the client, and the manifest is served from `public/`. The hooks behave the same as in plain React.
### Install [#1-install-1]
```bash
npm i @tonconnect/ui-react
```
### Host the manifest [#2-host-the-manifest-1]
Drop `tonconnect-manifest.json` into your project's `public/` directory:
```text
public/tonconnect-manifest.json
```
Next.js serves the file at `https://yourapp.com/tonconnect-manifest.json`. Make sure your hosting layer does not add CORS or auth gates — see [Manifest 404 and CORS](https://docs.ton.org/llms/applications/ton-connect/troubleshooting/content.md).
### Set up App Router [#3-set-up-app-router]
`TonConnectUIProvider` reads from local storage and opens modals — both browser-only. Mount it in a client component:
```tsx
// app/providers.tsx
'use client';
import { TonConnectUIProvider } from '@tonconnect/ui-react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
Then wrap the root layout:
```tsx
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
Components that use `useTonWallet`, `useTonConnectUI`, etc. must also start with `'use client'`.
### Set up Pages Router [#4-set-up-pages-router]
Dynamic-import the provider with SSR off so it does not run on the server:
```tsx
import dynamic from 'next/dynamic';
import type { AppProps } from 'next/app';
const TonConnectUIProvider = dynamic(
() => import('@tonconnect/ui-react').then(m => m.TonConnectUIProvider),
{ ssr: false }
);
function MyApp({ Component, pageProps }: AppProps) {
return (
);
}
export default MyApp;
```
### SSR pitfalls [#ssr-pitfalls]
* **Local storage.** TON Connect persists the session in `localStorage`. Code that reads wallet state during SSR cannot know whether a session will restore. Render wallet-dependent UI in a client component and use `useIsConnectionRestored()` to distinguish "restoring" from "disconnected."
* **Browser-only APIs.** Anything from `@tonconnect/ui-react` that touches `window`, modals, or storage must run in a client component or be lazy-loaded with `ssr: false`.
The hooks, button, and transaction-sending API are identical to plain React — see [Build a dApp with React](#build-a-dapp-with-react) for the rest.
## Build a dApp with vanilla JS [#build-a-dapp-with-vanilla-js]
Same flow as the [React tutorial](#build-a-dapp-with-react) — connect button, status subscription, transaction — built with `@tonconnect/ui` for plain HTML / JavaScript.
### Install [#1-install-2]
Via npm:
```bash
npm i @tonconnect/ui
```
Or via CDN:
```html
```
The CDN bundle exposes the API on `window.TON_CONNECT_UI`.
### Host the manifest [#2-host-the-manifest-2]
Place `tonconnect-manifest.json` at the root of your domain. Hosting rules in [What you need](#1-prepare-the-manifest).
### Mark up a connect-button container [#3-mark-up-a-connect-button-container]
```html
```
### Initialize the UI [#4-initialize-the-ui]
```javascript
const ui = new TON_CONNECT_UI.TonConnectUI({
manifestUrl: 'https://yourapp.com/tonconnect-manifest.json',
buttonRootId: 'ton-connect',
});
```
The library renders the connect button into `#ton-connect`. Tapping it opens the wallet picker.
If you imported via npm:
```javascript
import { TonConnectUI } from '@tonconnect/ui';
const ui = new TonConnectUI({ /* same options */ });
```
### Subscribe to connection status [#5-subscribe-to-connection-status]
```javascript
ui.onStatusChange(wallet => {
document.getElementById('send').disabled = !wallet;
});
```
`wallet` is `null` when disconnected, or a connected `Wallet` (with `device`, `account`, and optional `connectItems`) otherwise.
### Send a transaction [#6-send-a-transaction-1]
```javascript
import { toUserFriendlyAddress } from '@tonconnect/ui';
document.getElementById('send').onclick = async () => {
const wallet = ui.wallet;
if (!wallet) return;
const address = toUserFriendlyAddress(wallet.account.address); // or window.TON_CONNECT_UI.toUserFriendlyAddress
try {
await ui.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300,
network: '-239',
messages: [
{ address, amount: '100000000' }, // 0.1 Gram
],
});
} catch (error) {
console.error('Transaction failed:', error);
}
};
```
The destination `address` must be in user-friendly format; see the note in the [React example](#6-send-a-transaction). Amounts are in **nanograms**: `1 Gram = 10⁹ nanograms`.
### Restore on reload [#restore-on-reload]
`onStatusChange` fires whenever the wallet state changes — connect, disconnect, and a successful session restore.
## Build without a UI (`@tonconnect/sdk`) [#build-without-a-ui-tonconnectsdk]
`@tonconnect/sdk` is the headless TON Connect implementation — the same protocol layer that ships inside `@tonconnect/ui-react` and `@tonconnect/ui`, with no wallet picker, no modal, and no DOM dependencies. Use it on a server, in a custom UI you render yourself, or as a reference when porting TON Connect to another language.
For a regular browser dApp, prefer [`@tonconnect/ui-react`](#build-a-dapp-with-react) (React, Next.js) or [`@tonconnect/ui`](#build-a-dapp-with-vanilla-js) (vanilla JS). They wrap this SDK and add the wallet picker, connect button, and notifications.
This section covers the headless API end-to-end: install, connector setup, custom storage, wallet discovery, the connect handshake, status events, and `sendTransaction`. The same shape applies whether you call it from a server or a custom in-browser UI.
### Install [#1-install-3]
```bash
npm i @tonconnect/sdk
```
### Create a connector [#2-create-a-connector]
```ts
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect({
manifestUrl: 'https://yourapp.com/tonconnect-manifest.json',
storage: myStorage,
});
await connector.restoreConnection();
```
`manifestUrl` is the public URL of your `tonconnect-manifest.json`. The wallet fetches it during connect and shows the metadata to the user. See [What you need](#1-prepare-the-manifest) for hosting rules.
`storage` is an `IStorage` implementation. In a browser, the SDK falls back to `window.localStorage` if you omit it. Anywhere else — Node.js, a worker — supply your own. `restoreConnection()` reads from storage and wires the connector back to the bridge if a session is already there. Call it once per instance, not on every request.
### Custom storage [#3-custom-storage]
```ts
interface IStorage {
setItem(key: string, value: string): Promise;
getItem(key: string): Promise;
removeItem(key: string): Promise;
}
```
A trivial in-memory implementation suits one-shot flows:
```ts
class MemoryStorage implements IStorage {
private data = new Map();
async setItem(key: string, value: string) { this.data.set(key, value); }
async getItem(key: string) { return this.data.get(key) ?? null; }
async removeItem(key: string) { this.data.delete(key); }
}
```
For long-running servers, back `IStorage` with a per-user record in your database (Postgres, Redis, etc.) keyed by your user ID. See [Long-lived servers](#long-lived-servers).
### Discover wallets [#4-discover-wallets]
```ts
const wallets = await connector.getWallets();
```
Each entry is a `WalletInfo` with the fields a custom UI needs to render a picker and start a connect:
```ts
interface WalletInfoBase {
name: string; // human-readable display name
appName: string; // stable identifier
imageUrl: string;
aboutUrl: string;
tondns?: string;
platforms: ('ios' | 'android' | 'macos' | 'windows'
| 'linux' | 'chrome' | 'firefox' | 'safari')[];
features?: Feature[];
}
interface WalletInfoRemote extends WalletInfoBase {
universalLink: string;
bridgeUrl: string;
deepLink?: string;
}
interface WalletInfoInjectable extends WalletInfoBase {
jsBridgeKey: string;
injected: boolean;
embedded: boolean;
}
type WalletInfo =
| WalletInfoRemote
| WalletInfoInjectable
| (WalletInfoRemote & WalletInfoInjectable);
```
A wallet that supports both transports satisfies the intersection. Narrow with `'universalLink' in wallet` for HTTP wallets and `'jsBridgeKey' in wallet` for injected ones.
### Connect [#5-connect]
For an HTTP wallet, `connect()` returns a universal link. Show it to the user as a clickable URL, a deep link, or a QR code:
```ts
const link = connector.connect({
universalLink: 'https://connect.mytonwallet.org',
bridgeUrl: 'https://tonconnectbridge.mytonwallet.org/bridge/',
});
```
For a JS-injected wallet (browser extension or in-wallet browser), pass the bridge key. The wallet handles the handoff in-page, so `connect()` returns `void`:
```ts
connector.connect({ jsBridgeKey: 'mytonwallet' });
```
To request `ton_proof` alongside the address, pass it under `request`:
```ts
connector.connect(
{ universalLink, bridgeUrl },
{ request: { tonProof: nonce } },
);
```
See [Connect a wallet](https://docs.ton.org/llms/applications/ton-connect/how-to/connect/content.md) for the proof-verification flow.
### Listen for status changes [#6-listen-for-status-changes]
```ts
const unsubscribe = connector.onStatusChange(wallet => {
if (wallet) {
// wallet.account.address — raw 0: (convert to user-friendly before passing to sendTransaction)
// wallet.account.publicKey — hex string without 0x, optional (some wallets omit it)
// wallet.connectItems?.tonProof — TonProofItemReply, may carry proof or error
} else {
// disconnected — by the user or by the wallet
}
});
```
The same callback fires for connects, restores, and wallet-initiated disconnects. Call `unsubscribe()` when you no longer need it.
### Send a transaction [#7-send-a-transaction]
```ts
const result = await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300,
network: '-239', // mainnet (use '-3' for testnet)
messages: [
{ address: 'UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ', // burn address
amount: '20000000' },
],
});
console.log(result.boc); // base64 BoC of the signed external message
```
Each wallet advertises its own per-call limit on the `SendTransaction` feature entry: `wallet.device.features.find(f => typeof f === 'object' && f.name === 'SendTransaction')?.maxMessages`.
### Long-lived servers [#long-lived-servers]
* One `TonConnect` instance per signed-in user, with an `IStorage` keyed by user ID, and an in-process cache so the same instance is reused across requests.
* The HTTP bridge stays open over SSE for as long as the connector is live. Call `pauseConnection()` when a user goes idle and `unPauseConnection()` when they return.
* React to wallet-initiated disconnects through `onStatusChange`. When the callback fires with `null`, evict the cached connector and clear any session token you issued.
* Persist the session per user, not globally. Two users sharing one `TonConnect` will leak addresses and overwrite each other's session keypairs.
## Next steps [#next-steps]
* [Connect a wallet and authenticate the user with `ton_proof`](https://docs.ton.org/llms/applications/ton-connect/how-to/connect/content.md)
* [Send a structured transaction](https://docs.ton.org/llms/applications/ton-connect/how-to/send-transaction/content.md)
* [Sign data](https://docs.ton.org/llms/applications/ton-connect/how-to/sign-data/content.md)
* [Sign and relay a gasless message](https://docs.ton.org/llms/applications/ton-connect/how-to/sign-message-gasless/content.md)
* [Connect-and-act in one tap](https://docs.ton.org/llms/applications/ton-connect/how-to/embedded-request/content.md)
* [Handle wallet-initiated disconnects](https://docs.ton.org/llms/applications/ton-connect/how-to/disconnect/content.md)
* [Filter wallets by required features](https://docs.ton.org/llms/applications/ton-connect/how-to/filter-wallets/content.md)
* [Enable WalletConnect support](https://docs.ton.org/llms/applications/ton-connect/how-to/walletconnect-support/content.md)
# TON Connect overview (https://docs.ton.org/llms/applications/ton-connect/overview/content.md)
## What TON Connect is [#what-ton-connect-is]
**TON Connect** is the standard wallet connection protocol for the TON blockchain.
It links a dApp to a user's wallet over an end-to-end encrypted session so the app can read the connected address, request signatures, and send transactions — without ever touching the user's keys.