在本教程中,我们将使用LayerZero 建立一个简单的跨链消息转账合约,并使用默认的UA配置,发送一个跨链消息。

  • 原文: https://medium.com/@Tim4l1f3/layerzero-tutorial-for-beginners-d3fe9326e8b7
  • 译文出自:登链翻译计划
  • 译者:翻译小组
  • 校对:Tiny 熊
  • 本文永久链接:learnblockchain.cn/article…

前提条件

本教程用LayerZero 建立一个简单的跨链消息转账合约,需要你对Solidity Hardhat有一定的程度了解。

概述

首先,我们先来了解一下LayerZero, LayerZero是一个Omnichain互操作性协议,设计用于跨链的轻量级消息传递。LayerZero提供了无需信任、且真实的、有保证的、可配置的消息传递。LayerZero是由一套低费用(gas-efficient)、不可升级的

我们选择 Create an advanced sample project 为教程创建一个hardhat项目。

要发送跨链消息,合约在源链调用端点(endpoint)的send()方法,然后在目标链调用lzReceive()方法接收消息。为了使用端点合约,我们需要从 LayerZero 库 中导入接口。

备注:端点(endpoint)是在各链部署的合约,参考文档

2. 创建Solidity合约

创建合约文件LayerZeroDemo1.sol

//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; pragma abicoder v2;  import "../interfaces/ILayerZeroEndpoint.sol"; import "../interfaces/ILayerZeroReceiver.sol"; import "hardhat/console.sol";  contract LayerZeroDemo1 is ILayerZeroReceiver {     event ReceiveMsg(         uint16 _srcChainId,         address _from,         uint16 _count,         bytes _payload     );     ILayerZeroEndpoint public endpoint;     uint16 public messageCount;     bytes public message;      constructor(address _endpoint) {         endpoint = ILayerZeroEndpoint(_endpoint);     }      function sendMsg(         uint16 _dstChainId,         bytes calldata _destination,         bytes calldata payload     ) public payable {         endpoint.send{value: msg.value}(             _dstChainId,             _destination,             payload,             payable(msg.sender),             address(this),             bytes("")         );     }      function lzReceive(         uint16 _srcChainId,         bytes memory _from,         uint64,         bytes memory _payload     ) external override {         require(msg.sender == address(endpoint));         address from;         assembly {             from := mload(add(_from, 20))         }         if (             keccak256(abi.encodePacked((_payload))) ==             keccak256(abi.encodePacked((bytes10("ff"))))         ) {             endpoint.receivePayload(                 1,                 bytes(""),                 address(0x0),                 1,                 1,                 bytes("")             );         }         message = _payload;         messageCount += 1;         emit ReceiveMsg(_srcChainId, from, messageCount, message);     }      // Endpoint.sol estimateFees() returns the fees for the message     function estimateFees(         uint16 _dstChainId,         address _userApplication,         bytes calldata _payload,         bool _payInZRO,         bytes calldata _adapterParams     ) external view returns (uint256 nativeFee, uint256 zroFee) {         return             endpoint.estimateFees(                 _dstChainId,                 _userApplication,                 _payload,                 _payInZRO,                 _adapterParams             );     } }

LayerZeroDemo1合约从源链向目标链发送一条消息,在合约构造时使用了端点地址,并且使用了两个接口:ILayerZeroEndpointILayerZeroReceiver

自定义函数sendMsg()封装了endpoint.send(…),其将在目标链上触发对lzReceive()的调用。

在源链调用endpoint.send(…)后,接收链上会自动调用重载的lzReceive函数。

自定义函数estimateFees()封装了endpoint.estimateFees(…),该函数将返回跨链消息的所需的费用。

3. 在不同的链上部署合约

Fantom 测试网络创建部署脚本:

const hre = require("hardhat");  async function main() {   const LayerZeroDemo1 = await hre.ethers.getContractFactory("LayerZeroDemo1");   const layerZeroDemo1 = await LayerZeroDemo1.deploy(     "0x7dcAD72640F835B0FA36EFD3D6d3ec902C7E5acf"   );   await layerZeroDemo1.deployed();   console.log("layerZeroDemo1 deployed to:", layerZeroDemo1.address); }  main().catch((error) => {   console.error(error);   process.exitCode = 1; });

在 Fantom 测试网上部署合约:

npx hardhat run scripts/deploy_testnet.js --network testnet

Mumbai(Polygon测试网络)创建部署脚本:

const hre = require("hardhat");  async function main() {   const LayerZeroDemo1 = await hre.ethers.getContractFactory("LayerZeroDemo1");   const layerZeroDemo1 = await LayerZeroDemo1.deploy(     "0xf69186dfBa60DdB133E91E9A4B5673624293d8F8"   );   await layerZeroDemo1.deployed();   console.log("layerZeroDemo1 deployed to:", layerZeroDemo1.address); }  main().catch((error) => {   console.error(error);   process.exitCode = 1; });

在Mumbai测试网络部署合约:

npx hardhat run scripts/deploy_mumbai.js --network mumbai

成功部署两个合约后,我们得到了合约地址,例如:

Mubai测试网络: 0x37587469690CC37EE19Ff6163ce7275BB1b17d3b

Fantom 测试网络: 0xD67D01D6893cC4a2E17557765987d41E778fadca

4. 测试跨链消息传递

为 Mumbai 测试网络创建一个 javascript 测试脚本:

const hre = require("hardhat"); const { ethers } = require("ethers");  async function main() {   const LayerZeroDemo1 = await hre.ethers.getContractFactory("LayerZeroDemo1");    const layerZeroDemo1 = await LayerZeroDemo1.attach(     "0x37587469690CC37EE19Ff6163ce7275BB1b17d3b"   );   const count = await layerZeroDemo1.messageCount();   const msg = await layerZeroDemo1.message();   console.log(count);   console.log(ethers.utils.toUtf8String(msg)); }  main().catch((error) => {   console.error(error);   process.exitCode = 1; });

该脚本将合约实例关联到前面部署的合约地址:0x37587469690CC37EE19Ff6163ce7275BB1b17d3b。脚本将读取合约中的消息计数器和最后一条消息,现在返回的是0和空字符串。

使用hardhat运行脚本:

npx hardhat run scripts/demo1_mumbai.js --network mumbai

LayerZero跨链协议入门教程

接着在 Fantom 测试网创建一个 javascript 测试脚本:

const { formatBytes32String } = require("ethers/lib/utils"); const { ethers } = require("ethers"); const hre = require("hardhat");  async function main() {   const LayerZeroDemo1 = await hre.ethers.getContractFactory("LayerZeroDemo1");   const layerZeroDemo1 = await LayerZeroDemo1.attach(     "0xD67D01D6893cC4a2E17557765987d41E778fadca"   );    const fees = await layerZeroDemo1.estimateFees(     10009,     "0x37587469690CC37EE19Ff6163ce7275BB1b17d3b",     formatBytes32String("Hello LayerZero"),     false,     []   );   console.log(ethers.utils.formatEther(fees[0].toString()));   await layerZeroDemo1.sendMsg(     10009,     "0x37587469690CC37EE19Ff6163ce7275BB1b17d3b",     formatBytes32String("Hello LayerZero"),     { value: ethers.utils.parseEther("1") }   ); }  main().catch((error) => {   console.error(error);   process.exitCode = 1; });

Fantom 测试网测试脚本将合约实例关联上地址 0xD67D01D6893cC4a2E17557765987d41E778fadca。该脚本会从 Fantom 测试网向Mumbai测试网上的合约(地址:0x37587469690CC37EE19Ff6163ce7275BB1b17d3b) 发送一条消息“Hello LayerZero” ,并估算了消息费用(演示目的)。最后发送带有费用的消息, 为简单起见,这里为 1FTM。如果源交易比提供的金额少,它将把额外的金额退还到我们传递的地址 _refundAddress

使用 Hardhat 运行脚本:

npx hardhat run scripts/demo1_testnet.js --network testnet

脚本完成后,我们可以在 FTMScan 测试网中查找合约0xd67d01d6893cc4a2e17557765987d41e778fadca上的交易:

LayerZero跨链协议入门教程

再次运行 Mumbai 测试脚本,控制台将打印:

LayerZero跨链协议入门教程

小结

教程完成了,Mumbai测试网络的合约收到Fantom测试链发来的消息,增加计数器。LayerZero 使整个过程变得非常简单。

教程源码:https://github.com/The-dLab/LayerZero-Demo

LayerZero 测试网地址: https://layerzero.gitbook.io/docs/technical-reference/testnet/testnet-addresseshttps://medium.com/@Tim4l1f3/layerzero-tutorial-for-beginners-d3fe9326e8b7


本翻译由 Duet Protocol 赞助支持。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注