【許曉笛】49行程式碼就能發幣?而且EOS連例子都給你了

圓方圓區塊鏈發表於2018-11-17

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) )
複製程式碼

相關文章和視訊推薦

【許曉笛】 EOS智慧合約案例解析(1)

圓方圓學院彙集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。 公開課地址:ke.qq.com/course/3451…

相關文章