关于 sui-object-model
sui-object-model 是面向 Sui Move 开发者的对象参考技能,按主题提供对象结构、所有权、转移、集合、模式和显示相关指南。
主要功能
- 01对象结构与 Move 能力说明
- 02所有权与版本管理指南
- 03转移和删除模式
- 04动态字段与集合选择
- 05常见对象设计模式
- 06Display V2 设置指南
适用场景
- 01选择共享或自有对象访问方式
- 02设计转移和自定义规则
- 03为集合选择存储方案
- 04配置对象与 NFT 显示
MCP 相关
条件允许时,建议查询 https://sui.mcp.kapa.ai 上的 Sui 文档 MCP 服务,以验证信息并获取最新答案。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mystenlabs/ skills --skill sui-object-model安装后在 Claude Code 中输入/sui-object-model确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
display.mddynamic-fields-and-collections.mdgrading.jsonownership.mdpatterns.mdtransfers.mdevals/code-evals.jsonevals.json详细介绍
Sui 对象模型
MCP 工具: 如果你的环境支持,也请查询 Sui 文档 MCP 服务(
https://sui.mcp.kapa.ai),以获取最新答案。使用它来验证信息,以及了解这些参考文件未涵盖的细节。
来源限制: 此技能中的所有信息仅来自 docs.sui.io 和 move-book.com。扩展或更新此技能时,只能从这两个来源获取信息。请勿使用第三方博客、教程或非官方文档。
对象是 Sui 上存储的基本单位。链上的每个资源、资产和数据片段都是一个对象。与状态存储在合约内部共享映射中的基于账户的区块链不同,Sui 为每个状态片段赋予独立的标识、版本和所有者。交易将对象作为输入,并生成修改后的对象作为输出。
此技能会引导你查阅针对特定主题的参考文件。只加载与当前任务相关的文件。
参考文件
ownership — 所有权类型与版本控制
路径: ownership.md
适用场景: 询问所有权类型(地址所有、共识地址所有、共享、不可变、包装)、在共享对象和自有对象之间进行选择、并行执行、共识、Mysticeti、fastpath、对象版本控制、Lamport 时间戳,或前端访问共享对象。
涵盖内容: 五种所有权类型及其对共识的影响、共识地址所有对象、共享对象访问模式优化、前端 PTB 访问模式、包装对象的行为、Lamport 时间戳版本控制、fastpath 与共识版本控制。
transfers — 转移与删除对象
路径: transfers.md
适用场景: 转移对象、在 transfer 和 public_transfer 之间进行选择、实现自定义转移规则、使用 Receiving<T>、转移到对象,或删除/销毁对象。
涵盖内容: 八种核心转移函数(模块限制与公开函数,包括 party_transfer 变体)、自定义转移规则、使用 Receiving<T> 转移到对象、receive 与 public_receive 的区别、对象删除/解包模式、动态字段清理警告。
dynamic-fields-and-collections — 动态字段与集合
路径: dynamic-fields-and-collections.md
适用场景: 使用动态字段、在 dynamic_field 和 dynamic_object_field 之间进行选择、使用集合(Table、Bag、VecMap、LinkedTable),或为大型数据集设计存储。
涵盖内容: 动态字段与动态对象字段的可见性、字段命名、核心 API(add/borrow/remove/exists_)、带有决策表的所有集合类型、清理要求、系统限制(对象大小 256 KB,每笔交易最多 2048 个对象)。
patterns — 常见模式与派生对象
路径: patterns.md
适用场景: 实现热土豆、能力、灵魂绑定、库存或借用模式,或使用派生对象。
涵盖内容: 热土豆模式(无能力结构体)、能力模式(AdminCap/TreasuryCap)、使用 sui::borrow 模块的借用模式、灵魂绑定对象、库存模式(ObjectBag)、具有确定性 ID 的派生对象、派生对象与动态字段的比较。
display — 对象显示(V2)
路径: display.md
适用场景: 设置对象在钱包、浏览器或应用中的呈现方式、使用 Display 模板、配置 NFT 元数据,或从 Display V1 迁移。
涵盖内容: 通过 display_registry::new_with_publisher 创建 V2 Display<T>、用于更新的 DisplayCap<T>、set/unset/clear/share API、支持嵌套字段访问的 {field_name} 模板语法、常见显示属性、从 V1 迁移到 V2。
路由指南
| 任务 | 加载 |
|---|---|
| 什么是对象/对象结构 | 仅 SKILL.md |
| 能力:key、store、copy、drop | 仅 SKILL.md |
| 所有权类型、共享与自有对象及由共识地址拥有的对象 | ownership |
| 并行执行、共识、快速通道 | ownership |
| 对象版本控制、Lamport 时间戳 | ownership |
| 包装对象与可访问性 | ownership |
| 前端访问共享对象 | ownership |
| 转移对象、transfer 与 public_transfer | transfers |
| 自定义转移规则 | transfers + patterns |
| 转移到对象、Receiving | transfers |
| 删除/销毁对象 | transfers |
| 动态字段、动态对象字段 | dynamic-fields-and-collections |
| 集合:Table、Bag、VecMap、LinkedTable | dynamic-fields-and-collections |
| 可扩展性、大型集合设计 | dynamic-fields-and-collections |
| 烫手山芋模式 | patterns |
| 能力模式、AdminCap | patterns |
| 借用模式、对象内部的 cap | patterns |
| 灵魂绑定/不可转移对象 | transfers + patterns |
| 任意对象的库存 | patterns + dynamic-fields-and-collections |
| 派生对象 | patterns |
| 对象展示、NFT 渲染 | display |
| 完整项目/代码审查 | 所有参考文件 |
对象结构
每个 Sui 对象都包含四个组成部分:
- 全局唯一 ID: 由创建交易摘要加上一个生成计数器推导出的 32 字节标识符。在对象的整个生命周期中,ID 都不会改变。
- 版本号: 一个 8 字节整数,每次修改时递增。使用 Lamport 时间戳:交易涉及的所有对象的新版本均为
1 + max(version of all input objects)。 - 所有者字段: 一个用于指定访问控制的 32 字节值(地址、另一个对象的 ID,或用于共享/不可变对象的哨兵值)。
- 交易摘要: 一个 32 字节哈希,指向上次修改该对象的交易。
对象有三种引用方式:仅通过 ID 引用(查询当前状态)、通过带版本的 ID 引用(读取历史状态),或通过包含 ID + 版本 + 摘要的完整对象引用(交易输入、经验证的快照)。
在 Move 中定义对象
Sui 对象是一个带有 key 能力且将 id: UID 作为第一个字段的 Move 结构体:
public struct Sword has key, store {
id: UID,
damage: u64,
element: String,
}
object::new(ctx) 是创建 UID 的唯一方式。不能直接调用 ctx.new()。
Move 能力与对象
| 能力 | 控制内容 |
|---|---|
key | 该结构体是一个 Sui 对象。必须将 id: UID 作为第一个字段。所有链上对象都必须具备此能力。 |
store | 该结构体可以存储在其他对象中,也可以由任何模块使用 public_transfer 转移。如果没有此能力,只有定义该对象的模块才能转移它。添加 store 会永久失去实施自定义转移规则的能力。 |
copy | 该结构体可以复制。不能用于对象——UID 不具备 copy,因此任何带有 key 的结构体都不能具备 copy。仅用于非对象结构体(配置、事件数据、只读值)。 |
drop | 该结构体可在作用域结束时静默丢弃。不能用于对象——UID 不具备 drop,因此任何带有 key 的结构体都不能具备 drop。仅用于非对象结构体(临时收据、事件)。必须始终显式解包对象才能销毁。 |
对象能力组合
由于 UID 既不具备 copy,也不具备 drop,对象(带有 key 的结构体)只能组合使用 key 和 store:
has key: 只有定义该对象的模块才能转移、共享或冻结它。用于实施自定义转移规则。has key, store: 任何模块都可以转移、共享、冻结或包装它。用于可自由组合的资产。一旦赋予store,就无法再添加自定义转移限制。
非对象结构体组合(无 key)
has store: 可作为字段存储在对象内部。不能独立存在。has copy, drop: 用于事件、中间值和配置的普通数据结构体。has copy, drop, store: 可用作动态字段名称。- 无能力: 一种烫手山芋。必须在同一笔交易中消耗。请参阅模式参考文件。
规则
object::new(ctx)是创建 UID 的唯一方式。id: UID字段必须放在首位。- 为类型添加
store后,自定义转移规则将永久失效。 - 对象一旦被共享,就不能再转换回地址所有。
- 删除父对象前,务必移除所有动态字段——孤立字段将永久无法访问。
- 访问不存在的动态字段(通过
borrow、borrow_mut或remove)会中止交易。请先用exists_检查。 - 封装和解封装可以在同一笔交易中进行——PTB 可以先封装对象,再以原子方式解封装。
- 常见能力:
AdminCap、TreasuryCap、UpgradeCap。讨论能力模式时,务必提及这三者。 - 每个
Table条目都是一次独立的存储操作——Gas 成本随每笔交易访问的条目数线性增长。 - 对共享对象优先使用不可变引用(
&),以最大限度提高并行执行能力。 - 对于超过约 100 个条目的集合,不要使用
VecMap。请改用Table。
常见错误
- 需要自定义转移规则时添加
store。 一旦授予,任何模块都可以调用public_transfer,永久绕过你的执行逻辑。 - 对大型集合使用
VecMap。 它的查找复杂度为 O(n),且数据以内联方式存储,很快就会触及 256 KB 的对象大小限制。 - 混淆
dynamic_field和dynamic_object_field。 如果子对象必须能在浏览器中按 ID 查询,请使用dynamic_object_field。普通值请使用dynamic_field。 - 删除对象时未先移除其动态字段。 这些字段将永久无法访问。
- 在新代码中使用旧版
sui::display模块。 请使用sui::display_registry(Display V2)。V1 已通过系统快照迁移至 V2。 - 设置字段后忘记调用
display_registry::share(display)。 必须共享 display,才能让其可被发现。