我们设计一个实现基本代币和余额接口的模块,代币可以在不同地址下的余额之间铸造和转移。
/// 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的存储区别:
mapping(address => uint256)
 /// Struct representing the balance of each address.
struct Balance has key {
    coin: Coin // same Coin from Step 1
}Move没有自己的存储,相反 Move 使用的"全局存储"(我们称之为区块链状态)按地址编制索引。每个地址下都有"Move 模块(代码)"和"Move资源(值)"。
[package]
name = "myCoin"
version = "0.0.0"
[addresses]
std = "0x1"
MyCoinAddr = "0xf"
[dependencies]
AptosStdlib = { local = "../aptos-stdlib" }
MoveStdlib = { local = "../move-stdlib" }
/// 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限制只有模块发布者才能铸造代币
此方法将资源发布到给定地址。由于通过铸币或转账接收硬币需要此资源,因此用户必须先调用此方法,然后才能接收代币
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}});
    }
}
铸币方法将硬币铸造到给定的账户,在这里我们要求必须得到模块所有者的批准。我们使用assert语句实现。
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私有方法存入代币
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;
}
查询地址余额
public fun balance_of(owner: address): u64 acquires Balance {
    borrow_global<Balance>(owner).coin.value
}
此函数从的余额中提取代币,并将代币存入的余额中。
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 私有方法从余额中提取代币
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地址
// 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);
    }
}
$ 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                        如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!