编程化代币铸造

我们已经学习了如何使用生成的 TreasuryCap 对象来铸造代币。 然而,只有 TreasuryCap 的所有者可以调用它。如果我们想允许用户自由铸造代币(可能有一定的限制)呢?这该如何实现?

如果你查看 TreasuryCap 对象结构体的定义,它具有 store 能力:

/// 允许持有者铸造和销毁类型为 `T` 的代币的能力。可转让。
public struct TreasuryCap<phantom T> has key, store {
    id: UID,
    total_supply: Supply<T>
}

这意味着,它可以存储在其他结构体和对象中!因此,解决方案是将其包装在一个任何人都可以访问并提供给铸币函数作为参数的共享对象中:

use std::string;
use sui::url;

public struct MYCOIN has drop {}

public struct TreasuryCapHolder has key {
    id: UID,
    treasury_cap: TreasuryCap<MYCOIN>,
}

fun init(otw: MYCOIN, ctx: &mut TxContext) {
    let (treasury_cap, metadata) = coin::create_currency(
        otw,
        9,
        b"MYC",
        b"MyCoin",
        b"My Coin description",                       
        option::some(url::new_unsafe(string::utf8(b"https://mycoin.com/logo.png"))),
        ctx,
    );
    transfer::public_freeze_object(metadata);
    
    let treasury_cap_holder = TreasuryCapHolder {
        id: object::new(ctx),
        treasury_cap,
    };
    transfer::share_object(treasury_cap_holder);
}

entry fun mint(treasury_cap_holder: &mut TreasuryCapHolder, ctx: &mut TxContext) {
    let treasury_cap = &mut treasury_cap_holder.treasury_cap;
    let coins = coin::mint(treasury_cap, 1000, ctx);
    // 用coin做点什么
}

在上述示例中,我们将 TreasuryCap 包装在一个共享的 TreasuryCapHolder 对象中。现在任何人都可以将 &mut TreasuryCapHolder 传递给铸币函数,自由地铸造 MYCOIN 代币。实际上,开发人员应该添加一些限制,例如总共可以铸造多少代币、每个用户可以铸造多少代币、基于白名单的控制等。

如在对象课程中讨论的那样,除了将 TreasuryCap 对象包装到另一个持有对象中之外,我们还可以利用动态字段、动态对象字段甚至对象所有权来保留 TreasuryCap。然而,包装通常是首选,因为在访问时它更简单。