美文网首页EOS基础知识集锦eos
【eos全家桶系列】eos系统合约介绍 — 发币合约eosio.

【eos全家桶系列】eos系统合约介绍 — 发币合约eosio.

作者: guaiguaihw | 来源:发表于2018-07-31 16:13 被阅读293次

    简介

    本章将深入源码,为大家分析eos的系统合约eosio.token的实现细节。eosio.token是eos的发币合约,这个合约主要实现了EOS代币的创建、发行、转账等功能。

    主要合约方法

    eosio.token系统合约的源码在eos/contracts/eosio.token中,eos项目方独立开了github,负责eosio.token合约的更新和维护。

    eosio.token合约,在eosio.token.hpp头文件中,主要定义了以下三个合约方法:

    - create:负责创建资产

    - issue:负责发行资产

    - transfer:负责资产转账

    eosio.token.hpp头文件中定义的主要方法

    下面,将为大家一一介绍各个方法的功能实现细节

    create方法

    create方法的实现在eosio.token.cpp中,需要传入两个参数完成币种创建:

    - issuer:资产发行账户

    - maximum_supply:最大发行量

    create方法实现细节

    ceate方法调用实例如下,eosio.token合约部署在eosio.token账户,资产发行账户为eosio,最大发行量10亿,币种精度4,币种符号EOS

    cleos push action eosio.token create '[ "eosio", "1000000000.0000 EOS"]' -p eosio.token

    深入源码来看,create方法通过以下步骤完成了资产的创建:

    - 获取eosio.token合约部署账户的授权

    - 判断币种符号 (sysmol name) 是否合法,币种符号必须是大写字母,长度小于8位

    - 判断发行量是否越界且是否为正数,支持的最大发行量 amount <= 2^62-1

    - 查询statstable表,判断代币符号是否存在,eosio.token支持发行多资产

    - 建表,将代币符号、发行总量、发行方存入数据库

    以上步骤,主要逻辑详见:eos/contracts/eosiolib/symbol.hppeos/contracts/eosiolib/asset.hppeos/contracts/eosiolib/multi_index.hpp

    issue方法

    create方法的实现在eosio.token.cpp中,需要传入两个参数完成币种的发行:

    - to:发行金额打入的账户

    - quantity:发行金额

    - memo:交易备注

    issue方法实现细节

    issue方法调用实例如下,资产发行账户eosio授权,将10亿EOS打入eosio账户中,备注是test issue

    cleos push action eosio.token issue '[ "eosio", "1000000000.0000 EOS", "test issue"]' -p eosio

    深入源码来看,issue方法通过以下步骤完成了资产的发行:

    - 前置检查:查表判断币种是否存在、memo最大长度不能超过256字节

    - 查表获取币种信息:发行账户、最大发行量、币种精度、币种符号

    - 获取发行账户的授权

    - 前置检查:发行金额为正数且不超过最大发行量、币种精度校验

    - 更新表,增加发行资产的余额

    - 如果to账户和发行账户不一致,调用内联合约转账

    以上步骤,主要逻辑详见:eos/contracts/eosiolib/symbol.hppeos/contracts/eosiolib/asset.hppeos/contracts/eosiolib/multi_index.hppeos/contracts/eosiolib/currency.hpp

    这里特别要说明最后一个步骤,内联合约的调用。实现逻辑在eos/contracts/eosiolib/currency.hpp

    issue方法最后调用的inline合约方法 - eosio.token的transfer方法

    eos智能合约之间,通过action通信,共享数据库存储。一个智能合约,可以异步的读取另一个智能合约的数据库状态。智能合约有两种通信状态:

    - Inline 内联合约。指的是在一个已有的交易里调用其他智能合约的方法。如果当前交易失败了,内联合约的执行也不受影响,内联合约执行失败或成功并没有通知,但执行成功会上链

    - Deffered 延迟合约。指的是不是立即执行,而是在未来的某个时间计划去执行的合约。当前,可以构造一个交易去发送延迟合约交易,也可以发送一个交易去取消延迟合约。延迟合约也不能保证执行成功,执行失败或者成功并没有通知,但执行成功会上链

    在issue方法中,当发现issuer账户和to账户不一致时,会调用lnline合约,触发eosio.token合约的transfer方法,将发行的金额转入to账户。当我们执行issue方法后,会发现除了产生issue的action后,还会有transfer的action:

    inline合约方法调用成功后会上链

    transfer方法

    transfer方法的实现在eosio.token.cpp中,需要传入四个参数完成币种的转账:

    - from:出币账户

    - to:入金账户

    - quantity:转账金额

    - memo:交易备注

    transfer方法的实现细节

    深入源码来看,issue方法通过以下步骤完成了资产的转账:

    - 前置检查:判断是否转账给自己、判断to账户是否存在

    - 获得from账户的授权

    - 获取币种信息:发行账户、最大发行量、币种精度、币种符号

    - 分别通知from、to账户合约调用结果

    - 前置检查:转账金额为正且不超过最大发行量、币种精度正确、memo长度不大于256

    - 加减from和to地址账户余额

    以上步骤,主要逻辑详见:eos/contracts/eosiolib/symbol.hppeos/contracts/eosiolib/asset.hppeos/contracts/eosiolib/multi_index.hppeos/contracts/eosiolib/currency.hpp

    这里特别要说明第四个步骤,通知from、to账户合约调用结果。实现逻辑在eos/contracts/eosiolib/action.hppeos/libraries/chain/apply_context.cppeos/libraries/chain/transaction_context.cpp

    eosio.token的transfer方法调用require_recipient 将相关账户放入_notified数组中 封装好trace通知内容,并执行通知 trace通知内容封装过程

    首先,eosio智能合约的执行结果,会分别通知from、to、eosio.token。我们发送转账交易,会发现有三条actions,通知所有涉及的账户,这是eos系统合约设计的通知机制。大家在执行cleos get actions获取交易结果时,可以通过receiver过滤出发给自己账户的通知。

    transfer方法调用成功后,发送给所有相关账户的通知上链

    receipt的通知详情,调用cleos get actions bp1 -j 获取:

    后记

    本章为大家介绍了eosio.token合约的实现细节,从源码层面为大家分析了eosio.token如何实现资产的创建、发行、转账的。

    目前,基于eos发行资产的项目方,都会参考eosio.token的实现,去实现自己的发币合约。但是,由于eos是一个刚刚完成主网上线的新项目,有许多隐藏的bug有待发现。例如,我们最后讲到的transfer方法的receipt通知机制,由于实现过于复杂,前段时间就被慢雾发现了有严重的安全漏洞,会使交易所的提币账户ram被耗尽,详细issue

    因此,大家在编写自己的发币合约时,务必要检查好相关逻辑,以免被恶意攻击造成资产的损失。eos社区目前还没有出合约代码的标准规范,但我相信不久的将来,一定会有详细的规范出台。

    接下来的文章,将继续从源码层面为大家讲解eos的系统合约实现细节,尽请期待!

    相关文章

      网友评论

        本文标题:【eos全家桶系列】eos系统合约介绍 — 发币合约eosio.

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