原文|End-to-EndMultichainTestingwithRelayer.solRelayer.sol为你的Forge测试环境带来了原生的多链端到端测试能力。通过继承抽象的Relayer测试辅助类,你的测试可以:启动多个网络的分叉(fork)、真实地发送L2ToL2
原文|End-to-End Multichain Testing with Relayer.sol
Relayer.sol
为你的 Forge 测试环境带来了原生的多链端到端测试能力。通过继承抽象的 Relayer
测试辅助类,你的测试可以:启动多个网络的分叉(fork)、真实地发送 L2ToL2CrossDomainMessenger
事件、并在同一个 forge test
流程中完成消息的中继传输——无需额外的 relayer 或脚本粘合。在本文中你将学到如何:
Superchain Interop(超级链互操作)有望彻底改变去中心化应用开发的范式。它将实现低延迟、无缝的跨链消息传递与资产桥接,而为了构建适应这一未来的应用,你需要升级自己的跨链测试工作流。
超级链的跨链交互流程是事件驱动的:
某个合约调用 L2ToL2CrossDomainMessenger.sendMessage()
,消息器发出 SentMessage
事件,然后一个链下 relayer 监听该事件并向目标链发送执行交易——只有这样,消息载荷才会真正执行。
Relayer.sol
将这一 relayer 逻辑直接内嵌到 Forge 中,无需不稳定的 sleep 等待,也不需要手动 cast
命令,非常适合本地 CI 流程中的自动化测试。
最终,Relayer.sol
将跨链测试从“分别跑两个测试套件,然后祈祷桥接成功”转变为“在 Forge 内部验证:这个消息确实在链 B 上成功执行了”。它去除了外部依赖,减少了样板代码,并使你的测试环境更加贴近主网现实。
Relayer.sol 极大简化了跨链测试流程
forge install ethereum-optimism/interop-lib
Relayer.sol
位于 repo https://github.com/ethereum-optimism/interop-lib 的 src/test/Relayer.sol
下。
安装 Supersim
brew install ethereum-optimism/tap/supersim # macOS/Linux
启动一个原版超级链
supersim
Supersim 启动三个本地 anvil 节点,预先部署 Superchain 互作合约,并公开 JSON-RPC 端点:
Chain 链 | ID | RPC URL RPC 网址 |
---|---|---|
L1(主网) | 900 | http://127.0.0.1:8545 |
L2-A | 901 | http://127.0.0.1:9545 |
L2-B | 902 | http://127.0.0.1:9546 |
有关 Supersim 以及自定义本地开发工作流程的各种方式的更多信息,请查看 Supersim 文档 。
在 foundry.toml
中告诉 Foundry 这些 RPC
[rpc_endpoints]
l2a = "<http://127.0.0.1:9545>"
l2b = "<http://127.0.0.1:9546>"
需要测试网? 如果您想尝试互作的测试网,请跳过 Supersim,或者通过更改 foundry.toml
以指向这些测试网端点,将您的项目从本地开发升级到测试网(请参阅文档以获取最新的端点):
[rpc_endpoints]
devnet0 = "<https://interop-alpha-0.optimism.io>"
devnet1 = "<https://interop-alpha-1.optimism.io>"
以下是参考 CrossChainIncrementer.t.sol
测试的精简版本:
contract IncrementerTest is Relayer {
/**
* 0. Constructor – pass Supersim RPC URLs to Relayer so it can map
* chainIds ↔ forkIds under the hood.
*/
constructor() Relayer(_rpcUrls()) {}
function _rpcUrls() internal view returns (string[] memory urls) {
urls = new string[](2);
urls[0] = vm.rpcUrl("l2a"); // source
urls[1] = vm.rpcUrl("l2b"); // destination
}
// 1. Fork identifiers
uint256 l2aFork;
uint256 l2bFork;
// ──────────────── 2. Contract handles ────────────────
Counter src; // lives on l2a fork
Counter dst; // lives on l2b fork
function setUp() public {
// Foundry forks
l2aFork = vm.createFork(vm.rpcUrl("l2a"));
l2bFork = vm.createFork(vm.rpcUrl("l2b"));
// 2. Deploy contracts on each chain
vm.selectFork(l2aFork);
src = new Counter();
vm.selectFork(l2bFork);
dst = new Counter();
}
function testIncrementAcrossChains() public {
// 3. Build a message on the source chain
vm.selectFork(l2aFork);
L2ToL2CrossDomainMessenger(payable(CDM_ADDR)).sendMessage(
address(dst),
abi.encodeCall(dst.increment, ()),
100_000
);
// 4. Relay everything that was just logged
relayAllMessages();
// 5. Assert on the destination chain
vm.selectFork(l2bFork);
assertEq(dst.count(), 1);
}
}
让我们来了解一下这里发生了什么。
vm.createFork
会克隆远程链的状态;vm.selectFork
用于切换当前激活的链分叉。请保留返回的 ID —— 在你跨链切换时将会用到它们。
Relayer
构造函数调用 vm.recordLogs()
表示每个触发的事件都会被捕获。你无需手动添加这一逻辑,只需继承这个辅助类即可!
L2ToL2CrossDomainMessenger.sendMessage
为您提供开箱即用的重放保护和域绑定。完全按照您在链上的方式使用它。
relayAllMessages()
通过 vm.getRecordedLogs()
获取日志缓冲区,筛选出 SentMessage
事件,并在对应的目标分叉上重新执行每条消息。vm.log[]
的一个切片传给 relayMessages()
,手动决定哪些事件需要中继。一旦消息中继完成,切换回目标分叉(再次调用 vm.selectFork("l2a")
),然后像普通单元测试一样进行断言。由于所有操作都是在同一进程中同步执行的,不会出现竞态条件或轮询循环的问题。、
要查看此测试模式的实际效果,请查看此处 !
有时你只想中继部分事件。由于 SentMessage
日志中不包含来源链的信息,你需要手动传入生成这些日志的 sourceChainId
。
Vm.Log[] memory logs = vm.getRecordedLogs();
relayMessages(slice(logs, 1, 3), 901); // 仅中继第二条和第三条消息
这个功能在你需要缓存日志并进行中继以外的操作时特别有用。因为 vm.getRecordedLogs()
每次调用都会清空缓冲区,你可以先获取一次,存储下来,然后对原始事件进行自定义断言、解码、模糊测试等操作,最后将相同的切片(或过滤后的子集)传入 relayMessages()
。这允许你仅中继感兴趣的消息,重复中继以测试重放保护机制,或保留日志用于覆盖率统计 —— 无需额外的链上事件,也不会丢失数据。
Interop 库还提供了一个 Promise
原语,用于保障消息交付的语义;早期测试套件可见于 Promise.t.sol
。未来该辅助模块将添加更多原生的 Promise 工具!
vm.getRecordedLogs()
每次调用都会清空缓冲区。如需多次使用,请务必缓存结果。只需不到 40 行模板代码,你就能实现真实、确定性的多链测试,几秒内运行完成:
supersim & # 一次性启动 Supersim
forge test -vvvv # 所有消息都在本地中继并测试
在幕后,Forge 会:
这一切都发生在 EVM 内部,无需依赖外部基础设施 —— 这就是 Relayer.sol
的强大之处。用它试一试,打破几条跨链消息,在上线前让你的逻辑变得坚不可摧。祝你测试愉快!
在加密行业,尤其是 OP Labs,我们的工作独一无二。尽管面临的挑战巨大,复杂性惊人,但有时,简单的流程就能带来质的飞跃。
OP Labs 正在招聘愿意在技术与安全的最前沿工作的优秀人才。如果你想加入一个世界级的团队,参与世界级的项目,欢迎联系我们!
Join us
微信公众号: Optimism 中文
Twitter: https://x.com/Optimismzh
Telegram:https://t.me/optimism_cn
Medium: https://medium.com/@optimismcn
微信群:公众号后台回复 【加群】
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!