Messages and transactions overview
Messages
Messages are objects of the following structure:
message$_
{X:Type}
info:CommonMsgInfo
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X)
= Message X;initis an optional field ofStateInittype used to initialize the contract state, stored either in-place or in a ref of the cell with a message.bodyis the actual message content that can be stored either in-place or in a reference. Typically, it is the payload of the message that will be read by the receiver.infodescribes the type of the message, and fields specific to messages of this type:- Internal messages are messages from one contract to another.
- Incoming external messages are messages from the outside world to the contract.
- Outbound external messages are messages from the contract to the outside world. They can be interpreted as logs.
Transactions
A transaction is a record that stores the state changes of a contract. A contract's state cannot be changed without a transaction. When a contract processes a message, a transaction may occur as the result of its processing.
- When an internal message is processed, a transaction is always created.
- When an incoming external message is processed, a transaction is created only if the contract accepts the message.
- When an outbound external message is processed, a transaction is never created, because outbound external messages can't change contract state.
However, a transaction may be created independently of message processing by
- tick-tock transactions,
- split-prepare transactions,
- split-install transactions,
- storage-tx transactions.
Each transaction has the following structure:
transaction$0111
account_addr:bits256
lt:uint64
prev_trans_hash:bits256
prev_trans_lt:uint64
now:uint32
outmsg_cnt:uint15
orig_status:AccountStatus
end_status:AccountStatus
^[
in_msg:(Maybe ^(Message Any))
out_msgs:(HashmapE 15 ^(Message Any))
]
total_fees:CurrencyCollection
state_update:^(HASH_UPDATE Account)
description:^TransactionDescr
= Transaction;Transactions implement the concept of AccountChain described in the TON Blockchain whitepaper. Each account state can be interpreted as a separate blockchain, so transactions follow a strict order defined by the prev_trans_hash field. Thanks to the TON consensus protocol, a transaction becomes final when the first masterchain block references it by storing the hash of the corresponding ShardChain state, which in turn stores the hash of the AccountChain state.
Because transactions form the AccountChain, each one carries a logical timestamp, lt, that strictly increases with every new transaction of the account. The now field stores the Unix time when the transaction was created.
The state_update field is a Merkle update that captures the difference between the previous and current state of the account. The contract status before and after the transaction is duplicated for convenience.
Other fields, such as in_msg, out_msgs, and outmsg_cnt, relate to the messages processed and emitted during the transaction. A trace may start from a transaction rather than a message, in which case in_msg is Nothing. However, a trace cannot continue without messages: if it contains n transactions it must contain at least n-1 messages. Consequently, a trace can include at most one non-ordinary transaction, because messages can trigger only an ordinary transaction.
The total_fees field stores the total fees paid by the transaction. Its type supports extra currencies, but blockchain fees are charged only in Gram.
Message queues
A shard's outbound queue stores internal messages awaiting delivery. A separate dispatch queue stores deferred outgoing messages until they can be processed.
The dispatch queue groups messages by sender account. Each account queue indexes messages by their 64-bit created_lt and stores a 48-bit message count. Empty account queues are omitted.
Account queues and dictionary augmentation data also carry total_balance:CurrencyCollection. This balance sums the deferred messages' value and fwd_fee, including any extra currencies. The augmentation stores the minimum created_lt and the aggregate balance for its subtree.
The block.tlb schema includes legacy and balance-carrying constructors, with legacy ones marked by the suffix _old:
// Legacy
account_dispatch_queue_old$1
messages:^(Hashmap 64 EnqueuedMsg) count:uint48 = AccountDispatchQueue;
// Since v2026.10
account_dispatch_queue$000
messages:^(Hashmap 64 EnqueuedMsg) count:uint48
total_balance:CurrencyCollection = AccountDispatchQueue;
// Legacy
dispatch_queue_aug_old$0
min_created_lt:uint63 = DispatchQueueAugData;
// Since v2026.10
dispatch_queue_aug$10
min_created_lt:uint64
total_balance:CurrencyCollection = DispatchQueueAugData;
// Queue
_ (HashmapAugE 256 AccountDispatchQueue DispatchQueueAugData) = DispatchQueue;In legacy augmentation data, the $0 tag followed by uint63 occupies the same 64 bits as the earlier min_created_lt with its high bit unset. The queue reads both formats and defines their balance calculation.