Skip to main content
Internal messages are the messages sent from a contract to an arbitrary account. They are the most common type of a message.

After processing

The contents of an internal message after it was processed are as follows:
int_msg_info$0
    ihr_disabled:Bool
    bounce:Bool
    bounced:Bool
    src:MsgAddressInt
    dest:MsgAddressInt
    value:CurrencyCollection
    extra_flags:(VarUInteger 16)
    fwd_fee:Grams
    created_lt:uint64
    created_at:uint32
= CommonMsgInfo;

message$_
    {X:Type}
    info:CommonMsgInfo
    init:(Maybe (Either StateInit ^StateInit))
    body:(Either X ^X)
= Message X;
  • ihr_disabled — unused, always set to true.
  • bounce — whether the message is bounceable.
  • bounced — whether the message has been bounced.
  • src — address of the contract that sent the message.
  • dest — address of the account that received the message.
  • value — amount of Toncoin and extra-currency attached to the message.
  • extra_flags — used with the new bounce format.
  • fwd_fee — fee charged for forwarding the message.
  • created_lt — logical time when the message was created.
  • created_at — unix time when the message was created.

Before processing

When a contract sends a message, the requirements for the structure above are relaxed.
int_msg_info$0
    ihr_disabled:Bool
    bounce:Bool
    bounced:Bool
    // NB! different type
    src:MsgAddress
    dest:MsgAddressInt
    value:CurrencyCollection
    extra_flags:(VarUInteger 16)
    fwd_fee:Grams
    created_lt:uint64
    created_at:uint32
= CommonMsgInfoRelaxed;

message$_
    {X:Type}
    info:CommonMsgInfoRelaxed
    // NB! actually StateInitWithLibs
    init:(Maybe (Either StateInit ^StateInit))
    body:(Either X ^X)
= MessageRelaxed X;
_
    fixed_prefix_length:(Maybe (## 5))
    special:(Maybe TickTock)
    code:(Maybe ^Cell)
    data:(Maybe ^Cell)
    library:(HashmapE 256 SimpleLib)
= StateInitWithLibs;
The process of transforming the relaxed version of the structure into the strict version occurs in the action phase and is performed by the handler of send message actions. This action rewrites some fields of the structure with correct values and validates the StateInit field against the StateInitWithLibs type.

Deploy

It is possible to simultaneously send both the payload in the body field and the StateInit in the init field to initialized the contract and process the payload in the same transaction.

Message value

The message may set value field that tells to transfer Toncoin and extra-currency to the recipient of the message. The actually transferred amount depends on the value of this field and a send mode.

Bounces

A bounce message is used to inform the sender that handling of their message failed. It is sent automatically to a sender when
  • there is enough Toncoin to send it left from handling the failed message,
  • and the message is bounceable,
  • and when either

Default bounce

If the bounce flag is set to true, the message is bounceable. If the bounce conditions are met, the bounce message is produced from the failed message with the following transformation:
  • src and dest fields are swapped.
  • The bounced flag is set to true to tell it’s the bounce message.
  • The bounce flag is set to false to prevent infinite loop of bouncing messages until no Toncoin is left to spend.
  • body is replaced with the concatenation of 32 bits equal to one (0xffffffff) and the first 256 bits of the old body. The new body is stored in the message in-place, with left of the Either.
This message is then sent to the src address of the original message.

New bounce format

The default bounce format has a flaw, that its body is too small to store even an internal address, and thus has limited usability for real-world applications. A new bounce format was introduced to address this issue. Using the extra_flags field, it is possible to change how the new body will be constructed. All other transformations remain the same.
  • If (extra_flags & 1) = 1 the new bounce format is enabled. The bounced message now contains the root cell of the body of the failed message, with all the refs removed from it.
    • If (extra_flags & 2) = 2 is also set, the bounced message contains the entire body of the original message, without removing any refs.
All other bits in extra_flags are reserved for future use. When a message in new bounce format is bounced, the bounce message body has the following format (new_bounce_body):
_
    value:CurrencyCollection
    created_lt:uint64
    created_at:uint32
= NewBounceOriginalInfo;

_
    gas_used:uint32
    vm_steps:uint32
= NewBounceComputePhaseInfo;

// NB! 0xfffffffe is different from the old 0xffffffff
new_bounce_body#fffffffe
    original_body:^Cell
    original_info:^NewBounceOriginalInfo
    bounced_by_phase:uint8
    exit_code:int32
    compute_phase:(Maybe NewBounceComputePhaseInfo)
= NewBounceBody;
  • original_body — the cell that contains the body of the original message. If extra_flags & 2 then the whole body is returned; otherwise only the root without refs is included.
  • original_info — the value, lt, and Unix time of the original message.
  • bounced_by_phase:
    • 0 - compute phase was skipped. exit_code denotes the skip reason:
      • exit_code = -1 — no state (an account is uninit or frozen, and no StateInit is present in the message).
      • exit_code = -2 — bad state (an account is uninit or frozen, and StateInit in the message has the wrong hash).
      • exit_code = -3 — no gas.
      • exit_code = -4 — account is suspended.
    • 1 — compute phase failed. exit_code is the value from the compute phase.
    • 2 — action phase failed. exit_code is the value from the action phase.
  • exit_code — 32-bit exit code, see above.
  • compute_phase — exists if it was not skipped, i.e., when bounced_by_phase is not 0.
  • gas_used — same as gas_used of TrComputePhase of the transaction.
  • vm_steps — same as vm_steps of TrComputePhase of the transaction.
The bounced message has the same 0th and 1st bits in extra_flags as the original message. The rest of the bits are set to zero.