前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.MOVE从入门到实战-简单的ERC20

6.MOVE从入门到实战-简单的ERC20

作者头像
Tiny熊
发布2022-11-07 11:12:26
4300
发布2022-11-07 11:12:26
举报
文章被收录于专栏:深入浅出区块链技术

本文作者:木头[1]

公共接口设计

代码语言:javascript
复制
/// Publish an empty balance resource under `account`'s address. This function must be called before
/// minting or transferring to the account.
public fun init_account(account: &signer) { ... }

/// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner.
public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { ... }

/// Returns the balance of `owner`.
public fun balance_of(owner: address): u64 acquires Balance { ... }

/// Transfers `amount` of tokens from `from` to `to`.
public fun transfer(from: &signer, to: address, amount: u64) acquires Balance { ... }

Move 和 Solidity 的存储区别:

Solidity:在大多数以太坊ERC-20[2]合约中,每个地址的余额存储在类型为的状态变量中,该状态变量存储在特定智能合约的存储器中。

代码语言:javascript
复制
mapping(address => uint256)

Move:每个地址下的"move 资源存储"是从类型到值的映射。观察力敏锐的读者可能会观察到,这意味着每个地址每种类型的一个值只能有一个值。这方便地为我们提供了按地址索引的本机映射。在我们的模块中,我们定义了以下资源,表示每个地址持有的硬币数量:

代码语言:javascript
复制
/// Struct representing the balance of each address.
struct Balance has key {
   coin: Coin // same Coin from Step 1
}

Move 没有自己的存储,相反 Move 使用的"全局存储"(我们称之为区块链状态)按地址编制索引。每个地址下都有"Move 模块(代码)"和"Move 资源(值)"。

接口模块实现

新建项目[3]

Move.toml

代码语言:javascript
复制
[package]
name = "myCoin"
version = "0.0.0"

[addresses]
std = "0x1"
MyCoinAddr = "0xf"

[dependencies]
AptosStdlib = { local = "../aptos-stdlib" }
MoveStdlib = { local = "../move-stdlib" }

代币基础模块

代码语言:javascript
复制
/// sources/MyCoin.move
module MyCoinAddr::MyCoin{
    use std::signer;

    /// Address of the owner of this module
    const MODULE_OWNER: address = @MyCoinAddr;

    /// Error codes
    const ENOT_MODULE_OWNER: u64 = 0;
    const EINSUFFICIENT_BALANCE: u64 = 1;
    const EALREADY_HAS_BALANCE: u64 = 2;
    const ACCOUNT_INITIALIZED: u64 = 3;

    struct Coin has store {
        value: u64
    }

    ///  Struct representing the balance of each address.
    struct Balance has key {
        coin: Coin
    }
}

MODULE_OWNER限制只有模块发布者才能铸造代币

方法 init_account()

此方法将资源发布到给定地址。由于通过铸币或转账接收硬币需要此资源,因此用户必须先调用此方法,然后才能接收代币

代码语言:javascript
复制
public fun init_account(account: &signer) {
    let account_addr = signer::address_of(account);
    // TODO: add an assert to check that `account` doesn't already have a `Balance` resource.
    assert!(!exists<Balance>(account_addr), ACCOUNT_INITIALIZED);
    if(!exists<Balance>(account_addr)){
        move_to(account, Balance {coin: Coin {value: 0}});
    }
}

方法 mint()

铸币方法将硬币铸造到给定的账户,在这里我们要求必须得到模块所有者的批准。我们使用 assert 语句实现。

代码语言:javascript
复制
public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance {
    // Only the owner of the module can initialize this module
    assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER);

    // Deposit `amount` of tokens to `mint_addr`'s balance
    deposit(mint_addr, Coin { value: amount });
}

deposit私有方法存入代币

代码语言:javascript
复制
fun deposit(_addr: address, check: Coin) acquires Balance {
    let balance = balance_of(_addr);
    // borrow_global_mut
    let balance_ref = &mut borrow_global_mut<Balance>(_addr).coin.value;
    let Coin { value } = check;
    *balance_ref = balance + value;
}

方法 balance_of()

查询地址余额

代码语言:javascript
复制
public fun balance_of(owner: address): u64 acquires Balance {
    borrow_global<Balance>(owner).coin.value
}

方法 transfer()

此函数从的余额中提取代币,并将代币存入的余额中。

代码语言:javascript
复制
public fun transfer(from: &signer, to: address, amount: u64) acquires Balance {
    // balance - amount
    let check = withdraw(signer::address_of(from), amount);
    // add amount
    deposit(to, check);
}

withdraw 私有方法从余额中提取代币

代码语言:javascript
复制
fun withdraw(addr: address, amount: u64):Coin acquires Balance {
    let balance = balance_of(addr);
    // balance must be greater than the withdraw amount
    assert!(balance >= amount, EINSUFFICIENT_BALANCE);
    let balance_ref = &mut borrow_global_mut<Balance>(addr).coin.value;
    *balance_ref = balance - amount;
    Coin { value: amount }
}

编写脚本

  1. 将资源发布到0xf 0xa地址,并且只能发布一次
  2. 铸造 100 个代币到0xa地址
  3. 0xa地址转账 50 个代币给到0xf地址
代码语言:javascript
复制
// sources/Main.move
script {

    use MyCoinAddr::MyCoin;
    use std::signer;
    use std::debug;

    fun main(account: signer, mint_addr: signer) {
        //Initialize account
        MyCoin::init_account(&account);
        MyCoin::init_account(&mint_addr);
        // mint
        MyCoin::mint(&account, signer::address_of(&mint_addr), 100);
        // balance
        let mintBalance = MyCoin::balance_of(signer::address_of(&mint_addr));
        debug::print(&mintBalance);
        // transfer
        MyCoin::transfer(&mint_addr, signer::address_of(&account), 50);

        // balance
        let accountBalance = MyCoin::balance_of(signer::address_of(&account));
        debug::print(&accountBalance);
        let mintNewBalance = MyCoin::balance_of(signer::address_of(&mint_addr));
        debug::print(&mintnewBalance);
    }
}

执行脚本

代码语言:javascript
复制
$ move build
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING myCoin
$ move sandbox publish -v
Found 1 modules
Publishing a new module 0000000000000000000000000000000F::MyCoin (wrote 566 bytes)
Wrote 566 bytes of module ID's and code
$ move sandbox run sources/Main.move --signers 0xf 0xa
[debug] 100
[debug] 50
[debug] 50

参考资料

[1]

木头: https://learnblockchain.cn/people/3015

[2]

ERC-20: https://learnblockchain.cn/article/977

[3]

新建项目: https://learnblockchain.cn/article/4512

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 公共接口设计
  • 接口模块实现
    • Move.toml
      • 代币基础模块
        • 方法 init_account()
          • 方法 mint()
            • 方法 balance_of()
              • 方法 transfer()
              • 编写脚本
                • 执行脚本
                  • 参考资料
                  相关产品与服务
                  对象存储
                  对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档