EOS學(xué)習(xí)實(shí)戰(zhàn)(三)教你如何發(fā)幣!

學(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


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末臂港,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子周蹭,更是在濱河造成了極大的恐慌趋艘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凶朗,死亡現(xiàn)場離奇詭異瓷胧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)棚愤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門搓萧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宛畦,你說我怎么就攤上這事瘸洛。” “怎么了次和?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵反肋,是天一觀的道長。 經(jīng)常有香客問我踏施,道長石蔗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任畅形,我火速辦了婚禮养距,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘日熬。我一直安慰自己棍厌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耘纱,像睡著了一般敬肚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上束析,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天帘皿,我揣著相機(jī)與錄音,去河邊找鬼畸陡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛虽填,可吹牛的內(nèi)容都是我干的丁恭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼斋日,長吁一口氣:“原來是場噩夢啊……” “哼牲览!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恶守,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤第献,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兔港,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庸毫,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年衫樊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了飒赃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡科侈,死狀恐怖载佳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臀栈,我是刑警寧澤蔫慧,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站权薯,受9級(jí)特大地震影響姑躲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜崭闲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一肋联、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刁俭,春花似錦橄仍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虑粥。三九已至,卻和暖如春宪哩,著一層夾襖步出監(jiān)牢的瞬間娩贷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工锁孟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彬祖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓品抽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親突倍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盆昙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.生成區(qū)塊:在config.ini中添加如下: ubuntu系統(tǒng)下位置 Linux:~/.local/share...
    櫻桃小丸子zz閱讀 3,229評(píng)論 2 3
  • EOS和EOS的不同之處 在EOS網(wǎng)絡(luò)中存在兩種貨幣跳夭,一種是EOS,還有一種是EOS網(wǎng)絡(luò)中的代幣们镜。說到這里大家似乎...
    zZ_OoO閱讀 1,523評(píng)論 0 2
  • 黑山憩四方币叹,白水一線川 清輝柔如目,月下有游魂 東坡?lián)艄痂O粒廊撕蔚们?前者不可追,后事應(yīng)當(dāng)懇
    楊景寬閱讀 475評(píng)論 0 1
  • 前兩天匹舞,我看看之前所寫的文章閱讀數(shù)據(jù)线脚。 若是我寫關(guān)于賺錢的文章叫榕,閱讀量點(diǎn)贊和轉(zhuǎn)發(fā)量就比較高。而讓我覺得真的是核心的...
    豪爸育兒記閱讀 213評(píng)論 0 0
  • 20余年前的某天晰绎,我是在上小學(xué)括丁,抑或是剛剛升入初中已經(jīng)忘了舵稠。在明姐的家里偶然翻得一本書,藍(lán)色的皮子上有大海构资、小船和...
    無雙_7b56閱讀 635評(píng)論 1 1