这里先介绍一下代币运行在 Move 上的玩法。

下载 Move Cli

Move 运行需要 Move CLI 客户端,就像运行 Java 代码需要下载配置 JDK。

  1. // 下载 move cli 文件
  2. $ cargo install --git https://github.com/diem/move move-cli --branch main
  3. // 在环境变量中配置PATH,如果安装了oh-my-zsh,在~/.zshrc中配置
  4. $ vim ~/.bash_profile
  5. // 添加move,保存并退出
  6. MOVE_HOME=/Users/{...}/.cargo/bin
  7. export PATH={...}:${MOVE_HOME}
  8. // 使配置文件生效
  9. $ source ~/.bash_profile

初始化Move项目

  1. // 初始化
  2. $ move package new toycoin
  3. // 初始化后的目录结构
  4. toycoin
  5. -- sources
  6. -- Move.toml
  7. // 在sources下创建 module 和 scripts 目录
  8. $ cd toycoin
  9. $ mkdir -p sources/modules
  10. $ mkdir -p sources/scripts

创建代币

1.编写模块文件

首先创建一个 module 文件,并把她发布在 0x1 address上,(Move 的标准库在是 Std address 上 ),在source/modules/Coin.move文件定义。

  1. address 0x1 {
  2. module Coin {
  3. // 默认情况下,move中的结构体是不能被复制和直接销毁的
  4. // has drop: 表示Coin结构体可以被直接销毁
  5. struct Coin has drop {
  6. value: u64,
  7. }
  8. public fun mint(value: u64): Coin {
  9. Coin { value }
  10. }
  11. }
  12. }

然后使用 Move Cli 发布 Modules。

  1. // -v 打印发布信息
  2. $ move sandbox publish -v
  3. Found 1 modules
  4. Publishing a new module 00000000000000000000000000000001::Coin (wrote 119 bytes)

发布完成后,会自动生成 build 和 storage 目录,先跳过。

2.运行可执行文件

首先创建一个 scripts 文件,在sources/scripts/Test.move文件定义。

  1. script {
  2. use 0x1::Coin;
  3. fun main() {
  4. let _coin = Coin::mint(100);
  5. }
  6. }

然后使用 Move Cli 执行。

  1. $ move sandbox run sources/scripts/Test.move

3.注意

  1. address 0x1 {
  2. module Coin {
  3. struct Coin has drop {
  4. value: u64,
  5. }
  6. public fun mint(value: u64): Coin {
  7. Coin { value }
  8. }
  9. }
  10. }

以上代码可以正常运行,但是这样实现的 Coin 不是很有用。如果 Coin 赋予了一个值,必须要确保她被使用掉了,例如:传递到其他函数体。否则,此 Coin 可能会丢失。
Move中,一个 resource 的值 (如Coin或者Asset),不能复制只能传递出去。

销毁代币

1.修改模块文件

只有 module 里面可以定义对 resource (如Coin或者Asset) 进行销毁。在source/modules/Coin.move添加以下定义。

  1. public fun value(coin: &Coin): u64 {
  2. coin.value
  3. }
  4. public fun burn(coin: Coin): u64 {
  5. let Coin { value } = coin;
  6. value
  7. }

以上代码中,value方法参数是传入了一个Coin的引用,这里只是读一下Coin的值,并不是传递到value函数体中了。而burn方法参数是将Coin结构体传递进来,在调用burn方法的时候,Coin结构体就传入了此方法作用域中。

然后使用 Move Cli 重新发布 Modules。

  1. $ move sandbox publish -v
  2. Updating an existing module 00000000000000000000000000000001::Coin (wrote 170 bytes)
  3. Wrote 170 bytes of module ID's and code

2.编写可执行文件

再创建一个 scripts 文件,在sources/scripts/Burn.move文件定义。

  1. script {
  2. // move 原生依赖提供的打印方法
  3. use Std::Debug;
  4. use 0x1::Coin;
  5. fun main() {
  6. let coin = Coin::mint(100);
  7. Debug::print(&Coin::value(&coin));
  8. Coin::burn(coin);
  9. }
  10. }

因为上面使用了move的原生依赖,所以需要在Move.toml中添加依赖,最终为:

  1. [package]
  2. name = "toycoin"
  3. version = "0.0.0"
  4. [addresses]
  5. Std = "0x1" # Specify and assign 0x1 to the named address "Std"
  6. [dependencies]
  7. MoveNursery = { git = "https://github.com/diem/move.git", subdir = "language/move-stdlib/nursery", rev = "7e593a2" }

然后使用 Move Cli 执行。

  1. $ move sandbox run sources/scripts/Burn.move
  2. [debug] 100

3.补充

通过”&”来传递 Coin 结构体的引用,这里只是读取了一下值;当没有”&”的 Coin 传递到 burn函数后,Coin 结构体就不在我们 script 的作用域中了,因为 move 要确保一个 resource (Coin或asset) 不会意外走丢。