Cell & bag of cells (BoC)
Cell
A cell is a fundamental data structure in the TON blockchain. Each cell can store up to 1023 bits of data and maintain up to 4 references to other cells.


Bag of cells
A Bag of Cells (BoC) is a serialization format that encodes cells into byte arrays, as defined by the TL-B schema.


In TON, everything is built from cells—smart contract code, stored data, and even entire blocks—enabling a highly flexible and modular architecture.


Cell serialization
Let’s walk through a basic example of a BoC:


1[8_] -> {
24[0AAAAA],
7[FE] -> {
24[0AAAAA]
}
}
In this case, we have a 0-bit root cell that references two other cells:
- The first is a 24-bit cell.
- The second is a 7-bit cell that itself references a 24-bit cell.
To serialize this structure into a byte sequence, we first identify unique cells. In the example, we consider 3 unique cells out of 4 total.
1[8_]
24[0AAAAA]
7[FE]
To filter out duplicates, cells must be compared by their hashes.
Next, we arrange the cells in a specific order so that parent cells never reference cells that come before them in the list. In other words, any referenced cell must appear after the cells that reference it. We get:
1[8_] -> index 0 (root cell)
7[FE] -> index 1
24[0AAAAA] -> index 2
Now, let’s calculate the descriptors for each of the 3 cells mentioned earlier. These descriptors consist of 2 bytes that encode metadata about the cell’s data size and reference structure.
- Refs descriptor (1st byte)
This byte is calculated using the formula: r + 8·s + 32·l
.
Where:
r
is the number of cell's references (links) in the range0 ≤ r ≤ 4
.s
is the exotic flag (1 for exotic cells, 0 for ordinary ones).l
is the level of the cell in the range0 ≤ l ≤ 3
.
- Bits descriptor (2nd byte)
This byte indicates the size of the cell’s bitstring and is calculated as: floor(b / 8) + ceil(b / 8)
.
Where 0 <= b <= 1023
is the number of bits in the cell.
This descriptor represents the length of full 4-bit groups in the cell’s data and is always at least 1 for non-empty data.
The result is:
1[8_] -> 0201 -> 2 refs, length 1
7[FE] -> 0101 -> 1 ref, length 1
24[0AAAAA] -> 0006 -> 0 refs, length 6
For data with incomplete 4-bit groups, 1 bit is added to the end of the sequence. This means it denotes the end bit of the group and is used to determine the actual size of incomplete groups. Let's add the bits below: Let’s add the end bits to each of the cells:
1[8_] -> C0 -> 0b10000000->0b11000000
7[FE] -> FF -> 0b11111110->0b11111111
24[0AAAAA] -> 0AAAAA -> do not change (full groups)
We now specify which cells each one references:
0 1[8_] -> 0201 -> refers to 2 cells with such indexes
1 7[FE] -> 02 -> refers to cells with index 2
2 24[0AAAAA] -> no refs
Now we serialize the cells:
0201 C0 0201
0101 FF 02
0006 0AAAAA
Finally, we concatenate all parts into a single-byte array:
0201c002010101ff0200060aaaaa
Size: 14 bytes.
Show example
func (c *Cell) descriptors() []byte {
ceilBytes := c.bitsSz / 8
if c.bitsSz%8 ! = 0 {
ceilBytes++
}
// calc size
ln := ceilBytes + c.bitsSz / 8
specBit := byte(0)
if c.special {
specBit = 8
}
return []byte{byte(len(c.refs)) + specBit + c.level*32, byte(ln)}
}