> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-ton-storage.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Overall: serialization

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

A consolidated summary of how each Tolk type is serialized into TL-B–compatible binary data.

<Aside type="caution" title={"Low-level details"}>
  This page assumes prior knowledge of [TL-B](/languages/tl-b/overview)
  and [TVM](/tvm/overview).
  It is intended as a concise low‑level reference page.
</Aside>

## `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 LDI` resulting in 0 or -1

## `address`

* standard (internal) address; 267 bits: 0b100 + 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_none` or `addr_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 using `skipBitsNValidation = 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.

```tolk theme={null}
struct (0x12345678) A {
    a: int8
    b: cell?
}

fun demo() {
    val a: A = {
        a: 123,
        b: createEmptyCell(),
    };
    // 41 bits and 1 ref: opcode + int8 + '1' + empty ref
    a.toCell()
}
```

### 32-bit prefixes (opcodes)

By convention, all messages (incoming and outgoing) use 32-bit prefixes:

```tolk theme={null}
struct (0x7362d09c) TransferNotification {
    queryId: uint64
    // ...
}
```

### 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 prefix
* `0x0F` — 8-bit prefix
* `0b010` — 3-bit prefix
* `0b00001111` — 8-bit prefix

Example. Let's express the following TL-B scheme:

```tl-b theme={null}
asset_simple$001 workchain:int8 ptr:bits32 = Asset;
asset_booking$1000 order_id:uint64 = Asset;
// ...
```

In Tolk, use structures and union types:

```tolk theme={null}
struct (0b001) AssetSimple {
    workchain: int8
    ptr: bits32
}

struct (0b1000) AssetBooking {
    orderId: uint64
}

type Asset = AssetSimple | AssetBooking // | ...
```

When deserializing, `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):

```tolk theme={null}
AssetBooking.fromSlice(s)   // expecting '1000...' (binary)
AssetBooking{...}.toCell()  // '1000...'
```

## 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":

```
len: (## 8)        // 8 bits of len
data: (bits len)   // 0..255 bits of data
```

To express this, create a `type` and **define a custom serializer**:

```tolk theme={null}
type ShortString = slice

fun ShortString.packToBuilder(self, mutate b: builder) {
    val nBits = self.remainingBitsCount();
    b.storeUint(nBits, 8);
    b.storeSlice(self);
}

fun ShortString.unpackFromSlice(mutate s: slice) {
    val nBits = s.loadUint(8);
    return s.loadBits(nBits);
}
```

And just use `ShortString` as a regular type — everywhere:

```tolk theme={null}
tokenName: ShortString
fullDomain: Cell<ShortString>
```

Method names `packToBuilder` and `unpackFromSlice` are reserved for this purpose, their signatures must match exactly as shown.

## Enums

The serialization type can be specified manually:

```tolk theme={null}
// `Role` will be (un)packed as `int8`
enum Role: int8 {
    Admin,
    User,
    Guest,
}

struct ChangeRoleMsg {
    ownerAddress: address
    newRole: Role    // int8: -128 <= V <= 127
}
```

Otherwise, it is calculated automatically.
For `Role` above, `uint2` is sufficient to fit values `0, 1, 2`:

```tolk theme={null}
// `Role` will (un)packed as `uint2`
enum Role {
	  Admin,
	  User,
	  Guest,
}
```

Input values are validated during deserialization.
For `enum Role: int8` any (input\<0 || input>2) triggers exception 5 (integer out of range).

Non-range values are also validated:

```tolk theme={null}
enum OwnerHashes: uint256 {
    id1 = 0x1234,
    id2 = 0x2345,
    ...
}

// on serialization, just "store uint256"
// on deserialization, "load uint256" + throw 5 if v not in [0x1234, 0x2345, ...]
```

## Nullable types `T?` (except `address?`)

* often called "Maybe"; '0' or '1'+T
* TL-B `(Maybe T)`
* asm `1 STI` + IF ...
* asm `1 LDI` + IF ...

The exception: `address?` is serialized as "internal or none" (2/267 bits): null -> '00', otherwise -> address.

## Union types `T1 | T2 | ...`

Rules for union type serialization:

* `T | null` is TL/B `Maybe T` ('0' or '1'+T)
* if all `T_i` have prefixes `struct (0x1234) A`, they are used
* otherwise, a compiler auto-generates a prefix tree

### Manual serialization prefixes

If all `T_i` have manual prefixes, they are used:

```tolk theme={null}
struct (0b001)  AssetSimple   { /* body1 */ }
struct (0b1000) AssetBooking  { /* body2 */ }
struct (0b01)   AssetNothing  {}

struct Demo {
    // '001'+body1 OR '1000'+body2
    e: AssetSimple | AssetBooking
    // '001'+body1 OR '1000'+body2 OR '01'
    f: AssetSimple | AssetBooking | AssetNothing
}
```

If a prefix exists for `A` but not for `B`, the union `A | B` cannot be serialized: it seems like a bug in code.

### Auto-generated prefix tree

If `T_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 `null` exists, 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
* if no `null`, just distributed sequentially
  * example: `A|B|C` => 00+A | 01+B | 10+C

```tolk theme={null}
struct WithUnion {
    f: int8 | int16 | int32
}
```

This field will be packed as: '00'+int8 OR '01'+int16 OR '10'+int32.
On deserialization, the same format is expected (prefix '11' will throw an exception).

Same for structs without a manual prefix:

```tolk theme={null}
struct A { ... }    // 0x... prefixes not specified
struct B { ... }
struct C { ... }

struct WithUnion {
    // auto-generated prefix tree: 00/01/10
    f: A | B | C
    // with null, like Maybe<A|B>: 0/10/11
    g: A | B | null
    // even this works; when '11', a ref exists
    h: A | int32 | C | cell
}
```

## 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](/languages/tl-b/complex-and-non-trivial-examples#hashmap))
* 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

* [Overall: TVM stack representation](/languages/tolk/types/overall-tvm-stack)
* [Type system overview](/languages/tolk/types/list-of-types)
* [Automatic serialization](/languages/tolk/features/auto-serialization)
