EOS智能合約 -- 合約交互

這篇文章早早就寫好了,但是最近工作特別忙,一直沒有潤色,所以就沒更新。而且,EOS Dawn 4.0 也發(fā)布了,感覺研究不過來了。。。。

合約開發(fā)一些小思考

熟悉合約的開發(fā)之后,其實可以發(fā)現(xiàn),合約的編寫本身比較“簡單”;因為合約開發(fā)講究實現(xiàn)功能:邏輯實現(xiàn)簡單、復(fù)雜合約盡量拆分、抱著安全。

習(xí)慣各種復(fù)雜業(yè)務(wù)邏輯的開發(fā)者,肯定感覺合約寫起來很簡單。但是,這也是另一種“復(fù)雜”;因為你要在一個有限功能、有限存儲、節(jié)約資源的框架下,實現(xiàn)你想實現(xiàn)的功能,想想其實挺有挑戰(zhàn)的O(∩_∩)O

稍微說了點想法,還是快點開始正題吧!

智能合約之間的調(diào)用

這個之前在以太坊一些小問題中說過,為了讓智能合約能夠更新,最好是邏輯、數(shù)據(jù)業(yè)務(wù)分開在不懂合約中,然后用邏輯合約調(diào)用數(shù)據(jù)合約;雖然EOS的智能合約沒有這方面問題,但是,合約間調(diào)用還是少不了的。EOS中合約的調(diào)用,主要的實現(xiàn)就是靠函數(shù):

//file: contracts/eosiolib/action.h

template<typename... Args>
   void dispatch_inline( account_name code, action_name act,
                         vector<permission_level> perms,
                         std::tuple<Args...> args ) {
      action( perms, code, act, std::move(args) ).send();
   }

從入?yún)ⅲ湍艽篌w看出如何使用了:

  • code:合約名稱;
  • act:action的名稱;
  • perms:授權(quán)信息,格式如下:
    permission_level( account_name a, permission_name p )
    比如 level{tester, N(active)};
  • args:action的入?yún)ⅲY(jié)構(gòu)使用的C++的tuple;

這是,比如麻煩的調(diào)用,程序也提供了比較方面的使用方式,如下的宏定義:

#define INLINE_ACTION_SENDER3( CONTRACT_CLASS, FUNCTION_NAME, ACTION_NAME  )\
::eosio::inline_dispatcher<decltype(&CONTRACT_CLASS::FUNCTION_NAME), ACTION_NAME>::call

#define INLINE_ACTION_SENDER2( CONTRACT_CLASS, NAME )\
INLINE_ACTION_SENDER3( CONTRACT_CLASS, NAME, ::eosio::string_to_name(#NAME) )

#define INLINE_ACTION_SENDER(...) BOOST_PP_OVERLOAD(INLINE_ACTION_SENDER,__VA_ARGS__)(__VA_ARGS__)

#define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\
INLINE_ACTION_SENDER(std::decay_t<decltype(CONTRACT)>, NAME)( (CONTRACT).get_self(),\
BOOST_PP_TUPLE_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)) );

至于,如何使用呢,我們接下來用個例子。

調(diào)用例子

我們就用前面一章中的例子來展示如何調(diào)用,blog_view,這章中,我們實現(xiàn)了一個簡單的用戶上傳博客的功能,然后審核員能夠?qū)徍擞脩舻奈恼率欠裼?strong>敏感信息;
比較符合區(qū)塊鏈開發(fā)思路的方式,既然用戶上傳知識、審核員審核文章,這都是工作量,那就要給用戶和審核員一些利益,好讓用戶多過來上傳文章,壯大我們的區(qū)塊鏈合約;我們就可以在審核員審核通過后,自動的使用合約給用戶和審核員發(fā)送token獎勵;

也就是在approved函數(shù)中,添加獎勵功能;
首先假設(shè),使用eosio.token合約,發(fā)布了token “BLOG幣”,并使用issue發(fā)行給合約blog.view一定量的幣;

///注意要include eosio.token的頭文件
/// @abi action
        void approved(const uint64_t ID) {

            auto itrid = idlists.find(ID);
            eosio_assert(itrid != idlists.end(), "this blog doesn't exists!\n");
            blog_index approve_blogs(_self, itrid->producer);

            auto itr = approve_blogs.find( ID );
            eosio_assert(itr != approve_blogs.end(), "this blog doesn't exists!\n");
            eosio_assert(itr->status == Status::s_reviewing, "this blog is reviewed!\n");
            require_auth(itr->reviewer);
            
            approve_blogs.modify(itr, itrid->producer, [&](auto& g){
                g.status = Status::s_approved;
                g.approve_status = std::string("approved");
            });
            //審核通過后,給予獎勵
            SEND_INLINE_ACTION( eosio::token(N(eosio.token)), transfer, {_self,N(active)}, { _self, producer, itrid->producer, "reward"} );
        }

可以看到,最后一個語句就是調(diào)用的其他合約 eosio.token,這語句是合約中最最簡單的調(diào)用方式,參數(shù)詳解:

  • eosio::token(N(eosio.token)) 前面是eosio.token頭文件中定義的結(jié)構(gòu),然后傳入的參數(shù),是該合約上傳的賬戶;
  • transfer 即需要調(diào)用的方法;
  • {_self,N(active)} 本次交易,需要的權(quán)限;
  • 后面的參數(shù),就是本次action需要的所有參數(shù);

當(dāng)然,實現(xiàn)的內(nèi)部調(diào)用的方法,還是很多種形式,比如action().send()、dispatch_inline()、INLINE_ACTION_SENDER等等,其實最根本的,還是action.send(),其他所有方法都是對該方法的封裝。

PS:合約間調(diào)用,還有一個比較嚴重的問題,就是目前合約調(diào)用的權(quán)限簽名,只支持調(diào)用合約的簽名。比如合約A,調(diào)用合約B的action,假設(shè)為transfer,transfer需要驗證發(fā)送者權(quán)限,則只能驗證合約A的權(quán)限。假如,用戶h,調(diào)用A合約,A合約調(diào)用B合約的transfer,則只能有合約B,本身發(fā)出轉(zhuǎn)賬,用h用戶的賬戶發(fā)出轉(zhuǎn)賬是不行的。。。挺繞的。
比如上面的例子,只能是_self本身發(fā)出轉(zhuǎn)賬,任何其他賬戶都不行。
期望在4.0改進吧,不然限制太大。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容