學(xué)習(xí)區(qū)塊鏈乐纸,最刺激的莫過于發(fā)幣衬廷,第一篇文章里介紹了如何搭建EOS開發(fā)環(huán)境,第二篇文章我們已經(jīng)介紹了如何部署調(diào)用合約锯仪,實(shí)際上隱含著對(duì)錢包和賬號(hào)的操作泵督!
這一篇我們重點(diǎn)介紹智能合約如何發(fā)幣!既如何用(yekai)給(dinglinlin)發(fā)幣庶喜。提示:本篇篇幅較長請(qǐng)耐新閱讀小腊。
另,為方便大家交流久窟,需要EOS實(shí)戰(zhàn)系列代碼的小伙伴可以加QQ2082049536索要秩冈,希望跟大家一同進(jìn)步。
使用eosio.token發(fā)幣
我們先將eos官方給提供的eosio.token代碼拷貝到開發(fā)目錄斥扛。
yekaideMacBook-Pro:contracts yk$ cp -r ~/eoshome/eos/contracts/eosio.token/ eosio.token
yekaideMacBook-Pro:contracts yk$ ls
bak? ? ? ? ? ? ? ? eosio.token? ? ?
database? ? ? ? ? jing? ? ? ? ? ? ? tic_tac_toe
debug? ? ? ? ? ? ? moment?
yekaideMacBook-Pro:contracts yk$ cd eosio.token/
yekaideMacBook-Pro:eosio.token yk$ ls
CMakeLists.txt? eosio.token.abi eosio.token.cpp eosio.token.hpp
同樣得到abi文件入问,hpp文件,cpp文件稀颁,缺少wast文件芬失,通過eosiocpp可以生成!
yekaideMacBook-Pro:eosio.token yk$ eosiocpp -o eosio.token.wast eosio.token.cpp eosio.token.cpp:6:10: fatal error: 'eosio.token/eosio.token.hpp' file not found#include ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
上述有一個(gè)錯(cuò)誤匾灶,我們需要修改cpp包含頭文件的路徑棱烂,在本目錄下編譯路徑有點(diǎn)問題。 修改為 "eosio.token.hpp"阶女。
/**
*? @file
*? @copyright defined in eos/LICENSE.txt
*/
#include "eosio.token.hpp"
namespace eosio {
void token::create( account_name issuer,
? ? ? ? ? ? ? ? ? ? asset? ? ? ? maximum_supply,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_freeze,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_recall,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_whitelist )
{
? ? require_auth( _self );
? ? auto sym = maximum_supply.symbol;
? ? eosio_assert( sym.is_valid(), "invalid symbol name" );
? ? eosio_assert( maximum_supply.is_valid(), "invalid supply");
? ? eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");
? ? stats statstable( _self, sym.name() );
? ? auto existing = statstable.find( sym.name() );
? ? eosio_assert( existing == statstable.end(), "token with symbol already exists" );
? ? statstable.emplace( _self, [&]( auto& s ) {
? ? ? s.supply.symbol = maximum_supply.symbol;
? ? ? s.max_supply? ? = maximum_supply;
? ? ? s.issuer? ? ? ? = issuer;
? ? ? s.can_freeze? ? = issuer_can_freeze;
? ? ? s.can_recall? ? = issuer_can_recall;
? ? ? s.can_whitelist = issuer_can_whitelist;
? ? });
}
void token::issue( account_name to, asset quantity, string memo )
{
? ? print( "issue" );
? ? auto sym = quantity.symbol.name();
? ? stats statstable( _self, sym );
? ? const auto& st = statstable.get( sym );
? ? require_auth( st.issuer );
? ? eosio_assert( quantity.is_valid(), "invalid quantity" );
? ? eosio_assert( quantity.amount > 0, "must issue positive quantity" );
? ? eosio_assert( quantity <= st.max_supply - st.supply, "quantity exceeds available supply");
? ? statstable.modify( st, 0, [&]( auto& s ) {
? ? ? s.supply += quantity;
? ? });
? ? add_balance( st.issuer, quantity, st, st.issuer );
? ? if( to != st.issuer )
? ? {
? ? ? SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
? ? }
}
void token::transfer( account_name from,
? ? ? ? ? ? ? ? ? ? ? account_name to,
? ? ? ? ? ? ? ? ? ? ? asset? ? ? ? quantity,
? ? ? ? ? ? ? ? ? ? ? string? ? ? /*memo*/ )
{
? ? print( "transfer" );
? ? require_auth( from );
? ? auto sym = quantity.symbol.name();
? ? stats statstable( _self, sym );
? ? const auto& st = statstable.get( sym );
? ? require_recipient( from );
? ? require_recipient( to );
? ? eosio_assert( quantity.is_valid(), "invalid quantity" );
? ? eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
? ? sub_balance( from, quantity, st );
? ? add_balance( to, quantity, st, from );
}
void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {
? accounts from_acnts( _self, owner );
? const auto& from = from_acnts.get( value.symbol.name() );
? eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
? if( has_auth( owner ) ) {
? ? ? eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
? ? ? eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
? ? ? eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
? } else if( has_auth( st.issuer ) ) {
? ? ? eosio_assert( st.can_recall, "issuer may not recall token" );
? } else {
? ? ? eosio_assert( false, "insufficient authority" );
? }
? from_acnts.modify( from, owner, [&]( auto& a ) {
? ? ? a.balance -= value;
? });
}
void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
{
? accounts to_acnts( _self, owner );
? auto to = to_acnts.find( value.symbol.name() );
? if( to == to_acnts.end() ) {
? ? ? eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
? ? ? to_acnts.emplace( ram_payer, [&]( auto& a ){
? ? ? ? a.balance = value;
? ? ? });
? } else {
? ? ? eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
? ? ? to_acnts.modify( to, 0, [&]( auto& a ) {
? ? ? ? a.balance += value;
? ? ? });
? }
}
} /// namespace eosio
EOSIO_ABI( eosio::token, (create)(issue)(transfer) )
yekaideMacBook-Pro:eosio.token yk$
再次執(zhí)行編譯生成wast文件
yekaideMacBook-Pro:eosio.token yk$ eosiocpp -o eosio.token.wast eosio.token.cpp
終于可以發(fā)幣了
有可能看到如圖所示颊糜,這是由于nodes重啟后哩治,錢包需要解鎖,此時(shí)上篇提到的錢包密碼在此處就將有用武之地了衬鱼!
yekaideMacBook-Pro:eosio.token yk$ cleos wallet unlock
輸入錢包密碼就會(huì)解鎖成功了业筏!再次發(fā)布合約!
yekaideMacBook-Pro:eosio.token yk$ cleos set contract yekai ../eosio.token/
Reading WAST/WASM from ../eosio.token/eosio.token.wast...
Assembling WASM...
Publishing contract...
executed transaction: 0cfdf14e4d5d7351b31ba88a029b9c96693fdaf9d9f7738738356cb01ad48dff? 8320 bytes? 2200576 cycles
#? ? ? ? eosio <= eosio::setcode? ? ? ? ? ? ? {"account":"yekai","vmtype":0,"vmversion":0,"code":"0061736d010000000181011560067f7e7f7f7f7f0060057f...
#? ? ? ? eosio <= eosio::setabi? ? ? ? ? ? ? ? {"account":"yekai","abi":{"types":[],"structs":[{"name":"transfer","base":"","fields":[{"name":"from...
看到上述結(jié)果代表成了鸟赫!激動(dòng)人心的時(shí)刻也開始了蒜胖!
馬上發(fā)幣,手里有幣惯疙,心里不慌
計(jì)劃發(fā)布一個(gè)葉開幣翠勉,持幣的可以找我換飛刀!需要指定發(fā)行者issuer霉颠,指定最大發(fā)行量以及幣符號(hào)(YKC)对碌,還有三個(gè)參數(shù)can_freeze,can_recall蒿偎,can_whitelist分別代表是否可以凍結(jié)朽们,是否可以回收,是否使用白名單诉位。
yekaideMacBook-Pro:eosio.token yk$ cleos push action yekai create '{"issuer":"yekai", "maximum_supply": "1000000000.0000 YKC", "can_freeze": 1, "can_recall": 1, "can_whitelist": 1}' -p yekai@active
executed transaction: 60aba3068a0e3afebd81d23c3a5b954321eb1d29926a46199c7168590f3cf1fa? 248 bytes? 104448 cycles
#? ? ? ? yekai <= yekai::create? ? ? ? ? ? ? ? {"issuer":"yekai","maximum_supply":"1000000000.0000 YKC","can_freeze":1,"can_recall":1,"can_whitelis...
這樣執(zhí)行成功骑脱,我們就可以發(fā)幣了
yekaideMacBook-Pro:eosio.token yk$ cleos push action yekai issue '{"to":"yekai","quantity":"1000.0000 YKC","memo":"issue first"}' -p yekai@active
executed transaction: fd0079f68e354e70a2c6af53d091531064681a256fbe807292bb11b20dcc408d? 264 bytes? 109568 cycles
#? ? ? ? yekai <= yekai::issue? ? ? ? ? ? ? ? {"to":"yekai","quantity":"1000.0000 YKC","memo":"issue first"}
>> issue
可以查看yekai當(dāng)前的余額,兩個(gè)yekai一個(gè)代表合約苍糠,一個(gè)代表范圍叁丧,accounts代表表名,accounts在哪定義的岳瞭?
yekaideMacBook-Pro:eosio.token yk$ cleos get table yekai yekai accounts
{
? "rows": [{
? ? ? "balance": "1000.0000 YKC",
? ? ? "frozen": 0,
? ? ? "whitelist": 1
? ? }
? ],
? "more": false
}
轉(zhuǎn)賬給dinglinlin拥娄,先創(chuàng)建一個(gè)賬戶dinglinlin
yekaideMacBook-Pro:eosio.token yk$ cleos create key
Private key: 5JibbdFPc4f5ZX9Qq8sWpX8yACNwAzex5ogHWxtTGVSYeUkvWJq
Public key: EOS5vn5Jj5oU1zP7rKDwbXsEjLbQnT8yvLF1PcyCEFKzoAX3xVz2J
yekaideMacBook-Pro:eosio.token yk$ cleos create account eosio dinglinlin EOS5vn5Jj5oU1zP7rKDwbXsEjLbQnT8yvLF1PcyCEFKzoAX3xVz2J EOS5vn5Jj5oU1zP7rKDwbXsEjLbQnT8yvLF1PcyCEFKzoAX3xVz2J
executed transaction: d710f137d34568981eb0bd65fbf4e7306cc813e47b067d06138af9eea15b352a? 352 bytes? 102400 cycles
#? ? ? ? eosio <= eosio::newaccount? ? ? ? ? ? {"creator":"eosio","name":"dinglinlin","owner":{"threshold":1,"keys":[{"key":"EOS5vn5Jj5oU1zP7rKDwbX...
yekaideMacBook-Pro:eosio.token yk$
yekaideMacBook-Pro:eosio.token yk$ cleos wallet import 5JibbdFPc4f5ZX9Qq8sWpX8yACNwAzex5ogHWxtTGVSYeUkvWJq
imported private key for: EOS5vn5Jj5oU1zP7rKDwbXsEjLbQnT8yvLF1PcyCEFKzoAX3xVz2J
轉(zhuǎn)賬給dinglinlin
yekaideMacBook-Pro:eosio.token yk$ cleos push action yekai transfer '{"from":"yekai","to":"dinglinlin","quantity":"20.0000 YKC","memo":"my first transfer"}' -p yekai@active
executed transaction: ae530eaab3c7b2dbecb73df0dc7d74c5861ff1d0cc50655f2f31d46004e4187d? 272 bytes? 112640 cycles
#? ? ? ? yekai <= yekai::transfer? ? ? ? ? ? ? {"from":"yekai","to":"dinglinlin","quantity":"20.0000 YKC","memo":"my first transfer"}
>> transfer
#? ? dinglinlin <= yekai::transfer? ? ? ? ? ? ? {"from":"yekai","to":"dinglinlin","quantity":"20.0000 YKC","memo":"my first transfer"}
再次查看余額,葉開和丁琳琳金額發(fā)生了變化瞳筏!
yekaideMacBook-Pro:eosio.token yk$ cleos get table yekai dinglinlin accounts
{
? "rows": [{
? ? ? "balance": "20.0000 YKC",
? ? ? "frozen": 0,
? ? ? "whitelist": 1
? ? }
? ],
? "more": false
}
yekaideMacBook-Pro:eosio.token yk$ cleos get table yekai yekai accounts
{
? "rows": [{
? ? ? "balance": "980.0000 YKC",
? ? ? "frozen": 0,
? ? ? "whitelist": 1
? ? }
? ],
? "more": false
}
abi文件三要素
發(fā)幣已然成功稚瘾,然而少了點(diǎn)什么,我們?cè)倩剡^來介紹abi文件的內(nèi)容姚炕。abi文件有三要素摊欠,當(dāng)然不是陽光、空氣和水柱宦!abi文件的三要素是struct些椒,action,table掸刊。
yekaideMacBook-Pro:eosio.token yk$ cat eosio.token.abi
{
? "types": [],
? "structs": [{
? ? ? "name": "transfer",
? ? ? "base": "",
? ? ? "fields": [
? ? ? ? {"name":"from", "type":"account_name"},
? ? ? ? {"name":"to", "type":"account_name"},
? ? ? ? {"name":"quantity", "type":"asset"},
? ? ? ? {"name":"memo", "type":"string"}
? ? ? ]
? ? },{
? ? "name": "create",
? ? "base": "",
? ? "fields": [
? ? ? ? {"name":"issuer", "type":"account_name"},
? ? ? ? {"name":"maximum_supply", "type":"asset"},
? ? ? ? {"name":"can_freeze", "type":"uint8"},
? ? ? ? {"name":"can_recall", "type":"uint8"},
? ? ? ? {"name":"can_whitelist", "type":"uint8"}
? ? ]
? },{
? ? "name": "issue",
? ? "base": "",
? ? "fields": [
? ? ? ? {"name":"to", "type":"account_name"},
? ? ? ? {"name":"quantity", "type":"asset"},
? ? ? ? {"name":"memo", "type":"string"}
? ? ]
? },{
? ? ? "name": "account",
? ? ? "base": "",
? ? ? "fields": [
? ? ? ? {"name":"balance", "type":"asset"},
? ? ? ? {"name":"frozen", "type":"uint8"},
? ? ? ? {"name":"whitelist", "type":"uint8"}
? ? ? ]
? ? },{
? ? ? "name": "currency_stats",
? ? ? "base": "",
? ? ? "fields": [
? ? ? ? {"name":"supply", "type":"asset"},
? ? ? ? {"name":"max_supply", "type":"asset"},
? ? ? ? {"name":"issuer", "type":"account_name"},
? ? ? ? {"name":"can_freeze", "type":"uint8"},
? ? ? ? {"name":"can_recall", "type":"uint8"},
? ? ? ? {"name":"can_whitelist", "type":"uint8"},
? ? ? ? {"name":"is_frozen", "type":"uint8"},
? ? ? ? {"name":"enforce_whitelist", "type":"uint8"}
? ? ? ]
? ? }
? ],
? "actions": [{
? ? ? "name": "transfer",
? ? ? "type": "transfer",
? ? ? "ricardian_contract": ""
? ? },{
? ? ? "name": "issue",
? ? ? "type": "issue",
? ? ? "ricardian_contract": ""
? ? }, {
? ? ? "name": "create",
? ? ? "type": "create",
? ? ? "ricardian_contract": ""
? ? }
? ],
? "tables": [{
? ? ? "name": "accounts",
? ? ? "type": "account",
? ? ? "index_type": "i64",
? ? ? "key_names" : ["currency"],
? ? ? "key_types" : ["uint64"]
? ? },{
? ? ? "name": "stat",
? ? ? "type": "currency_stats",
? ? ? "index_type": "i64",
? ? ? "key_names" : ["currency"],
? ? ? "key_types" : ["uint64"]
? ? }
? ],
? "ricardian_clauses": []
}
struct 結(jié)構(gòu)
struct不會(huì)碰到太多問題免糕,就是我們定義的結(jié)構(gòu)體
action 動(dòng)作
action是abi文件的靈魂,eos是以action驅(qū)動(dòng),當(dāng)然锝得得action说墨。
table
table其實(shí)是非必須的,比如hello的例子中就沒有table苍柏,table做什么用呢尼斧?既然是table,就可以當(dāng)成數(shù)據(jù)庫的table试吁,那么什么用處也就清晰了棺棵!本例使用table存儲(chǔ)每個(gè)用戶的持幣余額!說到這里熄捍,也就能理解之前的操作為什么用accounts這個(gè)表了烛恤!
修改示例代碼重新得到abi
很遺憾的是官方給的示例代碼是無法通過eosiocpp生成官方版的abi文件的,咱們做一下跳坑練習(xí)余耽!
yekaideMacBook-Pro:eosio.token yk$ eosiocpp -g eosio.token.abi eosio.token.cpp
yekaideMacBook-Pro:eosio.token yk$ cat eosio.token.abi
{
? "____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-05-11T06:32:03",
? "types": [],
? "structs": [],
? "actions": [],
? "tables": [],
? "ricardian_clauses": []
}
很郁悶的發(fā)現(xiàn)abi的文件空空如也缚柏,整個(gè)人都不好了!接下來就看動(dòng)手能力了碟贾,我們先將hpp和cpp源碼改造一下币喧,將namespace的使用方式去掉,經(jīng)過證明袱耽,我們需要使用全局空間杀餐,不能再次定義eosio這個(gè)命名空間!
代碼改造如下(第一次修改)
eosio.token.hpp
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include#include#includenamespace eosiosystem { class system_contract;}using namespace eosio ; using std::string; class token : public contract { public: token( account_name self ):contract(self){} /// @abi action void create( account_name issuer, asset maximum_supply, uint8_t issuer_can_freeze, uint8_t issuer_can_recall, uint8_t issuer_can_whitelist ); void issue( account_name to, asset quantity, string memo ); void transfer( account_name from, account_name to, asset quantity, string memo ); private: friend eosiosystem::system_contract; inline asset get_supply( symbol_name sym )const; inline asset get_balance( account_name owner, symbol_name sym )const; private: struct account { asset balance; bool frozen = false; bool whitelist = true; uint64_t primary_key()const { return balance.symbol.name(); } }; struct currency_stats { asset supply; asset max_supply; account_name issuer; bool can_freeze = true; bool can_recall = true; bool can_whitelist = true; bool is_frozen = false; bool enforce_whitelist = false; uint64_t primary_key()const { return supply.symbol.name(); } }; typedef eosio::multi_indexaccounts; typedef eosio::multi_index stats;
? ? ? ? void sub_balance( account_name owner, asset value, const currency_stats& st );
? ? ? ? void add_balance( account_name owner, asset value, const currency_stats& st,
? ? ? ? ? ? ? ? ? ? ? ? ? account_name ram_payer );
? ? ? public:
? ? ? ? struct transfer_args {
? ? ? ? ? ? account_name? from;
? ? ? ? ? ? account_name? to;
? ? ? ? ? ? asset? ? ? ? quantity;
? ? ? ? ? ? string? ? ? ? memo;
? ? ? ? };
? };
? asset token::get_supply( symbol_name sym )const
? {
? ? ? stats statstable( _self, sym );
? ? ? const auto& st = statstable.get( sym );
? ? ? return st.supply;
? }
? asset token::get_balance( account_name owner, symbol_name sym )const
? {
? ? ? accounts accountstable( _self, owner );
? ? ? const auto& ac = accountstable.get( sym );
? ? ? return ac.balance;
? }
eosio.token.cpp
/**
*? @file
*? @copyright defined in eos/LICENSE.txt
*/
#include "eosio.token.hpp"
void token::create( account_name issuer,
? ? ? ? ? ? ? ? ? ? asset? ? ? ? maximum_supply,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_freeze,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_recall,
? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_whitelist )
{
? ? require_auth( _self );
? ? auto sym = maximum_supply.symbol;
? ? eosio_assert( sym.is_valid(), "invalid symbol name" );
? ? eosio_assert( maximum_supply.is_valid(), "invalid supply");
? ? eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");
? ? stats statstable( _self, sym.name() );
? ? auto existing = statstable.find( sym.name() );
? ? eosio_assert( existing == statstable.end(), "token with symbol already exists" );
? ? statstable.emplace( _self, [&]( auto& s ) {
? ? ? s.supply.symbol = maximum_supply.symbol;
? ? ? s.max_supply? ? = maximum_supply;
? ? ? s.issuer? ? ? ? = issuer;
? ? ? s.can_freeze? ? = issuer_can_freeze;
? ? ? s.can_recall? ? = issuer_can_recall;
? ? ? s.can_whitelist = issuer_can_whitelist;
? ? });
}
void token::issue( account_name to, asset quantity, string memo )
{
? ? print( "issue" );
? ? auto sym = quantity.symbol.name();
? ? stats statstable( _self, sym );
? ? const auto& st = statstable.get( sym );
? ? require_auth( st.issuer );
? ? eosio_assert( quantity.is_valid(), "invalid quantity" );
? ? eosio_assert( quantity.amount > 0, "must issue positive quantity" );
? ? eosio_assert( quantity <= st.max_supply - st.supply, "quantity exceeds available supply");
? ? statstable.modify( st, 0, [&]( auto& s ) {
? ? ? s.supply += quantity;
? ? });
? ? add_balance( st.issuer, quantity, st, st.issuer );
? ? if( to != st.issuer )
? ? {
? ? ? SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
? ? }
}
void token::transfer( account_name from,
? ? ? ? ? ? ? ? ? ? ? account_name to,
? ? ? ? ? ? ? ? ? ? ? asset? ? ? ? quantity,
? ? ? ? ? ? ? ? ? ? ? string? ? ? /*memo*/ )
{
? ? print( "transfer" );
? ? require_auth( from );
? ? auto sym = quantity.symbol.name();
? ? stats statstable( _self, sym );
? ? const auto& st = statstable.get( sym );
? ? require_recipient( from );
? ? require_recipient( to );
? ? eosio_assert( quantity.is_valid(), "invalid quantity" );
? ? eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
? ? sub_balance( from, quantity, st );
? ? add_balance( to, quantity, st, from );
}
void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {
? accounts from_acnts( _self, owner );
? const auto& from = from_acnts.get( value.symbol.name() );
? eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
? if( has_auth( owner ) ) {
? ? ? eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
? ? ? eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
? ? ? eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
? } else if( has_auth( st.issuer ) ) {
? ? ? eosio_assert( st.can_recall, "issuer may not recall token" );
? } else {
? ? ? eosio_assert( false, "insufficient authority" );
? }
? from_acnts.modify( from, owner, [&]( auto& a ) {
? ? ? a.balance -= value;
? });
}
void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
{
? accounts to_acnts( _self, owner );
? auto to = to_acnts.find( value.symbol.name() );
? if( to == to_acnts.end() ) {
? ? ? eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
? ? ? to_acnts.emplace( ram_payer, [&]( auto& a ){
? ? ? ? a.balance = value;
? ? ? });
? } else {
? ? ? eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
? ? ? to_acnts.modify( to, 0, [&]( auto& a ) {
? ? ? ? a.balance += value;
? ? ? });
? }
}
EOSIO_ABI( token, (create)(issue)(transfer) )
這次abi文件有變化了朱巨,但是好像還缺少點(diǎn)什么!
{
? "____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-05-11T06:41:35",
? "types": [],
? "structs": [{
? ? ? "name": "create",
? ? ? "base": "",
? ? ? "fields": [{
? ? ? ? ? "name": "issuer",
? ? ? ? ? "type": "account_name"
? ? ? ? },{
? ? ? ? ? "name": "maximum_supply",
? ? ? ? ? "type": "asset"
? ? ? ? },{
? ? ? ? ? "name": "issuer_can_freeze",
? ? ? ? ? "type": "uint8"
? ? ? ? },{
? ? ? ? ? "name": "issuer_can_recall",
? ? ? ? ? "type": "uint8"
? ? ? ? },{
? ? ? ? ? "name": "issuer_can_whitelist",
? ? ? ? ? "type": "uint8"
? ? ? ? }
? ? ? ]
? ? },{
? ? ? "name": "issue",
? ? ? "base": "",
? ? ? "fields": [{
? ? ? ? ? "name": "to",
? ? ? ? ? "type": "account_name"
? ? ? ? },{
? ? ? ? ? "name": "quantity",
? ? ? ? ? "type": "asset"
? ? ? ? },{
? ? ? ? ? "name": "memo",
? ? ? ? ? "type": "string"
? ? ? ? }
? ? ? ]
? ? },{
? ? ? "name": "transfer",
? ? ? "base": "",
? ? ? "fields": [{
? ? ? ? ? "name": "from",
? ? ? ? ? "type": "account_name"
? ? ? ? },{
? ? ? ? ? "name": "to",
? ? ? ? ? "type": "account_name"
? ? ? ? },{
? ? ? ? ? "name": "quantity",
? ? ? ? ? "type": "asset"
? ? ? ? },{
? ? ? ? ? "name": "memo",
? ? ? ? ? "type": "string"
? ? ? ? }
? ? ? ]
? ? }
? ],
? "actions": [{
? ? ? "name": "create",
? ? ? "type": "create",
? ? ? "ricardian_contract": ""
? ? },{
? ? ? "name": "issue",
? ? ? "type": "issue",
? ? ? "ricardian_contract": ""
? ? },{
? ? ? "name": "transfer",
? ? ? "type": "transfer",
? ? ? "ricardian_contract": ""
? ? }
? ],
? "tables": [],
? "ricardian_clauses": []
}
上面看似abi文件沒有問題了史翘,但實(shí)際上tables部分,也就是abi的三要素少了一個(gè)tables冀续,這樣數(shù)據(jù)是存儲(chǔ)不下來的琼讽,發(fā)幣會(huì)有問題!
關(guān)鍵點(diǎn)沥阳,添加注釋
再次編譯跨琳,結(jié)果更多的錯(cuò)誤!不要慌桐罕!
abi_generation_exception: Unable to generate abi
false: types can only be: vector, struct, class or a built-in type. (bool)
? ? {"type":"bool"}
? ? thread-0? abi_generator.cpp:606 add_type
? ? {}
? ? thread-0? abi_generator.cpp:290 handle_decl
在eos的智能合約里脉让,導(dǎo)出的table數(shù)據(jù)中不可以有bool類型,其實(shí)提示的已經(jīng)較為明顯了功炮,另外就是加那行注釋是有實(shí)際作用的溅潜,eosiocpp會(huì)做正則匹配,然后才會(huì)導(dǎo)出table信息到abi薪伏。
/**
*? @file
*? @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include
#include
#include
namespace eosiosystem {
? class system_contract;
}
using namespace eosio ;
? using std::string;
? class token : public contract {
? ? ? public:
? ? ? ? token( account_name self ):contract(self){}
? ? ? ? /// @abi action
? ? ? ? void create( account_name issuer,
? ? ? ? ? ? ? ? ? ? ? asset? ? ? ? maximum_supply,
? ? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_freeze,
? ? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_recall,
? ? ? ? ? ? ? ? ? ? ? uint8_t? ? ? issuer_can_whitelist );
? ? ? ? void issue( account_name to, asset quantity, string memo );
? ? ? ? void transfer( account_name from,
? ? ? ? ? ? ? ? ? ? ? ? account_name to,
? ? ? ? ? ? ? ? ? ? ? ? asset? ? ? ? quantity,
? ? ? ? ? ? ? ? ? ? ? ? string? ? ? memo );
? ? ? private:
? ? ? ? friend eosiosystem::system_contract;
? ? ? ? inline asset get_supply( symbol_name sym )const;
? ? ? ? inline asset get_balance( account_name owner, symbol_name sym )const;
? ? ? private:
? ? ? ? /// @abi table accounts i64
? ? ? ? struct account {
? ? ? ? ? ? asset? ? balance;
? ? ? ? ? ? uint8_t frozen? ? = 0;
? ? ? ? ? ? uint8_t? ? whitelist = 1;
? ? ? ? ? ? uint64_t primary_key()const { return balance.symbol.name(); }
? ? ? ? };
? ? ? ? /// @abi table stats i64
? ? ? ? struct stat {
? ? ? ? ? ? asset? ? ? ? ? supply;
? ? ? ? ? ? asset? ? ? ? ? max_supply;
? ? ? ? ? ? account_name? issuer;
? ? ? ? ? ? uint8_t? ? ? ? ? can_freeze? ? ? ? = 1;
? ? ? ? ? ? uint8_t? ? ? ? ? can_recall? ? ? ? = 1;
? ? ? ? ? ? uint8_t? ? ? ? ? can_whitelist? ? ? = 1;
? ? ? ? ? ? uint8_t? ? ? ? ? is_frozen? ? ? ? ? = 0;
? ? ? ? ? ? uint8_t? ? ? ? ? enforce_whitelist? = 0;
? ? ? ? ? ? uint64_t primary_key()const { return supply.symbol.name(); }
? ? ? ? };
? ? ? ? typedef eosio::multi_index accounts;
? ? ? ? typedef eosio::multi_index stats;
? ? ? ? void sub_balance( account_name owner, asset value, const stat& st );
? ? ? ? void add_balance( account_name owner, asset value, const stat& st,
? ? ? ? ? ? ? ? ? ? ? ? ? account_name ram_payer );
? ? ? public:
? ? ? ? struct transfer_args {
? ? ? ? ? ? account_name? from;
? ? ? ? ? ? account_name? to;
? ? ? ? ? ? asset? ? ? ? quantity;
? ? ? ? ? ? string? ? ? ? memo;
? ? ? ? };
? };
? asset token::get_supply( symbol_name sym )const
? {
? ? ? stats statstable( _self, sym );
? ? ? const auto& st = statstable.get( sym );
? ? ? return st.supply;
? }
? asset token::get_balance( account_name owner, symbol_name sym )const
? {
? ? ? accounts accountstable( _self, owner );
? ? ? const auto& ac = accountstable.get( sym );
? ? ? return ac.balance;
? }
注意一下修改變化滚澜,account和stat結(jié)構(gòu)體前都加了注釋,另外導(dǎo)出時(shí)對(duì)table的name長度有限制嫁怀,所以去掉了currency_和后面的s设捐,當(dāng)然相應(yīng)的函數(shù)調(diào)用部分都要調(diào)整借浊。 別忘了同步修改cpp文件對(duì)應(yīng)的函數(shù)接口部分,這樣基本可以大公告成了萝招!
再次發(fā)幣
先部署合約
cleos set contract yekai ../eosio.token
給linlin妹子再來點(diǎn)幣
yk$ cleos push action yekai transfer '{"from":"yekai","to":"dinglinlin","quantity":"66.0000 YKC","memo":"my sencond transfer"}' -p yekai@active
executed transaction: 08f6f04ee43e51423e84379080e1788461fc6b36bdbbf58c3a1fe518e2140e90? 280 bytes? 112640 cycles
#? ? ? ? yekai <= yekai::transfer? ? ? ? ? ? ? {"from":"yekai","to":"dinglinlin","quantity":"66.0000 YKC","memo":"my sencond transfer"}
>> transfer
#? ? dinglinlin <= yekai::transfer? ? ? ? ? ? ? {"from":"yekai","to":"dinglinlin","quantity":"66.0000 YKC","memo":"my sencond transfer"}
再次分別查看余額
yekaideMacBook-Pro:eosio.token yk$ cleos get table yekai yekai accounts
{
? "rows": [{
? ? ? "balance": "914.0000 YKC",
? ? ? "frozen": 0,
? ? ? "whitelist": 1
? ? }
? ],
? "more": false
}
yekaideMacBook-Pro:eosio.token yk$ cleos get table yekai dinglinlin accounts
{
? "rows": [{
? ? ? "balance": "86.0000 YKC",
? ? ? "frozen": 0,
? ? ? "whitelist": 1
? ? }
? ],
? "more": false
}
總結(jié)
本篇主要介紹如何發(fā)幣蚂斤,如何編譯智能合約代碼,以及智能合約編寫時(shí)碰到的問題槐沼,把遇到的坑總結(jié)如下:
/// @abi 有特殊作用
類型必須使用內(nèi)建類型曙蒸,或者結(jié)構(gòu)體,類岗钩,vector等
table結(jié)構(gòu)體長度是有限制的纽窟,不能太長,這也需要注意
table指定主鍵有時(shí)也需要自己指定兼吓,例如:/// @abi table tablename i64