int
- Not serializable. Use
intNor other numeric types.
intN
- Fixed N-bit signed integer
- TL-B:
intN - Stored using
{N} STI - Loaded using
{N} LDI
uintN
- Fixed N-bit unsigned integer
- TL-B:
uintN - Stored using
{N} STU - Loaded using
{N} LDU
coins
- Alias to
varuint16 - TL-B:
VarUInteger 16 - Stored using
STGRAMS - Loaded using
LDGRAMS
varintN (N = 16 or 32)
- Variable-length signed integer: 4 or 5 bits for
length + 8 * lenbit number - TL-B:
VarInteger {N} - Stored using
STVARINT{N} - Loaded using
LDVARINT{N}
varuintN (N = 16 or 32)
- Variable-length unsigned integer: 4 or 5 bits for
length + 8 * lenbit number - TL-B:
VarUInteger {N} - Stored using
STVARUINT{N} - Loaded using
LDVARUINT{N}
bool
- One bit:
0or1 - TL-B:
Bool - Stored using
1 STI - Loaded using
1 LDIresulting in0or-1
address
- Standard internal address (267 bits):
0b100 + workchain + hash - TL-B:
addr_std - Stored using
STSTDADDR - Loaded using
LDSTDADDR
address? (nullable)
- Internal address or none (2 or 267 bits):
00for null, otherwise an address - TL-B:
addr_noneoraddr_std - Stored using
STOPTSTDADDR - Loaded using
LDOPTSTDADDR
any_address
- Any valid TL-B address, from 2 to 523 bits
- TL-B:
MsgAddress - Stored using
STSLICE - Loaded using
LDMSGADDR
cell, Cell<T>
- A reference
- TL-B:
^Cell/^T - Stored using
STREF - Loaded using
LDREF
cell?, Cell<T>? (nullable)
- Maybe reference (
0or1+ref) - TL-B:
Maybe ^Cell/Maybe ^T - Stored using
STOPTREF - Loaded using
LDOPTREF
bitsN
- N bits
- TL-B:
bitsN - Stored using
STSLICE, preceded by a runtime check that the slice contains exactly N bits and zero references; the check can be turned off usingskipBitsNValidation = false. - Loaded using
LDSLICE/LDSLICEXfor N > 256
RemainingBitsAndRefs
- Represents the remainder of a slice when reading, and a raw slice when writing.
- TL-B:
Cell - Stored using
STSLICE - Loaded by copying the current slice and resetting the reader to an empty slice.
builder, slice
- Can be used for writing, but not for reading.
- Not recommended, as they do not reveal internal structure and have unpredictable size.
- Auto-generated TypeScript wrappers cannot parse them.
struct
If a struct has a prefix, it is written first. The fields are then serialized sequentially.
32-bit prefixes (opcodes)
By convention, all incoming and outgoing messages use 32-bit prefixes:Not only 32-bit prefixes
Declaring messages with opcodes does not differ from declaring ordinary structs. A prefix can have any bit width:0x000F— 16-bit prefix0x0F— 8-bit prefix0b010— 3-bit prefix0b00001111— 8-bit prefix
Asset is matched using the explicitly declared prefixes.
If a struct has a prefix, it is applied consistently in all contexts, both standalone and as part of a union:
Type aliases
A type alias is identical to its underlying type, unless a custom serializer is defined. To implement a “variadic string” encoded aslen + data:
ShortString can then be used as a regular type everywhere:
packToBuilder and unpackFromSlice are reserved for this purpose. Their signatures must match exactly as shown.
enum
The serialization type can be specified manually:
Role above, uint2 is sufficient to fit values 0, 1, 2:
enum Role: int8, any input value outside the range of defined enum variants, e.g., < 0 or > 2, triggers exception 5.
Values not explicitly listed in the enum definition are also rejected:
Nullable types T? (except address?)
- Often called
Maybe;0or1+T - TL-B:
(Maybe T) - Stored using
1 STI+IF… - Loaded using
1 LDI+IF…
address? is serialized as internal or none (2 or 267 bits):
00– null;- otherwise – a standard internal address.
Union types T1 | T2 | ...
T | nullis serialized as TL-BMaybe T.- If all
T_ihave prefixesstruct (0x1234) A, those prefixes are used. - Otherwise, the compiler generates a prefix tree automatically.
Manual serialization prefixes
If allT_i have manual prefixes, they are used:
A but not for B, the union A | B cannot be serialized.
Auto-generated prefix tree
IfT_i do not have manual prefixes, the compiler generates a prefix tree.
-
A two-component union
T1 | T2is serialized as TL-BEitherusing prefixes 0 and 1. Example:int32 | int64→0 + int32or1 + int64. -
For unions with more components, longer prefixes are generated. Example:
int32 | int64 | int128 | int256→00 / 01 / 10 / 11
- If
nullis present, it is assigned prefix 0, and all other variants use1 + tree:A|B|C|D|null→0 | 100+A | 101+B | 110+C | 111+D.
- If
nullis not present, variants are assigned sequentially:A|B|C→00+A | 01+B | 10+C.
00 + int801 + int1610 + int32
Tensors (T1, T2, ...)
Tensor components are serialized sequentially, akin to struct fields.
string
- Serialized as a reference: a string is a snake-encoded cell
- TL-B:
^Cell - Stored using
STREF - Loaded using
LDREF
array<T>
- Serializable when
Tis serializable, e.g.,array<int8>orarray<bool?>. - Binary format:
uint8length, followed by chained cell references (snake refs), each containing aboolflag for the next reference and serialized elements.
array<uint8> [1, 2, 3, 4, 5] can be packed into a single chunk with all 5 elements in a single reference, resulting in the following bitcode:
uint8is 5 (length)boolistrue(has ref)- ref
cell:boolisfalse(no next ref)0x0102030405(1, 2, 3, 4, 5)
ref 1 ref 2345, or ref 12 + ref 34 + ref 5, and so on. For example, ref 123 + ref 45 produces:
uint8is 5 (length)boolistrue(has ref)- ref
cell:boolistrue(has next ref)0x010203- ref
cell:boolisfalse(no next ref)0x0405
uint8 = 0, followed by a bool = false, which equates to nine zero bits.
The compiler precalculates chunk size to fit as many elements into a cell as possible. Client-side libraries can follow a simpler strategy — for example, write into a cell until there is space, then create a nested reference, repeating the process.
Shaped tuples [T1, T2, ...]
Shaped components are serialized sequentially: serialization is identical to tensors. But their nature is different: [T1, ...] are stored in a TVM tuple, whereas (T1, ...) act like N variables on a stack.
map<K, V>
- Maybe reference:
0for empty or1+reffor dictionary contents - TL-B:
HashmapE n X - Stored using
STDICT - Loaded using
LDDICT
Callables (...ArgsT) -> ResultT
- Callables cannot be serialized.
- Lambdas can be used within contract logic but cannot be serialized for off‑chain responses.
unknown
- Cannot be serialized. Prefer using
array<T>with serializableTinstead ofarray<unknown>(tuple).