EOS数字资产合约实战(四)eosio.token.cpp的创建资产,发行资产,交易资产

eosio.token.cpp部分代码的解析(eosi.token.hpp实现)创建资产,发行资产,交易资产的三个函数

#include <eosio.token/eosio.token.hpp>

namespace eosio{

        //创建资产种类和属性
        //issuer   发币人    
        //maximum_supply 发币的最大量  
        //issuer_can_freeze  发币人是否冻结
        //issuer_can_recall 发币人是否可以召回
        //issuer_can_whitelist 发币人是否可以设置白名单, 有的币是发给特定的人,有的人不能接受这种代币(资产)

       void token::create(account_name issuer, asset maxium_supply, uint8_t issuer_can_freeze,
                                  uint8_t issuer_can_recall, uint8_t issuer_can_whitelist){
             require_auth(_self);            //必须有智能合约主人的授权。(智能合约的主人就是这个智能合约账户本身)
             auto sym = maximum_supply.sumbol;   //设置这种资产的符号。(BTC,EOS)
                
            eosio_assert(sym.is_valid()," invalid name");  //这种资产符号是不是合法的,如果不符合,报错信息: invalid name
            eosio_assert(maximum_supply.is_valid(),"invalid supply");   //这种资产的最大量不符合要求 ,报错信息:invalid supply
            eosio_assert(maximum_supply.amount>0,"maximum_supply must be posivive");//这种资产最大的发行量必须必须大于0
               
               
                //新建一个多索引列表,这个列表的类型是资产资料类型(currency_stats)
                stats   statstable(_self, sym.name());         
                //新建这个多索引列表以后,我们就可以和数据库通讯了。
                // 首先查询这个资产的名字是否存在,是否被占用了

               auto existing = statstable.find(sym.name());
              eosio_assert(existing==statstable.end(),"token symble already existing"); //如果这个迭代器 existing不等于列表的end, 说明已经存在,那么就报错信息token symble already existing
                 
                 //如果等于的话,说明该资产名不存在,我们接下加入进来。
                 statstable.emplace(_self,[&](auto & s){
                      s.supply.symble = maximum_supply.symbol;
                      s.max_supply = maximum_supply;
                      s.issuer = issuer;
                      s.can_freeze = issuer_can_freeze;   //c++ 整型转到布尔型, 自动强制转换,非0为真。
                      s.can_recall = issuer_can_recall;
                      s.can_whitelist = issuer_can_whitelist;                      
                 });   
       }
       
       //发布资产数量(增发)
       //to  发给谁
       //quantity   发多少
       //mem   发行的时候的备注

       void token::issue(account_name to, asset quantity, string memo) //从函数表面看是直接发到to账户,在底层,还是发给创建者账户,然后再给to 账户加上资产
       {
                print("issue"); //先print一下,告诉系统,开始发资产了。 cleos eos 命令行程序
                auto sym = quantity.symbol.name();  //先定义一个变量储存资产的名字
                //新建一个资产资料列表
                stats stastable(_self, sym);
                const auto   st =stastable.get(sym); //在多索引列表中找该资产。
                //增发资产的时候,有没有发币人issuer的授权
                 require_auth(st.issuer);  //只能由创建者来发币,不能别人发币(资产)。
                 eosio_assert(st.is_valid()," invalid name");  //这种资产符号是不是合法的,如果不符合,报错信息: invalid name
                 eosio_assert(quantity.amount>0,"must issue posivive quantity");//这种资产最大的发行量必须必须大于0
                 eosio_assert(quantity<=st.max_supply-st.supply,"quantity exceeds availbe supply");//还能发行的资产要小于等于最大可以发行的资产减去已经发行的
                 
                 stastable.modify(st,0,[&](auto &s){
                       s.supply += quantity;  //增发的资产数量
                 });
                 
                 //调用add_balance()函数
                 //to  给谁加
                 //quantity 增发的数量
                 //st    增加的资产状态
                 //st.issuer  支付RAM的人(发币人)

                 //这样处理不是很好    add_balance(to, quantity,st, st.issuer);  
                  //add_balance以上的操作 有点问题,EOS官方不是这样实现的,这样实现的,会给某人(to)无声无息的在列表中给这个人增加了资产,但不会通知到被增发的账户的。 除非被增发的账户不断的去查询。   
                  //发行资产如何通知到被增发的账户呢?先不直接给需要被增发的账户to 增发,而是先给发起资产发行人增发。然后让资产发行人再转给需要被增发的账户(to )。调用SEND_INLINE_ACTION()这个宏。  
            
                 add_balance(st.issuer, quantity,st,st.ssuer); 
                 if(to!=issuer)//不是给issuer自己增发
                 {
                      SEND_INLINE_ACTION(*this,transfer,{st.issuer,N(active)},{st.issuer,to,quanity, memo});//特别注意:如果给issuer自己增发资产,这句代码就不用了。
                      //SEND_INLINE_ACTION在一个ACTION中再嵌套一个ACTION(条用了transfer),这样就可以通知到被增发的账户to 知道自己被增发了。
                      //*this    就是本智能合约
                      //transfer   就是要发起的ACTION函数
                      //需要的st.issuer的active 权限
                     //就是传入transfer 的函数 参数说明,1是发行人转出  2 转给谁, 3 转的数量   4 交易备注。

                 }                               
       }
       
       
       
       //交易资产(转账)
       //from  谁转出来
       //to       转给谁
       //quantity   数量
       //memo  转账的时候的备注

       void token::transfer(account_name from , account_name to, asset quantity, string memo)       
       {
             print("transfer"); //打印一个信息,表示要转账了。
             require_auth(from );  //检查发行人的授权。
             
             auto  sym  =quanity.symbol.name(); //把资产名字取出来
             stats stastable(_self, sym);   //系统和数据库交互的一个工具,得到该智能合约的拥有者名下的这个资产的数据表。
             //_self   这个资产的拥有者(发行人)

             const auto & st = statstable.get(sym);
            
             //收据 ,就是把资产从from转到to后,需要得到收据。
             require_recipient(from ); //得到from 收据
             require_recipient(to);  //得到to收据
             
             eosio_assert(quanity.is_valid(),"invalid quantity");  //如果是无效的,报错信息
             eosio_assert(quantity.amount>0,"must transfer posivive quantity"); //如果不大于0,报错信息
             
             //实现交易
             sub_balance(from,quantity,st);
             add_balance(to,quantity,st,from);
       }


//三个公有函数(三个action)暴露给系统。
EOSIO_ABI(eosio::token,(create)(issue)(transfer))

猜你喜欢

转载自blog.csdn.net/akai9898/article/details/82016957