使用EOS3.0发行代币

作者: 剑有偏锋 | 来源:发表于2018-05-10 23:07 被阅读268次

    一 运行eos客户端,启动私有网络

    ./nodeos -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::account_history_api_plugin

    eosio generated block bcc817bc... #637 @ 2018-05-10T09:22:13.000 with 0 trxs, lib: 636
    eosio generated block 527d07ae... #638 @ 2018-05-10T09:22:13.500 with 0 trxs, lib: 637
    

    二 创建钱包

    ./cleos wallet create
    会返回一个钱包私钥

    Creating wallet: default
    Save password to use in the future to unlock this wallet.
    Without password imported keys will not be retrievable.
    "PW5J9ASbLXgn2RmuW2YdHwuzsys3YJkGJonegRmxK52DyWCKcYNXn"
    

    (1)钱包私钥可以用于钱包解锁,
    命令为 “cleos wallet unlock --password 私钥”

    (2)如重复执行“./cleos wallet create”,则报错,提示钱包文件已存在

    Error 3140001: Wallet already exists
    Try to use different wallet name.
    Error Details:
    Wallet with name: 'default' already exists at /home/li/.local/share/eosio/nodeos/data/./default.wallet
    

    三 加载 bios 合约

    ./cleos set contract eosio ../../contracts/eosio.bios -p eosio

    Reading WAST...
    Assembling WASM...
    Publishing contract...
    executed transaction: 24cee6eb3def42662b3cc2879e75f6b3386c8d5b8dda2eb31d1bffd5170d0c80  3280 bytes  2200576 cycles
    #         eosio <= eosio::setcode               {"account":"eosio","vmtype":0,"vmversion":0,"code":"0061736d0100000001581060037f7e7f0060057f7e7e7e7e...
    #         eosio <= eosio::setabi                {"account":"eosio","abi":{"types":[],"structs":[{"name":"set_account_limits","base":"","fields":[{"n...
    

    注意:eosio.bios 路径根据实际情况选择目录

    如果我们把 EOS 看做一个操作系统,那么 bios 合约就是让我们能进行最底层的操作的合约,其它合约的运行建立在 bios 合约的基础之上,所以我们先来加载 bios 合约。

    四 创建账户

    (1)生成密钥对
    ./cleos create key

    Private key: 5Ke4aKjY9PGZJnxNV54REsGUqQqRZNpJKr6unnkWLmU1oTT16Cw
    Public key: EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm
    

    (2)把用户私钥导入钱包
    ./cleos wallet import 5Ke4aKjY9PGZJnxNV54REsGUqQqRZNpJKr6unnkWLmU1oTT16Cw

    imported private key for: EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm
    

    (3)用公钥创建账户

    ./cleos create account eosio bytemaster EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm

    executed transaction: 78d3a0752630842bc08d99a2d584982b8ccc89a98b0b5aeadd0792ea76737830  352 bytes  102400 cycles
    #         eosio <= eosio::newaccount            {"creator":"eosio","name":"bytemaster","owner":{"threshold":1,"keys":[{"key":"EOS7KYYgetJuZ7SpkQj9aD...
    

    (4)查看账户,确实创建成功了
    ./cleos get account bytemaster

    {
      "account_name": "bytemaster",
      "permissions": [{
          "perm_name": "active",
          "parent": "owner",
          "required_auth": {
            "threshold": 1,
            "keys": [{
                "key": "EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm",
                "weight": 1
              }
            ],
            "accounts": []
          }
        },{
          "perm_name": "owner",
          "parent": "",
          "required_auth": {
            "threshold": 1,
            "keys": [{
                "key": "EOS7KYYgetJuZ7SpkQj9aDw2Sui7EuLGsKqRp7gq7qQZMx7gkfcGm",
                "weight": 1
              }
            ],
            "accounts": []
          }
        }
      ]
    }
    

    (5)另外再创建一个账户,tester
    ./cleos create key

    Private key: 5KTVgaQwPkyCxJdZqTiZLMbxjZfcqKqFLnLSoUvuGUoUdvTCFaR
    Public key: EOS6H3yfhgcrH1mJs92bbvzYAakMShjcj8SmnmQd3NFBSwVz6EKyM
    

    ./cleos wallet import 5KTVgaQwPkyCxJdZqTiZLMbxjZfcqKqFLnLSoUvuGUoUdvTCFaR

    imported private key for: EOS6H3yfhgcrH1mJs92bbvzYAakMShjcj8SmnmQd3NFBSwVz6EKyM
    

    ./cleos create account eosio tester
    EOS6H3yfhgcrH1mJs92bbvzYAakMShjcj8SmnmQd3NFBSwVz6EKyM EOS6H3yfhgcrH1mJs92bbvzYAakMShjcj8SmnmQd3NFBSwVz6EKyM

    executed transaction: 8ff09b833b2c9a8b9143af165158e052c5ae10c8f35554aa678a95c962d1fd58  352 bytes  102400 cycles
    #         eosio <= eosio::newaccount            {"creator":"eosio","name":"tester","owner":{"threshold":1,"keys":[{"key":"EOS6H3yfhgcrH1mJs92bbvzYAa...
    

    五 部署货币合约

    (1)查看bytemaster的合约
    ./cleos get code bytemaster

    code hash: 0000000000000000000000000000000000000000000000000000000000000000
    

    (2)部署代币合约
    ./cleos set contract bytemaster ../../contracts/eosio.token

    Reading WAST...
    Assembling WASM...
    Publishing contract...
    executed transaction: e1b0fdb6626b4e64640efa8a63cf6c6fb487c5b9897c30ba9778667827b91425  8040 bytes  2200576 cycles
    #         eosio <= eosio::setcode               {"account":"bytemaster","vmtype":0,"vmversion":0,"code":"0061736d01000000018a011660067f7e7f7f7f7f006...
    #         eosio <= eosio::setabi                {"account":"bytemaster","abi":{"types":[],"structs":[{"name":"transfer","base":"","fields":[{"name":...
    

    (3)查看bytemaster的合约,看到代币合约已经部署
    ./cleos get code bytemaster

    code hash: 7c6a300874835ad928de4f30712023758157bd50cb423ab039443f56a84167ff
    

    (4)创建代币
    ./cleos push action bytemaster create '[ "bytemaster", "1000000000.0000 EOS", 0, 0, 0]' -p bytemaster@active

    executed transaction: 56f722fc175854b52a56d32c98d41d3e1c8b3bcfb9cc8c2520503b04bc037a68  248 bytes  104448 cycles
    #    bytemaster <= bytemaster::create           {"issuer":"bytemaster","maximum_supply":"1000000000.0000 EOS","can_freeze":0,"can_recall":0,"can_whi...
    

    其中create接口,在eosio.token.abi有声明

    六 发行代币

    ./cleos push action bytemaster issue '[ "bytemaster", "100.0000 EOS", "memo" ]' -p bytemaster

    issue '[ "bytemaster", "100.0000 EOS", "memo" ]' -p bytemaster
    executed transaction: 4f932f48780e3c83d82ba263844302398f42f79e8bd2b52d3f8eaa2bc0deb79e  256 bytes  107520 cycles
    #    bytemaster <= bytemaster::issue            {"to":"bytemaster","quantity":"100.0000 EOS","memo":"memo"}
    >> issue
    

    其中issue接口,在eosio.token.abi有声明

    七 测试代币转账

    ./cleos push action bytemaster transfer '[ "bytemaster", "tester", "25.0000 EOS", "m" ]' -p bytemaster

    executed transaction: e7ebf695a213842dc3049f388fda128a8d9c05d078273bc75eeb5863fabcd104  256 bytes  109568 cycles
    #    bytemaster <= bytemaster::transfer         {"from":"bytemaster","to":"tester","quantity":"25.0000 EOS","memo":"m"}
    >> transfer
    #        tester <= bytemaster::transfer         {"from":"bytemaster","to":"tester","quantity":"25.0000 EOS","memo":"m"}
    

    其中transfer接口,在eosio.token.abi有声明

    八 总结

    《1 了解发布token的顺序
    启动私有链
    创建钱包
    加载 bios 合约
    创建用户
    部署token合约
    创建代币
    发行代币

    九 引用

    https://github.com/EOSIO/eos/wiki/Tutorial-eosio-token-Contract 《Tutorial eosio token Contract》
    http://liyuechun.org/2018/04/13/eos-contract/ 《第二篇 - 从零到壹学习EOS - EOS Currency 合约案例》
    https://mp.weixin.qq.com/s/3_4KCu8YcbGlEO2Pn6vK_A 《最友善EOS开发教程——从如何发行「新垣结衣币」说起》

    十 eosio.token合约相关文件内容

    包含(eosio.token.abi, eosio.token.hpp eosio.token.cpp)

    eosio.token.abi

    {
      "types": [],
      "structs": [{
          "name": "transfer",
          "base": "",
          "fields": [
            {"name":"from", "type":"account_name"},
            {"name":"to", "type":"account_name"},
            {"name":"quantity", "type":"asset"},
            {"name":"memo", "type":"string"}
          ]
        },{
         "name": "create",
         "base": "",
         "fields": [
            {"name":"issuer", "type":"account_name"},
            {"name":"maximum_supply", "type":"asset"},
            {"name":"can_freeze", "type":"uint8"},
            {"name":"can_recall", "type":"uint8"},
            {"name":"can_whitelist", "type":"uint8"}
         ]
      },{
         "name": "issue",
         "base": "",
         "fields": [
            {"name":"to", "type":"account_name"},
            {"name":"quantity", "type":"asset"},
            {"name":"memo", "type":"string"}
         ]
      },{
          "name": "account",
          "base": "",
          "fields": [
            {"name":"balance", "type":"asset"},
            {"name":"frozen", "type":"uint8"},
            {"name":"whitelist", "type":"uint8"}
          ]
        },{
          "name": "currency_stats",
          "base": "",
          "fields": [
            {"name":"supply", "type":"asset"},
            {"name":"max_supply", "type":"asset"},
            {"name":"issuer", "type":"account_name"},
            {"name":"can_freeze", "type":"uint8"},
            {"name":"can_recall", "type":"uint8"},
            {"name":"can_whitelist", "type":"uint8"},
            {"name":"is_frozen", "type":"uint8"},
            {"name":"enforce_whitelist", "type":"uint8"}
          ]
        }
      ],
      "actions": [{
          "name": "transfer",
          "type": "transfer",
          "ricardian_contract": ""
        },{
          "name": "issue",
          "type": "issue",
          "ricardian_contract": ""
        }, {
          "name": "create",
          "type": "create",
          "ricardian_contract": ""
        }
    
      ],
      "tables": [{
          "name": "accounts",
          "type": "account",
          "index_type": "i64",
          "key_names" : ["currency"],
          "key_types" : ["uint64"]
        },{
          "name": "stat",
          "type": "currency_stats",
          "index_type": "i64",
          "key_names" : ["currency"],
          "key_types" : ["uint64"]
        }
      ],
      "ricardian_clauses": []
    }
    

    eosio.token.hpp

    /**
     *  @file
     *  @copyright defined in eos/LICENSE.txt
     */
    #pragma once
    
    #include <eosiolib/asset.hpp>
    #include <eosiolib/eosio.hpp>
    
    #include <string>
    
    namespace eosiosystem {
       class system_contract;
    }
    
    namespace eosio {
    
       using std::string;
    
       class token : public contract {
          public:
             token( account_name self ):contract(self){}
    
             void create( account_name issuer,
                          asset        maximum_supply,
                          uint8_t      issuer_can_freeze,
                          uint8_t      issuer_can_recall,
                          uint8_t      issuer_can_whitelist );
    
    
             void issue( account_name to, asset quantity, string memo );
    
             void transfer( account_name from,
                            account_name to,
                            asset        quantity,
                            string       memo );
    
          private:
    
             friend eosiosystem::system_contract;
    
             inline asset get_supply( symbol_name sym )const;
             
             inline asset get_balance( account_name owner, symbol_name sym )const;
    
          private:
             struct account {
                asset    balance;
                bool     frozen    = false;
                bool     whitelist = true;
    
                uint64_t primary_key()const { return balance.symbol.name(); }
             };
    
             struct currency_stats {
                asset          supply;
                asset          max_supply;
                account_name   issuer;
                bool           can_freeze         = true;
                bool           can_recall         = true;
                bool           can_whitelist      = true;
                bool           is_frozen          = false;
                bool           enforce_whitelist  = false;
    
                uint64_t primary_key()const { return supply.symbol.name(); }
             };
    
             typedef eosio::multi_index<N(accounts), account> accounts;
             typedef eosio::multi_index<N(stat), currency_stats> stats;
    
             void sub_balance( account_name owner, asset value, const currency_stats& st );
             void add_balance( account_name owner, asset value, const currency_stats& st,
                               account_name ram_payer );
    
          public:
             struct transfer_args {
                account_name  from;
                account_name  to;
                asset         quantity;
                string        memo;
             };
       };
    
       asset token::get_supply( symbol_name sym )const
       {
          stats statstable( _self, sym );
          const auto& st = statstable.get( sym );
          return st.supply;
       }
    
       asset token::get_balance( account_name owner, symbol_name sym )const
       {
          accounts accountstable( _self, owner );
          const auto& ac = accountstable.get( sym );
          return ac.balance;
       }
    
    } /// namespace eosio
    

    eosio.token.cpp

    /**
     *  @file
     *  @copyright defined in eos/LICENSE.txt
     */
    
    #include <eosio.token/eosio.token.hpp>
    
    namespace eosio {
    
    void token::create( account_name issuer,
                        asset        maximum_supply,
                        uint8_t      issuer_can_freeze,
                        uint8_t      issuer_can_recall,
                        uint8_t      issuer_can_whitelist )
    {
        require_auth( _self );
    
        auto sym = maximum_supply.symbol;
        eosio_assert( sym.is_valid(), "invalid symbol name" );
        eosio_assert( maximum_supply.is_valid(), "invalid supply");
        eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");
    
        stats statstable( _self, sym.name() );
        auto existing = statstable.find( sym.name() );
        eosio_assert( existing == statstable.end(), "token with symbol already exists" );
    
        statstable.emplace( _self, [&]( auto& s ) {
           s.supply.symbol = maximum_supply.symbol;
           s.max_supply    = maximum_supply;
           s.issuer        = issuer;
           s.can_freeze    = issuer_can_freeze;
           s.can_recall    = issuer_can_recall;
           s.can_whitelist = issuer_can_whitelist;
        });
    }
    
    
    void token::issue( account_name to, asset quantity, string memo )
    {
        print( "issue" );
        auto sym = quantity.symbol.name();
        stats statstable( _self, sym );
        const auto& st = statstable.get( sym );
    
        require_auth( st.issuer );
        eosio_assert( quantity.is_valid(), "invalid quantity" );
        eosio_assert( quantity.amount > 0, "must issue positive quantity" );
        eosio_assert( quantity <= st.max_supply - st.supply, "quantity exceeds available supply");
    
        statstable.modify( st, 0, [&]( auto& s ) {
           s.supply += quantity;
        });
    
        add_balance( st.issuer, quantity, st, st.issuer );
    
        if( to != st.issuer )
        {
           SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
        }
    }
    
    void token::transfer( account_name from,
                          account_name to,
                          asset        quantity,
                          string       /*memo*/ )
    {
        print( "transfer" );
        require_auth( from );
        auto sym = quantity.symbol.name();
        stats statstable( _self, sym );
        const auto& st = statstable.get( sym );
    
        require_recipient( from );
        require_recipient( to );
    
        eosio_assert( quantity.is_valid(), "invalid quantity" );
        eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
    
        sub_balance( from, quantity, st );
        add_balance( to, quantity, st, from );
    }
    
    void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {
       accounts from_acnts( _self, owner );
    
       const auto& from = from_acnts.get( value.symbol.name() );
       eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
    
       if( has_auth( owner ) ) {
          eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
          eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
          eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
       } else if( has_auth( st.issuer ) ) {
          eosio_assert( st.can_recall, "issuer may not recall token" );
       } else {
          eosio_assert( false, "insufficient authority" );
       }
    
       from_acnts.modify( from, owner, [&]( auto& a ) {
           a.balance -= value;
       });
    }
    
    void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
    {
       accounts to_acnts( _self, owner );
       auto to = to_acnts.find( value.symbol.name() );
       if( to == to_acnts.end() ) {
          eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
          to_acnts.emplace( ram_payer, [&]( auto& a ){
            a.balance = value;
          });
       } else {
          eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
          to_acnts.modify( to, 0, [&]( auto& a ) {
            a.balance += value;
          });
       }
    }
    
    } /// namespace eosio
    
    EOSIO_ABI( eosio::token, (create)(issue)(transfer) )
    

    相关文章

      网友评论

      • altcoin:不错超级详细。
      • 黑马王子77:值得好好学习下
      • 李子心诚:任何人都可以发代币吗??那这种代币本身的信用和安全性如何保障那? 基础怎么保证?
      • 李子心诚:【综述】 亏得会编程要不看不懂,也看不下去哈哈。 。
        【结构】 很清晰了,按先后顺序分解的很清晰 。
        【优点】 喜欢工科和编程的我 还是蛮喜欢这种风格的,就是读起来要费脑些 。这种文章很挑人啊 。
        【建议】偏工科,说明性的文字偏少了,没有编程基础根本看不懂 。这种文章不重排版,还可以,不过我也在思考此类文章排版要怎样进行?
        【思考】 写的很清晰了,就是偏重于工科,必须有编程基础才能看懂。
        【评分】(1-5分) 4 分

      本文标题:使用EOS3.0发行代币

      本文链接:https://www.haomeiwen.com/subject/rzcorftx.html