大家好,我想介绍一个 CKB 上的 UDT 合约项目:standard-udt-contracts: xcshuan/ckb-standard-udt-contracts。
原始设计: Enhanced UDT Standard - English / CKB Development & Technical Discussion - Nervos Talk
先做一个说明:这个项目的合约开发过程中大量使用了 AI 辅助,包括代码实现、测试补充和文档整理。但合约核心逻辑、状态机路径、权限校验和关键安全边界我都已经人工逐项审阅过。AI 在这里主要承担的是实现和整理工作,最终的协议设计取舍和合约逻辑判断仍然由人工完成。
这个项目实现了一组围绕 sUDT、xUDT、元数据、供应量追踪、权限控制和访问控制构建的标准化合约。目标是提供一套更完整、更可组合、边界更清晰的 UDT 合约基础设施。
项目包含五个主要 type script:
-
sudt:sUDT token type script -
sudt-meta:sUDT metadata type script -
xudt:xUDT token type script -
xudt-meta:xUDT metadata type script -
access-list:xUDT 使用的 AccessList shard type script
同时项目还包含:
-
lib/types:共享 Molecule schema、生成类型和严格解析器 -
lib/script-utils:共享 no-std 脚本工具,包括权限验证、token delta 计算、cell 扫描等 -
tests:基于ckb-testtool的集成测试和测试插件
核心功能
这个项目支持:
-
普通 UDT 转账
-
授权 mint
-
授权 protocol burn
-
用户自行销毁 token cell
-
可选的 total supply tracking
-
metadata cell 创建、更新和销毁
-
metadata authority 和 mint authority
-
xUDT pause mode
-
xUDT whitelist / blacklist access mode
-
AccessList 分片管理
-
动态扩展插件,包括 dynamic linking 和 spawn 两种执行模式
Supply Tracking 设计
供应量追踪是可选的,并且在 token 创建后不可变。
如果启用 CONFIG_SUPPLY_TRACKED,metadata 中的 current_supply 必须和交易中的 token cell delta 对齐:
-
mint 增加 supply,需要
mint_authority -
protocol burn 减少 supply,需要
mint_authority -
user destruction 不减少 tracked supply
-
metadata 不能单独修改
current_supply
这里区分了 protocol burn 和 user destruction:
-
如果交易消费了 metadata input cell,负 delta 被视为 protocol burn
-
如果没有消费 metadata input cell,负 delta 被视为用户自行销毁 token cell
这样可以允许用户销毁自己的 token cell 回收 CKB,同时不要求 mint authority,也不影响协议层记录的 total supply。
metadata cell 本身也可以销毁以回收 CKB,但条件更严格:
-
必须是 supply-tracked mode
-
current_supply必须为 0 -
必须由
mint_authority授权
对于 xUDT,如果 access mode 仍然开启,销毁 metadata 时还要求:
-
input 中包含 full-domain AccessList
-
output 中不能再留下绑定到该 metadata 的 AccessList cell
AccessList 和访问控制
xUDT 支持三种 access state:
-
disabled
-
blacklist
-
whitelist
AccessList 使用 shard 结构覆盖 lock hash domain。每个 shard 有自己的 range 和 entries。entries 在类型层保证:
-
在 shard range 内
-
有序
-
不重复
xUDT 在转账时根据 access mode 验证 input lock:
-
whitelist:必须提供 membership proof
-
blacklist:必须提供 non-membership proof
Access mode 的全局切换由 xudt-meta 管理:
-
disabled → active 需要 full-domain AccessList outputs
-
active → disabled 需要 full-domain AccessList inputs
-
whitelist ↔ blacklist 需要 full-domain inputs 和 outputs
普通 AccessList 更新不需要消费全域,只需要 input shards 和 output shards 覆盖同一段连续区间。在这段区间内,可以同时修改 entries、split shard、merge shard。
权限模型
metadata 中可以配置多种 authority:
-
InputLock -
InputType -
OutputType -
DynamicLinking -
Spawn
其中 mint_authority 是最高权限,控制:
-
mint
-
protocol burn
-
supply-changing metadata update
-
mint authority 修改
-
extension list 修改
-
metadata/access authority 的 fallback 授权
项目中把权限验证逻辑抽到了共享的 AuthorityVerifier。同一条验证路径会复用 verifier,并缓存重复 authority check,避免重复扫描 cell 或重复执行动态权限代码。
即使是 no-op update,只要消费 metadata 或 AccessList state cell,也必须通过相应 authority 验证。状态 cell 的 unlock 权限不依赖 lock script,而由 type script 中的 authority 规则控制。
技术边界
项目强调 type script 的职责边界:
-
token script 负责 token movement
-
metadata script 负责 metadata state
-
access-list script 负责 AccessList shard lifecycle
-
shared libs 只提供解析和底层机制,不拥有业务规则
例如:
-
token script 不验证 metadata lifecycle
-
metadata script 不验证 token ownership
-
xUDT 只消费 AccessList proof,不负责 AccessList shard 状态机
-
AccessList script 不关心 token 转账语义
这种拆分让协议更容易测试、组合和审计。
一个需要注意的索引问题
这里还有一个实际工程问题需要说明:CKB 原生节点 RPC 本身不适合按 script 检索 live cell。通常要查找“使用某个 script 的 cell”,需要使用 CKB Indexer RPC 的 get_cells。现在 indexer 已经可以集成在 CKB node 里,CKB v0.106.0 之后也推荐直接启用 node 内置 indexer。
get_cells 的查询入口主要是完整的 Script 结构:
{
"script": {
"code_hash": "...",
"hash_type": "type",
"args": "..."
},
"script_type": "lock"
}
或者:
{
"script": {
"code_hash": "...",
"hash_type": "type",
"args": "..."
},
"script_type": "type"
}
也就是说,常规 get_cells 查询是按 code_hash + hash_type + args 组成的完整 Script 查询,并指定查 lock 还是 type,而不是直接传 script_hash。
这对 xUDT 有一个影响:xUDT type args 中保存的是 metadata type script hash。拼装转账交易时,钱包或应用可以从 xUDT args 得到 meta type hash,但现有 indexer RPC 不能直接用这个 script hash 定位对应的 metadata cell。实际集成时需要额外处理:
-
钱包、SDK 或应用自己缓存 token → metadata cell 的映射;
-
提供额外的服务接口,通过 meta type hash 查询 metadata cell;
-
或者推动 indexer 增加按 type script hash 定位 cell 的查询接口。
这个问题不影响链上合约验证逻辑,但会影响钱包、SDK 和应用侧的交易构建体验,是后续标准化和工具链支持里需要解决的一环。
测试
项目包含较完整的 ckb-testtool 集成测试,覆盖:
-
sUDT / xUDT mint、burn、transfer、user destruction
-
metadata 创建、更新、销毁
-
supply tracking
-
access mode transition
-
AccessList shard lifecycle
-
whitelist / blacklist proof
-
authority fallback
-
dynamic linking / spawn extension
-
debug/release 差异
目前 debug 集成测试覆盖 160+ 个用例。
总结
standard-udt-contracts 的目标不是只实现一个简单 UDT,而是提供一套完整的标准 UDT 合约框架:
-
可选供应量追踪
-
可治理 metadata
-
可回收 CKB 的 state cell cleanup
-
xUDT access control
-
可扩展插件系统
-
明确的权限模型
-
清晰的脚本职责边界
希望这个项目能为 CKB 上更复杂的 token、资产和应用协议提供基础组件,也欢迎大家 review 设计、提出建议或参与讨论。