Accept Message Effects
accept_message
and set_gas_limit
may cause not that straightforward effects when doing exactly what it's said in the stdlib reference.
External messages
External messages are processed as follows:
- The
gas_limit
is set togas_credit
(ConfigParam 20 and ConfigParam 21), which is equal to 10k gas. - During the spending of those credits, a contract should call
accept_message
toset_gas_limit
, indicating that it is ready to pay fees for message processing. - If
gas_credit
is reached or computation is finished, andaccept_message
is not called, the message will be completely discarded (as if it never existed at all). - Otherwise, a new gas limit, equal to
contract_balance/gas_price
(in the case ofaccept_message
) or a custom number (in the case ofset_gas_limit
), will be set; after the transaction ends, full computation fees will be deducted from the contract balance (in this way,gas_credit
is indeed credit, not free gas).
Note that if, after accept_message
, some error is thrown (either in ComputePhase or ActionPhase), the transaction will be written to the blockchain, and fees will be deducted from the contract balance. However, storage will not be updated, and actions will not be applied, as is the case in any transaction with an error exit code.
As a result, if the contract accepts an external message and then throws an exception due to an error in the message data or the sending of an incorrectly serialized message, it will pay for processing but will have no way of preventing message replay. The same message will be accepted by the contract over and over until it consumes the entire balance.
Internal message
By default, when a contract receives an internal message, the gas limit is set to message_balance
/gas_price
. In other words, the message pays for its processing. By using accept_message
/set_gas_limit
, the contract may change the gas limit during execution.
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.
For instance, 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 a message fee of 0.001 TON, then the bounce message will contain 0.1 - 0.005 - 0.001
= 0.094
TON.
If in the same example, the computation cost is 0.5 (instead of 0.005), 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.