日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【许晓笛】 EOS 智能合约案例解析(2)

發(fā)布時間:2023/12/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【许晓笛】 EOS 智能合约案例解析(2) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

詳解 EOS 智能合約的 cpp 文件

之前的文章介紹了 eosio.token 智能合約的 hpp 文件,這次向大家介紹 eosio.token.cpp 文件,cpp 文件即 C++ 代碼文件,智能合約所有的業(yè)務(wù)邏輯內(nèi)容都是在 cpp 文件中實(shí)現(xiàn)的。

eosio.token.cpp 文件地址: github.com/EOSIO/eos/b…

了解 C/C++ 開發(fā)的同學(xué)肯定熟悉,cpp 文件的主要使命是實(shí)現(xiàn) hpp 文件中聲明的函數(shù)(方法),包括公有函數(shù)(EOS 里也叫 action)和私有函數(shù)。hpp 里挖的坑,cpp 要一個不留地實(shí)現(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ù)耐ǖ?/span>accounts from_acnts( _self, owner );//在數(shù)據(jù)表中查詢要減少的代幣結(jié)構(gòu)體,就是 hpp 文件中定義的 account 結(jié)構(gòu)體const auto& from = from_acnts.get( value.symbol.name() );//校驗(yàn),要減少的代幣數(shù)量應(yīng)該小于目前擁有的代幣數(shù)量,否則會報錯。eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );//判斷是否有被操作賬戶的授權(quán)if( has_auth( owner ) ) {//校驗(yàn),賬戶是否被凍結(jié)eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );//校驗(yàn),這種代幣是否被凍結(jié)eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );//校驗(yàn),賬戶是否在白名單中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;}); }復(fù)制代碼

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() ) {//校驗(yàn),該代幣是否開啟了白名單功能eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );//使用 emplace 方法,在數(shù)據(jù)表中增加一項(xiàng)to_acnts.emplace( ram_payer, [&]( auto& a ){//匿名函數(shù)體,代幣數(shù)量等于每次轉(zhuǎn)入的數(shù)量,因?yàn)橹皼]有a.balance = value;});//如果數(shù)據(jù)表中已經(jīng)存在此項(xiàng),只需增加代幣數(shù)量} else {//檢查賬戶是否在白名單中eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );//使用 modify 方法,修改項(xiàng)目to_acnts.modify( to, 0, [&]( auto& a ) {//直接修改代幣數(shù)量a.balance += value;});} } 復(fù)制代碼

公有函數(shù)

EOS 合約中的公有函數(shù)大多是供別的賬戶調(diào)用的 Action,根據(jù) hpp 文件,我們需要實(shí)現(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;//校驗(yàn),新代幣名稱是否有效eosio_assert( sym.is_valid(), "invalid symbol name" );//校驗(yàn),最大發(fā)行量是否有效eosio_assert( maximum_supply.is_valid(), "invalid supply");//校驗(yàn),最大發(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() );//校驗(yàn),是否已經(jīng)存在相同名稱的代幣eosio_assert( existing == statstable.end(), "token with symbol already exists" );//使用 emplace 方法,在數(shù)據(jù)表中增加一項(xiàng)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;}); }復(fù)制代碼

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)賬備忘(目前還沒實(shí)現(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 );//校驗(yàn),轉(zhuǎn)出的代幣是否有效eosio_assert( quantity.is_valid(), "invalid quantity" );//校驗(yàn),轉(zhuǎn)賬數(shù)量要大于0eosio_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 ); } 復(fù)制代碼

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} );} } 復(fù)制代碼

設(shè)置 action

大家知道 EOS 系統(tǒng)的智能合約是以 action 為基本動作單位的,我們要將需要聲明為 action 的函數(shù)告知 EOS 系統(tǒng),通過以下宏即可實(shí)現(xiàn)。

//將 create issue transfer 三個共有函數(shù)聲明為 action,供其他賬戶調(diào)用。 EOSIO_ABI( eosio::token, (create)(issue)(transfer) ) 復(fù)制代碼

相關(guān)文章和視頻推薦

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

圓方圓學(xué)院匯集大批區(qū)塊鏈名師,打造精品的區(qū)塊鏈技術(shù)課程。 在各大平臺都長期有優(yōu)質(zhì)免費(fèi)公開課,歡迎報名收看。

公開課地址:ke.qq.com/course/3451…

總結(jié)

以上是生活随笔為你收集整理的【许晓笛】 EOS 智能合约案例解析(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。