BoC (bag of cells)
Serialisation format for a tree of TON cells. Used to ship contract code, message bodies, and proofs over the wire — both binary and base64-encoded forms exist.
Aliases: bag of cells, boc format
BoC — short for Bag of Cells — is the serialisation format TON uses to ship cell trees over the wire and store them on disk. Whenever you see a “cell” leave the TVM — to be sent across the network, embedded in a transaction, exposed to a wallet UI — it is encoded as a BoC.
What it actually is
A BoC is a deterministic, length-prefixed binary blob that contains:
- A header with version flags, hash settings, root cell count, and total cell count.
- A list of unique cells in the tree, deduplicated. Each cell appears once, even if multiple parents reference it.
- For each cell, descriptor bytes (data length, reference count, exotic flag), the data bits, and the indices of its referenced cells.
- Optional cached hashes and depths so a verifier doesn’t have to recompute the tree from scratch.
The deduplication is important: a cell tree with shared subtrees compresses much better as a BoC than as a naive recursive serialisation.
Why “bag”
Even though the cells form a DAG with one or more roots, the on-disk representation is a flat list — a “bag” — with explicit references between entries. Decoding rebuilds the tree by following indices.
Where you encounter BoCs
- Contract bytecode. A FunC/Tact/Tolk source file compiles to a BoC of TVM bytecode; that BoC is what gets deployed.
- Message bodies. External messages (signed by a wallet, broadcast to the network) are BoCs.
- State init. When deploying a contract, the
StateInitpackaging — code + data — is a BoC. - Block proofs. Light clients verify state by walking BoC-encoded Merkle proofs.
- Explorer URLs. TonScan and Tonviewer often expose a “raw cell” link that downloads the BoC for a transaction or a contract.
Encodings
A BoC is binary. To put it in JSON, paste it into a CLI flag, or send it through a JSON-RPC API, you encode it as base64 (or sometimes hex). The two main forms you see in the wild:
te6cck...— raw base64, common in TON Center / TON API responses.b5ee9c72...— hex, common in raw cell dumps and explorer downloads.
Both decode to the same byte sequence; the magic bytes at the start identify the format.
Determinism
A given cell tree always serialises to the same BoC, byte-for-byte, given the same flag settings. That determinism is critical:
- It lets two nodes hash the same cell tree and get the same answer.
- It lets users and tools verify on-chain content by re-serialising and comparing hashes.
- It is what makes Merkle proofs work — the verifier can recompute the parent hash from the children.
Practical notes for developers
- Most BoC handling is done through libraries (
@ton/core,pytoniq,ton4j). Hand-rolling BoC parsing is rarely necessary. - When debugging a “wrong message” issue, dump the message body as a BoC and inspect it in TonScan’s cell viewer — the structure is usually obvious.
- Cell hashes live alongside the data in the BoC; you don’t recompute them on every read.
Compared with other formats
BoC is to TON what RLP is to Ethereum: a low-level serialisation that the protocol commits to and that all tools can decode. It’s more verbose than something like CBOR but built specifically for the cell-DAG model, with native support for shared subtrees and partial Merkle proofs — features that generic formats cannot express compactly.