自定义转账规则
每个Sui对象必须具有key
能力。另一方面,store
能力是你可以添加到Sui对象的可选能力。具有store
能力的对象:
- 可以被任何人使用
sui::transfer::public_transfer
函数进行转账; - 可以被包装在其他对象中。
对于自定义转账规则来说,如果Sui对象O
没有store
能力,则不能调用sui::transfer::public_transfer
函数对其进行转账。定义O
的Move模块是唯一能够使用sui::transfer::transfer
函数转移该类型对象的实体。因此,定义对象O
的模块可以为O
定义自定义转账函数,该函数可以接受任意数量的参数,并强制执行对执行转账操作所需的任何限制(例如,必须支付费用才能转移对象)。
store能力和转账规则
对象的自定义转账规则使你能够定义必须满足的有效转账操作的转账条件。在将store
能力添加到对象时,你应该有意识地添加,因为这样你可以在无需通过定义它的模块的情况下提供对该对象的无限制访问。在启用了对象的公共转账之后,就无法重新启用自定义转账规则或关于对象转账的任何类型的限制。
示例
此示例创建了一个名为O
的对象类型,只有当其内部的unlocked
标志设置为true
时才能进行转账:
struct O has key {
id: UID,
// An `O` object can only be transferred if this field is `true`
unlocked: bool
}
在定义对象O
的同一模块中,你可以为O
定义一个名为transfer_unlocked
的自定义转账规则。该规则接受要转移的对象和要转移到的地址,并在将其转移到指定地址之前验证该对象是否已解锁。
module examples::custom_transfer {
// Error code for trying to transfer a locked object
const EObjectLocked: u64 = 0;
struct O has key {
id: UID,
// An `O` object can only be transferred if this field is `true`
unlocked: bool
}
// Check that `O` is unlocked before transferring it
public fun transfer_unlocked(object: O, to: address) {
assert!(object.unlocked, EObjectLocked);
sui::transfer::transfer(object, to)
}
}
使用自定义转账规则,你可以为同一对象定义多个不同的转账规则。每个规则可能具有不同的限制,执行事务时可以动态强制执行这些限制。因此,如果你只想允许将锁定的对象转移到特定地址,可以将以下函数添加到前面的模块:
const EObjectNotLocked: u64 = 1;
const HomeAddress = @0xCAFE;
public fun transfer_locked(object: O) {
assert!(!object.unlocked, EObjectNotLocked);
sui::transfer::transfer(object, HomeAddress)
}
有了这些规则,任何对象 O
都有两种不同的自定义转账规则;它要么是解锁的,任何人都可以转账,要么是锁定的,只有 0xCAFE
可以转账。重要的是,这两种转账 O
的方式是转移任何类型为 O
的对象的唯一方式。特别是,因为 O
没有 store
能力,你不能使用 sui::transfer::public_transfer
函数进行转账。事实上,转移 O
的唯一方式是使用 examples::custom_transfer::transfer_unlocked
和 examples::custom_transfer::transfer_locked
。