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

詳解 EOS 智能合約的 cpp 文件

之前的文章介紹了 eosio.token 智能合約的 hpp 文件,這次向大家介紹 eosio.token.cpp 文件,cpp 文件即 C++ 代碼文件,智能合約所有的業務邏輯內容都是在 cpp 文件中實現的。

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

了解 C/C++ 開發的同學肯定熟悉,cpp 文件的主要使命是實現 hpp 文件中聲明的函數(方法),包括公有函數(EOS 里也叫 action)和私有函數。hpp 里挖的坑,cpp 要一個不留地實現。

私有函數

照慣例,私有函數都是工具函數,供類內部的其他函數調用。

sub_balance(減資產)函數

作用:從指定賬戶中減去資產 參數:被操作賬戶,資產數,資產狀態

//                   參數:被操作賬戶          資產種類與數量      資產狀態結構體
void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {//建立一個 multi_index,用來操作數據庫//這里的參數 _self 表示數據的擁有者為智能合約本身,參數 owner 表示儲存在名為被操作賬戶的表中//這樣并不是直接建立了一個新表,而是讓 C++ 程序與數據庫對應的表之間建立了數據傳輸的通道accounts from_acnts( _self, owner );//在數據表中查詢要減少的代幣結構體,就是 hpp 文件中定義的 account 結構體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" );}//通過 Lambda 表達式(匿名函數)修改將代幣結構體from_acnts.modify( from, owner, [&]( auto& a ) {//匿名函數 函數體   a.balance -= value;});
}復制代碼

add_balance(增加資產)函數

作用:從指定賬戶中增加資產 參數:被操作賬戶,資產數,資產狀態,存儲資源支付賬戶

//                   參數:被操作賬戶         代幣數量      代幣狀態結構體             儲存支付賬戶
void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
{//建立一個 multi_index,用來操作數據庫accounts to_acnts( _self, owner );//在數據表中查詢要增加的代幣結構體auto to = to_acnts.find( value.symbol.name() );//如果 to == to_acnts.end(),說明查找到數據表的末尾都沒有對應的結構體,說明該賬戶沒有該代幣if( to == to_acnts.end() ) {//校驗,該代幣是否開啟了白名單功能eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );//使用 emplace 方法,在數據表中增加一項to_acnts.emplace( ram_payer, [&]( auto& a ){//匿名函數體,代幣數量等于每次轉入的數量,因為之前沒有a.balance = value;});//如果數據表中已經存在此項,只需增加代幣數量} else {//檢查賬戶是否在白名單中eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );//使用 modify 方法,修改項目to_acnts.modify( to, 0, [&]( auto& a ) {//直接修改代幣數量a.balance += value;});}
}
復制代碼

公有函數

EOS 合約中的公有函數大多是供別的賬戶調用的 Action,根據 hpp 文件,我們需要實現 create、issue、transfer 三個公有函數(action)。

create(新建代幣)函數

create 函數用來創建一種新的代幣,并設置這種新代幣的各種參數。

                    //參數:發幣賬戶
void token::create( account_name issuer,//最大發行量asset        maximum_supply,//發幣者是否可以凍結代幣uint8_t      issuer_can_freeze,//發幣者是否可以召回代幣uint8_t      issuer_can_recall,//是否可以設置白名單uint8_t      issuer_can_whitelist )
{//需要 eosio.token 賬戶本身的授權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");//建立一個 milti_index 數據表,用來與數據庫交互stats statstable( _self, sym.name() );//在表中搜索相同名稱的代幣auto existing = statstable.find( sym.name() );//校驗,是否已經存在相同名稱的代幣eosio_assert( existing == statstable.end(), "token with symbol already exists" );//使用 emplace 方法,在數據表中增加一項statstable.emplace( _self, [&]( auto& s ) {// 使用匿名函數,將傳入的參數賦值給 currency_stats 結構體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(轉賬)函數

transfer 應該是這個智能合約最常用的函數,就是將代幣從一個賬戶轉到另一個。

                    //轉出方賬戶名
void token::transfer( account_name from,//轉入方賬戶名account_name to,//代幣種類與數量asset        quantity,//轉賬備忘(目前還沒實現)string       /*memo*/ )
{//打印轉賬提示print( "transfer" );//檢查轉出方權限require_auth( from );//得到代幣名稱auto sym = quantity.symbol.name();//建立一個 milti_index 數據表,用來與數據庫交互stats statstable( _self, sym );//在數據表中尋找代幣的 currency_stats 結構體const auto& st = statstable.get( sym );//向轉出方獲取回執require_recipient( from );//向轉入方獲取回執require_recipient( to );//校驗,轉出的代幣是否有效eosio_assert( quantity.is_valid(), "invalid quantity" );//校驗,轉賬數量要大于0eosio_assert( quantity.amount > 0, "must transfer positive quantity" );//調用 sub_balance 私有方法sub_balance( from, quantity, st );//調用 add_balance 私有方法add_balance( to, quantity, st, from );
}
復制代碼

issue(發幣)函數

上面的 create 函數創建代幣后只是給定了參數,并沒有真正的代幣被創建出來,需要 issue 函數進行發幣。

                //參數:代幣接收方     代幣數量和種類      備忘
void token::issue( account_name to, asset quantity, string memo )
{//打印提示print( "issue" );//獲取代幣名稱auto sym = quantity.symbol.name();//建立一個 milti_index 數據表,用來與數據庫交互stats statstable( _self, sym );//在數據表中搜索代幣 currency_stats 結構體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 ){//這里使用了一個特殊處理,先給發幣者增加相應的代幣,再調用 transfer 函數轉賬給代幣接受方。//這樣做的目的是讓代幣接受方收到通知SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );}
}
復制代碼

設置 action

大家知道 EOS 系統的智能合約是以 action 為基本動作單位的,我們要將需要聲明為 action 的函數告知 EOS 系統,通過以下宏即可實現。

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

相關文章和視頻推薦

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

圓方圓學院匯集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450245.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450245.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450245.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 中 transient關鍵字

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 java語言的關鍵字&#xff0c;變量修飾符&#xff0c;如果用transient聲明一個實例變量&#xff0c;當對象存儲時&#xff0c;它的值不需…

java中int轉成String位數不足前面補零

java中int轉成String位數不足前面補零 轉載自&#xff1a;http://ych0108.iteye.com/blog/2174134java中int轉String位數不夠前面補零 String.format("%010d", 25); //25為int型 10代表前面要補的字符 10代表字符串長度 d表示參數為整數類型 今天想將int 轉String 位…

Oops! the requested resource is not found!

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 情況一&#xff1a;調用 dubbo 服務失敗&#xff0c;報錯如題&#xff1a;Oops! the requested resource is not found! 原因很簡單&am…

django URL路由基礎

URL是Web服務的入口&#xff0c;用戶通過瀏覽器發送過來的任何請求&#xff0c;都是發送到一個指定的URL地址&#xff0c;然后被響應。 在Django項目中編寫路由&#xff0c;就是向外暴露我們接收哪些URL的請求&#xff0c;除此之外的任何URL都不被處理&#xff0c;也沒有返回。…

Linux在超級計算機領域一統天下

摘要&#xff1a;在世界超級計算機排行榜500強榜單中&#xff0c;基于Linux的超級計算機占據了462個席位&#xff0c;比率高達92%。基于Windows的超級計算機僅有2個席位&#xff0c;份額為0.4%。中國基于Windows的超級計算機Magic Cube排名94位&#xff0c;澳大利亞基于Windows…

Qtum量子鏈漏洞賞金計劃正式開啟

本次Qtum量子鏈賞金計劃為了更好的借助社區的力量參與到QTUM主網及周邊應用的開發建設中&#xff0c;讓QTUM持續地保持安全、高效的運行&#xff0c;同時能滿足更多用戶的需求。Bug分級與獎勵體系1、如果已經有類似的Issue或者Qtum團隊已經知道并在解決該問題的情況將不適用于該…

.SpelEvaluationException: EL1008E: Property or field ‘cache_department_list_Tree‘ cannot be found

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; .SpelEvaluationException: EL1008E: Property or field cache_department_list_Tree cannot be found on object…

修過的一個android framework原生系統代碼bug

“坑”描述&#xff1a; 在對我們自己研發的一款android終端進行camera拍照壓力測試時&#xff0c;發現當拍照張數達到幾萬張時&#xff0c;查看內存占用情況&#xff0c;發現內存泄露。 填“坑”&#xff1a; frameworks/base/core/jni/android/graphics/YuvToJpegEncoder.…

Koa項目搭建過程詳細記錄

2019獨角獸企業重金招聘Python工程師標準>>> Java中的Spring MVC加MyBatis基本上已成為Java Web的標配。Node JS上對應的有Koa、Express、Mongoose、Sequelize等。Koa一定程度上可以說是Express的升級版。許多Node JS項目已開始使用非關系型數據庫(MongoDB)。Sequel…

商業項目中代碼質量是否重要?

這是一篇比較老的 文章&#xff0c;但是文中的這些問題在現在仍然普遍存在。代碼質量的高低與商業產品的優劣是否有直接的影響&#xff1f;開發者Frank Sommers在文中給出了他的看法。文章內容如下。在大多數商業項目中&#xff0c;代碼質量并不被看重&#xff0c;因為大部分情…

Class is not a root resource. It, or one of its interfaces must be annotated with @Path:

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; Class is not a root resource. It, or one of its interfaces must be annotated with Path:XXXX 這是一個dub…

Equation漏洞混淆利用分析總結(下)

樣本三 如下所示在該樣本中&#xff0c;使用了Ole10Native的流&#xff0c;因此沒有equative head&#xff0c;默認讀取紅框中的4位長度。之后的metf head為01. 可以看到metf head的長度為01時&#xff0c;直接進入到if判斷中(該if中的函數實際是一個異常處理函數&#xff0c;但…

閑扯工程師的版本管理概念

如果你所在的公司還在通過qq給客戶發sdk升級包等&#xff0c;你可以考慮換一家公司了。

resource fork, Finder information, or similar detr

1.關閉當前項目和Xcode 2.打開終端或者iterm cd ~/Library/Developer/Xcode/DerivedData/ 3. xattr -rc . 4.重新打開項目 5.如果不行那你就再試試其他的辦法吧&#xff0c;我就是這樣弄好的 如果有需要裝系統的話可以看一下我自己封裝的系統&#xff0c;原裝系統無精簡&#x…

5 個常用的軟件質量指標

在軟件開發中&#xff0c;軟件質量是衡量軟件是否符合需求、標準的重要體現。除了 代碼質量外&#xff0c;影響軟件整體質量的因素還有很多。因此&#xff0c;要確保軟件的整體質量&#xff0c;就需要在各個環節嚴格控制。本文列出了衡量軟件質量的5個最常用的指標。1. SLOC&a…

介紹一個對陌生程序快速進行性能瓶頸分析的技巧

前言 工作多年&#xff0c;一直做的是curd系統。前幾年做的系統應用場景&#xff0c;大多對數據庫依賴比較重。例如報表統計&#xff0c;數據遷移&#xff0c;批量對賬等。所以這些系統出現性能瓶頸一般出在數據庫操作上面。 如果程序因為數據庫操作出現性能瓶頸是比較好辦的&a…

[WARNING] The POM for XXX-system:jar:1.9.0-SNAPSHOT is missing, no dependency information available

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 在 git-bash 中 想要啟動一個工程服務就是不成功&#xff0c;始終提示jar包找不到&#xff0c;本地代碼已提交。 這時可直接登陸git&am…

關于tcp網絡通訊的幾個場景的小測試

以下場景基于阻塞式IO 發送端向接收端快速的發送數據&#xff0c;接收端如果不接受或者很慢速的接受會發生什么情況。 發送端快速向接收端發送大量數據&#xff0c;然后立即退出&#xff0c;接收端會發生什么情況。

測試一體機ASM failgroup的相關問題處理

環境&#xff1a;3臺虛擬機 RHEL 7.3 Oracle RAC 11.2.0.4問題現象&#xff1a;RAC運行正常&#xff0c;ASM磁盤組Normal冗余&#xff0c;有failgroup整體故障&#xff0c;有failgroup配置錯誤。溫馨提示&#xff1a;本文并不是市場上任何一款商業的一體機產品&#xff0c;只是…

掌握窮變富的12條原則 迅速從普通人變成有錢人

“窮忙”和“富閑”是對立面&#xff0c;“窮”對“忙”&#xff0c;“富”對“閑”&#xff0c;很多“窮忙女”是在拿青春當賭注&#xff0c;希望自己今天的“美麗”明天就能在市場上有個不錯的“回報”&#xff1b;而多數“富閑女”則是在拿智慧當籌碼&#xff0c;既不可替代…