Skip to main content

Messages TL-B schemes

This section provides a detailed explanation of the TL-B schemes used for messages.

Message TL-B

TL-B

The main TL-B scheme for messages is defined as a combination of several nested structures.

message$_ {X:Type} info:CommonMsgInfo
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = Message X;

message$_ {X:Type} info:CommonMsgInfoRelaxed
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = MessageRelaxed X;

_ (Message Any) = MessageAny;
  • Message X refers to the standard message structure.
  • MessageRelaxed X is a variant that uses a CommonMsgInfoRelaxed body.
  • Message Any is a union of both structures.

The message structure is unified using X:Type, which in this context represents a cell. According to TL-B rules, all data can be stored within a single cell—if it fits within 1023 bits—or distributed across references using the caret symbol ^.

A serialized Message X is placed into the action list using the FunC method send_raw_message(). The smart contract then executes this action, and the message is sent.

Definition of explicit serialization

To construct valid binary data according to a TL-B structure, serialization must be performed as defined recursively for each type. To serialize a Message X, you must also know how to serialize nested structures like StateInit, CommonMsgInfo, etc.

Each nested structure is defined in a separate TL-B scheme, which must be referenced and resolved recursively. This continues until the serialization of the top-level structure becomes explicit—that is, every bit is defined by a boolean or a bit-representable type, e.g., bits, uint, varuint.

Structures not commonly used in regular development are marked with an asterisk * in the Type column. For example, *Anycast is typically omitted during serialization.

message$_

This is the top-level TL-B scheme for messages, referred to as Message X:

message$_ {X:Type} info:CommonMsgInfo
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = Message X;
StructureTypeRequiredDescription
message$_ConstructorDefined according to the constructor rule. The empty tag $_ indicates that no bits are added initially.
infoCommonMsgInfoRequiredContains detailed message properties such as destination and value. It is always stored in the message's root cell.
initStateInitOptionalThe general structure is used in TON to initialize new contracts. It can be placed in either a cell reference or the root cell.
bodyXRequiredMessage payload. It can be placed in either a cell reference or the root cell.
nothing$0 {X:Type} = Maybe X;
just$1 {X:Type} value:X = Maybe X;
left$0 {X:Type} {Y:Type} value:X = Either X Y;
right$1 {X:Type} {Y:Type} value:Y = Either X Y;

Recall how Maybe and Either work—we can serialize different cases:

  • [CommonMsgInfo][10][StateInit][0][X] - a Message X fully serialized into a single cell.


  • [CommonMsgInfo][11][^StateInit][1][^X] - a Message X with references.


CommonMsgInfo TL-B

CommonMsgInfo

CommonMsgInfo is a set of parameters that define how the message will be delivered on the TON blockchain.

//internal message
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddressInt dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfo;

//external incoming message
ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt
import_fee:Grams = CommonMsgInfo;

//external outgoing message
ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfo;

int_msg_info$0

int_msg_info represents an internal message, meaning it can only be sent between smart contracts. Use case: regular cross-contract communication within the TON blockchain.

nanograms$_ amount:(VarUInteger 16) = Grams;
//internal message
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddressInt dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
StructureTypeRequiredDescription
int_msg_info$0ConstructorRequiredThe $0 tag indicates that the CommonMsgInfo begins with a 0 bit in serialization, denoting an internal message.
ihr_disabledBoolRequiredFlag indicating whether hypercube routing (IHR) is disabled.
bounceBoolRequiredSpecifies whether the message should be bounced if an error occurs during processing. If set to 1, the message is bounceable.
bouncedBoolRequiredIndicates that the message is a result of a bounce.
srcMsgAddressIntRequiredThe sender's smart contract address.
destMsgAddressIntRequiredThe recipient's smart contract address.
valueCurrencyCollectionRequiredDescribes the currency details, including the total funds transferred with the message.
ihr_feeVarUInteger 16RequiredFee for delivering the message using hypercube routing.
fwd_feeVarUInteger 16RequiredValidators set the fee for forwarding the message.
created_ltuint64RequiredLogic time of the message, used by validators to order actions in smart contracts.
created_atuint32RequiredUNIX timestamp indicating when the message was created.

ext_in_msg_info$10

ext_in_msg_info$10 – represents an external incoming message. This message is sent from the off-chain world to a smart contract. Use case: a wallet application sending a request to a wallet contract.

nanograms$_ amount:(VarUInteger 16) = Grams;
//external incoming message
ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt
import_fee:Grams = CommonMsgInfo;
StructureTypeRequiredDescription
ext_in_msg_info$10ConstructorRequiredThe $10 tag indicates that the CommonMsgInfo begins with 10 bits in serialization, denoting an external incoming message.
ihr_disabledBoolRequiredFlag indicating whether hyper routing is disabled. Currently, it is always set to true.
srcMsgAddressExtRequiredThe external sender’s address.
destMsgAddressIntRequiredThe destination smart contract address.
import_feeVarUInteger 16RequiredThe fee for executing and delivering the message.

ext_out_msg_info$11

ext_out_msg_info$11 – represents an external outgoing message. This message is sent from a smart contract to the off-chain world. Use case: logs.

//external outgoing message
ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
StructureTypeRequiredDescription
ext_out_msg_info$11ConstructorRequiredThe $11 tag indicates that the CommonMsgInfo begins with 11 bits in serialization, denoting an external outgoing message.
srcMsgAddressIntRequiredThe sender’s smart contract address.
destMsgAddressExtRequiredThe external destination address for the message.
created_ltuint64RequiredLogic times of the message, assigned by the validator. Used for ordering actions in the smart contract.
created_atuint32RequiredUNIX timestamp representing when the message was created.

StateInit TL-B

StateInit – delivers initial data to a contract during its deployment.

_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)
code:(Maybe ^Cell) data:(Maybe ^Cell)
library:(HashmapE 256 SimpleLib) = StateInit;
StructureTypeRequiredDescription
split_depth(## 5)OptionalA parameter for high-load contracts that defines the behavior of splitting into multiple instances across different shards. Currently, StateInit is used without it.
specialTickTock*OptionalA structure used for invoking smart contracts in every new blockchain block. Available only in the MasterChain and not typically used in regular user contracts.
codeCellOptionalThe contract's serialized code.
dataCellOptionalThe initial data for the contract.
libraryHashmapE 256 SimpleLib*OptionalCurrently, StateInit is used without libraries.

General detailed explanations for Hashmaps.

MsgAddressExt TL-B

addr_none$00 = MsgAddressExt;
addr_extern$01 len:(## 9) external_address:(bits len)
= MsgAddressExt;

MsgAddress is a scheme for various serializations of addresses. The structure depends on the participant, either off-chain or a smart contract, sending the message. Different structures are employed based on whether the message comes from an off-chain participant or a smart contract.

addr_none$00

addr_none$00 defines a null address for an off-chain participant. This indicates that an external message can be sent to a contract without specifying a unique sender's address.

addr_none$00 = MsgAddressExt;
StructureTypeRequiredDescription
addr_none$00ConstructorRequiredThe $00 tag in serialization indicates that MsgAddressExt starts with 00 bits. This signifies that the entire external address is 00.

addr_extern$01

addr_extern$01 len:(## 9) external_address:(bits len)
= MsgAddressExt;
StructureTypeRequiredDescription
addr_extern$01ConstructorRequiredThe $01 tag in serialization indicates that MsgAddressExt starts with 01 bits and describes an external address.
len## 9RequiredRepresents an unsigned N-bit number, similar to uintN.
external_address(bits len)RequiredA bitstring address, where the length of the address equals the previously defined len.

MsgAddressInt TL-B

addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;

addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;

addr_std$10

addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
StructureTypeRequiredDescription
addr_std$10ConstructorRequiredThe $10 tag in serialization indicates that MsgAddressInt starts with 10 bits and describes an internal address.
anycastAnycast*OptionalRepresents additional address data. Currently not used in ordinary internal messages.
workchain_idint8RequiredThe WorkChain where the smart contract of the destination address is located. Currently, this value always equals zero.
address(bits256)RequiredThe smart contract account ID number.

addr_var$11

addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
StructureTypeRequiredDescription
addr_var$11ConstructorRequiredThe $11 tag indicates that in the serialization of MsgAddressInt, the address starts with 11 bits, representing an internal contract address.
anycastAnycast*OptionalAdditional address data is not currently used in regular internal messages.
addr_len## 9RequiredSame as uintN – represents an unsigned N-bit number.
workchain_idint32RequiredThe WorkChain is where the smart contract for the destination address is located. Currently, this is always set to zero.
address(bits256)RequiredThe payload address (this could be the account ID).

Basic used types

CurrencyCollection

nanograms$_ amount:(VarUInteger 16) = Grams;
currencies$_ grams:Grams other:ExtraCurrencyCollection
= CurrencyCollection;
StructureTypeRequiredDescription
currencies$_ConstructorRequiredThe $_ empty tag indicates that no bits are added at the beginning during the serialization of CurrencyCollection.
grams(VarUInteger 16)RequiredRepresents the message value, expressed in nanoTons.
otherExtraCurrencyCollectionOptionalExtraCurrencyCollection is a dictionary intended for additional, typically empty currencies.
  • ExtraCurrencyCollection is a complex type usually written as an empty dictionary in messages.

VarUInteger n

var_uint$_ {n:#} len:(#< n) value:(uint (len * 8))
= VarUInteger n;
var_int$_ {n:#} len:(#< n) value:(int (len * 8))
= VarInteger n;
StructureTypeRequiredDescription
var_uint$_ConstructorRequiredThe var_uint$_ is an empty tag, indicating that no bits are added at the beginning of CurrencyCollection serialization.
lenuintNRequiredSpecifies the bit-length used to encode the next value.
value(uint (len * 8))OptionalAn optional unsigned integer encoded in (len * 8) bits.

Message example

Regular func internal message

  var msg = begin_cell()
.store_uint(0, 1) ;; tag
.store_uint(1, 1) ;; ihr_disabled
.store_uint(1, 1) ;; allow bounces
.store_uint(0, 1) ;; not bounced itself
.store_slice(source)
.store_slice(destination)
;; serialize CurrencyCollection (see below)
.store_coins(amount)
.store_dict(extra_currencies)
.store_coins(0) ;; ihr_fee
.store_coins(fwd_value) ;; fwd_fee
.store_uint(cur_lt(), 64) ;; lt of transaction
.store_uint(now(), 32) ;; unixtime of transaction
.store_uint(0, 1) ;; no init-field flag (Maybe)
.store_uint(0, 1) ;; inplace message body flag (Either)
.store_slice(msg_body)
.end_cell();

Regular func message in short form

Validators always overwrite message parts, which can be skipped and filled with zero bits. The message's sender is also skipped and serialized as addr_none$00.

  cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(amount)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_slice(message_body)
.end_cell();