Skip to main content

Message modes cookbook

Understanding the modes and flags for sending messages ensures your smart contracts behave as intended. This section illustrates their practical application through specific examples.

IMPORTANT

You can check this example as a real-world validation.

Message value and account balance

The contract reflects all TON tokens it holds in its 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 processes exactly one incoming message at a time.

To better understand the balance inside the TVM, refer to how the get_balance function operates.

Therefore, any blockchain payment may come either:

  • From the incoming message's value. Contracts pay computation fees this way unless they call accept_message, 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 and for the 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, storage and gas fees will consume part of the contract balance if the message value is above a certain amount.

According to the transaction flow, each transaction consists of five distinct phases:

  • Storage phase Handles storage fee and in_msg import fee.

  • Credit phase The in_msg value is credited to the account balance.

  • Compute phase Executes the smart contract code via TVM.

  • Action phase Processes transaction outputs including SENDRAWMSG operations.

  • Bounce phase Manages message bounce handling when applicable.

Execution order notes:

For non-bounceable messages: Credit → Storage → Compute → Action → Bounce

For bounceable messages: Storage → Credit → Compute → Action → Bounce

Compute, Action and Bounce phases may be skipped

Fee deduction sequence

  1. Storage fees
  2. Message import fees
  3. Computation gas fees
  4. Action processing fees + forward fees

Example of calculation

Fee in explorerValueHow it's obtained
Total fee0.001982134gas + storage + action + import
Fwd. fee0.001fwd_fee + action_fee + ihr_fee
Gas fee0.0011976compute phase, gas used
Storage fee0.000000003storage phase, account only
Action fee0.000133331action phase, cost per action
Import fee (hidden)0.0006512cost of import of in_ext_msg
Forward fee (each msg)0.000266669cost of fwd of in_msg
IHR fee (each msg)0.0006cost of ihr fwd of in_msg
IMPORTANT

The table is populated using this example transaction.

For live calculations, refer to the fee calculator.

Storage fee (part of total_fee) is always paid from the contract balance.

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.

1. (Mode 0, flag 0) basic message

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.

State after the transaction: Account A has 0.9 TON, Account B has 1.096 TON


Diagram: mode 0 basic messageDiagram: mode 0 basic message

2. (Mode 0, flag 2) error‐silent message

info

Please note that omitting the +2 flag may be unsafe. For more information, refer to this section.

State before transaction: Account A has 1 TON, Account B has 1 TON

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, the message will be skipped instead of throwing an exit code.

State after the transaction: Account A has 0.9 TON, Account B has 1.096 TON

tip

If no errors occur, the result is the same as mode = 0.


Diagram: mode 2 error-silent messageDiagram: mode 2 error-silent message

3. (Mode 0, flag 16) bounce on action error

State before transaction: Account A has 1 TON, Account B has 1 TON

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, the message will bounce and total_fee + fwd_fee will be deducted from value.

State after the transaction with error: Account A has 1 - (total_fee + fwd_fee) TON, Account B has 1 TON


Diagram: mode 16 bounce on action error (error)Diagram: mode 16 bounce on action error (error)

tip

If no errors occur, the result is the same as mode = 0.

The key difference is that flag 16 creates bounces for action phase errors. In contrast, the message's built‐in bounce flag handles protocol‐level failures like:

  • The destination contract does not exist.
  • The destination contract throws an unhandled exception.

Diagram: mode 16 bounce on action error (no error)Diagram: mode 16 bounce on action error (no error)

4. (Mode 0, flag 1) separate fees

info

Please note that using only this flag is unsafe, for more information refer to this section.

State before the transaction: Account A has 1 TON, Account B has 1 TON

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


Diagram: mode 1 separate feesDiagram: mode 1 separate fees

5. (Mode 0, flag 17) separate fees and bounce on action error

State before the transaction: Account A has 1 TON, Account B has 1 TON

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, 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 + fwd_fee) TON, Account B has 1 TON


Diagram: mode 17 separate fees with bounce (error)Diagram: mode 17 separate fees with bounce (error)

tip

If no errors occur, the result is the same as mode = 0, flag = 1.


Diagram: mode 17 separate fees with bounce (no error)Diagram: mode 17 separate fees with bounce (no error)

6. (Mode 64, flag 0) carry forward the remaining value

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 = 64, msg_fwd_fees are 0.004 TON, actual received value will be 0.6 TON, total_fee + fwd_fee are deducted from value.

State after the transaction: Account A has 0.896 TON, Account B has 0.5 TON, Account C has 1.6 - (total_fee + fwd_fee) TON

info

You can check this example. 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 the balance.

When sending multiple messages, you may get exit code 37 (Insufficient Toncoin) if funds are insufficient — for example, SENDRAWMSG doesn’t update the balance and mode 64 can carry remaining value, leaving a second send without funds.


Diagram: mode 64 carry remaining valueDiagram: mode 64 carry remaining value

7. (Mode 64, flag 1) carry forward with separate fees

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 = 65, msg_fwd_fees are 0.004 TON, actual received value will be 0.6 TON, total_fee + fwd_fee are deducted from balance.

State after the transaction: Account A has 0.896 TON, Account B has 0.5 - (total_fee + fwd_fee) TON, Account C has 1.6 TON

info

You can check this example. Please note that storage_fee is included in total_fee but is always paid from the contract balance.


Diagram: mode 65 carry remaining value with separate feesDiagram: mode 65 carry remaining value with separate fees

8. (Mode 64, flag 16) bounce‐protected carry forward

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


Diagram: mode 80 carry remaining value (error)Diagram: mode 80 carry remaining value (error)

tip

If no errors occur, the result is the same as mode = 64, flag 0. This mode is widely used for jetton transfers. You can check it in the C5 action list of the jetton wallet.



9. (Mode 64, flag 17) bounce‐protected carry forward with separate fees

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


Diagram: mode 81 carry remaining value (error)Diagram: mode 81 carry remaining value (error)

tip

If no errors occur, the result is the same as mode = 65.


Diagram: mode 81 carry remaining value (no error)Diagram: mode 81 carry remaining value (no error)

10. (Mode 128, flag 0) send whole balance

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


Diagram: mode 128 send whole balanceDiagram: mode 128 send whole balance

11. (Mode 128, flag 16) send the whole balance bounce‐protected

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


Diagram: mode 144 send whole balance (error)Diagram: mode 144 send whole balance (error)

tip

If no errors occur, the result is the same as mode = 128. This mode is widely used for jetton transfers. You can check it in the C5 action list of the jetton wallet.


Diagram: mode 144 send whole balance (no error)Diagram: mode 144 send whole balance (no error)

12. (Mode 128, flag 32) send the whole balance and destroy the contract

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

When the balance reaches 0 TON, destroy the contract.


Diagram: mode 160 send whole balance and destroyDiagram: mode 160 send whole balance and destroy

Was this article useful?