【许晓笛】49行代码就能发币?而且EOS连例子都给你了

简介:

Daniel Larimer 在他的博客介绍了EOS新的智能合约架构(EOS团队的开发速度实在是太吓人,根本追不上)。他给出了最简单的一个新币种的智能合约代码,仅有49行就能完成一个新币种的开发,一个新的“爱息欧”就诞生了。让我们一步一步实现吧。

首先实现私有成员,建立一个 account 结构体,这个结构体里保存的是所有持有我们这种代币的人的账户和余额。

   private:
      //account 结构体 
      struct account {
         //EOS 账户名
         account_name owner;
         //余额
         uint64_t     balance;
         //主键
         uint64_t primary_key()const { return owner; }

下一步 我们要利用 Boost 库中的多索引列表,将上面声明的结构体放入一个列表中,方便查询和修改。

      eosio::multi_index<N(accounts), account> _accounts;

接着,实现 add_balance() 函数,这个私有函数的目的是给特定的 EOS 账户增加特定的代币。

      void add_balance( account_name payer, account_name to, uint64_t q ) {
         //在列表中查询,看要收币的用户是否已经在列表中。
         auto toitr = _accounts.find( to );
         //如果不在列表中,说明用户从未持有过这种币,要将用户加入列表
         if( toitr == _accounts.end() ) {
            //增加一个用户
           _accounts.emplace( payer, [&]( auto& a ) {
              a.owner = to;
              //因为之前没有这种币,用户名下的余额为要接收的数量
              a.balance = q;
           });
           //如果用户在列表中,说明已经持有或持有过这种币
         } else {
           _accounts.modify( toitr, 0, [&]( auto& a ) {
               //直接将余额增加要转入的数量
              a.balance += q;
              //判断用户余额是否溢出(余额增加了q,之后数量应该大于q)
              eosio_assert( a.balance >= q, "overflow detected" );
           });
         }
      }

之后就要实现公有方法了,首先是构造函数,别忘了初始化 _accounts 列表。

  public:
      simpletoken( account_name self )
      :contract(self),_accounts( _self, _self){}

实现公有的 transfer(转账)函数,将代币从一个账户转移到另一个账户。

      void transfer( account_name from, account_name to, uint64_t quantity ) {
         //从付款方获取权限
         require_auth( from );
         //从列表中搜索发币方账户
         const auto& fromacnt = _accounts.get( from );
         //验证付款方余额,是否透支
         eosio_assert( fromacnt.balance >= quantity, "overdrawn balance" );
         //从付款方减去代币
         _accounts.modify( fromacnt, from, [&]( auto& a ){ a.balance -= quantity; } );
         //收款方增加代币(之前实现的私有函数)
         add_balance( from, to, quantity );
      }

OK,是不是以为大功告成了?还有最重要的 issue(发行)函数,要不从哪“印钱?”

      void issue( account_name to, uint64_t quantity ) {
         //得到合约主人的权限
         require_auth( _self );
         //直接印钱
         add_balance( _self, to, quantity );

最后一步,将我们的 transfer 和 issue 函数接口提供给 EOS 系统,通过一个宏就可以快速实现。

EOSIO_ABI( simpletoken, (transfer)(issue) )

这个宏是咋回事?我们看看 dispacher.hpp 文件中对这个宏的定义,其实是替开发者实现了 apply 函数,使得开发者可以专注于业务逻辑。

#define EOSIO_ABI( TYPE, MEMBERS ) \
extern "C" { \
   void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
      auto self = receiver; \
      if( code == self ) { \
         TYPE thiscontract( self ); \
         switch( action ) { \
            EOSIO_API( TYPE, MEMBERS ) \
         } \
         eosio_exit(0); \
      } \
   } \
} \

大功告成,看看全部的代码吧,是不是49行就搞定了?不过 EOS 表示以后会有系统的标准代币,连以上的具体逻辑都不用我们实现了,不过这段代码对系统学习 EOS 智能合约架构还是很有意义的。

#include <eosiolib/eosio.hpp>

class simpletoken : public eosio::contract {
   public:
      simpletoken( account_name self )
      :contract(self),_accounts( _self, _self){}

      void transfer( account_name from, account_name to, uint64_t quantity ) {
         require_auth( from );

         const auto& fromacnt = _accounts.get( from );
         eosio_assert( fromacnt.balance >= quantity, "overdrawn balance" );
         _accounts.modify( fromacnt, from, [&]( auto& a ){ a.balance -= quantity; } );

         add_balance( from, to, quantity );
      }

      void issue( account_name to, uint64_t quantity ) {
         require_auth( _self );
         add_balance( _self, to, quantity );
      }

   private:
      struct account {
         account_name owner;
         uint64_t     balance;

         uint64_t primary_key()const { return owner; }
      };

      eosio::multi_index<N(accounts), account> _accounts;

      void add_balance( account_name payer, account_name to, uint64_t q ) {
         auto toitr = _accounts.find( to );
         if( toitr == _accounts.end() ) {
           _accounts.emplace( payer, [&]( auto& a ) {
              a.owner = to;
              a.balance = q;
           });
         } else {
           _accounts.modify( toitr, 0, [&]( auto& a ) {
              a.balance += q;
              eosio_assert( a.balance >= q, "overflow detected" );
           });
         }
      }
};

EOSIO_ABI( simpletoken, (transfer)(issue) )
相关文章
|
5月前
|
人工智能 搜索推荐
Prompt工程问题之prompt中要求详细的输出内容如何解决
Prompt工程问题之prompt中要求详细的输出内容如何解决
57 4
|
5月前
|
语音技术 Python
语音识别,continue和break的使用,循环综合案例,完成发工资案例,函数的初体验,len()是内置好的函数,def 函数名 def xxx(),函数的定义 def xxx() ,调用函数
语音识别,continue和break的使用,循环综合案例,完成发工资案例,函数的初体验,len()是内置好的函数,def 函数名 def xxx(),函数的定义 def xxx() ,调用函数
|
7月前
|
机器学习/深度学习 数据采集 PyTorch
YOLO3的代码例子
YOLO3的代码例子
|
7月前
|
算法 开发者 Python
【Python 基础扫盲 】self参数、__init__方法和.__str__方法的用处和区别?
【Python 基础扫盲 】self参数、__init__方法和.__str__方法的用处和区别?
496 0
#PY小贴士# for 循环定义的变量,循环外可以用吗?
我们知道,在 python 中要获取一个变量的值,必须是先给它赋值过,不然就是未定义。那么这个 i,代码中没有显式的赋值,在循环体之外还可以用吗?
|
索引 Python
【Python从入门到精通2.1】石头剪子布知识点(print、基础数据类型、input输入、列表、字典、元组、for循环遍历、while循环、if条件语句、随机模块random、时间模块time)
【Python从入门到精通2.1】石头剪子布知识点(print、基础数据类型、input输入、列表、字典、元组、for循环遍历、while循环、if条件语句、随机模块random、时间模块time)
|
Python
Python def定义函数并进行序列解包源码操作解析
Python def定义函数并进行序列解包源码操作解析
99 0
|
Python
【Python零基础入门篇 · 2】:掌握各种运算符和变量、input()输入输出、映射函数map()结合input()和split()函数实现多值输入
【Python零基础入门篇 · 2】:掌握各种运算符和变量、input()输入输出、映射函数map()结合input()和split()函数实现多值输入
131 0
【Python零基础入门篇 · 2】:掌握各种运算符和变量、input()输入输出、映射函数map()结合input()和split()函数实现多值输入
|
测试技术 Python
【HttpRunner v3.x】笔记—8.用例引用、变量传递
【HttpRunner v3.x】笔记—8.用例引用、变量传递
【HttpRunner v3.x】笔记—8.用例引用、变量传递
|
Python
更好的print :嫌弃print太单调 那么来试试这几种方法吧
更好的print :嫌弃print太单调 那么来试试这几种方法吧
更好的print :嫌弃print太单调 那么来试试这几种方法吧