Cell (TVM data structure)
Atomic data unit in TON. Holds up to 1023 bits of data and up to 4 references to other cells. Every contract storage and message body is a tree of cells.
Aliases: ton cell, tvm cell
A cell is the fundamental data structure of the TON Virtual Machine. Everything on TON — contract code, contract storage, message bodies, jetton metadata, NFT content, transaction proofs — is a tree of cells.
What’s inside a cell
Each cell carries:
- Up to 1023 bits of payload data.
- Up to 4 references to other cells.
- A header that records lengths, depth, and a SHA-256 hash of the contents.
That’s it. No types, no schemas — those are layered on top via TL-B (a serialisation language) or by the contract reading the cell.
Immutability and DAG structure
Cells are immutable: once built and hashed, they cannot be modified. To “change” a cell you build a new one and update the reference. This makes cells form a directed acyclic graph (DAG):
- Circular references are forbidden (and impossible in practice — computing a hash that includes itself is impossible).
- The same cell can be referenced from multiple parents — the DAG can share subtrees, which saves space when cells are duplicated.
Every cell has a deterministic SHA-256 hash that depends on its data, its references’ hashes, and a few descriptor bits. This is what makes cells the building block of Merkle proofs.
Reading and writing
Contracts don’t manipulate cells in place. Instead:
- Builders are write cursors. You start with
begin_cell()(FunC) orbeginCell()(TypeScript libs), append data withstore_uint,store_slice,store_ref, and callend_cell()to materialise the cell. - Slices are read cursors. You start with
begin_parse()on a cell, read fields withload_uint,load_slice,load_ref.
That cursor-based model is one of the things that makes TON contract code feel different from Solidity. There is no mapping[address] — there are dictionaries (HashmapE) that compile down to cell trees, walked via slices.
Cell types
- Ordinary cells — the kind described above; what 99% of contract data looks like.
- Exotic cells — special types identified by a leading byte (
0x01pruned branch,0x02library reference,0x03Merkle proof,0x04Merkle update). They’re used by the protocol itself for proofs and code libraries; ordinary developers rarely build them by hand.
Storage and gas implications
- Reading a cell costs gas; reading a referenced cell (“loading a ref”) also costs gas. Deeply nested data is expensive.
- Storage fees scale with the total cell tree size. A contract that stores a giant dictionary pays storage fees on every cell.
- Cells encourage compact encoding: it is normal to pack 5–10 fields into a single cell’s bit space rather than spreading them across many cells.
Why this design
Cells are the protocol’s answer to two requirements at once:
- Cheap Merkle proofs — anyone can prove that a piece of state (a balance, a nonce) belongs to a contract by handing over the path of cell hashes from the value up to the contract’s root.
- Sharding-friendly state — because state is a hash-rooted tree, a sharded chain can verify another shard’s state with a small proof, no full node needed.
The trade-off is developer ergonomics: working with cells, slices, and builders is more low-level than typed Solidity structs, and it takes a while to internalise. Higher-level languages (Tact, Tolk) hide most of this with generated parsers/serialisers.