02-Starcoin – STC 部署第一个合约

合约安装环境

git clone https://github.com/starcoinorg/starcoin-framework.git
cd starcoin-framework
bash scripts/dev_setup.sh -y

要科学上网。 有时可能因为网络原因失败。多执行几次
安装完成后。会有生效一个mpm的CLI

mpm

有输出为安装成功

move 环境安装

git clone https://github.com/move-language/move.git
cd move
bash scripts/dev_setup.sh

如果失败。尝试cargo build --release
然后在./target/release/下复制move move-analyzer到path目录

move
rust-analyzer

有输出为配置成功。ctrl+c 退出

编辑器配置

VSCODE

合约编写

创建合约

mpm package new my_info
cd my_info
code .

这里使用VSCODE打开

├── Move.toml
└── sources
     └── my_info.move

默认情况下sources目录是空的。我们创建一个文件名为my_info.move的模块

module 0x2fe51c3d52c20c121f38a7765993e323::MyInfo{
}

执行 mpm package build

默认一个合约只有一个module可以使用。同时一个module可以use 其他module.
这里有一个钱包地址。是合约拥有者的地址。module是部署到这个钱包地址下。
同时move有resource这个概念。move是面向资源编程。同时每一个钱包地址都可以拥有无限个资源。

这里有两个概念。

  • module 拥有合约bytecode中的function
  • resource 拥有合约生命的resource

简单的例子。
将Token部署到 0x2fe51c3d52c20c121f38a7765993e323 是一个module。账户将token转账给另外一个账户的时候。

是将resource 结构体Copy到另外一个账户下。但这个账户并没有其他权限。只有一个resource .当调用合约是。是由0x2fe51c3d52c20c121f38a7765993e323 中的函数调用。获取到signer的address.通过address 借用到账户余额进行操作

编写合约


module MyInfo::MyInfo{
    use StarcoinFramework::Signer;

    struct Info has key,store{
        id:u128,
        age:u8,
    }

    fun init(account:&signer) {
        let a = Info{
            id:0,
            age:0,
        };
        move_to(account,a);        
    }

    fun info(account:&signer) acquires Info {
        let info = borrow_global_mut<Info>(Signer::address_of(account));
        info.id = info.id + 1;
        info.age = info.age +1;
    }

    public(script) fun init_info(account: signer){
        Self::init(&account);
    }

    public(script) fun set_info(account:signer) acquires Info{
        Self::info(&account);
    }
}

以上是参考官方的Couner例子改了一下。

有两个可执行函数。

init_info 给当前账户初始化resource
set_info 给当前合约resource 增加1

执行

mpm release 打包 release 包

account unlock #账户.

dev deploy /home/yusong/worker/move/my_info/release/my_info.v0.0.0.blob -b  #部署合约

部署完成后我们先确认钱包当前资源

state list  resource 0x2FE51c3D52C20c121f38a7765993e323
{
  "ok": {
    "resources": {
      "0x00000000000000000000000000000001::Account::Account": {
        "json": {
          "accept_token_events": {
            "counter": 1,
            "guid": "0x02000000000000002fe51c3d52c20c121f38a7765993e323"
          },
          "authentication_key": "0x68e22ee67b665e8c9a59c134791668132fe51c3d52c20c121f38a7765993e323",
          "deposit_events": {
            "counter": 8,
            "guid": "0x01000000000000002fe51c3d52c20c121f38a7765993e323"
          },
          "key_rotation_capability": {
            "vec": [
              {
                "account_address": "0x2fe51c3d52c20c121f38a7765993e323"
              }
            ]
          },
          "sequence_number": 5,
          "withdraw_events": {
            "counter": 4,
            "guid": "0x00000000000000002fe51c3d52c20c121f38a7765993e323"
          },
          "withdrawal_capability": {
            "vec": [
              {
                "account_address": "0x2fe51c3d52c20c121f38a7765993e323"
              }
            ]
          }
        },
        "raw": "0x2068e22ee67b665e8c9a59c134791668132fe51c3d52c20c121f38a7765993e323012fe51c3d52c20c121f38a7765993e323012fe51c3d52c20c121f38a7765993e32304000000000000001800000000000000002fe51c3d52c20c121f38a7765993e32308000000000000001801000000000000002fe51c3d52c20c121f38a7765993e32301000000000000001802000000000000002fe51c3d52c20c121f38a7765993e3230500000000000000"
      },
      "0x00000000000000000000000000000001::Account::AutoAcceptToken": {
        "json": {
          "enable": true
        },
        "raw": "0x01"
      },
      "0x00000000000000000000000000000001::Account::Balance<0x00000000000000000000000000000001::STC::STC>": {
        "json": {
          "token": {
            "value": 1157990203293
          }
        },
        "raw": "0x9d3f989d0d0100000000000000000000"
      },
      "0x00000000000000000000000000000001::Event::EventHandleGenerator": {
        "json": {
          "addr": "0x2fe51c3d52c20c121f38a7765993e323",
          "counter": 3
        },
        "raw": "0x03000000000000002fe51c3d52c20c121f38a7765993e323"
      }
    }
  }
}

目前我的账号是没有其他资源的。只有默认的资源。

account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::MyInfo::init_info -b

执行我们的init_info函数。初始化我们的资源给sender.这里没制定就是default 账户。

再次执行账号资源查看命令。可以看到输出多了一个节点。为我们的合约存储信息。

      "0x2fe51c3d52c20c121f38a7765993e323::MyInfo::Info": {
        "json": {
          "age": 0,
          "id": 0
        },
        "raw": "0x0000000000000000000000000000000000"
      }

接着我们尝试给我所有变量加1.

account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::MyInfo::set_info -b

执行后的resource

"0x2fe51c3d52c20c121f38a7765993e323::MyInfo::Info": {
        "json": {
          "age": 1,
          "id": 1
        },
        "raw": "0x0100000000000000000000000000000001"
}

增加部分功能


module MyInfo::NewMyInfo{
    use StarcoinFramework::Signer;

    struct Info has key,store{
        id:u128,
        age:u8,
    }

    fun init(account:&signer) {
        let a = Info{
            id:0,
            age:0,
        };
        move_to(account,a);        
    }

    fun sub(account:&signer) acquires Info{
        let info = borrow_global_mut<Info>(Signer::address_of(account));
        info.id = info.id + 1;
        info.age = info.age +1;        
    }

    fun add(account:&signer) acquires Info{
        let info = borrow_global_mut<Info>(Signer::address_of(account));
        info.id = info.id + 1;
        info.age = info.age +1;        
    }

    fun set(account:&signer,id:u128,age:u8) acquires Info {
        let info = borrow_global_mut<Info>(Signer::address_of(account));
        info.id = id;
        info.age = age;
    }

    public(script) fun init_info(account: signer){
        Self::init(&account);
    }

    public(script) fun set_info(account:signer,id:u128,age:u8) acquires Info{
        Self::set(&account,id,age);
    }

    public(script) fun sub_info(account:signer) acquires Info {
        Self::sub(&account);
    }

    public(script) fun add_info(account:signer) acquires Info {
        Self::sub(&account);
    }    
}

将合约改了以下。增加了add,sub,set,三种方式。我们部署和测试以下。

注意合约名称变了。目前没有升级需求。如需升级老合约。请看这里。

https://starcoin.org/zh/developer/blog/starcoin_stdlib_upgrade/

执行初始化

account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::NewMyInfo::init_info -b

直接增加100

account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::NewMyInfo::set_info --arg 1u128 --arg 100u8 -b

--arg 执行参数。id=1u128 age=100u8

验证下结果。

      "0x2fe51c3d52c20c121f38a7765993e323::MyInfo::Info": {
        "json": {
          "age": 1,
          "id": 1
        },
        "raw": "0x0100000000000000000000000000000001"
      },
      "0x2fe51c3d52c20c121f38a7765993e323::NewMyInfo::Info": {
        "json": {
          "age": 100,
          "id": 1
        },
        "raw": "0x0100000000000000000000000000000064"
      }

看到有两个资源。一个资源是老合约一个是新合约。新合约的age =100 和我们设置的是一样的。现在我们尝试用新账号初始化这个合约。

account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::NewMyInfo::init_info -b -s 0xac96380a94dceca80739826f24083c8c
account execute-function --function 0x2FE51c3D52C20c121f38a7765993e323::NewMyInfo::set_info --arg 1u128 --arg 255u8 -b -s 0xac96380a94dceca80739826f24083c8c
      "0x2fe51c3d52c20c121f38a7765993e323::NewMyInfo::Info": {
        "json": {
          "age": 255,
          "id": 1
        },
        "raw": "0x01000000000000000000000000000000ff"
      }

可以看到结果和之前验证的一样。也就是任何人都可以初始化这个module资源给自己。下一节为我们尝试部署一个标准token。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注