一个 Cell 能容纳多少地址?

发布: (2026年1月17日 GMT+8 02:15)
4 min read
原文: Dev.to

Source: Dev.to

介绍

在开发智能合约时,我需要在持久化存储中保存多个地址。
由于 TON 的存储以比特和单元(cell)计量,且存储和消息转发都会消耗 gas,准确了解一个单元能容纳多少地址非常重要。为了解答这个问题,我们必须查看地址在 TL‑B 层面的定义和序列化方式。

TL‑B 地址定义

addr_none$00 = MsgAddressExt;

addr_extern$01 len:(## 9) external_address:(bits len)
    = MsgAddressExt;

anycast_info$_ depth:(#= 1 }
    rewrite_pfx:(bits depth) = Anycast;

addr_std$10 anycast:(Maybe Anycast)
    workchain_id:int8 address:bits256 = MsgAddressInt;

addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
    workchain_id:int32 address:(bits addr_len) = MsgAddressInt;

_ _:MsgAddressInt = MsgAddress;
_ _:MsgAddressExt = MsgAddress;

恰好有四种地址构造器:

  • addr_none
  • addr_extern
  • addr_std
  • addr_var

以下章节将在严格依据 TL‑B 定义的前提下,计算每种构造器的精确比特大小。

地址构造器大小分析

addr_none

  • 构造标签 $002 比特

精确大小: 2 比特。

addr_extern

  • 构造标签 $01 → 2 比特
  • len:(## 9) → 9 比特(长度字段)
  • external_address:(bits len)len 比特,len ∈ [0, 511]

精确大小公式: 2 + 9 + len = 11 + len 比特

  • 最小大小(len = 0):11 比特
  • 最大大小(len = 511):522 比特

addr_std

  • 构造标签 $10 → 2 比特
  • anycast:(Maybe Anycast) → 存在标志 1 比特
    • 若存在:depth:(#<=30) → 5 比特,rewrite_pfx:(bits depth)depth 比特(depth ∈ [1, 30])
  • workchain_id:int8 → 8 比特
  • address:bits256 → 256 比特

精确大小公式:

2 + 1 + (anycast ? (5 + depth) : 0) + 8 + 256
  • 没有 anycast(存在位 = 0):267 比特
  • 有 anycast,且最大 depth = 30:302 比特

addr_var

  • 构造标签 $11 → 2 比特
  • anycast:(Maybe Anycast) → 存在标志 1 比特
    • 若存在:depth:(#<=30) → 5 比特,rewrite_pfx:(bits depth)depth 比特
  • addr_len:(## 9) → 9 比特(地址字段的长度)
  • workchain_id:int32 → 32 比特
  • address:(bits addr_len)addr_len 比特,addr_len ∈ [0, 511]

精确大小公式:

2 + 1 + (anycast ? (5 + depth) : 0) + 9 + 32 + addr_len
  • 没有 anycast,且地址长度最大(addr_len = 511):555 比特
  • 有 anycast,最大 depth = 30 且最大地址长度:590 比特

实际考虑(TVM ≥ 10)

  • 自 TVM 10 版起,anycast 地址不允许作为消息目的地,也不用于账户地址,且地址解析和 rewrite 指令也不支持。因此 Maybe Anycast 标志始终为 0,anycast 负载永远不会出现。
  • addr_var 为未来扩展而定义,但 在实际合约中目前未被使用
  • 当前活跃的工作链(主链和基础链)使用 addr_std,其特点是:
    • 256 比特的账户 ID
    • 较小的工作链 ID

主网中的真实地址大小

  • Anycast 未使用。
  • addr_var 未使用。
  • 所有内部地址均为 addr_std

因此 实际的内部地址大小固定为 267 比特

了解这个精确数值对于设计紧凑的存储布局、估算 gas 成本以及决定单元中能容纳多少地址至关重要。

Back to Blog

相关文章

阅读更多 »

Solana Devnet:您需要了解的一切

介绍 在 Solana 上构建?您需要 Devnet——一个免费的沙盒,您可以在其中测试、尝试错误并学习,而无需冒真实金钱的风险。什么是 Devnet?...