sui-move进阶:coin.move源码分析coin.move是SuiMove中实现可替代代币(fungibletokens)的核心模块(实际上,因为sui"一切皆对象"和所有权的设计,也自然而然地可以用来实现NFT)。它提供了创建、管理和操作代币的基础工具,包括代币的生成、分割、合
coin.move
是 Sui Move 中实现可替代代币(fungible tokens)的核心模块(实际上,因为sui"一切皆对象"和所有权的设计,也自然而然地可以用来实现NFT)。它提供了创建、管理和操作代币的基础工具,包括代币的生成、分割、合并、供应量管理以及监管功能。
在本教程中,我将部分解析 coin.move
的设计与功能。
coin.move
旨在提供一套通用的代币操作接口,并支持高级功能如:
Coin
是代币的核心结构,用于表示某种类型 T
的代币及其余额。
public struct Coin<phantom T> has key, store {
id: UID,
balance: Balance<T>,
}
字段解析:
CoinMetadata
用于存储代币的元数据信息,如名称、符号、小数位数等。
public struct CoinMetadata<phantom T> has key, store {
id: UID,
decimals: u8,
name: string::String,
symbol: ascii::String,
description: string::String,
icon_url: Option<Url>,
}
字段解析:
TreasuryCap
用于管理代币的总供应量。
public struct TreasuryCap<phantom T> has key, store {
id: UID,
total_supply: Supply<T>,
}
功能解析:
DenyCapV2
为受监管代币提供高级功能,如地址限制和全局暂停。
public struct DenyCapV2<phantom T> has key, store {
id: UID,
allow_global_pause: bool,
}
功能解析:
通过 value 获取 Coin 的余额:
public fun value<T>(self: &Coin<T>): u64 {
self.balance.value()
}
将一个代币分割为两部分:
public fun split<T>(self: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext): Coin<T> {
take(&mut self.balance, split_amount, ctx)
}
将两个代币合并:
public entry fun join<T>(self: &mut Coin<T>, c: Coin<T>) {
let Coin { id, balance } = c;
id.delete();
self.balance.join(balance);
}
创建一个余额为 0 的占位代币:
public fun zero<T>(ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance: balance::zero() }
}
public fun total_supply<T>(cap: &TreasuryCap<T>): u64 {
balance::supply_value(&cap.total_supply)
}
通过 TreasuryCap 创建新的代币:
public fun mint<T>(cap: &mut TreasuryCap<T>, value: u64, ctx: &mut TxContext): Coin<T> {
Coin {
id: object::new(ctx),
balance: cap.total_supply.increase_supply(value),
}
}
减少代币的总供应量:
public entry fun burn<T>(cap: &mut TreasuryCap<T>, c: Coin<T>): u64 {
let Coin { id, balance } = c;
id.delete();
cap.total_supply.decrease_supply(balance)
}
添加地址到禁止列表:
public fun deny_list_v2_add<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCapV2<T>,
addr: address,
ctx: &mut TxContext,
) {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_add(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
立即禁止所有地址使用代币:
public fun deny_list_v2_enable_global_pause<T>(
deny_list: &mut DenyList,
deny_cap: &mut DenyCapV2<T>,
ctx: &mut TxContext,
) {
assert!(deny_cap.allow_global_pause, EGlobalPauseNotAllowed);
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_enable_global_pause(DENY_LIST_COIN_INDEX, ty, ctx)
}
支持动态更新代币的元数据:
public entry fun update_name<T>(
_treasury: &TreasuryCap<T>,
metadata: &mut CoinMetadata<T>,
name: string::String,
) {
metadata.name = name;
}
public fun create_currency<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
ctx: &mut TxContext,
): (TreasuryCap<T>, CoinMetadata<T>) {
(
TreasuryCap {
id: object::new(ctx),
total_supply: balance::create_supply(witness),
},
CoinMetadata {
id: object::new(ctx),
decimals,
name: string::utf8(name),
symbol: ascii::string(symbol),
description: string::utf8(description),
icon_url,
},
)
}
注意这个witness
,这里使用了一次性见证者
的设计模式,我将在下一篇教程中进行讲述与探讨。
而我们同样可以创建被管理的代币:
public fun create_regulated_currency_v2<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
allow_global_pause: bool,
ctx: &mut TxContext,
): (TreasuryCap<T>, DenyCapV2<T>, CoinMetadata<T>) {
let (treasury_cap, metadata) = create_currency(
witness,
decimals,
symbol,
name,
description,
icon_url,
ctx,
);
let deny_cap = DenyCapV2 {
id: object::new(ctx),
allow_global_pause,
};
transfer::freeze_object(RegulatedCoinMetadata<T> {
id: object::new(ctx),
coin_metadata_object: object::id(&metadata),
deny_cap_object: object::id(&deny_cap),
});
(treasury_cap, deny_cap, metadata)
}
源代码对其的解释是:
通过调用
create_currency
创建一种新的货币类型,并附加了一项额外功能,允许将特定地址的代币冻结。当一个地址被添加到禁止列表时, 它将立即无法将该货币的代币用作交易的输入对象。
此外,从下一个纪元开始,这些地址将无法接收该货币的代币。
allow_global_pause
标志启用了一个额外的 API,可禁止所有地址操作该货币的代币。需要注意的是,这不会影响禁止列表中针对单个地址的条目, 也不会更改 "contains" API 的返回结果。
另外,如果需要使用上述代币管理的相关功能,在创建代币时,我们必须调用create_regulated_currency_v2
创建可被管理的代币。
Coin是sui链的基本资产,因此,理解和使用Coin也是sui move学习最重要的一部分。
还有一些额外的功能与特性我在本篇文章没有提到,希望大家主动去阅读源码,甚至编写用例进行调试。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!