Accept message effects
The accept_message
and set_gas_limit
TVM primitives play a crucial role in managing gas limits and transaction processing in TON smart contracts. While their basic functionality is documented in the stdlib reference, their effects on transaction processing, gas limits, and contract balances can be complex and have important security implications. This page explores these effects in detail, particularly focusing on how they impact external and internal message processing.
External messages
External messages follow this processing flow:
-
The
gas_limit
is initially set togas_credit
Param 20 and 21, which equals 10,000 gas units. -
During the Compute phase, a contract must call
accept_message
orset_gas_limit
to raise the gas limit and indicate its readiness to pay processing fees. -
If
gas_credit
is depleted or computation completes withoutaccept_message
, the external message is not included in a block and no transaction is created. -
Gas limit semantics:
accept_message
setsgl
to the maximum allowed (gm
).set_gas_limit(limit)
setsgl
tomin(limit, gm)
.gm
is capped by the network gas limit (Config Param 20 and 21).
-
After transaction completion, full computation fees are deducted from the contract balance (making
gas_credit
truly a credit, not free gas).
If an error occurs after accept_message
(in either Compute or Action phase):
- The transaction is recorded on the blockchain.
- Fees are deducted from the contract balance.
- Storage remains unchanged unless state was committed with
commit()
prior to the error. - Actions are not applied.
Note on action errors and flags:
- By default, a compute/action failure reverts state and cancels pending actions.
- With
ignore_errors
(send mode flag2
), failed sends are skipped without reverting other actions. - For action-phase errors, a bounce occurs only if the failed send used flag
16
(bounce on action error).
Critical security consideration
If a contract accepts an external message and then throws an exception (due to invalid message data or serialization errors), it:
- Pays for processing.
- Cannot prevent message replay.
- Will continue accepting the same message until its balance is depleted.
Internal messages
When a contract receives an internal message from another contract:
- Default gas limit:
message_value
/gas_price
(message covers its own processing). - The contract can modify this limit using
accept_message
/set_gas_limit
.
Note that manual settings of gas limits do not interfere with bouncing behavior; messages will be bounced if sent in bounceable mode and contain enough money to pay for their processing and the creation of bounce messages.
Case 1:
If you send a bounceable message with 0.1 TON in the BaseChain that is accepted by a contract with a 1 TON balance, and the computation costs 0.005 TON, with forwarding fees of 0.001 TON, then the bounce message will contain 0.1 - 0.005 - 0.001
= 0.094
TON.
Case 2:
If in the same example, the computation cost is 0.5 TON (instead of 0.005 TON), there will be no bounce (the message balance would be 0.1 - 0.5 - 0.001 = -0.401
, thus no bounce), and the contract balance will be 1 + 0.1 - 0.5
= 0.6
TON.