【eos不定期更新的日常】使用require_recipient触发合约动作原理介绍

背景介绍

eos的智能合约中,不少合约都会调用require_receipent方法,用于通知合约的参与方账户。这里的通知,实际上是调用被通知账户的智能合约,如果它部署了。被通知账户接到通知后,可以在其智能合约中做一系列操作,这个功能极大的方便了dapp的功能交互。

require_receipent如何传递通知

拿eosio.token发币合约为例,当用户触发了一个transfer转账动作,则会调用require_receipent方法通知from、to账户

4194218-bf02f0737f5b9b24.png
eosio.token transfer源码

看看require_receipent方法的实现,其实就是将需要通知的账户,加入通知列表中

4194218-822a70dfb6538d96.png
require_receipent函数

通知动作的执行,实际上是exec函数完成的,它会轮询通知列表,执行exec_one函数挨个通知

4194218-e8684cdca1676fd7.png
exec函数

exec_one函数,则会检查被通知账户是否部署了合约,如果部署了,则调用合约的apply函数,apply函数的用途会在稍后讲解。至此,require_recipient成功将消息传递给了被通知账户的合约。

4194218-39db74a24271dd67.png
exec_one函数

eosio.token合约源码:源码

require_recipient、exec、exec_one等方法:源码 

智能合约如何被调用

1. apply函数

前文提到了apply函数,实际上就是智能合约的入口。apply函数的作用就是监听合约的调用,当合约方法被调用时,apply函数会创建上下文环境,供合约方法运行

4194218-95df3b8068994e78.png
apply函数的作用

同样,apply函数作为智能合约入口,在接收到通知后,可以自定义处理逻辑、调用handler进行下一步动作。具体apply函数怎么实现,根据智能逻辑而定,但是每个智能合约必须实现apply函数。

extern "C"  {

        void apply( uint64_t receiver, uint64_t code, uint64_t action )  {

             // 下一步处理逻辑

       }

}

2. EOSIO_DISPATCH

EOSIO_DISPATCH宏是eosio.cdt合约编译器提供的一个默认定义,实现了最简单的apply函数,逻辑是当receiver==code时,被通知账户和合约部署账户相同时,才执行智能合约的方法

4194218-795783f9b2d6f68d.png
EOSIO_DISPATCH宏

EOSIO_DISPATCH_HELPER来具体做执行的动作

4194218-951b2ca9de839d78.png
EOSIO_DISPATCH_HELPER宏

依然拿eosio.token合约举例,合约的最后,直接调用了EOSIO_DISPATCH宏,用默认的apply去执行合约

4194218-f45ff8aebd084654.png
eosio.token源码

apply和EOSIO_DISPATCH用法详见:https://developers.eos.io/eosio-home/docs (Custom Dispatchers一节)

智能合约的通信原理详见:https://developers.eos.io/eosio-cpp/docs/communication-model

使用require_recipient触发合约动作示例

1. 需求

当A账户转账到B账户时,B账户部署合约检查memo,当memo不合法时,终止这笔转账

2. 合约实现示例

这里我们自己实现了apply函数,检测到合约动作是transfer时,即执行testrecipient::transfer方法。将这个合约部署在B账户上,则B账户在收到转账时,会调用testrecipient::transfer方法检测memo是否合法

4194218-dbd6adf50aba7da0.png
合约源码

往eosiotest账户部署上面的智能合约,则非法的转账会被拒绝

4194218-54179f2d7a6c9d60.png
执行结果

参考文章

智能合约通信模式:https://developers.eos.io/eosio-cpp/docs/communication-model

apply函数和EOSIO_DISPATCH的用法:https://developers.eos.io/eosio-home/docs/writing-a-custom-dispatcher

使用require_recipient触发合约动作:https://eos.live/detail/11530

使用eosio.cdt编译合约后,apply函数如何重写:http://knowledge.cryptokylin.io/topics/99

后记

最近,eos重磅级侧链准备出来了,作者也忙着coding没太多时间更新。后面等侧链的事情落地了,再为大家介绍一波,尽请期待!

猜你喜欢

转载自blog.csdn.net/weixin_34302798/article/details/86955004