sui coin 的一些概念 设计思想和练习

1. 货币具有如下特征, sui coin 实现对应的特征

1.1 货币的特征

  • 发币权限

    • 控制发布权限
      • 一般来说,我们需要控制货币的发行量, 一般限制特定的人或组织才能发型货币.
        • 若货币无限制发型, 货币就没有价值
    • sui 使用TreasuryCap 对象的所有权来控制货币的发行权
    • 共享发币权限—faucet
      • 这种情况只用作测试 本文不做讨论。
  • 货币的总供应量

    • sui 采用 Supply
      • 能增加发行量, 提供新的余额Balance , increase_supply
      • 能回收货币余额,减少货币供应 decrease_supply
  • coin货币的余额(balance) , 也就是:面值几块钱

    • 数字货币,余额可以变动
    • 可以3块的货币,拆成 2.5元 和0.5元 两个coin
  • coin 货币有特征, 人民币之所以是人民币,不是美元,是因为人民币有独特的图形

    • 对应 CoinMetadata

1.2 Sui Coin相关对象类型关系图

image-20241116221238292

- create_currency 是货币创建的函数, 返回一个TreasuryCap 对象和一个CoinMetadata对象
- CoinMetadata 表示货币的小数位,名称,图标.
- TreasuryCap 持有一个Supply对象,这个Supply是实现货币增长和减少的关键对象.
- Supply 能提供货币余额 Balance, 同时增加总货币供应量.
- Coin 表示可以保存在链上的货币
- Balance 可以转换成Coin 存储到链上,转移给某个用户
- Coin也可以转换成Balance  余额,Balance没有key能力, 但是具有store能力,可以作为其他对象的字段.
- Coin 和Balance 可以通过join(两个币合成一个),split( 一个币分成2个)

1.3 CoinMetadata ,

可以认为是一种货币的展现形式, 例如没有,就是这个样子的.

通过这个数据结构,告诉我的货币是美元,就能展现成美元的形式.

电影《无双》中为什么画家需要手绘美元母版? - 知乎

或者日元:

img

1.4 我们定义的货币Coin , 和CoinMetadata 是怎么关联上的呢**?

  • 是根据他们的泛型参数T 关联的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/// A coin of type `T` worth `value`. Transferable and storable
public struct Coin<phantom T> has key, store {
id: UID,
balance: Balance<T>,
}

/// Each Coin type T created through `create_currency` function will have a
/// unique instance of CoinMetadata<T> that stores the metadata for this coin type.
public struct CoinMetadata<phantom T> has key, store {
id: UID,
/// Number of decimal places the coin uses.
/// A coin with `value ` N and `decimals` D should be shown as N / 10^D
/// E.g., a coin with `value` 7002 and decimals 3 should be displayed as 7.002
/// This is metadata for display usage only.
decimals: u8,
/// Name for the token
name: string::String,
/// Symbol for the token
symbol: ascii::String,
/// Description of the token
description: string::String,
/// URL for the token logo
icon_url: Option<Url>,
}

2. 货币的诞生:

2.1 货币诞生相关函数的启发

参看 0x2:sui::coin 的创建货币的代码,需要一个otw对象.
image-20241111221059544

货币诞生需要这个泛型参数witness丢想是一个One Time Witness struct 对象

  • 这个结构体只能在模块同名大写, 并且由系统控制只构造一次

    例如 0x2::sui::SUI
    0X433 :: rmb::RMB

  • 不能通过编码构造这个对象

  • 避免通过升级package,增加一个函数 来构造otw 对象

这个例子中 witness 对象 只会在是一个OTW 对象,这个对象在模块初始化的时候构建,传入这个函数之后,在这个函数结束后销毁,因为它是移动所有权传递(没有copy ability), 同时具有drop ability.

这个方法执行的结果,会让这个货币相关查到Coin,CoinMetadata ,TreasuryCap ,Supply,Balance 这一系列对象,都有个类型参数type-argwitness参数的类型.

2.2 示例:发行一种日元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module coin_jp::jp{
public struct JP has drop{ }
const JpUrl:vector<u8> = b"https://tse4-mm.cn.bing.net/th/id/OIP-C.XVkbV--98d7_YfeLR2a_fAHaHa";

fun init( jp :JP , ctx : &mut TxContext)
{
let (treasuryCap,coinMetadata) = sui::coin::create_currency(
jp,
0,
b"YEN",
b"YEN of Japan",
b"Japanese money",
option::some(sui::url::new_unsafe_from_bytes(JpUrl)),
ctx);

transfer::public_transfer(treasuryCap,ctx.sender());
transfer::public_freeze_object(coinMetadata);
}
}
  • 注意模块名jp和 struct JP 的对应关系,OTW 结构体是模块名的大写. 这个结构体JP ,就是一个OTW 结构体,
  • init函数传入的jp对象,是package在部署的时候自动构造出来的对象.
  • 以后无法通过升级package来重新构建一个JP 类型的对象.这就保证了铸币能力 TreasuryCap.total_supply的唯一性.

这个定义,等于设置了一个日元的外观定义(CoinMetadata), 日元的增发权限 TreasuryCap , 以后发行的日元,余额, 都有特性花纹:

1
coin_jp::jp::JP

这个coin_jp是地址,当move package应该在发布的时候,确定其地址取值.

2.3 新建货币流程

image-20241116225504184

发布这个合约就是诞生了一种货币,我们其实只是定义了一种铸币权(包括货币增加 减少的能力), 和货币的样式 CoinMetadata, (方便在suiscan上浏览它)

3.货币的增发

增加货币(mint)流程

image-20241116231338675

1. 客户端发起mint_and_transfer 的rpc调用 。 客户端需要拥有访问TreasuryCap对象的权利 (增发货币的权力)
1. TreasuryCap 调用mint 方法还增加货币
1. Treasury 调用它的total_supply对象的increase_supply 方法
1. Supply 在balance 模块,能构建同一模块的Balance对象
1. Supply获得Balance对象
1. 返回Balance对象给TreasuryCap对象
1. TreasuryCap对象,用Balance对象来构造 coin模块中的Coin对象
1. 返回Coin对象
1. 通过public_transfer方法,讲Coin存到链上,归属给mint_and_transfer 参数中的地址。#

4. 发布合约,增发货币的调用脚本:

4.1 发布合约 脚本

1
sui client publish --skip-fetch-latest-git-deps --skip-dependency-verification
1
2
3
4
5
6
7
8
查看输出结果中的 0x2::coin::TreasuryCap 对象
│ ObjectID: 0x8e1bebaac6dd33bf486fb294981f13fb6946051f465db0c25401b61b01f7421e │
│ │ Sender: 0x540105a7d2f5f54a812c630f2996f1790ed0e60d1f9a870ce397f03e4cec9b38 │
│ │ Owner: Account Address ( 0x540105a7d2f5f54a812c630f2996f1790ed0e60d1f9a870ce397f03e4cec9b38 ) │
│ │ ObjectType: 0x2::coin::TreasuryCap<0x65a0995fd59c97b94fd975a3fb42c745cdff54711c1caae2934858e6eb99adb4::jp::JP> │
│ │ Version: 236167313 │
│ │ Digest: BnpekhzZQWQnR77hpGMZyhafRrMe57AyJainuFX8xEjg

相关对象标识, 为后续增发提供变量.

对象名 export name 对象值
package地址 PKG 0x65a0995fd59c97b94fd975a3fb42c745cdff54711c1caae2934858e6eb99adb4
0x2::coin::TreasuryCap 对象id JP_CAP 0x8e1bebaac6dd33bf486fb294981f13fb6946051f465db0c25401b61b01f7421e

4.2 调用合约 增发货币

1
2
3
4
5
6
7
8
9
10
11
12

# 根据前面的package地址和
export PKG=0x65a0995fd59c97b94fd975a3fb42c745cdff54711c1caae2934858e6eb99adb4
export JP_CAP=0x8e1bebaac6dd33bf486fb294981f13fb6946051f465db0c25401b61b01f7421e

# 获取当前激活的地址
export C_ADDR=`sui client active-address`

# 执行铸币,transfer给本地址
sui client call --package 0x2 --module coin --function mint_and_transfer --type-args $PKG::jp::JP --args $JP_CAP 8800000 $C_ADDR


查看输出结果,有创建的0x2::coin::Coin 对象.0x95245c704b124aa96f49ab1cdd459c7219d1dc1165faaeae80a514524e8308e2

1
2
3
4
5
6
7
8
9
10
11
 Created Objects:                                                                                                   │
│ ┌── │
│ │ ObjectID: 0x95245c704b124aa96f49ab1cdd459c7219d1dc1165faaeae80a514524e8308e2 │
│ │ Sender: 0x540105a7d2f5f54a812c630f2996f1790ed0e60d1f9a870ce397f03e4cec9b38 │
│ │ Owner: Account Address ( 0x540105a7d2f5f54a812c630f2996f1790ed0e60d1f9a870ce397f03e4cec9b38 ) │
│ │ ObjectType: 0x2::coin::Coin<0x65a0995fd59c97b94fd975a3fb42c745cdff54711c1caae2934858e6eb99adb4::jp::JP> │
│ │ Version: 236167314 │
│ │ Digest: Gh2shitikPnbxxffpPj5mnWwrUCNJChEPyCNaBB2YHMV



4.3 使用命令查看余额

1
2
3
# 查看获得货币
sui client balance $C_ADDR

1
2
3
4
5
6
7
8
9
10
11
ljl@ljl-i5-14400:~/work/sui/move-cn/letsmove/mover/nextuser/code$ sui client balance
[warn] Client/Server api version mismatch, client api version : 1.37.1, server api version : 1.37.2
╭──────────────────────────────────────────────╮
│ Balance of coins owned by this address │
├──────────────────────────────────────────────┤
│ ╭──────────────────────────────────────────╮ │
│ │ coin balance (raw) balance │ │
│ ├──────────────────────────────────────────┤ │
│ │ Sui 3637300968 3.63 SUI │ │
│ │ YEN of Japan 8800000 8.80M YEN │ │
│ ╰──────────────────────────────────────────╯ │

4.4 sui scan上查看coin对象

https://suiscan.xyz/testnet/object/0x95245c704b124aa96f49ab1cdd459c7219d1dc1165faaeae80a514524e8308e2

image-20241116223844785

1 . 能看到这个泛型的T 参数是模型名jp和结构体名JP的相似性

  1. owner是铸币时传递的地址
  2. 显示了货币的余额与图标

5. 附录:

最近在参加HOH 共学活动,

💧 HOH水分子公众号

🌊 HOH水分子X账号

📹 课程B站账号

💻 Github仓库 https://github.com/move-cn/letsmove