# Cells (https://docs-dmpho5eos-ton-core-docs.vercel.app/llms/foundations/serialization/cells/content.md)



## Basic structure [#basic-structure]

The TON Virtual Machine (TVM) memory, persistent storage, and smart contract code consist of cells. In turn, each cell consists of

* up to 1023 bits;
* up to 4 references to other cells.

<Callout>
  Circular references are forbidden and cannot be created, because computing [cryptographic hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function) of data that contains the same hash is impossible.
</Callout>

In this way, all cells are kept in TVM memory and persistent storage
constitute a [directed acyclic graph (DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph).

From the perspective of low-level cell operations, these data bits and cell references
are not intermixed. In other words, a cell essentially is a couple consisting of
a list of up to 1023 bits and a list of up to four cell references, without prescribing an
order in which the references and the data bits should be deserialized, even though TL-B
schemes appear to suggest such an order.

## Kinds of cells [#kinds-of-cells]

There are two kinds of cells: *ordinary* and *exotic*. The former are the simplest and most commonly used flavor of cells, which can
only contain data and references, while the latter are used for special purposes only. They sometimes appear in actual representations of
blocks and other data structures on TON Blockchain. Their memory layouts and purposes differ significantly from ordinary cells.

From the low-level perspective, ordinary and exotic cells can be distinguished
by a special 1-bit flag stored outside the main 1,023 bits and read by TVM at runtime. Users cannot read this flag directly.

TVM can support up to 256 different types of exotic cells, each identified by a special 8-bit type identifier stored in the first byte of the cell data.
TVM supports four types of exotic cells:

| Type ID | Description                                               |
| ------- | --------------------------------------------------------- |
| `0x01`  | [Pruned branch](/llms/foundations/serialization/pruned/content.md)        |
| `0x02`  | [Library reference](/llms/foundations/serialization/library/content.md)   |
| `0x03`  | [Merkle proof](/llms/foundations/serialization/merkle/content.md)         |
| `0x04`  | [Merkle update](/llms/foundations/serialization/merkle-update/content.md) |

## Level of a cell [#level-of-a-cell]

Every cell c has an attribute $Lvl(c)$ called its **level**, which takes integer values in the range `0…3`.
A cell's level affects the number of higher hashes it has.
The level of an ordinary cell $c$ is equal to the maximum of the levels of all its children $c_i$:

$$
Lvl(c) = \max_i Lvl(c_i).
$$

For instance, each cell in a tree of cells that does not contain any exotic cell has level 0.

Exotic cells may have different rules for setting their level.

## Standard cell representation and its hash [#standard-cell-representation-and-its-hash]

Before a cell can be transferred over the network or stored on disk, it must be serialized. A common way to do
this is to use the so-called *standard cell representation*, `CellRepr(c)`. The standard representation of a cell `c` is a byte sequence that is constructed as follows:

* Two descriptor bytes $d_1$ and $d_2$ are serialized first. Byte $d_1$ equals `r+8s+32l`, where `0 ≤ r ≤ 4` is the quantity of cell references contained
  in the cell, `0 ≤ l ≤ 3` is the level of the cell, and `0 ≤ s ≤ 1` is `1` for
  exotic cells and `0` for ordinary cells. Byte $d_2$ equals $\lfloor\frac{b}{8}\rfloor + \lceil\frac{b}{8}\rceil$, where `0 ≤ b ≤ 1023`
  is the quantity of data bits in `c`.
* Then the data bits are serialized as $\lceil\frac{b}{8}\rceil$ bytes. If `b` is not a multiple of eight, a binary `1` and up to six binary `0s` are appended to
  the data bits. After that, the data is split into $\lceil\frac{b}{8}\rceil$ 8-bit groups, and each group is interpreted as an unsigned big-endian integer 0 … 255
  and stored into a byte.
* Next, for every referenced cell, `2` bytes in big-endian format store the depth of the refs, i.e. the number of cells between the root of the\
  cell tree (the current cell) and the deepest reference, including it. For example, a cell containing only one reference and no further references
  would have a depth of `1`, while the referenced cell would have a depth of `0`.
* Finally, for every referenced cell, the SHA-256 hash of its standard representation is stored, occupying `32` bytes per referenced cell,
  recursively repeating the said algorithm. Note that cyclic cell references are not allowed, so this algorithm always terminates.
  If there are no referenced cells, neither depths nor hashes are stored.

In this way, $2 + \lceil\frac{b}{8}\rceil + 2r + 32r$ bytes of `CellRepr(c)` are obtained. Thus, we got the serialization of `c`.

However, the serialization of graphs formed by cells is arranged differently; see [bag of cells](/llms/foundations/serialization/boc/content.md) for details.

## Cell manipulation [#cell-manipulation]

Cells are read-only and immutable, but there are two major sets of ordinary cell manipulation instructions in TVM:

* Cell creation (or serialization) instructions, which are used to construct new cells from previously stored values and cells.
* Cell parsing (or deserialization) instructions, which are used to extract or load data previously stored into cells via serialization instructions.

All cell manipulation instructions require transforming values of `Cell` type into either [builder](/llms/tvm/builders-and-slices/content.md) or [slice](/llms/tvm/builders-and-slices/content.md) types before such cells can be modified or inspected.

Libraries like [`@ton/core`](https://github.com/ton-core/ton) and [`@ton-community/assets-sdk`](https://github.com/ton-community/assets-sdk) provide efficient cell handling.
Below are examples of sequential cell creation, populating it with data, and then parsing.

### Create a cell and store data [#create-a-cell-and-store-data]

To build a cell, you use the `beginCell()` function. While the cell is open, you can store various data types with `store...()` functions.
When you're done, you close the cell with the `endCell()` function.

```typescript
import { Address, beginCell } from "@ton/core";

const cell = beginCell()
  .storeUint(99, 64) // Stores uint 99 in 64 bits
  .storeAddress(Address.parse("EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c")) // Stores an address
  .storeCoins(123) // Stores 123 as coins
  .endCell(); // Closes the cell
```

Each cell has a 1023-bit limit. If you exceed this, an error occurs:

```typescript
// This will fail due to overflow
const cell = beginCell()
  .storeUint(1, 256)
  .storeUint(2, 256)
  .storeUint(3, 256)
  .storeUint(4, 256) // Exceeds 1023-bit limit (256 + 256 + 256 + 256 = 1024)
  .endCell();
```

To store more data, cells can reference up to four other cells. You can use the `storeRef()` function to create nested cells:

```typescript
const cell = beginCell()
  .storeUint(1, 256)
  .storeUint(2, 256)
  .storeRef(beginCell().storeUint(3, 256).storeUint(4, 256).endCell())
  .endCell();
```

You can store optional (nullable) values in cells by using the `storeMaybe...()` helpers:

```typescript
const cell = beginCell()
  .storeMaybeInt(null, 64) // Optionally stores an int
  .storeMaybeInt(1, 64)
  .storeMaybeRef(null) // Optionally stores a reference
  .storeMaybeRef(beginCell().storeCoins(123).endCell())
  .endCell();
```

### Load data from a cell [#load-data-from-a-cell]

To read data from a cell, you first convert it into a slice using the `beginParse()` function.
Then, you can extract various data types with `load...()` functions. **You read data in the same order it was stored**.

```typescript
const slice = cell.beginParse();
const uint = slice.loadUint(64);
const address = slice.loadAddress();
const coins = slice.loadCoins();
```

To load a referenced (nested) cell, use `loadRef()`:

```typescript
const slice = cell.beginParse();
const uint1 = slice.loadUint(256);
const uint2 = slice.loadUint(256);
const innerSlice = slice.loadRef().beginParse(); // Load and parse nested cell
const uint3 = innerSlice.loadUint(256);
const uint4 = innerSlice.loadUint(256);
```

You can parse optional values using the corresponding `loadMaybe...()` functions. Returned values are nullable, so do not forget to check them for null.

```typescript
const slice = cell.beginParse();
const maybeInt = slice.loadMaybeInt(64);
const maybeInt1 = slice.loadMaybeInt(64);
const maybeRef = slice.loadMaybeRef();
const maybeRef1 = slice.loadMaybeRef();
if (maybeRef1) {
  const coins = maybeRef1.beginParse().loadCoins();
}
```

## References [#references]

* [Parse and view TON smart contract cells in a human-readable format](https://ton-cell-abi-viewer.vercel.app/).
