基于coin创建的同质化代币

这篇具有很好参考价值的文章主要介绍了基于coin创建的同质化代币。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言

本文通过对sui-framework包下的coin相关实现进行部分解读,了解move中如何基于coin创建同质化代币

代币创建

阅读Coin合约的实现:

首先来看两个基本的obj


 struct CoinMetadata<phantom T> has key, store {
        id: UID,
        /// Number of decimal places the coin uses.
        /// A coin with `value ` N and `decimals` D should be shown as N / 10^D
        /// E.g., a coin with `value` 7002 and decimals 3 should be displayed as 7.002
        /// This is metadata for display usage only.
        decimals: u8,
        /// Name for the token
        name: string::String,
        /// Symbol for the token
        symbol: ascii::String,
        /// Description of the token
        description: string::String,
        /// URL for the token logo
        icon_url: Option<Url>
    }

这个obj定义了同质化代币的元数据,包括小数位数,代币名称,代币标志,代币的描述和url(可为空)。


    struct TreasuryCap<phantom T> has key, store {
        id: UID,
        total_supply: Supply<T>
    }

这个obj是同质化代币权限凭证,用有此凭证的人才可以进行铸币和销毁操作。同样地,泛型T也是一次性见证,用来区别代币种类。

那么我们要想创建一个同质化代币,应该进行什么操作呢?

  • 生成一次性见证:coin合约创建代币需要通过一次性见证来区分代币类型,并且由于一次性见证是唯一的,只有一个实例,且使用完被消耗。保证相同类型的代币不会被重复创建。
  • 调用Coin合约的create_currency函数:
 public fun create_currency<T: drop>(
        witness: T,
        decimals: u8,
        symbol: vector<u8>,
        name: vector<u8>,
        description: vector<u8>,
        icon_url: Option<Url>,
        ctx: &mut TxContext
    ): (TreasuryCap<T>, CoinMetadata<T>) {
        // Make sure there's only one instance of the type T
        assert!(sui::types::is_one_time_witness(&witness), EBadWitness);

        (
            TreasuryCap {
                id: object::new(ctx),
                total_supply: balance::create_supply(witness)
            },
            CoinMetadata {
                id: object::new(ctx),
                decimals,
                name: string::utf8(name),
                symbol: ascii::string(symbol),
                description: string::utf8(description),
                icon_url
            }
        )
    }

调用create_currency后,coin合约检查输入的witness是否为一次性见证,之后会为我们的代币创建TreasuryCap obj和CoinMetadata obj并返回。

  • 处理返回的TreasuryCap 和CoinMetadata
    CoinMetadata是我们的代币元数据
    如果使用transfer::public_freeze_object将其变为不可变对象,使其不能更改、传输或删除,但所有人都可以使用。
    如果后续需要更改代币元数据请勿这样处理。coin合约提供了一些方法允许TreasuryCap所有者对元数据进行更改
    TreasuryCap是权限凭证,因此一般将所有权转移给代币的主人,也就是交易发起者

实例:

module token::token{

    use std::option;
    use sui::coin::{Self, Coin, TreasuryCap};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};

    struct TOKEN has drop{}

    fun init(witness: TOKEN,ctx: &mut TxContext){
        let (treasury_cap,metadata) = coin::create_currency<TOKEN>(witness,18,b"shaflow",b"shaflow01",b"",option::none(),ctx);
        transfer::public_freeze_object(metadata);
        transfer::public_transfer(treasury_cap,tx_context::sender(ctx));
    }

}

在合约的构造函数中,我调用coin的create_currency创建了一个名称为shaflow的代币,并且将权限凭证转移给了合约创建者。

代币流通

先阅读合约实现
sui-framework/coin:

    struct Coin<phantom T> has key, store {
        id: UID,
        balance: Balance<T>
    }

这是一个obj,实现了key和store能力。其中参数T封装了一次性见证,用于区分代币种类。
可以将Coin理解一类同质化代币的小钱包,T就区分了钱包中封装了什么类型的代币,balance代表了封装的代币的余额,Coin的所有者就规定了这个钱包是属于谁的。而我们花费代币时,一般需要将我们拥有的Coin传入。
在交易过程中,可能有Coin封装balance生成,也可能有Coin被销毁,其中的balance被提取出来。

这是balance的类型
sui-framework/balance:

    struct Balance<phantom T> has store {
        value: u64
    }

balance合约中实现了与balance相关的函数:

sui-framework/balance:

    public fun value<T>(self: &Balance<T>): u64 {
        self.value
    }

    public fun zero<T>(): Balance<T> {
        Balance { value: 0 }
    }

    public fun destroy_zero<T>(balance: Balance<T>) {
        assert!(balance.value == 0, ENonZero);
        let Balance { value: _ } = balance;
    }

    public fun join<T>(self: &mut Balance<T>, balance: Balance<T>): u64 {
        let Balance { value } = balance;
        self.value = self.value + value;
        self.value
    }

    public fun split<T>(self: &mut Balance<T>, value: u64): Balance<T> {
        assert!(self.value >= value, ENotEnough);
        self.value = self.value - value;
        Balance { value }
    }

    public fun withdraw_all<T>(self: &mut Balance<T>): Balance<T> {
        let value = self.value;
        split(self, value)
    }
  • value: 传入balance的不可变引用,返回balance中的value值
  • zero:创建一个value为0的balance并返回
  • destroy_zero:用于销毁一个value为0的balance。传入balance。
  • join:用于将两个balance合并为一个balance。传入第一个balance的可变引用,第二个将直接对象传入。这样第一个balance的value将会被加上第二个balance拥有的value,之后第二个balance被释放销毁。
  • split: 用于拆分一个balance。传入带拆分balance的可变引用,然后传入要拆分的value。balance减去value,并新创建一个含有value的balance对象并返回。
  • withdraw_all: 将一个balance的value全部拆分,但是保留原balance对象

还记得supply吗?它被封装在TreasuryCap中,代表我们代币的总供应。让我们也阅读一下它的类型和相关函数的实现

    struct Supply<phantom T> has store {
        value: u64
    }

    public fun increase_supply<T>(self: &mut Supply<T>, value: u64): Balance<T> {
        assert!(value < (18446744073709551615u64 - self.value), EOverflow);
        self.value = self.value + value;
        Balance { value }
    }

    public fun decrease_supply<T>(self: &mut Supply<T>, balance: Balance<T>): u64 {
        let Balance { value } = balance;
        assert!(self.value >= value, EOverflow);
        self.value = self.value - value;
        value 
    }

  • increase_supply: 增加供应,传入supply的可变引用,要增加的供应量。函数最终返回了含有等量value的balance对象
  • decrease_supply: 减少供应,传入supply的可变引用,balance对象,最终supply减少,相应的balance对象被销毁
  • 注:assert!(value < (18446744073709551615u64 - self.value), EOverflow)与assert!(self.value >= value, EOverflow)是为了防止溢出。rust中存在溢出检查,但是在Release模式下发布不会存在溢出检查,所以猜测move的包是在Release模式下发布。
铸造代币

了解了这些,我们来看看如何铸造代币
coin合约提供了两个方法

    public fun mint<T>(
        cap: &mut TreasuryCap<T>, value: u64, ctx: &mut TxContext,
    ): Coin<T> {
        Coin {
            id: object::new(ctx),
            balance: balance::increase_supply(&mut cap.total_supply, value)
        }
    }

    public fun mint_balance<T>(
        cap: &mut TreasuryCap<T>, value: u64
    ): Balance<T> {
        balance::increase_supply(&mut cap.total_supply, value)
    }

通常情况下,我们只需要调用coin mint方法,函数会增加总供应并为我们返回一个Coin对象,之后我们把Coin对象转移给我们指定的铸造地址
如果需要铸造未被Coin封装的Balance,那么可以直接调用mint_balance

  • 注:需要TreasuryCap权限凭证的拥有者才可调用
    为刚才的实例合约补充mint方法
    public entry fun mint(treasury_cap: &mut TreasuryCap<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        let new_coin = coin::mint(treasury_cap,amount,ctx);
        transfer::public_transfer(new_coin,receipt);
    }

而继续阅读,会发现coin合约提供了一个更便利的方法,创建Coin后转移

    public entry fun mint_and_transfer<T>(
        c: &mut TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut TxContext
    ) {
        transfer::public_transfer(mint(c, amount, ctx), recipient)
    }

因此可以直接调用此函数实现mint 一下方法与上述事例补充函数等效

    public entry fun mint_and_tranfer(treasury_cap: &mut TreasuryCap<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        coin::mint_and_transfer(treasury_cap,amount,receipt,ctx);
    }
销毁代币
    public entry fun burn<T>(cap: &mut TreasuryCap<T>, c: Coin<T>): u64 {
        let Coin { id, balance } = c;
        object::delete(id);
        balance::decrease_supply(&mut cap.total_supply, balance)
    }

传入待销毁的coin,减少总供应,之后Coin被销毁

  • 注:需要TreasuryCap权限凭证的拥有者才可调用
    为实例合约补充burn功能
    public entry fun burn(treasury_cap:&mut TreasuryCap<TOKEN>,coin: Coin<TOKEN>){
        coin::burn(treasury_cap,coin);
    }
代币转移

Coin的拥有者可以将自己的Coin转移给其他人来实现
也可以我们在自己的合约中实现方便调用
接下来让我们继续完善代币合约,可以在自己的合约中定义转移规则方便代币在用户间的相互转移

    public entry fun transfer(coin:&mut Coin<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        let new_coin = coin::split(coin,amount,ctx);
        transfer::public_transfer(new_coin,receipt);
    }

这里没有amount做检查是因为检查会发生在balance::split

其中与coin有关的有这些函数


    public fun take<T>(
        balance: &mut Balance<T>, value: u64, ctx: &mut TxContext,
    ): Coin<T> {
        Coin {
            id: object::new(ctx),
            balance: balance::split(balance, value)
        }
    }

    public entry fun join<T>(self: &mut Coin<T>, c: Coin<T>) {
        let Coin { id, balance } = c;
        object::delete(id);
        balance::join(&mut self.balance, balance);
    }


    public fun split<T>(
        self: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext
    ): Coin<T> {
        take(&mut self.balance, split_amount, ctx)
    }

完整实例代码:

module token::token{

    use std::option;
    use sui::coin::{Self, Coin, TreasuryCap};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};
    use sui::event;


    struct TOKEN has drop{}


    fun init(witness: TOKEN,ctx: &mut TxContext){
        let (treasury_cap,metadata) = coin::create_currency<TOKEN>(witness,18,b"SULC",b"SUL COIN",b"",option::none(),ctx);
        transfer::public_freeze_object(metadata);
        transfer::public_transfer(treasury_cap,tx_context::sender(ctx));
    }

    public entry fun mint_and_transfer(treasury_cap: &mut TreasuryCap<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        coin::mint_and_transfer(treasury_cap,amount,receipt,ctx);
    }

    public entry fun burn(treasury_cap:&mut TreasuryCap<TOKEN>,coin: Coin<TOKEN>){
        coin::burn(treasury_cap,coin);
    }

    public entry fun mint(treasury_cap: &mut TreasuryCap<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        let new_coin = coin::mint(treasury_cap,amount,ctx);
        transfer::public_transfer(new_coin,receipt);
    }

    public entry fun transfer(coin:&mut Coin<TOKEN>,amount: u64,receipt: address,ctx: &mut TxContext){
        let new_coin = coin::split(coin,amount,ctx);
        transfer::public_transfer(new_coin,receipt);
    }

}

上述是基于coin合约创建同质化代币的基本内容。coin合约中还有提供的一些函数没有涉及,待继续阅读分析。
(未完待续)

Move语言学习交流QQ群: 79489587
Sui官方中文开发者电报群: https://t.me/sui_dev_cn文章来源地址https://www.toymoban.com/news/detail-853918.html

到了这里,关于基于coin创建的同质化代币的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Node.js和Web3.js实现链接MetaMask钱包并批量创建钱包并且批量发送代币

    MetaMask是一款基于浏览器的插件钱包,它可以安全地存储、发送和接收以太坊(Ethereum)代币。而Web3.js是一款JavaScript库,可以通过它连接以太坊区块链网络并管理以太坊钱包。 在此文中,我们将学习如何使用Node.js和Web3.js编程语言编写代码,实现链接MetaMask钱包并批量创建钱

    2024年02月08日
    浏览(79)
  • 基于ERC20代币协议实现的去中心化应用平台

    使用 solidity 实现的基于 ERC20 代币协议的借贷款去中心化应用平台(极简版)。实现存款、取款、贷款、还款以及利息计算的功能。 平台提供ERC20协议代币的相关存取和利息计算工作。部署智能合约时初始化贷款和存款的年利率、代币实现地址。 用户可以将手中的代币存入平台

    2024年02月04日
    浏览(72)
  • 零钱兑换(Coins Change) -动态规划C语言实现

    1. 前言 零钱兑换是经典的动态规划问题,也是贪心解法不足的反证答案。它要求兑换一定总整数的零钱,满足硬币数量最少的条件。假定我们有3类零钱,构成数组coins[]={1,7,10},现在兑换总额14的金额,如果采用贪心策略,我们有10+1+1+1+1=14, 共需要5枚硬币。实际上本题的最少

    2024年02月09日
    浏览(53)
  • 使用mid360从0开始搭建实物机器人入门级导航系统,基于Fast_Lio,Move_Base

    本文原本只是自己在拿到mid360后,开始进行开发过程的一些问题和学习的记录。毕竟实物和仿真还是有很多不同,且由于碰到的问题也比较多,READEME也越来越详细,所以就干脆整合起来,做成了一篇使用mid360的搭建入门的导航系统全流程分享。里面用到的都是主流的开源的框

    2024年02月05日
    浏览(62)
  • 【算法】Distribute Coins in Binary Tree 在二叉树中分配硬币

    给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。 在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。

    2024年02月16日
    浏览(40)
  • pyG edge_index矩阵 转 普通邻接矩阵,COO稀疏矩阵,包含同质图和异质图

    搜这个转化实在难找,在此记录一下! 同质图** 异质图 下面是pytorch版本

    2024年02月15日
    浏览(49)
  • 加密新潮流:社交代币衰落 社区代币崛起?

    这不是 Forefront 首次回顾加密行业中代币化社区赛道的年度发展历程,但毫无疑问,2022 年的情况确实发生了很大变化。 其中 Forefront 的第一份报告《2020 年社交代币年度回顾》 探讨了加密社交的新兴前景,涵盖了通过代币化时间的个人代币起源(Matthew Vernon 的「Boi」)、Sh

    2024年02月13日
    浏览(34)
  • 【算法】回溯:与递归,dfs的同质与分别,剪枝与恢复现场的详细理解,n皇后的回溯解法及算法复杂度分析。

    目录 ​编辑 1.什么是回溯 2.关于剪枝 3.关于恢复现场 4.题目:二叉树的所有路径(凸显恢复现场:切实感受回溯与深搜) 问题分析 ①函数设置为:void Dfs(root) ②函数设置为:void Dfs(root,path) 解题思想:使⽤深度优先遍历(DFS)求解。 代码实现 5.N后问题 问题分析 4皇后的放置

    2024年04月16日
    浏览(41)
  • 前端Vue项目调用页面web3.js:连接metaMask钱包,(查询钱包ETH余额,查询代币余额,ETH转账,代币转账,代币授权,查询授权数量,计算价格)等功能

    这里分享下相关文档 1.web3.js中文文档 https://learnblockchain.cn/docs/web3.js/getting-started.html 2.metamask官方文档:https://docs.metamask.io/ 第一种方法:连接钱包 源码: 第二种方法: 连接钱包 安装依赖直接可以使用 源码: 其他功能: 1、在 mounted 中自动检测浏览器是否安装MetaMask钱包 2、查询

    2024年02月11日
    浏览(51)
  • 专访Move语言之父|带你领略Sui Move的不同风采

    近日,我们与 Mysten Labs的首席技术官、Move编程语言创作者 Sam Blackshear进行了交谈,讨论了他为什么开发Sui Move这种新的智能合约编程语言、Sui能够扩展的功能以及去中心化技术对构建者的好处。 编程语言只是一种与计算机进行友好、安全、高效和明确的交互工具,对于计算机

    2024年02月16日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包