摘要:相關(guān)文章和視頻推薦許曉笛智能合約案例解析許曉笛智能合約案例解析圓方圓學(xué)院匯集大批區(qū)塊鏈名師,打造精品的區(qū)塊鏈技術(shù)課程。
詳解 EOS 智能合約的 cpp 文件
之前的文章介紹了 eosio.token 智能合約的 hpp 文件,這次向大家介紹 eosio.token.cpp 文件,cpp 文件即 C++ 代碼文件,智能合約所有的業(yè)務(wù)邏輯內(nèi)容都是在 cpp 文件中實現(xiàn)的。
eosio.token.cpp 文件地址: https://github.com/EOSIO/eos/...
了解 C/C++ 開發(fā)的同學(xué)肯定熟悉,cpp 文件的主要使命是實現(xiàn) hpp 文件中聲明的函數(shù)(方法),包括公有函數(shù)(EOS 里也叫 action)和私有函數(shù)。hpp 里挖的坑,cpp 要一個不留地實現(xiàn)。
私有函數(shù)照慣例,私有函數(shù)都是工具函數(shù),供類內(nèi)部的其他函數(shù)調(diào)用。
sub_balance(減資產(chǎn))函數(shù)作用:從指定賬戶中減去資產(chǎn)
參數(shù):被操作賬戶,資產(chǎn)數(shù),資產(chǎn)狀態(tài)
// 參數(shù):被操作賬戶 資產(chǎn)種類與數(shù)量 資產(chǎn)狀態(tài)結(jié)構(gòu)體 void token::sub_balance( account_name owner, asset value, const currency_stats& st ) { //建立一個 multi_index,用來操作數(shù)據(jù)庫 //這里的參數(shù) _self 表示數(shù)據(jù)的擁有者為智能合約本身,參數(shù) owner 表示儲存在名為被操作賬戶的表中 //這樣并不是直接建立了一個新表,而是讓 C++ 程序與數(shù)據(jù)庫對應(yīng)的表之間建立了數(shù)據(jù)傳輸?shù)耐ǖ? accounts from_acnts( _self, owner ); //在數(shù)據(jù)表中查詢要減少的代幣結(jié)構(gòu)體,就是 hpp 文件中定義的 account 結(jié)構(gòu)體 const auto& from = from_acnts.get( value.symbol.name() ); //校驗,要減少的代幣數(shù)量應(yīng)該小于目前擁有的代幣數(shù)量,否則會報錯。 eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); //判斷是否有被操作賬戶的授權(quán) if( has_auth( owner ) ) { //校驗,賬戶是否被凍結(jié) eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" ); //校驗,這種代幣是否被凍結(jié) 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" ); //如果沒有被操作賬戶的授權(quán),檢查是否有發(fā)幣者的授權(quán) } else if( has_auth( st.issuer ) ) { //如果有發(fā)幣者的授權(quán),那么肯定是在召回代幣,查看代幣是否可以召回 eosio_assert( st.can_recall, "issuer may not recall token" ); } else { //如果兩種授權(quán)都沒有,則失敗,沒有足夠的權(quán)限 eosio_assert( false, "insufficient authority" ); } //通過 Lambda 表達(dá)式(匿名函數(shù))修改將代幣結(jié)構(gòu)體 from_acnts.modify( from, owner, [&]( auto& a ) { //匿名函數(shù) 函數(shù)體 a.balance -= value; }); }add_balance(增加資產(chǎn))函數(shù)
作用:從指定賬戶中增加資產(chǎn)
參數(shù):被操作賬戶,資產(chǎn)數(shù),資產(chǎn)狀態(tài),存儲資源支付賬戶
// 參數(shù):被操作賬戶 代幣數(shù)量 代幣狀態(tài)結(jié)構(gòu)體 儲存支付賬戶 void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer ) { //建立一個 multi_index,用來操作數(shù)據(jù)庫 accounts to_acnts( _self, owner ); //在數(shù)據(jù)表中查詢要增加的代幣結(jié)構(gòu)體 auto to = to_acnts.find( value.symbol.name() ); //如果 to == to_acnts.end(),說明查找到數(shù)據(jù)表的末尾都沒有對應(yīng)的結(jié)構(gòu)體,說明該賬戶沒有該代幣 if( to == to_acnts.end() ) { //校驗,該代幣是否開啟了白名單功能 eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" ); //使用 emplace 方法,在數(shù)據(jù)表中增加一項 to_acnts.emplace( ram_payer, [&]( auto& a ){ //匿名函數(shù)體,代幣數(shù)量等于每次轉(zhuǎn)入的數(shù)量,因為之前沒有 a.balance = value; }); //如果數(shù)據(jù)表中已經(jīng)存在此項,只需增加代幣數(shù)量 } else { //檢查賬戶是否在白名單中 eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" ); //使用 modify 方法,修改項目 to_acnts.modify( to, 0, [&]( auto& a ) { //直接修改代幣數(shù)量 a.balance += value; }); } }公有函數(shù)
EOS 合約中的公有函數(shù)大多是供別的賬戶調(diào)用的 Action,根據(jù) hpp 文件,我們需要實現(xiàn) create、issue、transfer 三個公有函數(shù)(action)。
create(新建代幣)函數(shù)create 函數(shù)用來創(chuàng)建一種新的代幣,并設(shè)置這種新代幣的各種參數(shù)。
//參數(shù):發(fā)幣賬戶 void token::create( account_name issuer, //最大發(fā)行量 asset maximum_supply, //發(fā)幣者是否可以凍結(jié)代幣 uint8_t issuer_can_freeze, //發(fā)幣者是否可以召回代幣 uint8_t issuer_can_recall, //是否可以設(shè)置白名單 uint8_t issuer_can_whitelist ) { //需要 eosio.token 賬戶本身的授權(quán) require_auth( _self ); auto sym = maximum_supply.symbol; //校驗,新代幣名稱是否有效 eosio_assert( sym.is_valid(), "invalid symbol name" ); //校驗,最大發(fā)行量是否有效 eosio_assert( maximum_supply.is_valid(), "invalid supply"); //校驗,最大發(fā)行量是否大于零 eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); //建立一個 milti_index 數(shù)據(jù)表,用來與數(shù)據(jù)庫交互 stats statstable( _self, sym.name() ); //在表中搜索相同名稱的代幣 auto existing = statstable.find( sym.name() ); //校驗,是否已經(jīng)存在相同名稱的代幣 eosio_assert( existing == statstable.end(), "token with symbol already exists" ); //使用 emplace 方法,在數(shù)據(jù)表中增加一項 statstable.emplace( _self, [&]( auto& s ) { // 使用匿名函數(shù),將傳入的參數(shù)賦值給 currency_stats 結(jié)構(gòu)體 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; }); }transfer(轉(zhuǎn)賬)函數(shù)
transfer 應(yīng)該是這個智能合約最常用的函數(shù),就是將代幣從一個賬戶轉(zhuǎn)到另一個。
//轉(zhuǎn)出方賬戶名 void token::transfer( account_name from, //轉(zhuǎn)入方賬戶名 account_name to, //代幣種類與數(shù)量 asset quantity, //轉(zhuǎn)賬備忘(目前還沒實現(xiàn)) string /*memo*/ ) { //打印轉(zhuǎn)賬提示 print( "transfer" ); //檢查轉(zhuǎn)出方權(quán)限 require_auth( from ); //得到代幣名稱 auto sym = quantity.symbol.name(); //建立一個 milti_index 數(shù)據(jù)表,用來與數(shù)據(jù)庫交互 stats statstable( _self, sym ); //在數(shù)據(jù)表中尋找代幣的 currency_stats 結(jié)構(gòu)體 const auto& st = statstable.get( sym ); //向轉(zhuǎn)出方獲取回執(zhí) require_recipient( from ); //向轉(zhuǎn)入方獲取回執(zhí) require_recipient( to ); //校驗,轉(zhuǎn)出的代幣是否有效 eosio_assert( quantity.is_valid(), "invalid quantity" ); //校驗,轉(zhuǎn)賬數(shù)量要大于0 eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); //調(diào)用 sub_balance 私有方法 sub_balance( from, quantity, st ); //調(diào)用 add_balance 私有方法 add_balance( to, quantity, st, from ); }issue(發(fā)幣)函數(shù)
上面的 create 函數(shù)創(chuàng)建代幣后只是給定了參數(shù),并沒有真正的代幣被創(chuàng)建出來,需要 issue 函數(shù)進(jìn)行發(fā)幣。
//參數(shù):代幣接收方 代幣數(shù)量和種類 備忘 void token::issue( account_name to, asset quantity, string memo ) { //打印提示 print( "issue" ); //獲取代幣名稱 auto sym = quantity.symbol.name(); //建立一個 milti_index 數(shù)據(jù)表,用來與數(shù)據(jù)庫交互 stats statstable( _self, sym ); //在數(shù)據(jù)表中搜索代幣 currency_stats 結(jié)構(gòu)體 const auto& st = statstable.get( sym ); //檢查發(fā)幣者授權(quán) require_auth( st.issuer ); //檢查資產(chǎn)是否有效 eosio_assert( quantity.is_valid(), "invalid quantity" ); //檢查資產(chǎn)是否大于零 eosio_assert( quantity.amount > 0, "must issue positive quantity" ); //檢查創(chuàng)造的總資產(chǎn)是否大于最大代幣數(shù) eosio_assert( quantity <= st.max_supply - st.supply, "quantity exceeds available supply"); //更新資產(chǎn)創(chuàng)造數(shù)量記錄 statstable.modify( st, 0, [&]( auto& s ) { s.supply += quantity; }); //給發(fā)布者增加資產(chǎn) add_balance( st.issuer, quantity, st, st.issuer ); //判斷代幣接受方是否是發(fā)幣者 if( to != st.issuer ) { //這里使用了一個特殊處理,先給發(fā)幣者增加相應(yīng)的代幣,再調(diào)用 transfer 函數(shù)轉(zhuǎn)賬給代幣接受方。 //這樣做的目的是讓代幣接受方收到通知 SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} ); } }設(shè)置 action
大家知道 EOS 系統(tǒng)的智能合約是以 action 為基本動作單位的,我們要將需要聲明為 action 的函數(shù)告知 EOS 系統(tǒng),通過以下宏即可實現(xiàn)。
//將 create issue transfer 三個共有函數(shù)聲明為 action,供其他賬戶調(diào)用。 EOSIO_ABI( eosio::token, (create)(issue)(transfer) )
【許曉笛】 EOS 智能合約案例解析(1)
【許曉笛】 EOS 智能合約案例解析(3)
圓方圓學(xué)院匯集大批區(qū)塊鏈名師,打造精品的區(qū)塊鏈技術(shù)課程。 在各大平臺都長期有優(yōu)質(zhì)免費(fèi)公開課,歡迎報名收看。
公開課地址:https://ke.qq.com/course/345101
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/24419.html
摘要:構(gòu)造函數(shù)為空,參數(shù)為智能合約賬戶名。每個智能合約類都要繼承類類構(gòu)造函數(shù)創(chuàng)建代幣函數(shù)聲明函數(shù),這個函數(shù)用來新建一種代幣,并輸入代幣的各種屬性,同時函數(shù)也是一個。 詳解 EOS 智能合約的 hpp 文件 為了幫助大家熟悉 EOS 智能合約,EOS 官方提供了一個代幣(資產(chǎn))智能合約 Demo —— eosio.token。eosio.token 智能合約目前還不是特別完善,個別功能還沒有完...
摘要:文件地址智能合約文件由部分組成定義類型的別名各個類型的數(shù)據(jù)結(jié)構(gòu)智能合約的數(shù)據(jù)結(jié)構(gòu)體李嘉圖條款注格式不支持注釋,上面的雙斜線大家理解就好。是李嘉圖合約,剛剛被加入到智能合約中,官方還沒有進(jìn)一步說明。 詳解 EOS 智能合約的 abi 文件 這次向大家介紹 eosio.token 智能合約的最后一個文件 —— abi文件。ABI 全稱 Application Binary Interfac...
摘要:相關(guān)文章和視頻推薦許曉笛智能合約案例解析圓方圓學(xué)院匯集大批區(qū)塊鏈名師,打造精品的區(qū)塊鏈技術(shù)課程。 Daniel Larimer 在他的博客介紹了EOS新的智能合約架構(gòu)(EOS團(tuán)隊的開發(fā)速度實在是太嚇人,根本追不上)。他給出了最簡單的一個新幣種的智能合約代碼,僅有49行就能完成一個新幣種的開發(fā),一個新的愛息歐就誕生了。讓我們一步一步實現(xiàn)吧。 首先實現(xiàn)私有成員,建立一個 account 結(jié)...
摘要:為了解決這個問題,采取了三步用戶賬戶自定義分級權(quán)限。用戶權(quán)限與智能合約之間的映射。圖中不難看出,權(quán)限是賬戶最高權(quán)限,可以執(zhí)行權(quán)限。如果沒有發(fā)現(xiàn)任何符合的映射,會直接檢查本次執(zhí)行是否滿足了權(quán)限,若不足,會檢查。 到底什么叫智能合約? 名詞解釋:本篇文章出現(xiàn)很多 Action 和 Active,Action (動作)為 EOS 中賬戶可以接受的動作,也就是別人可以對你做什么;Active ...
摘要:對于很多沒有中間語言的字節(jié)碼的編程語言來說,根本不存在解釋執(zhí)行與編譯執(zhí)行的選項,比如傳統(tǒng)只能編譯執(zhí)行,直接將代碼編譯成為可執(zhí)行的二進(jìn)制機(jī)器碼,我們電腦上文件就是編譯的成果。 Daniel Larimer 在最近的博客中透露,EOS 新增了官方的 WebAssembly 解釋器,用來解釋執(zhí)行 WebAssembly 智能合約,加上之前的編譯執(zhí)行,EOS 智能合約有了兩種執(zhí)行方式。 對于很...
閱讀 1012·2021-11-23 10:11
閱讀 3854·2021-11-16 11:50
閱讀 921·2021-10-14 09:43
閱讀 2713·2021-10-14 09:42
閱讀 2710·2021-09-22 16:02
閱讀 1056·2019-08-29 10:57
閱讀 3378·2019-08-29 10:57
閱讀 2268·2019-08-26 13:52