Coin
标准代币协议
Coin 是 Sui 上的标准代币协议
/// A coin of type `T` worth `value`. Transferable and storable
public struct Coin<phantom T> has key, store {
id: UID,
balance: Balance<T>
}
Coin
内部有一个 id
字段表面是一个对象,只有一个 类型为 Balance
的字段 我们把 Balance
的源码也放出来
public struct Balance<phantom T> has store {
value: u64
}
Balance
类型只有一个类型为u64
的 value
字段 和一个泛型的占位符 T
示例: 创建一个 Coin
module coin_test::solo {
use sui::coin;
use sui::transfer::{public_freeze_object, public_transfer};
use sui::tx_context::sender;
public struct SOLO has drop {}
fun init(witness: SOLO, ctx: &mut TxContext) {
// 创建一个coin
let (treasuryCap, metadata) = coin::create_currency(
witness,
6, // decimals
b"USDC", // symbol
b"USDC", // name
b"Stable coin", // description
option::none(), // icon url
ctx
);
// 共享 metadata 所有权, 不可被修改
public_freeze_object(metadata);
// 铸币权发送给交易发起者
public_transfer(treasuryCap, sender(ctx));
}
}
命令行调用
sui client call --package 0x2 --module coin --function mint_and_transfer --args <treasuryCap> <amount> <recipient> --type-args <package id>::<module name>::<witness name>
实际调用的是方法 sui::coin::mint_and_transfer
--args
指定方法参数--type-args
指定方法接收的泛型
自定义铸币行为
treasuryCap
遵循的是 coin
标准的协议, 但可以自定义铸币行为
module coin_test::supply_coin {
use std::option;
use sui::balance;
use sui::balance::{Supply, supply_value};
use sui::coin;
use sui::coin::{treasury_into_supply, Coin, balance};
use sui::object;
use sui::transfer::{public_freeze_object, public_transfer, share_object};
public struct MintCap<phantom T> has key {
id: UID,
supply: Supply<T>
}
public struct SUPPLY_COIN has drop {}
fun init(witness: SUPPLY_COIN, ctx: &mut TxContext) {
// 创建一个coin
let (treasury, metadata) = coin::create_currency(
witness,
6, // decimals
b"USDC", // symbol
b"USDC", // name
b"Stable coin", // description
option::none(), // icon url
ctx
);
// 共享 metadata 所有权, 不可被修改
public_freeze_object(metadata);
// 销毁铸币权, 返回铸币权中保存的 supply 字段
let supply = treasury_into_supply(treasury);
let mintCap = MintCap {
id: object::new(ctx),
supply
};
share_object(mintCap);
}
public fun mint(mintCap: &mut MintCap<SUPPLY_COIN>, amount: u64, ctx: &mut TxContext): Coin<SUPPLY_COIN> {
let MintCap{id: _, supply} = mintCap;
if (supply_value(supply) + amount > 10000) abort 0;
let supply_balance = balance::increase_supply(&mut mintCap.supply, amount);
coin::from_balance(supply_balance, ctx)
}
}
锁定 Coin
module coin_lock::lock_coin {
use std::option;
use sui::balance::Balance;
use sui::coin;
use sui::coin::{TreasuryCap, balance};
use sui::object;
use sui::object::{UID, id};
use sui::transfer;
use sui::transfer::public_transfer;
use sui::tx_context::{Self, TxContext, sender};
const ErrNotRelease :u64 = 0x00001;
public struct LOCK_COIN has drop {}
public struct LockCoin has key {
id: UID,
balance: Balance<LOCK_COIN>,
release_time: u64
}
fun init(witness: LOCK_COIN, ctx: &mut TxContext) {
let (treasury, metadata) = coin::create_currency(witness, 6, b"USD", b"", b"", option::none(), ctx);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury, tx_context::sender(ctx));
}
public entry fun mint_and_lock(
treasury: &mut TreasuryCap<LOCK_COIN>,
amount: u64,
lock_day: u64,
to: address,
ctx: &mut TxContext
) {
let coin = coin::mint(treasury, amount, ctx);
let current_ms = tx_context::epoch_timestamp_ms(ctx);
let lock = LockCoin {
id: object::new(ctx),
balance: coin::into_balance(coin),
release_time: current_ms + (lock_day * 24 * 3600 * 1000)
};
transfer::transfer(lock, to);
}
public entry fun unlock_coin(lock_coin: LockCoin, ctx: &mut TxContext) {
let current_ms = tx_context::epoch_timestamp_ms(ctx);
assert!(current_ms > lock_coin.release_time, ErrNotRelease);
let LockCoin { id,balance,release_time:_ }= lock_coin;
let unlock_coin = coin::from_balance(balance,ctx);
public_transfer(unlock_coin,sender(ctx));
object::delete(id);
}
}