Skip to main content

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 section provided detailed descriptions of these modes and flags, in this section we will illustrate their practical application through specific examples.

IMPORTANT

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

Message value and account balance

Please check how get_balance works to better understand the transaction state.

There are two ways to pay for blockchain action:

Typically, it is charged from the contract balance, but in specific cases, it will use part of the message value.

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 and gas_fees if the message value is above certain amount.

According to the transaction flow there are 5 phases:

  • Storage, consisting of account storage and in_msg import
  • Credit, 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

The order is: storage_fee -> import_fee -> gas_fee -> action_fee + fwd_fee

IMPORTANT

The table is populated based on this example. You can check the live calculator.

Fee in ExplorerValueHow it's obtained
Total fee0,001982134gas + storage + action + import
total_fwd_fees0,001fwd_fee + action_fee + ihr_fee
gas_fees0,0011976compute phase, gas used
storage_fees0,000000003storage phase, account only
total_action_fees0,000133331action phase, cost per action
import_fee (hidden)0,0006512cost of import of ext_msg
fwd_fee (each msg)0,000266669cost of fwd of in_msg
ihr_fee (each msg)0.0006cost 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.

1. Send a regular 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 deducted from value.

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

Mode and FlagsCode
mode = 0, no flagsend_raw_message(msg, 0)

2. Send a regular message, no bounce the message on error and ignore it

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 deducted from value. In case of an error during transaction processing, the message will not bounce and will be ignored.

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

tip

Funds included with an ignored message will still be credited to the receiving address. If no errors occur, the result is the same as mode = 0.

Mode and FlagsCode
mode = 0, flag = 2send_raw_message(msg, 2)

3. Send a regular message, and bounce the message in case of an action error

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 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 transaction with error: Account A has 1 - (total_fee + fwd_fee) TON, Account B has 1 TON

tip

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

Mode and FlagsCode
mode = 0, flag = 16send_raw_message(msg, 16)

4. Send a regular message with separate fees

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 deducted from balance.

State after the transaction: Account A has 0.896 TON, Account B has 1.1 TON

Mode and FlagsCode
mode = 0, flag = 1send_raw_message(msg, 1)

5. Send a regular message with separate fees and bounce the message on error

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 deducted from balance. 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 an error: Account A has 1 - (total_fee + fwd_fee) TON, Account B has 1 TON

tip

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

Mode and FlagsCode
mode = 0, flag = 1 + 16 = 17send_raw_message(msg, 17)

6. Carry remaining value with new message

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 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 might check this example. Please note that storage_fee is included in total_fee but it is always paid from contract balance.

warning

Please note that SENDRAWMSG doesn't update balance.

If you try to send multiple messages (i.e. mode 0 and mode 64) you'll get exit code 37.

Mode and FlagsCode
mode = 64, no flagsend_raw_message(msg, 64)

7. Carry remaining value with a new message 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 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 might check this example. Please note that storage_fee is included in total_fee but it is always paid from contract balance.

Mode and FlagsCode
mode = 64, flag = 1send_raw_message(msg, 65)

8. Carry remaining value and bounce the message on error

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

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

tip

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

Mode and FlagsCode
mode = 64, flag = 16send_raw_message(msg, 80)

9. Carry the remaining value with a new message with separate fees and bounce the message on error

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 deducted from 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 transaction with an error: Account A has 1 - (total_fee + fwd_fee) TON, Account B has 1 TON, Account C has 1 TON

tip

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

Mode and FlagsCode
mode = 64, flag = 16 + 1send_raw_message(msg, 81)

10. Send all received tokens along with the contract 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, actual received value will be 1.1 - total_fee TON, total_fee 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 FlagsCode
mode = 128, no flagsend_raw_message(msg, 128)

11. Send all received tokens along with the contract balance and bounce the message on error

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

tip

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

Mode and FlagsCode
mode = 128, flag = 16send_raw_message(msg, 144)

12. Send all received tokens along with the contract balance and destroy the smart 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, msg_fwd_fees are 0.004 TON, actual received value will be 1.1 - total_fee TON, 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.

Mode and FlagsCode
mode = 128, flag = 32send_raw_message(msg, 160)