diff --git a/docs/v3/documentation/smart-contracts/message-management/message-modes-cookbook.mdx b/docs/v3/documentation/smart-contracts/message-management/message-modes-cookbook.mdx index 3a546ff2397..2e0bacc828b 100644 --- a/docs/v3/documentation/smart-contracts/message-management/message-modes-cookbook.mdx +++ b/docs/v3/documentation/smart-contracts/message-management/message-modes-cookbook.mdx @@ -1,39 +1,39 @@ -import ConceptImage from '@site/src/components/conceptImage'; -import ThemedImage from '@theme/ThemedImage'; +import ConceptImage from "@site/src/components/conceptImage"; +import ThemedImage from "@theme/ThemedImage"; -# Message Modes Cookbook +# Message modes cookbook -Understanding the different modes and flags available for sending messages is crucial to ensure that your smart contracts behave as intended. -While [message modes](/v3/documentation/smart-contracts/message-management/sending-messages#message-modes) section provided detailed descriptions of these modes and flags, in this section we will illustrate their practical application through specific examples. +Understanding the modes and flags available for sending messages is crucial to ensure your smart contracts behave as intended. +This section will illustrate their practical application through specific examples. :::info IMPORTANT -You can check [this example](https://testnet.tonviewer.com/transaction/42ed45726e4fe994b7fd6dbf953a2ac24ecd77753858abeda9d6755c664a537a) as a real-world validation. +You can check [this example](https://testnet.tonviewer.com/transaction/42ed45726e4fe994b7fd6dbf953a2ac24ecd77753858abeda9d6755c664a537a) as a real‐world validation. ::: #### Message value and account balance Please check how [get_balance](/v3/documentation/smart-contracts/func/docs/stdlib/#get_balance) works to better understand `balance` inside TVM. -All TON tokens owned by a contract are reflected in the [contract balance](https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/block.tlb#L263C1-L265C20). Some of these tokens are also attributed to the currently processed incoming [message](/v3/documentation/data-formats/tlb/msg-tlb#commonmsginfo) - a mechanism that works effectively because any TON transaction involving a [non-system contract](/v3/documentation/smart-contracts/contracts-specs/governance) processes exactly one incoming message at a time. +All TON tokens held by a contract are reflected in the contract `balance`. Some of these tokens are also assigned to the currently processed incoming `message`. This mechanism is effective because any TON transaction involving a [non‐system contract](/v3/documentation/smart-contracts/contracts-specs/governance) processes exactly one incoming message at a time. Therefore, any blockchain payment may come either: -- From the incoming message `value`. - For instance, computation fees are paid in this way, unless contract calls [accept_message](v3/documentation/smart-contracts/transaction-fees/accept-message-effects). This ensures that malicious actors cannot spend contract's balance on handling their data. -- From the contract `balance` (will not touch amount of TON designated as incoming this transaction). - Storage fees in workchains 0 and -1, as well as most actions, are currently examples of this. +- From the incoming message's `value`. + Contracts pay computation fees this way unless they call [accept_message](/v3/documentation/smart-contracts/transaction-fees/accept-message-effects), which prevents malicious actors from spending the contract's balance to process their data +- From the contract's `balance`, which leaves the incoming TON amount untouched during the transaction + This approach currently applies to storage fees in workchains 0 and -1, along with most common actions #### Fees -Actual transaction fees will vary depending on the blockchain configuration, the smart contract code and other factors. When a message is received, part of the contract `balance` will be consumed by [storage fees](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#storage-fee) and gas_fees if the message `value` [is above certain amount](/v3/documentation/tvm/tvm-overview#compute-phase-skipped). +Actual transaction fees will vary depending on the blockchain configuration, the smart contract code, and other factors. When a message is received, part of the contract `balance` will be consumed by storage and gas fees if the message `value` [is above a certain amount](/v3/documentation/tvm/tvm-overview#compute-phase-skipped). -According to the [transaction flow](/v3/documentation/tvm/tvm-overview#transactions-and-phases) there are 5 phases: +According to the [transaction flow](/v3/documentation/tvm/tvm-overview#transactions-and-phases), there are five distinct phases: -- Storage, consisting of [account storage](https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L651-L675) and [in_msg import](https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L783-L816) -- [Credit](https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L959-L981), where in_msg `value` is added to the `balance` -- Compute, where the actual smart contract code is executed in TVM -- Action, where actions like `SENDRAWMSG` are performed -- Bounce, where everything about bouncing is handled +1. **Storage**: This phase includes both account storage and in_msg import. +2. **Credit**: In this phase, the `value` of `in_msg` [is added](https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L959-L981) to the `balance`. +3. **Compute**: The TVM executes the smart contract code. +4. **Action**: This phase involves performing actions such as `SENDRAWMSG`. +5. **Bounce**: This phase manages everything related to bouncing. The order is: storage_fee -> import_fee -> gas_fee -> action_fee + fwd_fee @@ -41,183 +41,174 @@ The order is: storage_fee -> import_fee -> gas_fee -> action_fee + fwd_fee The table is populated based on [this example](https://tonviewer.com/transaction/b5e14a9c4a4e982fda42d6079c3f84fa48e76497a8f3fca872f9a3737f1f6262). You can check the [**live calculator**](/v3/documentation/smart-contracts/transaction-fees/fees#basic-fees-formula). ::: -| Fee in Explorer | Value | How it's obtained | -| :------------------------------------------------------------------------------------------------ | :---------- | :------------------------------ | -| Total fee | 0,001982134 | gas + storage + action + import | -| total_fwd_fees | 0,001 | fwd_fee + action_fee + ihr_fee | -| gas_fees | 0,0011976 | compute phase, gas used | -| storage_fees | 0,000000003 | storage phase, account only | -| total_action_fees | 0,000133331 | action phase, cost per action | -| import_fee (hidden) | 0,0006512 | cost of import of ext_msg | -| [fwd_fee](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#formula-1) (each msg) | 0,000266669 | cost of fwd of in_msg | -| [ihr_fee](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#ihr) (each msg) | 0.0006 | cost of ihr fwd of in_msg | +| Fee in Explorer | Value | How it's obtained | +| :---------------------------------------------------------------------------------------------------- | :---------- | :------------------------------ | +| Total fee | 0,001982134 | gas + storage + action + import | +| Fwd. fee | 0,001 | fwd_fee + action_fee + ihr_fee | +| Gas fee | 0,0011976 | compute phase, gas used | +| Storage fee | 0,000000003 | storage phase, account only | +| Action fee | 0,000133331 | action phase, cost per action | +| Import fee (hidden) | 0,0006512 | cost of import of ext_msg | +| [Forward fee](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#formula-1) (each msg) | 0,000266669 | cost of fwd of in_msg | +| [IHR fee](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#ihr) (each msg) | 0.0006 | cost of ihr fwd of in_msg | :::info -The transaction fees used in these examples are hypothetical and are for illustrative purposes only. Any fees other than message forwarding are out of scope of this article. +The transaction fees used in these examples are hypothetical and for illustrative purposes only. Any fees other than message forwarding are outside the scope of this article. Funds included with an ignored message will still be [credited to the receiving address](https://testnet.tonviewer.com/transaction/8a388731812c80ab9b0ea9531108425488af5def854e4bd6f0ed47362b56d557). ::: -## 1. Send a regular message +## 1. (Mode 0, Flag 0) Basic message {#mode0} State before transaction: Account A has 1 TON, Account B has 1 TON **A** sent 0.1 TON to **B**, [msg_fwd_fees](/v3/documentation/smart-contracts/transaction-fees/fees-low-level#forward-fees) are 0.004 TON, actual received value will be 0.096 TON, `fwd_fee` and `action_fee` are deducted from `value`. -State after transaction: Account A has 0.9 TON, Account B has 1.096 TON +State after the transaction: Account A has 0.9 TON, Account B has 1.096 TON

- +


- -| Mode and Flags | Code | -| :-------------------- | :------------------------- | -| `mode` = 0, no `flag` | `send_raw_message(msg, 0)` | - -## 2. Send a regular message, no bounce the message on error and ignore it +## 2. (Mode 0, Flag 2) Error‐silent message {#mode2} State before transaction: Account A has 1 TON, Account B has 1 TON -**A** sent 0.1 TON to **B**, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.096 TON, `fwd_fee` and `action_fee` are deducted from `value`. +**A** sent 0.1 TON to **B**. The `msg_fwd_fees` are 0.004 TON, and the actual received value will be 0.096 TON. The `fwd_fee` and `action_fee` are deducted from `value`. In case of an error during [action phase](/v3/documentation/smart-contracts/message-management/sending-messages#message-modes), the message will be skipped instead of throwing an [exit code](/v3/documentation/tvm/tvm-exit-codes#standard-exit-codes). -State after transaction: Account A has 0.9 TON, Account B has 1.096 TON +State after the transaction: Account A has 0.9 TON, Account B has 1.096 TON :::info tip -If no errors occur, the result is the same as [`mode = 0`](#1-send-a-regular-message). +If no errors occur, the result is the same as [mode = 0](#mode0). :::

- +


-| Mode and Flags | Code | -| :--------------------- | :------------------------- | -| `mode` = 0, `flag` = 2 | `send_raw_message(msg, 2)` | - -## 3. Send a regular message, and bounce the message in case of an action error +## 3. (Mode 0, Flag 16) Bounce on action error {#mode16} State before transaction: Account A has 1 TON, Account B has 1 TON -**A** sent 0.1 TON to **B**, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.096 TON, `fwd_fee` and `action_fee` are deducted from `value`. +**A** sent 0.1 TON to **B**. The `msg_fwd_fees` are 0.004 TON, and the actual received value will be 0.096 TON. The `fwd_fee` and `action_fee` are deducted from `value`. In case of an error during [action phase](https://retracer.ton.org/?tx=e9dccba82badc0d742f14eff41c203280f380e87180b5314fcfd742856e598f7&testnet=true), the message will bounce and `total_fee` + `fwd_fee` will be deducted from `value`. -State after transaction with error: Account A has 1 - ([total_fee](/v3/documentation/smart-contracts/transaction-fees/fees#basic-fees-formula) + `fwd_fee`) TON, Account B has 1 TON +State after the transaction with error: Account A has 1 - ([total_fee](/v3/documentation/smart-contracts/transaction-fees/fees#basic-fees-formula) + `fwd_fee`) TON, Account B has 1 TON

- +


:::info tip -If no errors occur the result is the same as [`mode = 0`](#1-send-a-regular-message). -::: +If no errors occur, the result is the same as [mode = 0](#mode0). + +The key difference is that `flag 16` creates bounces for [action phase errors](/v3/documentation/tvm/tvm-exit-codes#standard-exit-codes). In contrast, the message's [built‐in bounce flag](https://docs.ton.org/v3/guidelines/smart-contracts/howto/wallet#internal-message-creation) handles protocol‐level failures like: + +- The destination contract does not exist. +- The destination contract throws an unhandled exception. + :::

- +


-| Mode and Flags | Code | -| :---------------------- | :-------------------------- | -| `mode` = 0, `flag` = 16 | `send_raw_message(msg, 16)` | - -## 4. Send a regular message with separate fees +## 4. (Mode 0, Flag 1) Separate fees {#mode1} State before the transaction: Account A has 1 TON, Account B has 1 TON -**A** sent 0.1 TON to **B**, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.1 TON, `fwd_fee` and `action_fee` are deducted from `balance`. +**A** sent 0.1 TON to **B**. The `msg_fwd_fees` are 0.004 TON, and the actual received value will be 0.1 TON. The `fwd_fee` and `action_fee` are deducted from the `balance`. State after the transaction: Account A has 0.896 TON, Account B has 1.1 TON

- +


-| Mode and Flags | Code | -| :--------------------- | :------------------------- | -| `mode` = 0, `flag` = 1 | `send_raw_message(msg, 1)` | - -## 5. Send a regular message with separate fees and bounce the message on error +## 5. (Mode 0, Flag 17) Separate fees and bounce on action error {#mode17} State before the transaction: Account A has 1 TON, Account B has 1 TON -**A** sent 0.1 TON to **B**, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.1 TON, `fwd_fee` and `action_fee` are deducted from `balance`. -In case of an error [during action phase](https://retracer.ton.org/?tx=e9dccba82badc0d742f14eff41c203280f380e87180b5314fcfd742856e598f7&testnet=true), the message will bounce and `total_fee` + `fwd_fee` will be deducted from `value`. +**A** sent 0.1 TON to **B**. The `msg_fwd_fees` are 0.004 TON, and the actual received value will be 0.1 TON. The `fwd_fee` and `action_fee` are deducted from the `balance`. +In case of an error [during the action phase](https://retracer.ton.org/?tx=e9dccba82badc0d742f14eff41c203280f380e87180b5314fcfd742856e598f7&testnet=true), the message will bounce and `total_fee` + `fwd_fee` will be deducted from `value`. State after the transaction with an error: Account A has 1 - ([total_fee](/v3/documentation/smart-contracts/transaction-fees/fees#basic-fees-formula) + `fwd_fee`) TON, Account B has 1 TON

- +


:::info tip -If no errors occur the result is the same as [`mode = 1`](#4-send-a-regular-message-with-separate-fees). +If no errors occur, the result is the same as [mode = 1](#mode1). :::

- +


-| Mode and Flags | Code | -| :------------------------------- | :-------------------------- | -| `mode` = 0, `flag` = 1 + 16 = 17 | `send_raw_message(msg, 17)` | - -## 6. Carry remaining value with new message +## 6. (Mode 64, Flag 0) Carry forward the remaining value {#mode64} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON @@ -227,32 +218,29 @@ State after the transaction: Account A has 0.896 TON, Account B has 0.5 TON, Acc :::info You might check [this example](https://testnet.tonviewer.com/transaction/f63ab35f34e342cdd249f13018d5034ce3d80c488628d5a4db0a43163fa50adb). -Please note that `storage_fee` is included in `total_fee` but it is always paid from contract `balance`. +Please note that `storage_fee` is included in `total_fee` but is always paid from the contract `balance`. ::: :::warning -Please note that `SENDRAWMSG` doesn't update balance. +Please note that `SENDRAWMSG` doesn't update the balance. -If you try to send multiple messages (i.e. mode 0 **and** mode 64) you'll get exit code 37. +If you try to send multiple messages (e.g., mode 0 **and** mode 64), you'll get exit code 37. :::

- +


-| Mode and Flags | Code | -| :--------------------- | :-------------------------- | -| `mode` = 64, no `flag` | `send_raw_message(msg, 64)` | - -## 7. Carry remaining value with a new message with separate fees +## 7. (Mode 64, Flag 1) Carry forward with separate fees {#mode65} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON @@ -262,176 +250,164 @@ State after the transaction: Account A has 0.896 TON, Account B has 0.5 - (total :::info You might check [this example](https://testnet.tonviewer.com/transaction/ad93e784453b573d737d9d928b4377ff3779177753e05629e54f6629556568ad). -Please note that `storage_fee` is included in `total_fee` but it is always paid from contract `balance`. +Please note that `storage_fee` is included in `total_fee` but is always paid from the contract `balance`. :::

- +


-| Mode and Flags | Code | -| :---------------------- | :-------------------------- | -| `mode` = 64, `flag` = 1 | `send_raw_message(msg, 65)` | - -## 8. Carry remaining value and bounce the message on error +## 8. (Mode 64, Flag 16) Bounce‐protected carry forward {#mode80} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON **A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 80, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.6 TON, total_fee + `fwd_fee` are deducted from `value`. -In case of an error during the action phase, the message will bounce and `total_fee` + `fwd_fee` will be deducted from `value`. +If an error occurs during the action phase, the message will bounce, and `total_fee` + `fwd_fee` will be deducted from the `value`. State after the transaction with an error: Account A has 1 - (total_fee + `fwd_fee`) TON, Account B has 1 TON, Account C has 1 TON

- +


:::info tip -If no errors occur the result is the same as [`mode = 64`](#6-carry-remaining-value-with-new-message). This mode is widely used in TON for jetton transfers. You can [check it in C5 action list](https://retracer.ton.org/?tx=6489d60d9197c0be7ee64b0812139d82221e8f94c6e378c356acc10f9067310c) of the jetton wallet. +If no errors occur, the result is the same as [mode = 64, flag 0](#mode64). This mode is widely used in TON for jetton transfers. You can [check it in the C5 action list](https://retracer.ton.org/?tx=6489d60d9197c0be7ee64b0812139d82221e8f94c6e378c356acc10f9067310c) of the jetton wallet. :::

- +


-| Mode and Flags | Code | -| :----------------------- | :-------------------------- | -| `mode` = 64, `flag` = 16 | `send_raw_message(msg, 80)` | - -## 9. Carry the remaining value with a new message with separate fees and bounce the message on error +## 9. (Mode 64, Flag 17) Bounce‐protected carry forward with separate fees {#mode81} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON **A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 81, `msg_fwd_fees` are 0.004 TON, actual received value will be 0.6 TON, total_fee + `fwd_fee` are deducted from `balance`. -In case of an error during the action phase, the message will bounce and `total_fee` + `fwd_fee` will be are deducted from `value`. +If an error occurs during the action phase, the message will bounce, and `total_fee` + `fwd_fee` will be deducted from the `value`. -State after transaction with an error: Account A has 1 - (total_fee + `fwd_fee`) TON, Account B has 1 TON, Account C has 1 TON +State after the transaction with an error: Account A has 1 - (total_fee + `fwd_fee`) TON, Account B has 1 TON, Account C has 1 TON

- +


:::info tip -If no errors occur the result is the same as [`mode = 65`](#7-carry-remaining-value-with-new-message-with-separate-fees). +If no errors occur, the result is the same as [mode = 65](#mode65). :::

- +


-| Mode and Flags | Code | -| :--------------------------- | :-------------------------- | -| `mode` = 64, `flag` = 16 + 1 | `send_raw_message(msg, 81)` | - -## 10. Send all received tokens along with the contract balance +## 10. (Mode 128, Flag 0) Send whole balance {#mode128} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON -**A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 128, `msg_fwd_fees` are 0.004 TON, actual received value will be 1.1 - total_fee TON, total_fee is deducted from `value`. +**A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 128, `msg_fwd_fees` are 0.004 TON, the actual received value will be 1.1 - total_fee TON, total_fee is deducted from `value`. State after the transaction: Account A has 0.896 TON, Account B has 0 TON, Account C has 2.1 - (total_fee + `fwd_fee`) TON

- +


-| Mode and Flags | Code | -| :---------------------- | :--------------------------- | -| `mode` = 128, no `flag` | `send_raw_message(msg, 128)` | - -## 11. Send all received tokens along with the contract balance and bounce the message on error +## 11. (Mode 128, Flag 16) Send the whole balance bounce‐protected {#mode144} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON -**A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 144, `msg_fwd_fees` are 0.004 TON, actual received value will be 1.1 - total_fee TON, total_fee is deducted from `value`. +**A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 144, `msg_fwd_fees` are 0.004 TON, the actual received value will be 1.1 - total_fee TON, total_fee is deducted from `value`. State after the transaction with an error: Account A has 1 - (total_fee + `fwd_fee`) TON, Account B has 1 TON, Account C has 1 TON

- +


:::info tip -If no errors occur the result is the same as [`mode = 128`](#10-send-all-received-tokens-together-with-the-contract-balance). This mode is widely used in TON for jetton transfers, you can [check it in C5 action list](https://retracer.ton.org/?tx=e4f31e37eec74a8cfcecdad9246a6bbf3da20c4edb3635150cb0fa54b9def558) of the jetton wallet. +If no errors occur, the result is the same as [mode = 128](#mode128). This mode is widely used in TON for jetton transfers. You can [check it in the C5 action list](https://retracer.ton.org/?tx=e4f31e37eec74a8cfcecdad9246a6bbf3da20c4edb3635150cb0fa54b9def558) of the jetton wallet. :::

- +


-| Mode and Flags | Code | -| :------------------------ | :--------------------------- | -| `mode` = 128, `flag` = 16 | `send_raw_message(msg, 144)` | - -## 12. Send all received tokens along with the contract balance and destroy the smart contract +## 12. (Mode 128, Flag 32) Send the whole balance and destroy the contract {#mode160} State before the transaction: Account A has 1 TON, Account B has 1 TON, Account C has 1 TON -**A** sent 0.1 TON to **B** after that **B** sent 0.5 TON to **C** with `mode` = 160, `msg_fwd_fees` are 0.004 TON, actual received value will be 1.1 - total_fee TON, total_fee deducted from `value`. +**A** sent 0.1 TON to **B**, and after that, **B** sent 0.5 TON to **C** with `mode` = 160. The `msg_fwd_fees` are 0.004 TON. The actual received value will be 1.1 - total_fee TON, with total_fee deducted from `value`. State after the transaction: Account A has 0.896 TON, Account B has 0 TON and `nonexist`, Account C has 2.1 - (total_fee + `fwd_fee`) TON @@ -439,16 +415,19 @@ When the balance reaches 0 TON, destroy the contract.

- +


-| Mode and Flags | Code | -| :------------------------ | :--------------------------- | -| `mode` = 128, `flag` = 32 | `send_raw_message(msg, 160)` | +[cb]: https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/block.tlb#L263C1-L265C20 +[msg]: /v3/documentation/data-formats/tlb/msg-tlb#commonmsginfo +[storage_fee]: /v3/documentation/smart-contracts/transaction-fees/fees-low-level#storage-fee +[account_storage]: https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L651-L675 +[in_msg_import]: https://github.com/ton-blockchain/ton/blob/7151ff26279fef6dcfa1f47fc0c5b63677ae2458/crypto/block/transaction.cpp#L783-L816 diff --git a/docs/v3/documentation/tvm/tvm-exit-codes.md b/docs/v3/documentation/tvm/tvm-exit-codes.md index 183e20544f4..0fcb8ec4f61 100644 --- a/docs/v3/documentation/tvm/tvm-exit-codes.md +++ b/docs/v3/documentation/tvm/tvm-exit-codes.md @@ -1,43 +1,499 @@ -# TVM Exit codes +--- +title: Exit codes +--- -If TVM exits with an arbitrary 16-bit unsigned integer `exit_code`. `exit_code` higher than 1, it is considered an _error code_. Therefore, an exit with such a code may cause the transaction to revert or bounce. +Each transaction on the TON Blockchain comprises [multiple phases](/v3/documentation/tvm/tvm-overview#transactions-and-phases). An _exit code_ is a 32-bit signed integer that indicates whether the [compute](#compute) or [action](#action) phase succeeded. When unsuccessful, it contains the exception code that occurred. Each exit code represents a specific exception or transaction outcome. -## Standard exit codes +Exit codes 0 and 1 indicate standard (successful) execution of the [compute phase](#compute). Exit (or [result](#action)) code 0 indicates the standard (successful) execution of the [action phase](#action). Any other exit code indicates that a specific exception has occurred and that the transaction wasn't successful in one way or another, i.e., the transaction was reverted or the inbound message has bounced back. -:::info -The list of standard exit codes contains all universal TVM exit codes defined for the TON Blockchain. Alternative exit codes should be sought in the source code of the corresponding contract. +> TON Blockchain reserves exit code values from 0 to 127, while Tact utilizes exit codes from 128 to 255. Note that exit codes used by Tact indicate contract errors, which can occur when using Tact-generated FunC code and are therefore thrown in the transaction's [compute phase](#compute) and not during the compilation. + +The range from 256 to 65535 is free for developer-defined exit codes. + +:::note +While exit codes are 32-bit signed integers in the TON, attempting to throw an exit code outside the 16-bit unsigned integer range (0-65535) will trigger an error with [exit code 5](#5). This intentionally prevents the artificial generation of specific exit codes like [-14](#-14). ::: -| Exit Code | TVM Phase | Description | -|-----------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `0` | Compute Phase | Standard successful execution exit code. | -| `1` | Compute Phase | Alternative successful execution exit code. | -| `2` | Compute Phase | Stack underflow. The last op-code consumed more elements than there are on the stacks. 1 | -| `3` | Compute Phase | Stack overflow. More values have been stored on a stack than are allowed by this version of TVM. | -| `4` | Compute Phase | Integer overflow. Integer does not fit into −2256 ≤ x < 2256 or a division by zero has occurred. | -| `5` | Compute Phase | Integer is out of expected range. | -| `6` | Compute Phase | Invalid opcode. The instruction is unknown in the current TVM version. | -| `7` | Compute Phase | Type check error. An argument to a primitive has an incorrect value type. 1 | -| `8` | Compute Phase | Cell overflow. Writing to the builder is not possible since after operation there would be more than 1023 bits or 4 references. | -| `9` | Compute Phase | Cell underflow. The read operation from slice primitive tried to read more bits or references than available. | -| `10` | Compute Phase | Dictionary error. An error during manipulation with the dictionary (hashmaps). | -| `11` | Compute Phase | Most often caused by trying to call get-method whose id wasn't found in the code (missing `method_id` modifier or wrong get-method name specified when trying to call it). In [TVM docs](https://ton.org/tvm.pdf) its described as "Unknown error, may be thrown by user programs". | -| `12` | Compute Phase | Thrown by TVM in situations considered impossible. | -| `13` | Compute Phase | Out of gas error. Thrown by TVM when the remaining gas turns negative. | -| `-14` | Compute Phase | This indicates an out of gas error, the same as code `13`. It is negative because it [cannot be faked](https://github.com/ton-blockchain/ton/blob/20758d6bdd0c1327091287e8a620f660d1a9f4da/crypto/vm/vm.cpp#L492) | -| `32` | Action Phase | Action list is invalid. Set during the action phase if c5 register after execution contains unparsable object. | -| `-32` | Action Phase | (the same as prev 32) - Method ID not found. Returned by TonLib during an attempt to execute non-existent get method. | -| `33` | Action Phase | The action list is too long. | -| `34` | Action Phase | Action is invalid or not supported. Set during the action phase if current action cannot be applied. | -| `35` | Action Phase | Invalid Source address in the outbound message. | -| `36` | Action Phase | Invalid Destination address in the outbound message. | -| `37` | Action Phase | Not enough TON. The message sends too much TON, or there isn't enough TON remaining after deducting fees. | -| `38` | Action Phase | Not enough extra-currencies. | -| `40` | Action Phase | Not enough funds to process the message. This error is thrown when there is only enough gas to partially cover the message, but not enough to cover it completely. | -| `43` | Action Phase | The maximum number of cells in the library has been exceeded, or the maximum depth of the Merkle tree has been surpassed. | - -1 If you encounter such exception in a func contract it probably means a type error in asm declarations. - -:::info -Often you can see the exit code `0xffff` (65535 in decimal form). This usually means that the received opcode is unknown to the contract. When writing contracts, this code is set by the developer himself. +## Table of exit codes {#standard-exit-codes} + +The following table lists exit codes with an origin (where it can occur) and a short description. The table doesn't list the exit codes from contracts. To see such exit codes, refer to the source code of the specific contract. + +| Exit code | Origin | Brief description | +| :-------- | :------------------------------------- | :----------------------------------------------------------------------------------------------------- | +| 0 | [Compute][c] and [action][a] phases | Standard successful execution exit code. | +| 1 | [Compute phase][c] | Alternative successful execution exit code. Reserved, but doesn't occur. | +| 2 | [Compute phase][c] | Stack underflow. | +| 3 | [Compute phase][c] | Stack overflow. | +| 4 | [Compute phase][c] | Integer overflow. | +| 5 | [Compute phase][c] | Range check error — some integer is out of its expected range. | +| 6 | [Compute phase][c] | Invalid [TVM][tvm] opcode. | +| 7 | [Compute phase][c] | Type check error. | +| 8 | [Compute phase][c] | Cell overflow. | +| 9 | [Compute phase][c] | Cell underflow. | +| 10 | [Compute phase][c] | Dictionary error. | +| 11 | [Compute phase][c] | As described in [TVM][tvm] documentation: "Unknown error, may be thrown by user programs" | +| 12 | [Compute phase][c] | Fatal error thrown by [TVM][tvm] in unexpected situations | +| 13 | [Compute phase][c] | Out of gas error. | +| -14 | [Compute phase][c] | Equivalent to code 13. A negative value prevents [imitation](#13) | +| 14 | [Compute phase][c] | VM virtualization error (reserved but unused) | +| 32 | [Action phase][a] | Action list is invalid. | +| 33 | [Action phase][a] | Action list is too long. | +| 34 | [Action phase][a] | Action is invalid or not supported. | +| 35 | [Action phase][a] | Invalid source address in outbound message. | +| 36 | [Action phase][a] | Invalid destination address in outbound message. | +| 37 | [Action phase][a] | Not enough Toncoin. | +| 38 | [Action phase][a] | Not enough extra currencies. | +| 39 | [Action phase][a] | Outbound message does not fit into a cell after rewriting. | +| 40 | [Action phase][a] | Cannot process a message — not enough funds, the message is too large, or its Merkle depth is too big. | +| 41 | [Action phase][a] | Library reference is null during library change action. | +| 42 | [Action phase][a] | Library change action error. | +| 43 | [Action phase][a] | Exceeded the maximum number of cells in the library or the maximum depth of the Merkle tree. | +| 50 | [Action phase][a] | Account state size exceeded limits. | +| 128 | Tact compiler ([Compute phase][c]) | Null reference exception. Configurable since Tact 1.6 (not released yet). | +| 129 | Tact compiler ([Compute phase][c]) | Invalid serialization prefix. | +| 130 | Tact compiler ([Compute phase][c]) | Invalid incoming message — there's no receiver for the opcode of the received message. | +| 131 | Tact compiler ([Compute phase][c]) | Constraints error. Reserved, but never thrown. | +| 132 | Tact compiler ([Compute phase][c]) | Access denied — someone other than the owner sent a message to the contract. | +| 133 | Tact compiler ([Compute phase][c]) | Contract stopped. Reserved, but never thrown. | +| 134 | Tact compiler ([Compute phase][c]) | Invalid argument. | +| 135 | Tact compiler ([Compute phase][c]) | Code of a contract was not found. | +| ~~136~~ | ~~Tact compiler ([Compute phase][c])~~ | ~~Invalid address.~~ Removed since Tact 1.6 (not released yet) | +| ~~137~~ | ~~Tact compiler ([Compute phase][c])~~ | ~~Masterchain support is not enabled for this contract.~~ Removed since Tact 1.6 (not released yet) | + +:::note +The exit code 65535 (`0xffff`) typically indicates the same issue as exit code `130` - an unrecognized message opcode. It is assigned manually when developing contracts rather than generated by [TVM][tvm] or the Tact compiler. ::: + +## Exit codes in Blueprint projects {#blueprint} + +In [Blueprint][bp] tests, exit codes from the [compute phase](#compute) are specified in the `exitCode` field of the object argument for the `toHaveTransaction()` method of the `expect()` matcher. The field for the result codes (exit codes from the [action phase](#action)) in the same `toHaveTransaction()` method is called `actionResultCode`. + +Note that to do so, you'll have to do a couple of type checks before that: + +```typescript +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 that 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 wasn't skipped + if (tx.description.type === "generic" + && tx.description.computePhase.type === "vm") { + // Finally, we're able to peek into the transaction for general details freely, + // such as printing out the exit code of the compute phase if we so desire + console.log(tx.description.computePhase.exitCode); + } + + // ... +}); +``` + +## Compute phase {#compute} + +The [TVM][tvm] initialization and all computations occur during the [compute phase][c]. If this phase fails (resulting in an exit code other than 0 or 1), the transaction skips the [action phase](#action) and proceeds to generate bounce messages for transactions initiated by inbound messages. + +### 0: Normal termination {#0} + +This exit (or [result](#action)) code indicates a successful completion of the [compute](#compute) (or [action](#action)) phase of the transaction. + +### 1: Alternative termination {#1} + +This is an alternative exit code for successfully executing the [compute phase](#compute). Reserved, but never occurs. + +### 2: Stack underflow {#2} + +If some operation consumed more elements than there were on the stack, the error with exit code 2 is thrown: `Stack underflow`. + +```tact +asm fun drop() { DROP } + +contract Loot { + receive("I solemnly swear that I'm up to no good") { + try { + // Removes 100 elements from the stack, causing an underflow + repeat (100) { drop() } + } catch (exitCode) { + // exitCode is 2 + } + } +} +``` + +### 3: Stack overflow {#3} + +When you copy too many elements into a closure continuation, the system throws an error with exit code 3: `Stack overflow`. This error rarely occurs unless you work deep in [Fift and TVM assembly][fift] trenches. + +```tact +// Remember, kids, don't try to overflow the stack at home! +asm fun stackOverflow() { + x{} SLICE // s + BLESS // c + 0 SETNUMARGS // c' + 2 PUSHINT // c' 2 + SWAP // 2 c' + 1 -1 SETCONTARGS // ← this blows up +} + +contract ItsSoOver { + receive("I solemnly swear that I'm up to no good") { + try { + stackOverflow(); + } catch (exitCode) { + // exitCode is 3 + } + } +} +``` + +### 4: Integer overflow {#4} + +If the value in calculation goes beyond the range from `-2^{256} to 2^{256} - 1` inclusive, or there's an attempt to divide or modulo by zero, an error with exit code 4 is thrown: `Integer overflow`. + +```tact +let x = -pow(2, 255) - pow(2, 255); // -2^{256} + +try { + -x; // integer overflow by negation + // since the max positive value is 2^{256} - 1 +} catch (exitCode) { + // exitCode is 4 +} + +try { + x / 0; // division by zero! +} catch (exitCode) { + // exitCode is 4 +} + +try { + x * x * x; // integer overflow! +} catch (exitCode) { + // exitCode is 4 +} + +// There can also be an integer overflow when doing: +// addition (+), +// subtraction (-), +// division (/) by a negative number or modulo (%) by zero +``` + +### 5: Integer out of expected range {#5} + +Range check error — some integers are out of their 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: + +```tact +try { + // Repeat only operates on an inclusive range from 1 to 2^{31} - 1 + // and any valid integer value greater than that causes an error with exit code 5 + repeat (pow(2, 55)) { + dump("smash. logs. I. must."); + } +} catch (exitCode) { + // exitCode is 5 +} + +try { + // Builder.storeUint() function can only use up to 256 bits, so 512 is too much: + let s: Slice = beginCell().storeUint(-1, 512).asSlice(); +} catch (exitCode) { + // exitCode is 5 +} +``` + +### 6: Invalid opcode {#6} + +If you specify an instruction that the current [TVM][tvm] version does not define or try to set an unsupported [code page](/v3/documentation/tvm/tvm-overview#tvm-state), the system throws an error with exit code 6: `Invalid opcode`. + +```tact +// There's no such codepage, and attempt to set it fails +asm fun invalidOpcode() { 42 SETCP } + +contract OpOp { + receive("I solemnly swear that I'm up to no good") { + try { + invalidOpcode(); + } catch (exitCode) { + // exitCode is 6 + } + } +} +``` + +### 7: Type check error {#7} + +If an argument to a primitive is of an incorrect value type or there's any other mismatch in types during the [compute phase](#compute), an error with exit code 7 is thrown: `Type check error`. + +```tact +// The actual returned value type doesn't match the declared one +asm fun typeCheckError(): map { 42 PUSHINT } + +contract VibeCheck { + receive("I solemnly swear that I'm up to no good") { + try { + // The 0th index doesn't exist + typeCheckError().get(0)!!; + } catch (exitCode) { + // exitCode is 7 + } + } +} +``` + +### 8: Cell overflow {#8} + +> `Cell` is a [primitive][p] and a data structure, which ordinarly consists of up to 1023 continuously laid out bits and up to 4 references (refs) to other cells. + +A 'Builder' is utilized to create a 'Cell'. If you attempt to store more than 1023 bits of data or exceed 4 references to other cells, an error with exit code 8 is thrown: 'Cell overflow'. + +```tact +// Too much bits +try { + let data = beginCell() + .storeInt(0, 250) + .storeInt(0, 250) + .storeInt(0, 250) + .storeInt(0, 250) + .storeInt(0, 24) // 1024 bits! + .endCell(); +} catch (exitCode) { + // exitCode is 8 +} + +// Too much refs +try { + let data = beginCell() + .storeRef(emptyCell()) + .storeRef(emptyCell()) + .storeRef(emptyCell()) + .storeRef(emptyCell()) + .storeRef(emptyCell()) // 5 refs! + .endCell(); +} catch (exitCode) { + // exitCode is 8 +} +``` + +### 9: Cell underflow {#9} + +> `Cell` is a [primitive][p] and a data structure, which ordinarly consists of up to 1023 continuously laid out bits and up to 4 references (refs) to other cells. + +To parse a `Cell`, a `Slice` is used. If you try to load more data or references than `Slice` contains, an error with exit code 9 is thrown: `Cell underflow`. + +```tact +// Too few bits +try { + emptySlice().loadInt(1); // 0 bits! +} catch (exitCode) { + // exitCode is 9 +} + +// Too few refs +try { + emptySlice().loadRef(); // 0 refs! +} catch (exitCode) { + // exitCode is 9 +} +``` + +### 10: Dictionary error {#10} + +In Tact, the `map` type is an abstraction over the ["hash" map dictionaries of FunC](/v3/documentation/smart-contracts/func/docs/dictionaries#hashmap) and underlying [`HashmapE` type](/v3/documentation/data-formats/tlb/tl-b-types#hashmap) of [TL-B][tlb] and [TVM][tvm]. + +If there is an incorrect manipulation of dictionaries, such as improper assumptions about their memory layout, an error with exit code 10 is thrown: `Dictionary error`. Note that Tact prevents you from getting this error unless you do [Fift and TVM assembly][fift] work yourself: + +```tact +/// Pre-computed Int to Int dictionary with two entries — 0: 0 and 1: 1 +const cellWithDictIntInt: Cell = cell("te6cckEBBAEAUAABAcABAgPQCAIDAEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMLMbT1U="); + +/// Tries to preload a dictionary from a Slice as a map +asm fun toMapIntCell(x: Slice): map { PLDDICT } + +contract DictPic { + receive("I solemnly swear that I'm up to no good") { + try { + // The code misinterprets the Int to Int dictionary as a map + let m: map = toMapIntCell(cellWithDictIntInt.beginParse()); + + //The error happens only when we touch it + m.get(0)!!; + } catch (exitCode) { + // exitCode is 10 + } + } +} +``` + +### 11: "Unknown" error {#11} + +Described in [TVM][tvm] docs as "Unknown error, may be thrown by user programs", although most commonly used for problems with queueing a message send or problems with [get-methods](/v3/guidelines/smart-contracts/get-methods). + +```tact +try { + // Unlike nativeSendMessage, which uses SENDRAWMSG, this one uses SENDMSG, + // and therefore fails in the Compute phase when the message is ill-formed + nativeSendMessageReturnForwardFee(emptyCell(), 0); +} catch (exitCode) { + // exitCode is 11 +} +``` + +### 12: Fatal error {#12} + +Fatal error. Thrown by TVM in situations deemed impossible. + +### 13: Out of gas error {#13} + +If there isn't enough gas to end computations in the [compute phase](#compute), the error with exit code 13 is thrown: `Out of gas error`. + +But 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 shown. + +This design prevents user contracts from artificially producing the `-14` code since all functions that throw exit codes can only specify integers ranging from `0 to 65535` inclusive. + +```tact +try { + repeat (pow(2, 31) - 1) {} +} catch (exitCode) { + // exitCode is -14 +} +``` + +### -14: Out of gas error {#-14} + +See [exit code 13](#13). + +### 14: Virtualization error {#14} + +Virtualization error related to [prunned branch cells](/v3/documentation/data-formats/tlb/exotic-cells#pruned-branch). Reserved, but never thrown. + +## Action phase {#action} + +The [action phase][a] is processed after the successful execution of the [compute phase](#compute). It attempts to perform the actions stored in the action list by [TVM][tvm] during the compute phase. + +Some actions may fail during processing, in which case the system may skip them or revert the entire transaction, depending on the action modes. Developers call the code that indicates the resulting state of the [action phase][a] a _result code_. Since this code serves the same purpose as the compute phase's exit code, developers commonly refer to it as an exit code too. + +### 32: Action list is invalid {#32} + +If the list of actions contains [exotic cells][exotic], an action entry cell does not have references, or some action entry cell couldn't be parsed, an error with exit code 32 is thrown: `Action list is invalid`. + +Aside from this exit code, there's a boolean flag `valid`, which you can find under `description.actionPhase.valid` in the transaction results when working with [Sandbox and Blueprint](#blueprint). The transaction can set this flag to `false` even when the action phase throws some other exit code. + +### 33: Action list is too long {#33} + +If you queue more than 255 actions for execution, the [action phase](#action) throws an error with exit code 33: `Action list is too long`. + +```tact +// For example, let's attempt to queue reservations of a specific amount of nanoToncoins +// This won't fail in the compute phase but will result in exit code 33 in the action phase +repeat (256) { + nativeReserve(ton("0.001"), ReserveAtMost); +} +``` + +### 34: Invalid or unsupported action {#34} + +Currently, only four actions are supported: changing the contract code, sending a message, reserving a specific amount of `nanoToncoins`, and changing the library cell. If there's any issue with the specified action (invalid message, unsupported action, etc.), an error with exit code 34 is thrown: `Invalid or unsupported action`. + +```tact +// For example, let's try to send an ill-formed message: +nativeSendMessage(emptyCell(), 0); // won't fail in compute phase, + // but will result in exit code 34 in the action phase +``` + +### 35: Invalid source address in outbound message {#35} + +If the source address in the outbound message isn't equal to [`addr_none`](/v3/documentation/data-formats/tlb/msg-tlb#addr_none00) or to the address of the contract that initiated this message, an error with exit code 35 is thrown: `Invalid source address in the outbound message`. + +### 36: Invalid destination address in outbound message {#36} + +Suppose the destination address in the outbound message is invalid. In that case, e.g., it doesn't 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 the outbound message`. + +:::note +If the [optional flag +2][flag2] is set, this error will not be thrown, and the given message will not be sent. +::: + +### 37: Not enough Toncoin {#37} + +If all funds of the inbound message with [mode 64](/v3/documentation/smart-contracts/message-management/message-modes-cookbook#mode64) had been already consumed and there's not enough funds to pay for the failed action, or the [TL-B][tlb] layout of the provided value ([`CurrencyCollection`](/v3/documentation/data-formats/tlb/msg-tlb#currencycollection)) is invalid, or there are not enough funds to pay forward fees or not enough funds after deducting fees, an error with exit code 37 is thrown: `Not enough Toncoin`. + +:::note +If the [optional flag +2][flag2] is set, this error will not be thrown, and the given message will not be sent. +::: + +### 38: Not enough extra currencies {#38} + +Besides the native currency, Toncoin, TON Blockchain supports up to 2^{32} extra currencies. They differ from making new jettons because extra currencies are natively supported — one can potentially specify an extra [`HashmapE`](/v3/documentation/data-formats/tlb/tl-b-types#hashmap) of extra currency amounts in addition to the Toncoin amount in the internal message to another contract. Unlike Jettons, extra currencies can only be stored and transferred and do not have any other functionality. + +Currently, **there are no extra currencies** on TON Blockchain, but the exit code 38 is reserved for cases when there is not enough extra currency to send the specified amount: `Not enough extra currencies`. + +:::note +[Extra currencies](/v3/documentation/dapps/defi/coins) in TON Docs. + +[Extra currency mining](/v3/documentation/infra/minter-flow) in TON Docs. +::: + +### 39: Outbound message doesn't fit into a cell {#39} + +When processing the message, TON Blockchain tries to pack it according to the [relevant TL-B schemas](/v3/documentation/data-formats/tlb/msg-tlb). If it cannot, an error with exit code 39 is thrown: `Outbound message doesn't fit into a cell`. + +:::note +If the [optional flag +2][flag2] is set, this error will not be thrown, and the given message will not be sent. +::: + +### 40: Cannot process a message {#40} + +If there are insufficient 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`. + +:::note +If the [optional flag +2][flag2] is set, this error will not be thrown, and the given message will not be sent. +::: + +### 41: Library reference is null {#41} + +If the library reference was required during the library change action but was null, an error with exit code 41 is thrown: `Library reference is null`. + +### 42: Library change action error {#42} + +If an error occurs during an attempt to perform a library change action, an error with exit code 42 is thrown: `Library change action error`. + +### 43: Library limits exceeded {#43} + +Suppose the maximum number of cells in the library or the maximum depth of the Merkle tree is exceeded. In that case, an error with exit code 43 is thrown: `Library limits exceeded`. + +### 50: Account state size exceeded limits {#50} + +If the account state (contract storage, essentially) exceeds any of the limits specified in [config param 43 of TON Blockchain](/v3/documentation/network/configs/blockchain-configs#param-43) by the end of the [action phase](#action), an error with exit code `50` is thrown: `Account state size exceeded limits`. + +If the configuration is absent, the default values are: + +- `max_msg_bits` equals `2^{21}` — maximum message size in bits. +- `max_msg_cells` equals `2^{13}` — maximum number of cells a message can occupy. +- `max_library_cells` equals `1000` — maximum number of cells that can be used as [library reference cells][lib]. +- `max_vm_data_depth` equals `2^{9}` — maximum cells depth in messages and account state. +- `ext_msg_limits.max_size` equals `65535` — maximum external message size in bits. +- `ext_msg_limits.max_depth` equals `2^{9}` — maximum external message depth. +- `max_acc_state_cells` equals `2^{16}` — maximum number of cells an account state can occupy. +- `max_acc_state_bits` equals `2^{16} * 1023` — maximum account state size in bits. +- `max_acc_public_libraries` equals `2^{8}` — maximum number of [library reference cells][lib] that an account state can use on the masterchain. +- `defer_out_queue_size_limit` equals `2^{8}` — maximum number of outbound messages to be queued (regards validators and collators). + +## Tact compiler + +Tact utilizes exit codes from `128` to `255`. Note that exit codes used by Tact indicate contract errors that can occur when using Tact-generated FunC code and are therefore thrown in the transaction's [compute phase](#compute) and not during the compilation. + +The list of exit codes for the Tact compiler is in the [Tact docs](https://docs.tact-lang.org/book/exit-codes/#tact-compiler). + +[c]: /v3/documentation/tvm/tvm-overview#compute-phase +[a]: /v3/documentation/tvm/tvm-overview#transactions-and-phases +[flag2]: /v3/documentation/smart-contracts/message-management/message-modes-cookbook#mode2 +[tlb]: /v3/documentation/data-formats/tlb/tl-b-language +[lib]: /v3/documentation/data-formats/tlb/exotic-cells#library-reference +[p]: /v3/documentation/smart-contracts/func/docs/types#atomic-types +[tvm]: /v3/documentation/tvm/tvm-overview +[bp]: https://github.com/ton-org/blueprint +[fift]: /v3/documentation/fift/fift-and-tvm-assembly diff --git a/docs/v3/guidelines/nodes/running-nodes/archive-node.md b/docs/v3/guidelines/nodes/running-nodes/archive-node.md index 786ccd10512..bcff96f268c 100644 --- a/docs/v3/guidelines/nodes/running-nodes/archive-node.md +++ b/docs/v3/guidelines/nodes/running-nodes/archive-node.md @@ -1,56 +1,56 @@ -# Archive Node +# Archive node :::info -Read about [Full Node](/v3/guidelines/nodes/running-nodes/full-node) before this article +Before this article, read about [Full Node](/v3/guidelines/nodes/running-nodes/full-node). ::: ## Overview -An Archive Node is a type of Full Node that stores extended historical data of a blockchain. If you are creating a blockchain explorer or a similar application that requires access to historical data, using an Archive Node as an indexer is recommended. +An archive node is a type of full node that stores extended historical data from a blockchain. If you are creating a blockchain explorer or a similar application that requires access to historical data, it is recommended that you use an archive node as an indexer. ## OS requirements -We highly recommend install mytonctrl using the supported operating systems: +We highly recommend installing mytonctrl using the supported operating systems: - Ubuntu 20.04 - Ubuntu 22.04 - Debian 11 -## Hardware requirements +## Minimal hardware requirements -- 16 x Cores CPU -- 128GB ECC Memory -- 9TB SSD _OR_ Provisioned 64+k IOPS storage -- 1 Gbit/s network connectivity +- 16-core CPU +- 128 GB ECC Memory +- 12 TB SSD _OR_ Provisioned 64+k IOPS storage +- 1 Gbit/s network connectivity, both inbound and outbound - 16 TB/month traffic on peak load -- a public IP address (fixed IP address) +- Linux OS with open files limit above 400k +- A public IP address (fixed IP address) -:::info Data Compression -It requires 9TB for the uncompressed data. 6TB is based on using a ZFS volume with compression enabled. -The data volume increases by approximately 0.5TB and 0.25TB each month, with the latest update in November 2024. +:::info Data compression +Uncompressed data requires 12 TB of storage. A ZFS volume with compression reduces this to 11 TB. As of February 2025, the data volume is growing by approximately 0.1 to 1 TB per month, depending on the load. ::: ## Installation -### Install ZFS and Prepare Volume +### Install ZFS and prepare volume -Dumps come in form of ZFS Snapshots compressed using plzip, you need to install zfs on your host and restore the dump, see [Oracle Documentation](https://docs.oracle.com/cd/E23824_01/html/821-1448/gavvx.html#scrolltoc) for more details. +Dumps come in the form of ZFS snapshots compressed using plzip. You need to install ZFS on your host and restore the dump. See [Oracle Documentation](https://docs.oracle.com/cd/E23824_01/html/821-1448/gavvx.html#scrolltoc) for more details. -Usually, it's a good idea to create a separate ZFS pool for your node on a _dedicated SSD drive_, this will allow you to easily manage storage space and backup your node. +Usually, it's a good idea to create a separate ZFS pool for your node on a _dedicated SSD drive_. This will allow you to manage storage space and back up your node easily. -1. Install [zfs](https://ubuntu.com/tutorials/setup-zfs-storage-pool#1-overview) +1. Install [ZFS](https://ubuntu.com/tutorials/setup-zfs-storage-pool#1-overview): ```shell sudo apt install zfsutils-linux ``` -2. [Create pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool#3-creating-a-zfs-pool) on your dedicated 4TB `` and name it `data` +2. [Create a pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool#3-creating-a-zfs-pool) on your dedicated 4 TB `` and name it `data`: ```shell sudo zpool create data ``` -3. Before restoring we highly recommend to enable compression on parent ZFS filesystem, this will save you a [lot of space](https://www.servethehome.com/the-case-for-using-zfs-compression/). To enable compression for the `data` volume enter using root account: +3. We recommend enabling compression on the parent ZFS filesystem before restoring. This will save you a [significant amount of space](https://www.servethehome.com/the-case-for-using-zfs-compression/). To enable compression for the `data` volume, use the root account to enter the following: ```shell sudo zfs set compression=lz4 data @@ -58,20 +58,20 @@ sudo zfs set compression=lz4 data ### Install MyTonCtrl -Please, use a [Running Full Node](/v3/guidelines/nodes/running-nodes/full-node) to **install** and **run** mytonctrl. +Please use the [Running Full Node](/v3/guidelines/nodes/running-nodes/full-node) guide to **install** and **run** mytonctrl. -### Run an Archive Node +### Run an archive node #### Prepare the node -1. Before performing a restore, you must stop the validator using root account: +1. Before performing a restore, you must stop the validator using the root account: ```shell sudo -s systemctl stop validator.service ``` -2. Make a backup of `ton-work` config files (we will need the `/var/ton-work/db/config.json`, `/var/ton-work/keys`, and `/var/ton-work/db/keyring`). +2. Make a backup of `ton-work` config files (we will need `/var/ton-work/db/config.json`, `/var/ton-work/keys`, and `/var/ton-work/db/keyring`): ```shell mv /var/ton-work /var/ton-work.bak @@ -79,36 +79,34 @@ mv /var/ton-work /var/ton-work.bak #### Download the dump -1. Request `user` and `password` credentials to gain access for downloading dumps in the [@TONBaseChatEn](https://t.me/TONBaseChatEn) Telegram chat. -2. Here is an example command to download & restore the **mainnet** dump from the ton.org server: +Here is an example command to download & restore the **mainnet** dump from the ton.org server: ```shell -wget --user --password -c https://archival-dump.ton.org/dumps/latest.zfs.lz | pv | plzip -d -n | zfs recv data/ton-work +curl -L -s https://archival-dump.ton.org/dumps/mainnet_full_44888096.zfs.zstd | pv | zstd -d -T16 | zfs recv mypool/ton-db ``` -To install **testnet** dump use: +To install the **testnet** dump, use: ```shell -wget --user --password -c https://archival-dump.ton.org/dumps/latest_testnet.zfs.lz | pv | plzip -d -n | zfs recv data/ton-work +wget -c https://dump.ton.org/dumps/latest_testnet_archival.zfs.lz | pv | plzip -d -n | zfs recv data/ton-work ``` -The size of the dump is approximately **4TB**, so it may take several days (up to 4 days) to download and restore. The dump size can increase as the network grows. +The mainnet dump size is approximately 9 TB, so it may take several days to download and restore. The dump size will increase as the network grows. Prepare and run the command: -1. Install the tools if necessary (`pv`, `plzip`) -2. Replace `` and `` with your credentials -3. Tell `plzip` to use as many cores as your machine allows to speed up extraction (`-n`) +1. Install the necessary tools (`pv`, `plzip`, `zstd`). +2. Tell `plzip` to use as many cores as your machine allows to speed up extraction (`-n`). #### Mount the dump -1. Mount zfs: +1. Mount ZFS: ```shell zfs set mountpoint=/var/ton-work data/ton-work && zfs mount data/ton-work ``` -2. Restore `db/config.json`, `keys` and `db/keyring` from backup to `/var/ton-work` +2. Restore `db/config.json`, `keys`, and `db/keyring` from the backup to `/var/ton-work`: ```shell cp /var/ton-work.bak/db/config.json /var/ton-work/db/config.json @@ -116,25 +114,25 @@ cp -r /var/ton-work.bak/keys /var/ton-work/keys cp -r /var/ton-work.bak/db/keyring /var/ton-work/db/keyring ``` -3. Make sure that permissions for `/var/ton-work` and `/var/ton-work/keys` dirs promoted correctly: +3. Set the permissions for the `/var/ton-work` and `/var/ton-work/keys` directories correctly: -- The owner for the `/var/ton-work/db` dir should be `validator` user: +- The owner of the `/var/ton-work/db` directory should be the `validator` user: ```shell chown -R validator:validator /var/ton-work/db ``` -- The owner for the `/var/ton-work/keys` dir should be `ubuntu` user: +- The owner of the `/var/ton-work/keys` directory should be the `ubuntu` user: ```shell chown -R ubuntu:ubuntu /var/ton-work/keys ``` -#### Update Configuration +#### Update configuration -Update node configuration for the archive node. +Update the node configuration for the archive node. -1. Open the node config file `/etc/systemd/system/validator.service` +1. Open the node config file `/etc/systemd/system/validator.service`: ```shell nano /etc/systemd/system/validator.service @@ -143,16 +141,16 @@ nano /etc/systemd/system/validator.service 2. Add storage settings for the node in the `ExecStart` line: ```shell ---state-ttl 315360000 --archive-ttl 315360000 --block-ttl 315360000 +--state-ttl 3153600000 --archive-ttl 3153600000 ``` :::info -Please be patient once you start the node and observe the logs. -Dumps come without DHT caches, so it will take some time for your node to find other nodes and sync with them. -Depending on the age of the snapshot and your internet connection speed, -it might take your node anywhere **from a few hours to several days** to catch up with the network. -**On a minimum setup, this process can take up to 5 days.** -This is normal. +Please remain patient after starting the node and monitor the logs closely. +The dump files lack DHT caches, requiring your node to discover other nodes and synchronize with them. +Depending on the snapshot's age and your network bandwidth, +your node might need **anywhere from several hours to multiple days** to synchronize with the network. +**The synchronization process typically takes up to 5 days when using minimum hardware specifications.** +This is expected behavior. ::: :::caution @@ -168,32 +166,32 @@ If the node sync process has already taken 5 days, but the node is still out of systemctl start validator.service ``` -2. Open `mytonctrl` from _local user_ and check the node status using the `status`. +2. Open `mytonctrl` from the _local user_ and check the node status using the `status` command. ## Node maintenance -Node database requires cleansing from time to time (we advise once a week), to do so please perform following steps as root: +The node database requires cleansing from time to time (we advise doing this once a week). To do so, please perform the following steps as root: -1. Stop validator process (Never skip this!) +1. Stop the validator process (Never skip this!): ```shell sudo -s systemctl stop validator.service ``` -2. Remove old logs +2. Remove old logs: ```shell find /var/ton-work -name 'LOG.old*' -exec rm {} + ``` -4. Remove temp files +3. Remove temporary files: ```shell rm -r /var/ton-work/db/files/packages/temp.archive.* ``` -5. Start validator process +4. Start the validator process: ```shell systemctl start validator.service @@ -201,34 +199,34 @@ systemctl start validator.service ## Troubleshooting and backups -If for some reason something does not work / breaks you can always [roll back](https://docs.oracle.com/cd/E23824_01/html/821-1448/gbciq.html#gbcxk) to @archstate snapshot on your ZFS filesystem, this is the original state from dump. +If, for some reason, something does not work or breaks, you can always [roll back](https://docs.oracle.com/cd/E23824_01/html/821-1448/gbciq.html#gbcxk) to the `@archstate` snapshot on your ZFS filesystem. This is the original state from the dump. -1. Stop validator process (**Never skip this!**) +1. Stop the validator process (**Never skip this!**): ```shell sudo -s systemctl stop validator.service ``` -2. Check the snapshot name +2. Check the snapshot name: ```shell zfs list -t snapshot ``` -3. Rollback to the snapshot +3. Roll back to the snapshot: ```shell zfs rollback data/ton-work@dumpstate ``` -If your Node works well then you can remove this snapshot to save storage space, but we do recommend to regularly snapshot your filesystem for rollback purposes because validator node has been known to corrupt data as well as config.json in some cases. [zfsnap](https://www.zfsnap.org/docs.html) is a nice tool to automate snapshot rotation. +If your node operates properly, you may remove this snapshot to reclaim storage space. However, we recommend creating regular filesystem snapshots for rollback capability since the validator node may occasionally corrupt data and `config.json`. For automated snapshot management, [zfsnap](https://www.zfsnap.org/docs.html) handles rotation effectively. :::tip Need help? -Have question or need help? Please ask in the [TON dev chat](https://t.me/tondev_eng) to get help from the community. MyTonCtrl developers also hang out there. +Have a question or need help? Please ask in the [TON dev chat](https://t.me/tondev_eng) to get help from the community. MyTonCtrl developers also hang out there. ::: -## Tips & Tricks +## Tips & tricks :::info Basic info about archival dumps is present at https://archival-dump.ton.org/ @@ -236,7 +234,7 @@ Basic info about archival dumps is present at https://archival-dump.ton.org/ ### Remove dump snapshot -1. Find the right snapshot +1. Find the correct snapshot ```bash zfs list -t snapshot @@ -248,9 +246,9 @@ zfs list -t snapshot zfs destroy ``` -### Force archive node not to store blocks +### Force the archive node not to store blocks -To force node not to store archive blocks use the value 86400. Check [set_node_argument section](/v3/documentation/infra/nodes/mytonctrl/mytonctrl-overview#set_node_argument) for more. +To force the node not to store archive blocks, use the value `86400`. Check the [set_node_argument section](/v3/documentation/infra/nodes/mytonctrl/mytonctrl-overview#set_node_argument) for more details. ```bash installer set_node_argument --archive-ttl 86400 @@ -258,9 +256,9 @@ installer set_node_argument --archive-ttl 86400 ## Support -Contact technical support with [@mytonctrl_help](https://t.me/mytonctrl_help). +Contact technical support at [@mytonctrl_help](https://t.me/mytonctrl_help). -## See Also +## See also - [TON Node Types](/v3/documentation/infra/nodes/node-types) - [Run a Full Node](/v3/guidelines/nodes/running-nodes/full-node)