如何使用Wormhole发送跨链消息

  • QuickNode
  • 发布于 2025-01-08 21:55
  • 阅读 19

本文详细介绍了如何使用Wormhole协议在Avalanche Fuji和Ethereum Sepolia测试网之间构建跨链消息传递应用,并提供了具体的代码实现和部署步骤。

概述

更喜欢视频教程?跟随 Sahil 学习 Wormhole 协议的工作原理以及如何使用它来传输跨链消息。

Wormhole 是如何工作的?| @wormholecrypto - YouTube

QuickNode

131K 订阅者

Wormhole 是如何工作的?| @wormholecrypto

QuickNode

搜索

信息

购物

点击取消静音

如果播放没有立即开始,请尝试重新启动设备。

你已退出登录

你观看的视频可能会被添加到电视的观看历史记录中,并影响电视推荐。要避免这种情况,请取消并在电脑上登录 YouTube。

取消确认

分享

包含播放列表

检索分享信息时出错。请稍后再试。

稍后观看

分享

复制链接

观看

0:00

/ •直播

在 YouTube 上观看

订阅我们的 YouTube 频道以获取更多视频!订阅

构建跨链基础设施可能既耗时又复杂。幸运的是,Wormhole 帮助开发者和企业创建跨链基础设施,以发送/接收消息和任意数据等信息。

在本指南中,我们将学习如何构建一个可以在 Avalanche Fuji 和 Ethereum Sepolia 测试网之间发送消息的跨链消息传递应用程序。我们将使用 QuickNode 访问区块链节点,使用 Foundry 进行智能合约开发,并使用 Wormhole 的消息传递协议来实现安全的跨链通信。

让我们开始吧!

你将需要什么

你将做什么

  • 使用 Foundry 和 Node.js 设置开发环境
  • 为 Avalanche Fuji 和 Ethereum Sepolia 创建 QuickNode RPC 端点
  • 在不同链上部署发送者和接收者智能合约
  • 使用 Wormhole 配置跨链消息传递
  • 通过发送跨链消息测试消息传递系统
  • 使用 Wormhole Explorer 监控交易
依赖项 版本
node.js v22.12.0
forge forge 0.3.0

什么是 Wormhole?

Wormhole 是一种消息传递协议,支持不同区块链网络之间的通信。它充当跨链通信基础设施层,允许开发者构建跨多个链的互操作应用程序。

Wormhole 的关键特性包括:

  • 支持 20 多个区块链网络,包括 Ethereum、Avalanche、Solana 等
  • 通过加密验证实现快速安全的消息传递
  • 开发者友好的 SDK 和工具
  • 链无关架构,允许无缝集成
  • 经过多次审计的经过实战考验的安全性

Wormhole 的跨链消息传递如何工作

通过 Wormhole 进行跨链消息传递遵循以下关键步骤:

  1. 消息发起:当源链(例如 Avalanche)上的用户或合约调用触发消息通过 Wormhole 发送的函数时,该过程开始。此消息包含有效载荷数据和目标链信息。

  2. 守护者网络:Wormhole 的去中心化守护者网络观察源链上的这些消息。当检测到消息时,守护者:

    • 验证消息的有效性
    • 就消息内容达成共识
    • 创建并签署已验证操作批准(VAA)
  3. 消息传递:一旦创建了 VAA:

    • 接收者可以检索已签名的消息
    • 任何人都可以将 VAA 提交到目标链(例如 Ethereum)
    • 接收合约验证 VAA 的签名
    • 如果有效,则处理消息并执行预期操作
  4. 消息处理:在目标链上:

    • 接收者合约实现 Wormhole 的 IWormholeReceiver 接口
    • 它通过 Wormhole 的核心合约验证传入消息
    • 一旦验证通过,它将处理消息内容并执行预期逻辑

此过程确保:

  • 消息只传递一次
  • 消息顺序得以保留
  • 消息不能被篡改
  • 只有授权的发送者才能发起消息
  • 只有预期的接收者才能处理消息

此过程的高级图示如下:

Wormhole 消息流

在我们的示例应用程序中,我们将从 Avalanche Fuji 向 Ethereum Sepolia 发送消息,但相同的原则适用于任何支持的链对。

项目前提条件:创建 QuickNode 端点

在进入代码之前,让我们设置一些前提条件,例如获取我们需要的 RPC URL。你可以使用公共节点或部署和管理自己的基础设施;但是,如果你希望获得 8 倍的响应速度,可以将繁重的工作交给我们。在此注册一个免费账户。

登录 QuickNode 后,点击 创建端点 按钮,然后选择 Ethereum 链和 Sepolia 网络。

创建端点后,复制 HTTP Provider URL 链接并妥善保存,因为稍后你将需要它。现在,对 Avalanche 链和 Fuji 测试网网络执行相同的步骤,然后再进入下一部分。

多链水龙头的截图

项目前提条件:创建并资助 EVM 钱包

要进行跨链消息传递,你将需要 Sepolia ETH 和 Fuji AVAX 来支付各自网络上的 gas 费用。你可以从 多链 QuickNode 水龙头免费获取这些测试代币。

导航到 多链 QuickNode 水龙头 并连接你的钱包(例如 MetaMask、Coinbase Wallet)或粘贴你的钱包地址以获取测试 ETH。请注意,使用 EVM 水龙头需要 Ethereum 主网上的 0.001 ETH 余额。你还可以通过推特或使用 QuickNode 账户登录以获得奖励!

多链水龙头的截图

构建跨链消息传递应用程序

在本指南中,我们将使用 Wormhole 创建的 demo-wormhole-messaging 示例应用程序。

我们的项目结构将如下所示:

script/ - 部署和交互脚本
deploy-config/ - 链配置和部署的合约地址
out/ - 编译的合约工件
lib/ - 外部依赖项(由 Foundry 自动管理)
test/ - 智能合约的单元测试

在进入代码的核心部分之前,让我们先了解一下我们将部署的智能合约如何将消息从一条链传递到另一条链的架构。

智能合约架构

我们的跨链消息传递系统由三个主要合约组成:

  1. MessageSender.sol - 部署在源链(Avalanche Fuji)上
  2. MessageReceiver.sol - 部署在目标链(Ethereum Sepolia)上
  3. WormholeRelayer.sol - 由 Wormhole 本身部署,是所有消息通过的合约。我们不需要部署此合约,因为我们将使用 Wormhole 部署的合约。

消息发送者合约

现在,让我们深入了解每个合约的细节。发送者合约负责发起跨链消息。以下是合约代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeRelayer.sol";

contract MessageSender {
    IWormholeRelayer public wormholeRelayer;
    uint256 constant GAS_LIMIT = 50000; // 根据需要调整 gas 限制

    `constructor`(address _wormholeRelayer) {
        wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
    }

    function quoteCrossChainCost(uint16 targetChain) public view returns (uint256 cost) {
        (cost,) = wormholeRelayer.quoteEVMDeliveryPrice(targetChain, 0, GAS_LIMIT);
    }

    function sendMessage(uint16 targetChain, address targetAddress, string memory message) external payable {
        uint256 cost = quoteCrossChainCost(targetChain); // 动态计算跨链成本
        require(msg.value >= cost, "跨链传递资金不足");

        wormholeRelayer.sendPayloadToEvm{value: cost}(
            targetChain,
            targetAddress,
            abi.encode(message, msg.sender), // 有效载荷包含消息和发送者地址
            0, // 不需要接收者值
            GAS_LIMIT // 交易的 gas 限制
        );
    }
}

需要了解的重要事项:

  • 我们通过 Wormhole SDK 导入 IWormholeRelayer.sol 中继器接口。
  • constructor 在部署时接受 _wormholeRelayer 地址。
  • quoteCrossChainCost 函数根据 targetChain 返回我们的跨链消息传递的成本估算。
  • sendMessage 函数是主要函数,接受 targetChaintargetAddressmessage。请注意,你还可以发送数据资产(例如代币、NFT),但这是通过 实体 完成的,这是一个单独的工作流程。

消息接收者合约

接收者合约处理目标链上的传入消息。以下是合约代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeRelayer.sol";
import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeReceiver.sol";

contract MessageReceiver is IWormholeReceiver {
    IWormholeRelayer public wormholeRelayer;
    address public registrationOwner;

    // 映射以存储每条链的注册发送者
    mapping(uint16 => bytes32) public registeredSenders;

    event MessageReceived(string message);
    event SourceChainLogged(uint16 sourceChain);

    constructor(address _wormholeRelayer) {
        wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
        registrationOwner = msg.sender;  // 将合约部署者设置为所有者
    }

    // 修饰符以检查发送者是否为源链的注册发送者
    modifier isRegisteredSender(uint16 sourceChain, bytes32 sourceAddress) {
        require(registeredSenders[sourceChain] == sourceAddress, "未注册的发送者");
        _;
    }

    // 函数以注册特定链的有效发送者地址
    function setRegisteredSender(uint16 sourceChain, bytes32 sourceAddress) public {
        require(msg.sender == registrationOwner, "不允许设置注册发送者");
        registeredSenders[sourceChain] = sourceAddress;
    }

    // 更新 receiveWormholeMessages 以包含源地址检查
    function receiveWormholeMessages(
        bytes memory payload,
        bytes[] memory, // 额外的 VAA(可选,此处不需要)
        bytes32 sourceAddress,
        uint16 sourceChain,
        bytes32 // 传递哈希
    )
        public
        payable
        override
        isRegisteredSender(sourceChain, sourceAddress)
    {
        require(msg.sender == address(wormholeRelayer), "只有 Wormhole 中继器可以调用此函数");

        // 解码有效载荷以提取消息
        (string memory message) = abi.decode(payload, (string));

        // 使用 sourceChain 进行日志记录的示例
        if (sourceChain != 0) {
            emit SourceChainLogged(sourceChain);
        }

        // 发出事件以记录接收到的消息
        emit MessageReceived(message);
    }
}

让我们回顾一下代码:

  • 我们再次通过 Wormhole SDK 导入 IWormholeRelayer.sol 中继器接口,此外还导入了 IWormholeReceiver 接口。
  • constructor 使用 IWormholeRelayer 接口和地址初始化合约,并将 registrationOwner 设置为合约部署者。
  • isRegisteredSender 修饰符确保消息来自注册的发送者。
  • receiveWormholeMessages 函数从 MessageSender 合约接收消息。

在高层次上,此流程如下所示:

消息流

  1. 用户在发送者合约上调用 sendMessage(),并传入:
  • 目标链 ID
  • 接收者合约地址
  • 消息内容
  1. Sender 合约:
  • 计算传递成本
  • 编码消息
  • 调用 Wormhole 中继器并传递所需资金
  1. 在目标链上:
  • Wormhole 中继器调用 receiveWormholeMessages()
  • 接收者验证源并解码消息
  • 通过事件记录消息接收

需要注意的是,只有注册的合约才能发送消息,跨链成本会自动处理,并且可以在两条链上验证消息传递。

现在,让我们进入指南的技术编码部分。

设置项目

首先,让我们创建一个项目文件夹并克隆项目:

mkdir messaging-app && cd messaging-app
git clone git@github.com:wormhole-foundation/demo-wormhole-messaging.git # SSH
或
git clone https://github.com/wormhole-foundation/demo-wormhole-messaging.git # HTTPS

然后进入项目并安装所需的依赖项:

cd demo-wormhole-messaging
npm install
forge install

接下来,让我们在项目的根目录中创建一个包含你的私钥的 .env 文件:

echo > .env

记住 仅在本地使用 .env 文件,并在不使用时删除它们。

然后,打开文件并输入你的私钥:

PRIVATE_KEY=0x...

在继续之前,我们需要更新 deploy-config/chains.json 文件,打开文件并将其更新为以下内容:

{
    "chains": [\
      {\
        "description": "Avalanche testnet fuji",\
        "chainId": 6,\
        "rpc": "YOUR_QUICKNODE_AVALANCHE-FUJI_ENDPOINT",\
        "tokenBridge": "0x61E44E506Ca5659E6c0bba9b678586fA2d729756",\
        "wormholeRelayer": "0xA3cF45939bD6260bcFe3D66bc73d60f19e49a8BB",\
        "wormhole": "0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C"\
      },\
      {\
        "description": "Sepolia Testnet",\
        "chainId": 10002,\
        "rpc": "YOUR_QUICKNODE_SEPOLIA_ENDPOINT",\
        "tokenBridge": "0xDB5492265f6038831E89f495670FF909aDe94bd9",\
        "wormholeRelayer": "0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470",\
        "wormhole": "0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78"\
      }\
    ]
  }

记住 将占位符替换为实际的 RPC URL。还要确保在 Avalanche Fuji RPC URL 的末尾附加 /ext/bc/C/rpc/ 路径(例如,https://amazing-grace.avalanche-testnet.quiknode.pro/TOKEN/ext/bc/C/rpc/)。

你会注意到,此文件中使用的链 ID 并不对应于公共链 ID。相反,此链 ID 是特定于 Wormhole 协议的。你可以在此处查看 Wormhole 的完整链 ID 列表:参考

编译和测试智能合约

在本节中,我们将在部署之前编译和测试跨链消息传递应用程序的智能合约。

该项目包括三个主要测试用例:

  • testDeployment():验证合约是否正确部署并正确初始化
  • testReceiveMessage():确保接收者合约可以处理传入消息
  • testSendMessage():验证发送者合约可以正确发送消息

首先,让我们编译智能合约:

forge build

现在我们将运行测试以确保在部署智能合约之前一切正常:

forge test

你将看到类似于以下内容的输出:


[⠊] Compiling...
No files changed, compilation skipped

Ran 3 tests for test/CrossChainMessagingTest.sol:CrossChainMessagingTest
[PASS] testDeployment() (gas: 13008)
[PASS] testReceiveMessage() (gas: 19766)
[PASS] testSendMessage() (gas: 20922)
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.98ms (1.93ms CPU time)

Ran 1 test suite in 109.55ms (2.98ms CPU time): 3 tests passed, 0 failed,

>- 原文链接: [quicknode.com/guides/cro...](https://www.quicknode.com/guides/cross-chain/wormhole/how-to-create-a-cross-chain-messaging-app)
>- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。