int
Not serializable; use intN or other numeric types instead.
intN
- fixed N-bit signed integer
- TL-B
intN - stored via
{N} STI - loaded via
{N} LDI
uintN
- fixed N-bit unsigned integer
- TL-B
uintN - stored via
{N} STU - loaded via
{N} LDU
coins
- alias to
varuint16 - TL-B
VarUInteger 16 - stored via
STGRAMS - loaded via
LDGRAMS
varintN for N = 16 or N = 32
- variadic signed integer: 4/5 bits for len + 8*len bit number
- TL-B
VarInteger {N} - stored via
STVARINT{N} - loaded via
LDVARINT{N}
varuintN for N = 16 or N = 32
- variadic unsigned integer: 4/5 bits for len + 8*len bit number
- TL-B
VarUInteger {N} - stored via
STVARUINT{N} - loaded via
LDVARUINT{N}
bool
- one bit: ‘0’ or ‘1’
- TL-B
Bool - stored via
1 STI - loaded via
1 LDIresulting in 0 or -1
address
- standard (internal) address; 267 bits: ‘100’ + workchain + hash
- TL-B
addr_std - stored via
STSTDADDR - loaded via
LDSTDADDR
address? (nullable)
- internal or none address; 2 or 267 bits: null -> ‘00’, otherwise -> address
- TL-B
addr_noneoraddr_std - stored via
STOPTSTDADDR - loaded via
LDOPTSTDADDR
any_address
- any valid TL-B address, from 2 to 523 bits
- TL-B
MsgAddress - stored via
STSLICE - loaded via
LDMSGADDR
cell and Cell<T>
- a reference
- TL-B
^Cell/^T - stored via
STREF - loaded via
LDREF
cell? and Cell<T>? (nullable)
- maybe reference (‘0’ or ‘1’+ref)
- TL-B
Maybe ^Cell/Maybe ^T - stored via
STOPTREF - loaded via
LDOPTREF
bitsN
- just N bits
- TL-B
bitsN - stored via
STSLICE, preceded by a runtime check that the slice contains exactly N bits and zero references; this check can be disabled usingskipBitsNValidation = false. - loaded via
LDSLICE/LDSLICEX(for N > 256)
RemainingBitsAndRefs
- the remainder of a slice when reading, and a raw slice when writing
- TL-B
Cell - stored via
STSLICE - loaded by copying current slice and assigning current to an empty one
builder and slice
Can be used for writing, not for reading.
Not recommended, because they do not reveal internal structure and have unpredictable size.
Auto-generated TypeScript wrappers are not able to parse them.
Structures
If a struct has a prefix, it’s written first. Then its fields are serialized sequentially.32-bit prefixes (opcodes)
By convention, all messages (incoming and outgoing) use 32-bit prefixes:Not only 32-bit prefixes
Declaring messages with opcodes does not differ from declaring any other structs. Prefixes can be of any width:0x000F— 16-bit prefix0x0F— 8-bit prefix0b010— 3-bit prefix0b00001111— 8-bit prefix
Asset will follow manually provided prefixes, see “union types” below.
If a structure has a prefix, it is used consistently in all contexts (both standalone and within unions):
Type aliases
A type alias is identical to its underlying type unless a custom serializer is defined. Example. Need to implement a “variadic string” encoded as “len + data”:type and define a custom serializer:
ShortString as a regular type — everywhere:
packToBuilder and unpackFromSlice are reserved for this purpose, their signatures must match exactly as shown.
Enums
The serialization type can be specified manually:Role above, uint2 is sufficient to fit values 0, 1, 2:
enum Role: int8 any (input<0 || input>2) triggers exception 5 (integer out of range).
Non-range values are also validated:
Nullable types T? (except address?)
- often called “Maybe”; ‘0’ or ‘1’+T
- TL-B
(Maybe T) - asm
1 STI+ IF … - asm
1 LDI+ IF …
address? is serialized as “internal or none” (2/267 bits): null -> ‘00’, otherwise -> address.
Union types T1 | T2 | ...
Rules for union type serialization:
T | nullis TL/BMaybe T(‘0’ or ‘1’+T)- if all
T_ihave prefixesstruct (0x1234) A, they are used - otherwise, a compiler auto-generates a prefix tree
Manual serialization prefixes
If allT_i have manual prefixes, they are used:
A but not for B, the union A | B cannot be serialized: it seems like a bug in code.
Auto-generated prefix tree
IfT_i don’t have manual prefixes, the compiler generates a prefix tree.
A two-component union T1 | T2 is TL/B Either (prefixes 0/1).
For example, int32 | int64 becomes (‘0’+int32 or ‘1’+int64).
Multi-component unions have longer prefixes.
For example int32 | int64 | int128 | int256 forms a tree 00/01/10/11.
General rules:
- if
nullexists, it’s 0, all others are 1+tree (“maybe others”)- example:
A|B|C|D|null=> 0 | 100+A | 101+B | 110+C | 111+D
- example:
- if no
null, just distributed sequentially- example:
A|B|C=> 00+A | 01+B | 10+C
- example:
Tensors (T1, T2, ...)
Tensor components are serialized sequentially, in the same manner as structure fields.
tuple and typed tuples
Tuples cannot be serialized; serialization is not implemented for tuples.
But tuples can be returned from get methods, since contract getters work via the stack, not serialization.
map<K, V>
- maybe reference: ‘0’ (empty) or ‘1’+ref (dict contents)
- TL-B
HashmapE n X(follow hashmaps in TL-B) - stored via
STDICT - loaded via
LDDICT
Callables (...ArgsT) -> ResultT
Callables cannot be serialized.
Lambdas may be used within contract logic but cannot be serialized for off‑chain responses.
See also: