我们设计一个实现基本代币和余额接口的模块,代币可以在不同地址下的余额之间铸造和转移。
/// 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
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!