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))