Reactive Contract
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 会:
- 监控区块链
- 使用某些数据服务(通常是中心化的)
- 持有私钥
- 从自己的 EOA 地址发起交易
这种系统确实有用,但存在一些问题:
- 需要托管私钥
- 引入中心化组件
- 某些场景下并不适合
IoC 的优势
通过 控制反转,我们可以避免运行那些“模拟人类签名交易”的额外实体。
如果你已经定义好了:
某个链上事件发生后需要执行的一系列交易逻辑
那么这些逻辑应该能够 完全去中心化地运行,因为:
- 输入数据在链上
- 输出结果也在链上
Reactive Network 为智能合约提供了一个过去一直缺失的重要能力:
自动执行能力
即:
- 不需要人
- 不需要 bot
- 不需要签名交易
只需要 其他链上事件触发即可执行。
开发者无需运行 bot 或持有私钥,Reactive Network 节点会自动代表 RC 提交交易。
Reactive Contract 内部发生了什么
创建 Reactive Contract 时,首先需要指定:
- 要监听的 区块链
- 要监听的 合约地址
- 要监听的 事件(topic0)
RC 会持续监控这些地址,当检测到指定事件时就会执行。
这些事件可能包括:
- ETH 转账
- Token 转账
- DEX 交易
- 借贷
- 闪电贷
- 投票
- 巨鲸转账
- 任何智能合约活动
事件触发后的流程
当 RC 检测到相关事件后:
Reactive Network 会自动执行 RC 中实现的逻辑。
执行内容可能包括:
- 根据事件数据进行计算
- 更新合约状态
RC 是 有状态的(stateful),意味着:
- 可以存储数据
- 可以更新数据
- 可以累积历史信息
因此可以实现:
- 长期数据统计
- 基于历史数据 + 新事件的决策逻辑
执行结果
在事件处理过程中:
- RC 更新自己的状态
- RC 可以在 EVM 链上发起交易
整个过程:
- 在 Reactive Network 中完成
- 无需信任
- 自动执行
- 快速可靠
事件(Events)与回调(Callbacks)的工作原理
在 Ethereum 中,事件(Events) 允许智能合约在满足特定条件时记录信息,从而与外部世界进行通信。这使得 去中心化应用(dApps) 能够在某些事件发生时触发响应,而无需持续轮询区块链。事件会被 EVM 进行索引,因此可以非常容易地搜索和过滤。这对于监控区块链活动非常有用,例如:
- Token 转账
- 合约状态更新
- 来自预言机的价格变化
ReactVM 执行环境
Reactive Contracts 在 ReactVM 中运行。
ReactVM 的特点:
- 私有执行环境
- 只能与同一部署者部署的合约交互
这样可以确保:
- 执行环境安全
- 合约隔离
向目标链发送 Callback
Reactive Contracts 可以通过 Callback 事件 发起跨链交易。
流程:
- RC 触发 Callback
- Reactive Network 监听该事件
- Network 在目标链发送交易
Callback 事件参数
1 | event Callback( |
Callback 需要提供:
- chain_id:目标链 ID(EIP-155)
- _contract:目标合约地址
- **gas_limit **:目标交易 gas
- payload:编码后的函数调用数据
Callback 处理过程
例如:
1 | bytes memory payload = |
流程:
当 Callback 事件被触发后:
Reactive Network 会:
- 读取 payload
- 解析交易数据
- 在目标链提交交易
1 | react() |
关于授权的重要说明
为了安全性(防止 RC 伪造地址调用):
Reactive Network 会自动:
用 RVM ID 替换 payload 中前 160 bit 的参数。
这样可以确保目标合约能够识别调用来源是 ReactVM,而不是用户伪造的地址。
RVM ID:
- 等价于 ReactVM 地址
- 与合约部署者地址相同
因此:回调函数的 第一个参数永远是 ReactVM 地址,无论你在 Solidity 中如何命名。
ReactVM 与 Reactive Network —— 双状态环境
Reactive Contracts 在两个独立环境中同时存在,并拥有两个不同的状态。
Reactive Network 与 ReactVM 的区别
每一个 Reactive Contract 都有 两个实例:
- 一个在 Reactive Network 执行 subscription
- 一个在 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 | function detectVm() internal { |
判断逻辑
检查地址:0x0000000000000000000000000000000000fffFfF,情况:
Reactive Network
1 | 该地址存在代码 |
ReactVM
1 | 该地址没有代码 |
限制执行环境
使用 modifier 控制函数执行环境。
Reactive Network 专用函数
1 | modifier rnOnly() { |
只允许该函数在Reactive Network执行。
ReactVM 专用函数
1 | modifier vmOnly() { |
只允许该函数在ReactVM执行。
双变量状态管理
在 Reactive 架构中,每个已部署的合约可以运行在两种不同的运行状态中:
1 Reactive Network State
负责:
- 与系统合约交互
- 订阅事件
使用用于注册和管理事件订阅所需的变量和方法,变量来自AbstractReactive,包括:
servicevmservice.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 |
执行流程:
- 获取订阅列表
- 调用
service.unsubscribe()取消事件监听。
pause()函数防止RC对事件作出反应,取消订阅,从而有效阻止后续事件驱动的交易,直到事件恢复。
resume()
恢复监听:service.subscribe()
resume() 函数会重新订阅这些相同的事件,以便在新事件出现时 RC 继续响应
2 事件触发
即使用户没有发送交易,Reactive Network 也会:
- 监听源链事件
- 分发给 ReactVM
- ReactVM 执行逻辑
ReactVM 交易
ReactVM 中的交易, 用户无法直接调用,只能通过事件触发:
1 | Origin Chain Event |
react() 作用
- 更新状态
- 执行业务逻辑
- 发送 Callback
Callback 触发跨链交易
Callback 可以:
- 在其他链执行交易
- 自动触发
无需用户操作。
订阅事件(Event Subscription)
Reactive Network 的核心能力就是 **订阅事件 (Event Subscription)**。Reactive Contract 不会直接调用目标链。而是emit Callback(...),由 Reactive Network 去执行。
Reactive Contract 可以:
1 | 订阅某个链上事件 |
结构:
1 | Origin Chain (如 Sepolia) |
所以核心流程:
- 订阅事件
- 事件发生
- react() 被触发
- 执行 callback
订阅是通过 Reactive Network System Contract 完成的:
接口:
1 | interface ISubscriptionService { |
常见订阅方式
Wildcard(通配符)
Reactive Network 支持通配:
| 值 | 含义 |
|---|---|
| address(0) | 任意合约 |
| uint256(0) | 任意 chain |
| REACTIVE_IGNORE | 任意 topic |
例如:topic_1 = REACTIVE_IGNORE
表示匹配任何 topic1
1 监听某个合约的所有事件
1 | service.subscribe( |
含义:监听这个合约的所有事件
2 监听某种 Event
例如:UniswapV2 Sync 的topic0:0x1c411e9a96e07124...
1 | service.subscribe( |
含义:监听所有合约的 Sync 事件
3 同时限制 合约 + 事件
1 | service.subscribe( |
含义:监听某个 pair 的 Sync
react() 函数
用于处理传入事件通知的关键函数。react()只能被 Reactive Network 调用
该函数接收一个 LogRecord 作为输入,使得响应式合约(reactive contracts)能够动态地处理事件日志。
Reactive Contract 必须实现:function react(LogRecord calldata log) external{}
当事件发生时,Reactive Network 会调用react(log)
1 | function react(LogRecord calldata log) external vmOnly { |
根据 topic0 判断是什么事件
动态订阅 (Dynamic Subscription)
Reactive Contract 可以根据事件动态修改 subscription
例如:
1 | 用户订阅 |
实现:subscribe()、unsubscribe()
构造函数订阅(Constructor Subscribtion)
1 | // State specific to reactive network instance of the contract |
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)。
取消订阅需要:
- 查找 subscription
- 删除 storage
所以gas expensive
Examples
- 订阅特定合约的所有事件
你可以订阅来自0x7E0987E5b3a30e3f2828572Bb659A548460a3003的特定合约中所有事件。
1 | service.subscribe( |
- 订阅特定事件主题(Uniswap V2 Sync)
你可以订阅所有Uniswap V2 Sync 事件,其 topic_0 为:
0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1
1 | service.subscribe( |
- 组合参数
你可以将参数组合,订阅特定合约的特定事件:
1 | service.subscribe( |
- 处理来自不同来源的多个事件
要响应来自不同来源的多个事件,可以在构造函数中调用多次 subscribe:
1 | constructor( |
Gas 与费用模型
Reactive Contracts 在执行 callback 时需要支付 gas。费用来源是RC的合约余额。
在 Reactive Network 中:
RVM 交易和 Callback 会先执行,执行时不会立即检查 gas price 或扣费,然后再进行费用结算。
RC合约有两种状态,可在Reactscan查看:active(合约可以正常执行)、inactive(合约存在未结清的债务,需要结算)。
Reactive Contract 在执行 RVM 交易前 必须拥有足够的 REACT 资金。如果执行之后欠费debt,合约会被标记为inactive(停用)。此时的交易也就是一次性交易。
当合约被标记为inactive后:
- 新事件 **不会再触发 react()**;
- callback 不会执行;
- 合约 被暂停
- 只有执行
coverDebt()补齐欠款之后合约才会变为active(活跃)。- 只有先向合约充值之后再调用
coverDebt()函数才有效。
- 只有先向合约充值之后再调用
因此:
- 合约必须保持 足够的余额
- 否则合约会被 停用(inactive)
Reactive Network 的 RVM 交易是事件驱动执行,不是用户发起交易,触发者是:监听节点和网络系统。所以RC允许先执行后结算费用,而不是像普通EVM必须先付gas再执行。
流程:
1 | 事件触发 |
如果余额不足,callback 不会执行
RVM Transactions(RVM 交易)
RVM 交易在执行时 不包含 gas price。
费用会在之后进行计算,通常使用:
后续区块(通常是下一个区块)的 base fee
由于费用是在 区块级别统一结算 的,因此:
Reactscan 无法将费用精确关联到单个 RVM 交易。
==RVM交易的最大Gas Limit 为 900000 gas==
Reactive Transaction Fee(Reactive 交易费用)
Reactive Network 的交易费用计算公式:
$$
fee = BaseFee \times GasUsed
$$
其中:
BaseFee:记账区块中的 base fee,即 每单位 gas 的基础费用
GasUsed:交易执行消耗的 gas
Reactive Network 上的普通交易遵循标准 EVM gas 模型。
Reactive Network 中,系统合约 和 callback proxy 使用同一个地址:0x0000000000000000000000000000000000fffFfF
可以直接向合约充值:cast send $CONTRACT_ADDR --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY --value 0.1ether
偿还债务:cast send --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY $CONTRACT_ADDR "coverDebt()"
也可以通过系统合约充值:cast send --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY $SYSTEM_CONTRACT_ADDR "depositTo(address)" $CONTRACT_ADDR --value 0.1ether
特点:发送者支付交易费用,系统会自动结清债务。
Callback Pricing(Callback 定价)
Callback 的费用取决于:
- 目标链
- 当前 gas 价格
Callback 价格计算公式:
$$
p_{callback} = p_{base} \cdot C \cdot (g_{callback} + K)
$$
参数解释:
- $p_{base}$:基础 gas 价格:
tx.gasprice或block.basefee - C:目标网络定价系数(Destination Network Pricing Coefficient),用于调节不同链的费用。
- $g_{callback}$:Callback 实际使用的 gas。
- K:固定 gas 附加费用。
Callback Payment(Callback 支付)
Callback 使用 与 RVM 交易相同的支付模型。
如果合约余额不足:
合约会被 blocklisted
即:
- 无法执行交易
- 无法执行 callback
可以向Callback合约充值,只有先向合约充值之后再调用coverDebt()函数合约才有效。
cast send $CALLBACK_ADDR --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY --value 0.1ether
cast send --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_ADDR "coverDebt()"
也可以通过callback proxy充值
cast send --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_PROXY_ADDR "depositTo(address)" $CALLBACK_ADDR --value 0.1ether
如果实现pay()或者继承AbstractPayer则可以实现 自动债务清算。callback proxy在callback产生债务时会调用pay()。标准实现会:
- 验证调用者
- 检查余额
- 自动结算债务
Callback Gas Limit
Reactive Network 强制规定:callback 最小 gas limit = 100,000 gas
如果 callback gas limit 低于该值,请求会被忽略。
因为该最小值用于保证:内部审计、必要计算
Callback Contract Balance
查询余额:
cast balance $CONTRACT_ADDR --rpc-url $DESTINATION_RPC查询债务:
cast call $CALLBACK_PROXY_ADDR "debts(address)" $CONTRACT_ADDR --rpc-url $DESTINATION_RPC | cast to-dec查询储备金:
cast call $CALLBACK_PROXY_ADDR "reserves(address)" $CONTRACT_ADDR --rpc-url $DESTINATION_RPC | cast to-dec
Reactive Contract Balance
查询 REACT 余额:
cast balance $CONTRACT_ADDR --rpc-url $REACTIVE_RPC查询债务:
cast call $SYSTEM_CONTRACT_ADDR "debts(address)" $CONTRACT_ADDR --rpc-url $REACTIVE_RPC | cast to-dec查询储备金:
cast call $SYSTEM_CONTRACT_ADDR "reserves(address)" $CONTRACT_ADDR --rpc-url $REACTIVE_RPC | cast to-dec
核心代码:
AbstractCallback
AbstractCallback 继承自 AbstractPayer.sol,用于提供 callback 授权机制。
1 | // SPDX-License-Identifier: UNLICENSED |
rvm_id:被授权的 ReactVM 标识。vendor:callback proxy 地址。modifier rvmIdOnly(address _rvm_id):限制函数只能由指定的ReactVM调用。- 构造函数:
- 将部署者(ReactVM)设为
rvm_id - 设置 callback proxy 为支付接收方
- 将其加入授权支付发送者列表
- 将部署者(ReactVM)设为
AbstractPausableReactive
AbstractPausableReactive继承自 AbstractReactive.sol,提供可暂停的事件订阅机制。
功能:
pause()取消所有订阅resume()恢复订阅
1 | // SPDX-License-Identifier: UNLICENSED |
pause()函数逻辑
- rnOnly:确保只有 Reactive Network 才能调用这个函数。
- onlyOwner:限制只有 合约所有者(owner) 才能调用该函数。
- **service.unsubscribe()**:用于取消订阅,使该合约不再监听特定事件(这些事件由
chain_id、topic_0等参数定义)。
resume()函数逻辑
- rnOnly:确保只有 Reactive Network 才能调用这个函数。
- onlyOwner:限制只有 合约所有者(owner) 才能调用该函数。
- **service.subscribe()**:用于重新订阅,使该合约继续监听特定事件(这些事件由
chain_id、topic_0等参数定义)。
AbstractPayer
AbstractPayer提供 支付与债务结算功能。
功能:
- 授权支付发送者
- vendor(系统/代理)债务结算
- 合约直接充值
1 | // SPDX-License-Identifier: UNLICENSED |
AbstractReactive
AbstractReactive继承AbstractPayer、IReactive,是Reactive Contract 的基础合约。
功能:
- 接入系统合约
- 提供订阅服务
- 区分执行环境
1 | // SPDX-License-Identifier: UNLICENSED |
detectVm()
自动检测执行环境。
- 有代码 → RN 环境
- 无代码 → ReactVM
IPayable(支付和债务查询接口)
1 | interface IPayable { |
IPayer(发起支付和接收资金的最小接口)
1 | interface IPayer { |
ISubscriptionService(事件订阅服务接口)
1 | pragma solidity >=0.8.0; |
- chain_id:一个
uint256类型的值,表示事件来源链的 EIP-155 链 ID。 - _contract:在源链(origin chain)上触发该事件的合约地址。
- topic_0、topic_1、topic_2、topic_3:事件日志中的 topics,类型为
uint256。
IReactive (反应式合约的核心接口)
1 | pragma solidity >=0.8.0; |
结构化数据类型 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)。
ISystemContract(系统合约接口)
ISystemContract 结合了 IPayable.sol 和 ISubscriptionService.sol 的功能。它是用于支付和订阅管理的反应式网络系统合同接口。
1 | pragma solidity >=0.8.0; |
react() 函数逻辑
1 | // Methods specific to ReactVM contract instance |
System Contract(系统合约)
Reactive Network 的核心由三个合约组成:
System Contract
负责:
- Reactive Contract 支付
- 合约白名单 / 黑名单
- Cron 定时事件
Callback Proxy
负责:
- 执行跨链 callback
- 管理资金 / 储备 / 债务
- 限制回调权限
- 计算 callback gas 成本
AbstractSubscriptionService
负责:
- 事件订阅管理
- 支持 chain / contract / topics 过滤
- 支持通配符(REACTIVE_IGNORE)
- 发出订阅更新事件
CRON 功能(定时任务)
SystemContract 通过在固定块间隔发送事件,提供了基于时间的 cron 自动化机制。反应式合约可以订阅这些事件,实现计划执行,无需轮询或外部自动化。只有只有授权 validator 可以调用cron()。每次调用 cron() 都会根据当前块号的整除性,发出一个或多个 Cron 事件。较长的间隔产生事件频率较低。
特点:
- 无需外部 bot
- 无需轮询
- 完全链上自动化
事件规则:
根据区块号触发不同频率:
| 事件 | 区块间隔 | 时间 | Topic0 |
|---|---|---|---|
| Cron1 | 每个区块 | ~7 秒 | 0xf02d6ea5c22a71cffe930a4523fcb4f129be6c804db50e4202fb4e0b07ccb514 |
| Cron10 | 每 10 块 | ~1 分钟 | 0x04463f7c1651e6b9774d7f85c85bb94654e3c46ca79b0c16fb16d4183307b687 |
| Cron100 | 每 100 块 | ~12 分钟 | 0xb49937fb8970e19fd46d48f7e3fb00d659deac0347f79cd7cb542f0fc1503c70 |
| Cron1000 | 每 1000 块 | ~2 小时 | 0xe20b31294d84c3661ddc8f423abb9c70310d0cf172aa2714ead78029b325e3f4 |
| Cron10000 | 每 10000 块 | ~28 小时 | 0xd214e1d84db704ed42d37f538ea9bf71e44ba28bc1cc088b2f5deca654677a56 |