Reactive Contract(睿应层)

概述:

与传统的智能合约(Smart Contracts)不同,传统智能合约只能在用户发起交易时才会执行,而 RC 则能够主动监控 EVM 兼容链上的事件并对此作出反应。RC 会根据合约中实现的逻辑来处理这些事件,并在区块链上自动执行后续操作。这种创新引入了一种去中心化的机制,可以在无需人工干预的情况下自动对链上事件作出响应。

Ethereum 的世界中,智能合约彻底改变了我们对无信任协议执行方式的理解。

传统情况下,智能合约只有在用户主动发送交易时才会被触发执行

这种模式存在一些天然的限制:

  • 智能合约无法自主发起操作
  • 无法在没有外部触发的情况下响应链上的事件

因此必须依赖外部系统,例如:

  • 用户手动发送交易
  • 自动化脚本(例如交易机器人)

但这种方式带来了新的问题:

  • 需要持有私钥
  • 引入中心化控制点

Reactive Contracts(RC)正是为了解决这一限制而设计的。

RC 可以:

  • 自主监听 EVM 中发生的事件
  • 自动触发后续区块链操作

这使得开发者可以实现:

  • 多个链获取信息
  • 不同区块链之间执行逻辑
  • 无需中心化控制

RC 能够在整个区块链生态系统中自动执行复杂逻辑和交易

Reactive Contracts 的核心特征:

  • RC 不仅响应用户的直接交易,还能响应跨 EVM 链的事件。
  • 在事件发生后,它们可以执行链上操作,可能是在同一条链或其他链上

与预言机结合时,RC 可以对 链外事件(由预言机写入链上) 做出实时响应,并执行预先定义好的链上操作。这种 RC 与预言机的协作实现了对数字世界与现实世界的动态互动,大幅拓展了区块链应用的范围和功能。

RC的优势

1. 去中心化(Decentralization)

RC 在区块链上独立运行,消除了中心化控制点。

这样可以通过减少操控或单点故障的风险来提升系统安全性


2. 自动化(Automation)

RC 可以在链上事件发生时自动执行智能合约逻辑

这带来的好处包括:

  • 减少人工干预
  • 提供实时自动响应

3. 跨链互操作性(Cross-Chain Interoperability)

RC 可以与多个区块链交互

这意味着可以实现:

  • 复杂的跨链逻辑
  • 构建连接不同网络的应用

4. 更高的效率与功能性

通过对实时数据作出反应,RC 可以提升智能合约的效率,并支持更多高级功能,例如:

  • 复杂金融工具
  • 动态 NFT
  • 创新的 DeFi 应用

例如在 Ethereum 上运行的 DeFi 协议 Uniswap 就可以通过 RC 实现更自动化的交易逻辑。


5. 推动 DeFi 及更多领域创新

RC 为 DeFi 以及其他区块链应用开启了新的可能性,例如:

  • 自动化交易
  • 动态治理系统

从而打造一个更加响应式和互联的区块链生态系统

RC的劣势

Reactive Contract 无法阻止触发事件的交易,只能在事件发生后执行新的交易来响应或补救。

换句话说,Reactive Contract 不能阻止、取消、修改交易,RC只能监听事件、自动触发交易、自动执行策略。

==Reactive Network 可以理解为一种 去中心化的链上自动化执行网络,其功能类似自动化 bot,但由去中心化节点网络执行。==

RC 与传统智能合约的区别

RC 与传统智能合约的主要区别在于 “反应性(Reactivity)”

传统智能合约是被动的(Passive)

  • 只有在 EOA(Externally Owned Account) 发起交易时才会执行。

Reactive Contracts主动的(Reactive)

  • 持续监控区块链
  • 监听感兴趣的事件
  • 在检测到事件时 自动执行预定义的区块链操作

控制反转(Inversion of Control)

理解 RC 的一个关键概念是 控制反转(IoC)

传统智能合约采用的是 直接控制模型

  • 合约函数的执行由外部参与者触发,例如:
    • 用户(EOA)
    • 自动化机器人(bot)

而 RC 反转了这种控制关系

  • 合约根据预定义事件的发生来决定何时执行。

这种 IoC 模式改变了应用与区块链交互的方式,使系统更加:

  • 动态
  • 自动化
  • 响应式

没有 RC 时的情况

如果没有 Reactive Contract,你通常需要创建一个额外的实体(例如一个机器人 bot):

该 bot 会:

  1. 监控区块链
  2. 使用某些数据服务(通常是中心化的)
  3. 持有私钥
  4. 从自己的 EOA 地址发起交易

这种系统确实有用,但存在一些问题:

  • 需要托管私钥
  • 引入中心化组件
  • 某些场景下并不适合

IoC 的优势

通过 控制反转,我们可以避免运行那些“模拟人类签名交易”的额外实体。

如果你已经定义好了:

某个链上事件发生后需要执行的一系列交易逻辑

那么这些逻辑应该能够 完全去中心化地运行,因为:

  • 输入数据在链上
  • 输出结果也在链上

Reactive Network 为智能合约提供了一个过去一直缺失的重要能力:

自动执行能力

即:

  • 不需要人
  • 不需要 bot
  • 不需要签名交易

只需要 其他链上事件触发即可执行

开发者无需运行 bot 或持有私钥,Reactive Network 节点会自动代表 RC 提交交易。


Reactive Contract 内部发生了什么

创建 Reactive Contract 时,首先需要指定:

  • 要监听的 区块链
  • 要监听的 合约地址
  • 要监听的 事件(topic0)

RC 会持续监控这些地址,当检测到指定事件时就会执行。

这些事件可能包括:

  • ETH 转账
  • Token 转账
  • DEX 交易
  • 借贷
  • 闪电贷
  • 投票
  • 巨鲸转账
  • 任何智能合约活动

事件触发后的流程

当 RC 检测到相关事件后:

Reactive Network 会自动执行 RC 中实现的逻辑。

执行内容可能包括:

  • 根据事件数据进行计算
  • 更新合约状态

RC 是 有状态的(stateful),意味着:

  • 可以存储数据
  • 可以更新数据
  • 可以累积历史信息

因此可以实现:

  • 长期数据统计
  • 基于历史数据 + 新事件的决策逻辑

执行结果

在事件处理过程中:

  1. RC 更新自己的状态
  2. RC 可以在 EVM 链上发起交易

整个过程:

  • Reactive Network 中完成
  • 无需信任
  • 自动执行
  • 快速可靠

事件(Events)与回调(Callbacks)的工作原理

Ethereum 中,事件(Events) 允许智能合约在满足特定条件时记录信息,从而与外部世界进行通信。这使得 去中心化应用(dApps) 能够在某些事件发生时触发响应,而无需持续轮询区块链。事件会被 EVM 进行索引,因此可以非常容易地搜索和过滤。这对于监控区块链活动非常有用,例如:

  • Token 转账
  • 合约状态更新
  • 来自预言机的价格变化

ReactVM 执行环境

Reactive Contracts 在 ReactVM 中运行。

ReactVM 的特点:

  • 私有执行环境
  • 只能与同一部署者部署的合约交互

这样可以确保:

  • 执行环境安全
  • 合约隔离

向目标链发送 Callback

Reactive Contracts 可以通过 Callback 事件 发起跨链交易。

流程:

  1. RC 触发 Callback
  2. Reactive Network 监听该事件
  3. Network 在目标链发送交易

Callback 事件参数

1
2
3
4
5
6
event Callback(
uint256 indexed chain_id,
address indexed _contract,
uint64 indexed gas_limit,
bytes payload
);

Callback 需要提供:

  • chain_id:目标链 ID(EIP-155)
  • _contract:目标合约地址
  • **gas_limit **:目标交易 gas
  • payload:编码后的函数调用数据

Callback 处理过程

例如:

1
2
3
4
5
6
7
8
9
10
11
12
bytes memory payload =
abi.encodeWithSignature(
"onApproval(address,address,address,address,uint256)",
...
);

emit Callback(
SEPOLIA_CHAIN_ID,
address(approval_service),
GAS_LIMIT,
payload
);

流程:

当 Callback 事件被触发后:

Reactive Network 会:

  1. 读取 payload
  2. 解析交易数据
  3. 在目标链提交交易
1
2
3
4
5
6
7
  react()

emit Callback

Reactive Network

目标链执行函数

关于授权的重要说明

为了安全性(防止 RC 伪造地址调用):

Reactive Network 会自动:

RVM ID 替换 payload 中前 160 bit 的参数。

这样可以确保目标合约能够识别调用来源是 ReactVM,而不是用户伪造的地址。

RVM ID:

  • 等价于 ReactVM 地址
  • 与合约部署者地址相同

因此:回调函数的 第一个参数永远是 ReactVM 地址,无论你在 Solidity 中如何命名。

ReactVM 与 Reactive Network —— 双状态环境

Reactive Contracts 在两个独立环境中同时存在,并拥有两个不同的状态。

Reactive Network 与 ReactVM 的区别

每一个 Reactive Contract 都有 两个实例

  1. 一个在 Reactive Network 执行 subscription
  2. 一个在 ReactVM 处理 react()

需要注意:

  • 两个实例都会在每个网络节点上物理存储并运行
  • 两个实例拥有 相同代码
  • 但拥有 不同状态

并行化RC是一个架构决策,旨在确保即使事件数量庞大也能保持高性能。


Reactive Network

Reactive Network 的结构类似于普通的 Ethereum EVM 区块链,但增加了系统合约。

这些系统合约可以:

  • 订阅事件
  • 取消订阅事件

监听来源链,例如:

  • Ethereum
  • BNB Chain
  • Polygon
  • Optimism

执行环境:响应式合约可以使用所有标准的 EVM 功能。然而,它们运行在一个私有的 ReactVM 中,这限制了它们只能与同一部署者部署的合约进行交互。每个部署者地址都会拥有:

一个专属 ReactVM

Reactive Network 会持续监控事件日志,并将这些日志与响应式合约中定义的订阅条件进行匹配。当检测到符合条件的事件时,网络会触发 react() 方法,并将相关的事件信息作为参数传入。


ReactVM

ReactVM 是一个 受限制的虚拟机,专门用于在隔离环境中处理事件。从同一个地址部署的合约会在同一个 ReactVM 中执行。它们可以彼此交互,但不能与 Reactive Network 上的其他合约交互

特点:

  • 用于处理事件
  • 运行环境隔离

规则:

  • 同一地址部署的合约 → 在同一个 ReactVM 中运行
  • 可以互相调用
  • 不能调用 Reactive Network 上其他部署者的合约

ReactVM 与外界交互的两种方式

同一个ReactVM 中的合约可以通过 Reactive Network 与外部世界交互:

1 监听事件

ReactVM 会:

  • 监听已订阅事件
  • 当事件发生时执行代码

2 发起 Callback

根据事件输入执行代码后:

ReactVM 会请求 Reactive Network:

  • 向目标链发送 Callback
  • 执行链上交易

双状态架构

每个 Reactive Contract:

  • 代码相同
  • 状态不同
环境 状态
Reactive Network Network State
ReactVM VM State

因此每个函数必须明确:在哪个环境执行


如何识别执行环境

执行环境由变量 vm 决定。

项目中需要继承AbstractReactive


detectVm() 函数

系统通过检查一个系统合约地址来判断环境:

1
2
3
4
5
function detectVm() internal {
uint256 size;
assembly { size := extcodesize(0x0000000000000000000000000000000000fffFfF) }
vm = size == 0;
}

判断逻辑

检查地址:0x0000000000000000000000000000000000fffFfF,情况:

Reactive Network

1
2
3
该地址存在代码
size > 0
vm = false

ReactVM

1
2
3
该地址没有代码
size = 0
vm = true

限制执行环境

使用 modifier 控制函数执行环境。


Reactive Network 专用函数

1
2
3
4
modifier rnOnly() {
require(!vm, 'Reactive Network only');
_;
}

只允许该函数在Reactive Network执行。


ReactVM 专用函数

1
2
3
4
modifier vmOnly() {
require(vm, 'VM only');
_;
}

只允许该函数在ReactVM执行。


双变量状态管理

Reactive 架构中,每个已部署的合约可以运行在两种不同的运行状态中:

1 Reactive Network State

负责:

  • 与系统合约交互
  • 订阅事件

使用用于注册和管理事件订阅所需的变量和方法,变量来自AbstractReactive,包括:

  • service
  • vm
  • service.subscribe()

2 ReactVM State

负责:

  • 执行业务逻辑
  • 处理事件

变量由合约自己定义。

为了适应这两种状态,需要维护两套概念上的变量集合

  • 一套位于 基础合约(面向网络的合约上下文)
  • 另一套位于 ReactVM 上下文

在这个新的示例中:

  • Reactive Network 的变量来自继承的 AbstractReactive 合约
  • ReactVM 的变量则是在响应式合约本身中声明的

交易执行模型

Reactive Contract 中存在两类交易:Reactive Network 交易、ReactVM 交易


Reactive Network 交易

Reactive Network 中交易有两种来源:


1 用户触发

用户可以调用反应式网络的 RC 实例的方法来执行管理功能或更新合同状态。

例如:暂停事件订阅可以通过调用pause()函数实现:

1
function pause() external rnOnly onlyOwner

执行流程:

  1. 获取订阅列表
  2. 调用service.unsubscribe()取消事件监听。

pause()函数防止RC对事件作出反应,取消订阅,从而有效阻止后续事件驱动的交易,直到事件恢复。


resume()

恢复监听:service.subscribe()

resume() 函数会重新订阅这些相同的事件,以便在新事件出现时 RC 继续响应


2 事件触发

即使用户没有发送交易,Reactive Network 也会:

  1. 监听源链事件
  2. 分发给 ReactVM
  3. ReactVM 执行逻辑

ReactVM 交易

ReactVM 中的交易, 用户无法直接调用,只能通过事件触发:

1
2
3
4
5
6
7
Origin Chain Event

Reactive Network

ReactVM

react()

react() 作用

  1. 更新状态
  2. 执行业务逻辑
  3. 发送 Callback

Callback 触发跨链交易

Callback 可以:

  • 在其他链执行交易
  • 自动触发

无需用户操作。

订阅事件(Event Subscription)

Reactive Network 的核心能力就是 **订阅事件 (Event Subscription)**。Reactive Contract 不会直接调用目标链。而是emit Callback(...),由 Reactive Network 去执行。

Reactive Contract 可以:

1
2
3
4
5
6
7
  订阅某个链上事件

当事件发生

Reactive Network 自动调用 react()

合约执行逻辑

结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
Origin Chain (如 Sepolia)

│ emit Event

Reactive Network

│ 检测匹配 subscription

Reactive Contract

│ 调用 react()

执行逻辑

所以核心流程:

  1. 订阅事件
  2. 事件发生
  3. react() 被触发
  4. 执行 callback

订阅是通过 Reactive Network System Contract 完成的:

接口:

1
2
3
4
5
6
7
8
9
10
11
12
interface ISubscriptionService {
function subscribe(
uint256 chain_id,
address _contract,
uint256 topic_0,
uint256 topic_1,
uint256 topic_2,
uint256 topic_3
) external;

function unsubscribe(...) external{};
}

常见订阅方式

Wildcard(通配符)

Reactive Network 支持通配:

含义
address(0) 任意合约
uint256(0) 任意 chain
REACTIVE_IGNORE 任意 topic

例如:topic_1 = REACTIVE_IGNORE

表示匹配任何 topic1

1 监听某个合约的所有事件

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0xContract,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);

含义:监听这个合约的所有事件


2 监听某种 Event

例如:UniswapV2 Sync 的topic0:0x1c411e9a96e07124...

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0,
SYNC_TOPIC,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);

含义:监听所有合约的 Sync 事件


3 同时限制 合约 + 事件

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0xUniswapPair,
SYNC_TOPIC,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);

含义:监听某个 pair 的 Sync

react() 函数

用于处理传入事件通知的关键函数。react()只能被 Reactive Network 调用

该函数接收一个 LogRecord 作为输入,使得响应式合约(reactive contracts)能够动态地处理事件日志。

Reactive Contract 必须实现:function react(LogRecord calldata log) external{}

当事件发生时,Reactive Network 会调用react(log)

1
2
3
4
5
6
7
8
9
10
11
function react(LogRecord calldata log) external vmOnly {
if (log.topic_0 == SUBSCRIBE_TOPIC) {
...
}
else if (log.topic_0 == UNSUBSCRIBE_TOPIC) {
...
}
else {
...
}
}

根据 topic0 判断是什么事件

动态订阅 (Dynamic Subscription)

Reactive Contract 可以根据事件动态修改 subscription

例如:

1
2
3
4
5
6
7
用户订阅

监听 approval

用户取消订阅

停止监听

实现:subscribe()unsubscribe()

构造函数订阅(Constructor Subscribtion)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// State specific to reactive network instance of the contract
address private _callback;

// State specific to ReactVM instance of the contract
uint256 public counter;

constructor(
address _service,
address _contract,
uint256 topic_0,
address callback
) payable {
service = ISystemContract(payable(_service));
if (!vm) {
service.subscribe(
CHAIN_ID,
_contract,
topic_0,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);
}
_callback = callback;
}

Subscription 限制

Reactive Network 为了效率限制很多规则。

不支持:

至少有一个标准必须是具体的数值,以确保有意义的订阅。

  • 范围 ,例如amount > 100
  • OR ,例如 topic1 == A OR B
  • 集合 ,例如 topic in [A,B,C]

订阅不能使用 <>、区间或按位运算来匹配事件参数,只能使用严格的等值匹配。

订阅不能在单次订阅中使用“或”条件或多值集合。虽然多次调用 subscribe() 可以实现类似功能,但可能导致组合爆炸(combinatorial explosion)。


只支持

严格等于topic1 == X

禁止的订阅

由于数据量太大,以下订阅 不允许

不允许同时订阅所有链或所有合约的事件。只订阅单条链上的所有事件也不允许,因为被认为是不必要的。

  • 所有链 chain_id = 0
  • 所有合约 contract = address(0)
  • 所有 eventtopic0 = ignore

技术上允许重复订阅,但它们只作为一次订阅生效。用户每次发送交易给系统合约都要付费。由于 EVM 存储限制,在系统合约中防止重复订阅成本高昂,因此允许重复订阅以降低费用。

unsubscribe 为什么贵

取消订阅(Unsubscribing)是一项开销较大的操作,因为需要搜索并删除已有的订阅记录。允许存在重复或重叠的订阅,但客户端必须确保操作具有幂等性(idempotency)。

取消订阅需要:

  1. 查找 subscription
  2. 删除 storage

所以gas expensive

Examples

  • 订阅特定合约的所有事件

你可以订阅来自0x7E0987E5b3a30e3f2828572Bb659A548460a3003的特定合约中所有事件。

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0x7E0987E5b3a30e3f2828572Bb659A548460a3003,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);
  • 订阅特定事件主题(Uniswap V2 Sync)

你可以订阅所有Uniswap V2 Sync 事件,其 topic_0 为:
0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0, // 任意合约
0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);
  • 组合参数

你可以将参数组合,订阅特定合约的特定事件:

1
2
3
4
5
6
7
8
service.subscribe(
CHAIN_ID,
0x7E0987E5b3a30e3f2828572Bb659A548460a3003,
0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);
  • 处理来自不同来源的多个事件

要响应来自不同来源的多个事件,可以在构造函数中调用多次 subscribe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
constructor(
address _service,
address _contract1,
address _contract2,
uint256 topic_0,
address callback
) payable {
// 初始化订阅服务
SubscriptionService service = SubscriptionService(payable(_service));

if (!vm) {
// 第一次订阅
service.subscribe(
CHAIN_ID,
_contract1,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);

// 第二次订阅
service.subscribe(
CHAIN_ID,
address(0), // 任意合约
topic_0,
REACTIVE_IGNORE,
REACTIVE_IGNORE,
REACTIVE_IGNORE
);

// 可按需添加更多订阅
}

// 设置回调
_callback = callback;
}

Gas 与费用模型

Reactive Contracts 在执行 callback 时需要支付 gas。费用来源是RC的合约余额。

流程:

1
2
3
4
5
6
7
8
9
      事件触发

Reactive Network 执行 react()

emit Callback

节点向目标链发送交易

使用 RC 余额支付 gas

如果余额不足,callback 不会执行

核心代码:

ISubscriptionService(事件订阅服务接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pragma solidity >=0.8.0;

import './IPayable.sol';

interface ISubscriptionService is IPayable {
function subscribe(
uint256 chain_id,
address _contract,
uint256 topic_0,
uint256 topic_1,
uint256 topic_2,
uint256 topic_3
) external;

function unsubscribe(
uint256 chain_id,
address _contract,
uint256 topic_0,
uint256 topic_1,
uint256 topic_2,
uint256 topic_3
) external;
}
  • chain_id:一个 uint256 类型的值,表示事件来源链的 EIP-155 链 ID
  • _contract:在源链(origin chain)上触发该事件的合约地址。
  • topic_0、topic_1、topic_2、topic_3:事件日志中的 topics,类型为 uint256

IReactive Interface(反应接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
pragma solidity >=0.8.0;

import './IPayer.sol';

interface IReactive is IPayer {
struct LogRecord {
uint256 chain_id;
address _contract;
uint256 topic_0;
uint256 topic_1;
uint256 topic_2;
uint256 topic_3;
bytes data;
uint256 block_number;
uint256 op_code;
uint256 block_hash;
uint256 tx_hash;
uint256 log_index;
}

event Callback(
uint256 indexed chain_id,
address indexed _contract,
uint64 indexed gas_limit,
bytes payload
);

function react(LogRecord calldata log) external;
}

结构化数据类型 LogRecord:用于存储事件日志(event log)的详细信息

  • chain_id:事件来源区块链的 ID。
  • _contract:触发该事件的合约地址。
  • topic_0 到 topic_3:日志中的索引主题(indexed topics)。
  • data:事件日志中的非索引数据(non-indexed data)。
  • block_number:事件发生所在区块的区块号。
  • op_code:可能表示某种操作码(operation code)。
  • block_hash、tx_hash 和 log_index:用于追踪事件来源及其上下文的附加标识信息。

Callback 事件(Callback Event): 这是一个用于通知订阅者某些特定事件发生的事件

  • chain_id:事件所属区块链的 ID。
  • _contract:触发该事件的合约地址。
  • gas_limit:为回调(callback)分配的最大 gas 限制。
  • payload:回调时附带的编码数据(encoded data)。

react() 函数逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Methods specific to ReactVM contract instance
function react(LogRecord calldata log) external vmOnly {
if (log.topic_0 == SUBSCRIBE_TOPIC_0) {
bytes memory payload = abi.encodeWithSignature(
"subscribe(address,address)",
address(0),
address(uint160(log.topic_1))
);
emit Callback(REACTIVE_CHAIN_ID, address(this), CALLBACK_GAS_LIMIT, payload);
} else if (log.topic_0 == UNSUBSCRIBE_TOPIC_0) {
bytes memory payload = abi.encodeWithSignature(
"unsubscribe(address,address)",
address(0),
address(uint160(log.topic_1))
);
emit Callback(REACTIVE_CHAIN_ID, address(this), CALLBACK_GAS_LIMIT, payload);
}
}
}

pause()函数逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function pause() external rnOnly onlyOwner {
require(!paused, 'Already paused');
Subscription[] memory subscriptions = getPausableSubscriptions();
for (uint256 ix = 0; ix != subscriptions.length; ++ix) {
service.unsubscribe(
subscriptions[ix].chain_id,
subscriptions[ix]._contract,
subscriptions[ix].topic_0,
subscriptions[ix].topic_1,
subscriptions[ix].topic_2,
subscriptions[ix].topic_3
);
}
paused = true;
}
  • rnOnly:确保只有 Reactive Network 才能调用这个函数。
  • onlyOwner:限制只有 合约所有者(owner) 才能调用该函数。
  • **service.unsubscribe()**:用于取消订阅,使该合约不再监听特定事件(这些事件由 chain_idtopic_0 等参数定义)。

resume()函数逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function resume() external rnOnly onlyOwner {
require(paused, 'Not paused');
Subscription[] memory subscriptions = getPausableSubscriptions();
for (uint256 ix = 0; ix != subscriptions.length; ++ix) {
service.subscribe(
subscriptions[ix].chain_id,
subscriptions[ix]._contract,
subscriptions[ix].topic_0,
subscriptions[ix].topic_1,
subscriptions[ix].topic_2,
subscriptions[ix].topic_3
);
}
paused = false;
}
  • rnOnly:确保只有 Reactive Network 才能调用这个函数。
  • onlyOwner:限制只有 合约所有者(owner) 才能调用该函数。
  • **service.subscribe()**:用于重新订阅,使该合约继续监听特定事件(这些事件由 chain_idtopic_0 等参数定义)。