Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

能力系统概览(Abilities)

能力系统(Abilities)是 Move 语言最独特的类型系统特性之一,它通过四种能力——copydropkeystore——来精确控制类型的行为。不同于大多数编程语言中类型可以被随意复制和丢弃,Move 要求开发者显式声明类型的行为权限,从而在编译期保障链上资源的安全性。

能力声明

能力通过 has 关键字声明在结构体定义中:

module book::ability_syntax;

// 同时拥有多个能力,用逗号分隔
public struct Token has key, store {
    id: UID,
    value: u64,
}

// 没有任何能力的结构体
public struct Unique {
    value: u64,
}

四种能力详解

copy —— 可复制

拥有 copy 能力的类型,其值可以被隐式复制。没有 copy 的值在赋值或传参时会被 移动(move),原变量将不可再使用:

module book::ability_copy;

public struct Copyable has copy, drop {
    value: u64,
}

public struct NonCopyable has drop {
    value: u64,
}

#[test]
fun copy_vs_move() {
    let a = Copyable { value: 42 };
    let b = a;  // 复制,a 仍然可用
    assert_eq!(a.value, 42);
    assert_eq!(b.value, 42);

    let c = NonCopyable { value: 100 };
    let d = c;  // 移动,c 不再可用
    // assert!(c.value == 100); // 编译错误!c 已被移动
    assert_eq!(d.value, 100);
}

drop —— 可丢弃

拥有 drop 能力的类型,其值可以在离开作用域时被自动丢弃。没有 drop 的值必须被显式消费(解构或转移):

module book::ability_drop;

public struct Droppable has drop {
    value: u64,
}

public struct MustUse {
    value: u64,
}

public fun consume(item: MustUse) {
    let MustUse { value: _ } = item; // 必须显式解构
}

key —— 可作为存储键

拥有 key 能力的类型可以作为链上对象存在。在 Sui 中,key 结构体的第一个字段必须是 id: UID

module book::ability_key;

public struct MyObject has key {
    id: UID,
    data: u64,
}

key 是将结构体变为 Sui 对象的必要条件。拥有 key 的对象可以被转移、共享或冻结。

store —— 可存储

拥有 store 能力的类型可以被存储在其他拥有 key 的对象内部。store 也是对象能被公开转移(public_transfer)的必要条件:

module book::ability_store;

use std::string::String;

public struct Metadata has store, copy, drop {
    name: String,
    version: u64,
}

public struct Container has key, store {
    id: UID,
    metadata: Metadata,  // Metadata 有 store,可以存在对象中
}

能力组合总览

能力组合含义典型用途
无能力不可复制、不可丢弃、不可存储Hot Potato 模式
drop可丢弃Witness 模式
copy, drop可复制、可丢弃纯数据/值类型
key链上对象不可转移的对象
key, store可转移的链上对象NFT、代币等
store, copy, drop可存储的值类型嵌入对象的元数据
key, store, copy, drop完全能力对象较少见

内置类型的能力

所有原始类型天然拥有 copydropstore

类型能力
boolcopy, drop, store
u8 ~ u256copy, drop, store
addresscopy, drop, store
&T&mut Tcopy, drop
vector<T>取决于 T 的能力

完整示例

module book::abilities_example;

// Has all four abilities - can be copied, dropped, stored as object
public struct FullAbility has key, store, copy, drop {
    id: UID,
    value: u64,
}

// Can be copied and dropped but not stored
public struct Copyable has copy, drop {
    value: u64,
}

// No abilities - Hot Potato! Must be explicitly consumed
public struct HotPotato {
    value: u64,
}

// Only drop - Witness pattern
public struct Witness has drop {}

能力约束与泛型

在泛型函数或泛型结构体中,可以对类型参数施加能力约束:

module book::ability_constraints;

public struct Box<T: store> has key, store {
    id: UID,
    content: T,
}

public fun unbox<T: store>(box: Box<T>): T {
    let Box { id, content } = box;
    object::delete(id);
    content
}

T: store 意味着只有拥有 store 能力的类型才能放入 Box 中。这种约束在编译期就能捕获类型错误。

常见设计模式

Hot Potato 模式

没有任何能力的结构体不能被复制、丢弃或存储,必须在创建它的交易中被显式消费。这个模式常用于强制执行某些操作序列:

module book::hot_potato;

public struct FlashLoan {
    amount: u64,
}

public fun borrow(amount: u64): (u64, FlashLoan) {
    (amount, FlashLoan { amount })
}

public fun repay(loan: FlashLoan, payment: u64) {
    let FlashLoan { amount } = loan;
    assert!(payment >= amount);
}

Witness 模式

只有 drop 能力的结构体,通常用于一次性类型证明(One-Time Witness):

module book::witness;

public struct WITNESS has drop {}

小结

能力系统是 Move 语言安全性的核心保障。本节核心要点:

  • 四种能力copy(可复制)、drop(可丢弃)、key(可作为对象)、store(可存储)
  • 能力通过 has 关键字在结构体定义中声明
  • 所有原始类型拥有 copydropstore
  • 没有能力的结构体(Hot Potato)必须被显式消费,确保操作不可跳过
  • 只有 drop 的结构体(Witness)用于一次性类型证明
  • 泛型中可以通过能力约束限制类型参数
  • 能力系统在编译期强制执行资源安全规则,防止资产被意外复制或丢弃