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) )
複製程式碼
相關文章和視訊推薦
圓方圓學院彙集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。 公開課地址:ke.qq.com/course/3451…