Skip to content

外部消息

在项目配置中必须显式启用外部消息支持。如果不启用,编译将失败。

外部消息是那些没有发送者的消息,任何人都可以发送。外部消息是与链下系统集成或进行合约常规维护的好工具。处理外部消息与处理内部消息不同。在本节中,我们将介绍如何处理外部消息。

外部消息与内部消息的不同

外部消息与内部消息在以下方面不同:

合约自己支付燃气费用

处理内部消息时,通常由发送者支付燃气费用。处理外部消息时,合约支付燃气费用。这意味着你需要在外部消息中小心燃气费用的使用。你应该始终测试合约的燃气费用,并验证一切是否按预期工作。

消息必须手动接受

外部消息不会自动接受。你需要手动接受它们。这是通过调用 acceptMessage 函数完成的。如果你不调用 acceptMessage 函数,消息将被拒绝。这样做是为了防止外部消息的垃圾邮件。

消息接受前的 10k 燃气限制

10k 燃气是一个非常小的限制,Tact 本身在到达你的代码之前就可以消耗大量燃气。你应该始终测试合约的燃气使用情况,并验证一切是否按预期工作。

外部消息的 10k 燃气限制基于我们为整个区块链的 gas_limit 字段设置的参数。你可以参考这里:

消息接受后的无限燃气使用

在你接受燃气后,合约可以使用任意多的燃气。这样做是为了允许合约进行任何类型的处理。你应该始终测试合约的燃气使用情况,并验证一切是否按预期工作,避免可能耗尽合约余额的漏洞。

没有可用的上下文

处理外部消息时,上下文和发送者函数不可用。这是因为外部消息没有可用的上下文。这意味着你不能在外部消息中使用上下文和发送者函数。你需要仔细测试你的合约,以确保它不使用上下文和发送者函数。

启用外部消息支持

要启用外部消息支持,请在项目配置文件中启用它:

json
{
  "options": {
    "external": true
  }
}

外部接收器

外部接收器的定义与内部接收器相同,但使用 external 关键字而不是 receive

solidity
contract SampleContract {
    external("Check Timeout") {
 
        // 检查合约超时
        require(self.timeout > now(), "Not timeouted");
 
        // 接受消息
        acceptMessage();
 
        // 超时处理
        self.onTimeouted();
    }
}