如何使用 LayerZero V2 将任意代币跨链到 Berachain | 开发者必备

本文介绍了如何使用LayerZero V2部署全链可替代代币(OFTs),并展示了将$UNI代币从Sepolia测试网桥接到Berachain测试网的过程。通过详细的步骤说明,包括智能合约的编写与部署,开发者可以快速掌握如何通过LayerZero实现跨链通信和代币桥接。

导言

随着区块链技术的不断发展,跨链通信已经成为了加密世界中的重要需求。

LayerZero V2 推出的全链可替代代币(OFTs)标准,为跨链资产提供了一种创新解决方案。OFTs 不仅允许代币在不同区块链之间自由流通,还能够保持代币的统一供应,解决了传统跨链桥接中的流动性和资产包装问题。本

文将详细介绍如何通过 LayerZero V2 和 Foundry 工具,跨链桥接 $UNI 代币,从 Sepolia 测试网到 Berachain 测试网的完整过程。

通过对智能合约的编写与部署,开发者可以进一步了解 LayerZero 的跨链通信能力,并掌握其在多链环境下的实际应用。

如你在开发过程中遇到任何问题,可以按照文末的方式和官方团队进行沟通,也可以联系 DAppChaser,和我们的开发者一起讨论。

Erica


如何使用 LayerZero V2 将任意代币跨链到 Berachain | 开发者必备

使用LayerZero V2部署跨链代币

OFTs 简介

全链可替代代币(Omnichain Fungible Tokens, OFTs)是由 LayerZero 推出的一种新代币标准,用于跨链资产。OFTs 允许可替代代币在不同区块链间传输,无需使用资产包装或流动性池,且能够保持统一的供应。

LayerZero是一个通用的跨链消息传递协议,但在本文中,我们将重点讨论它的跨链桥接应用,尤其是OFTs。

LayerZero V2

LayerZero V2于2024年1月发布,带来了重要升级,它将消息验证与执行分离(在LayerZero V1中,这两者是通过 Relayers 绑定在一起的):

  1. 应用程序所有者可以选择一组去中心化验证网络(DVNs)来验证消息负载;
  2. 消息在目标链上的执行由执行者(Executors)处理。

除了其他改进之外,这些变化增强了全链应用开发者的可扩展性和定制性。有关更深入的探讨,请参阅这篇文章

本文将展示如何利用 LayerZero OFTs,将 $UNI 代币从 Sepolia 测试网桥接到Berachain 测试网。

📋需求

在开始之前,确保你的电脑上已安装并设置好以下内容:

Foundry

本指南需要安装Foundry。在终端窗口中运行以下命令:

curl -L https://foundry.paradigm.xyz | bash; 
 
foundryup;  
# foundryup installs the 'forge' and 'cast' binaries, used later

Foundry 的更多安装说明,请参见 Foundry 的安装指南。有关在 Berachain 上使用Foundry 的更多详细信息,请参见此指南

创建LayerZero项目

首先,我们将使用Foundry设置开发环境。

新建一个项目文件夹并初始化 Foundry:

forge init layerzero-oft --no-git --no-commit; 
 
cd layerzero-oft; 
# We observe the following basic layout 
# . 
# ├── foundry.toml 
# ├── script 
# │   └── Counter.s.sol 
# ├── src 
# │   └── Counter.sol 
# └── test 
#     └── Counter.t.sol

安装依赖

我们将使用与 LayerZeroOpenZeppelin 工具相关的多个依赖项,安装它们:

# FROM: ./layerzero-oft 
 
pnpm init; 
pnpm add -D @layerzerolabs/lz-evm-oapp-v2 @layerzerolabs/toolbox-foundry @layerzerolabs/lz-evm-protocol-v2 @layerzerolabs/lz-evm-messagelib-v2 @layerzerolabs/lz-definitions @openzeppelin/contracts --ignore-workspace;

将  foundry.toml  内容替换为以下内容以重新映射依赖项:

[profile.default] 
src = "src" 
out = "out" 
libs = [ 
    'node_modules/@layerzerolabs/toolbox-foundry/lib', 
    'node_modules', 
] 
remappings = [ 
    'forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std', 
    '@layerzerolabs/=node_modules/@layerzerolabs/', 
    '@openzeppelin/=node_modules/@openzeppelin/', 
]

交互概览

在编写合约之前,让我们简要介绍一下将$UNI代币从Sepolia桥接到Berachain过程中涉及的交互:

如何使用 LayerZero V2 将任意代币跨链到 Berachain | 开发者必备
  1. 在源链上,用户在  OFT Adapter 合约上执行桥接交易(我们创建的合约);
  2. $UNIOFT Adapter 中被锁定;
  3. LayerZero 终端合约发送一条包含在目标链上铸造 $UNI 代币的指令的消息;
  4. 消息由 DVN 验证;
  5. 执行者在目标链的终端合约上调用 lzReceive()  ,接收消息;
  6. $lzUNI  (我们创建的OFT)被铸造并发送给用户。

编写智能合约

编写智能合约

我们将需要在源链和目标链上部署多个智能合约,以推进上述过程。

新建一个文件 ./src/MyAdapter.sol 并粘贴以下内容:

// SPDX-License-Identifier: MIT 
pragma solidity ^0.8.22; 
 
import {OFTAdapter} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTAdapter.sol"; 
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 
 
contract MyAdapter is OFTAdapter { 
    constructor( 
        address _token, // a deployed, already existing ERC20 token address 
        address _layerZeroEndpoint, // local endpoint address 
        address _delegate // token owner used as a delegate in LayerZero Endpoint 
    ) OFTAdapter(_token, _layerZeroEndpoint, _delegate) Ownable(_delegate) {} 
}

该合约简单地实现了 OFTAdapter 合约,正如我们所提到的,这是源链上的合约,负责锁定代币并为现有代币扩展跨链功能。你可以在这里了解更多关于OFT适配器的信息。

此外,设置了一个合约委托,该地址被授予执行关键任务的能力,比如设置配置。

接下来,创建一个文件 ./src/MyOFT.sol,并粘贴以下内容:

// SPDX-License-Identifier: UNLICENSED 
pragma solidity ^0.8.22; 
 
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 
import {OFT} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol"; 
 
contract MyOFT is OFT { 
    constructor( 
        string memory _name, 
        string memory _symbol, 
        address _lzEndpoint, 
        address _delegate 
    ) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {} 
}

该合约实现了OFT合约,在这里我们定义了目标链上的代币详细信息(例如名称、符号)。同样,也定义了一个委托地址。

(你可以删除项目中生成的 src/Counter.soltest/Counter.t.solscript/Counter.s.sol 文件。)

部署与执行

步骤1:在 Sepolia 上部署 OFT 适配器

在项目根目录下创建一个 .env 文件,填入以下内容,并填写你的 PRIVATE_KEY 开始:

PRIVATE_KEY= 
SEPOLIA_ADAPTER_ADDRESS= 
BERACHAIN_OFT_ADDRESS=

我们将创建几个Foundry脚本来帮助部署。首先,创建 ./script/MyAdapter.s.sol 文件,并填入以下内容:

// SPDX-License-Identifier: UNLICENSED 
pragma solidity ^0.8.22; 
 
import {Script} from "forge-std/Script.sol"; 
import "../src/MyAdapter.sol"; 
 
contract MyAdapterScript is Script { 
    address constant UNI_TOKEN = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984; 
    address constant LAYERZERO_ENDPOINT = 
        0x6EDCE65403992e310A62460808c4b910D972f10f; 
 
    function run() public { 
        // Setup 
        uint256 privateKey = vm.envUint("PRIVATE_KEY"); 
        vm.startBroadcast(privateKey); 
 
        // Deploy 
        MyAdapter myAdapter = new MyAdapter( 
            UNI_TOKEN, 
            LAYERZERO_ENDPOINT, 
            vm.addr(privateKey) // Address of private key 
        ); 
 
        vm.stopBroadcast(); 
    } 
}

运行以下命令将在 Sepolia 测试网上部署 MyAdapter 合约。

(可选地添加标志 — etherscan-api-key YOUR_ETHERSCAN_API_KEY — 用于验证合约):

# FROM: ./layerzero-oft 
 
forge script script/MyAdapter.s.sol --rpc-url https://rpc.sepolia.org/ --broadcast  
 
# [Example Output]: 
# ##### sepolia 
# ✅  [Success]Hash: 0x16702f69752f1f7243793202435da6bd54d2ebec89294728c2bf0d55584ed732 
# Contract Address: 0xB66e0518570eA48286983322fc8F85301f955406 
# Block: 5525968 
# Paid: 0.007448778064556076 ETH (2482926 gas * 3.000000026 gwei)

在你的 .env 文件中将 SEPOLIA_ADAPTER_ADDRESS 更新为你部署的 MyAdapter 合约地址。

步骤2:在 Berachain 上部署 OFT

接下来,创建 ./script/MyOFT.s.sol 文件,并填入以下内容:

// SPDX-License-Identifier: UNLICENSED 
pragma solidity ^0.8.22; 
 
import {Script} from "forge-std/Script.sol"; 
import "../src/MyOFT.sol"; 
 
contract MyOFTScript is Script { 
    address constant LAYERZERO_ENDPOINT = 
        0x6EDCE65403992e310A62460808c4b910D972f10f; 
 
    uint32 constant SEPOLIA_ENDPOINT_ID = 40161; 
 
    function run() public { 
        // Setup 
        address SEPOLIA_ADAPTER_ADDRESS = vm.envAddress( 
            "SEPOLIA_ADAPTER_ADDRESS" 
        ); 
        uint256 privateKey = vm.envUint("PRIVATE_KEY"); 
        vm.startBroadcast(privateKey); 
 
        // Deploy 
        MyOFT myOFT = new MyOFT( 
            "Layer Zero UNI", 
            "lzUNI", 
            LAYERZERO_ENDPOINT, 
            vm.addr(privateKey) // Wallet address of signer 
        ); 
 
        // Hook up Berachain OFT to Sepolia's adapter 
        myOFT.setPeer( 
            SEPOLIA_ENDPOINT_ID, 
            bytes32(uint256(uint160(SEPOLIA_ADAPTER_ADDRESS))) 
        ); 
        vm.stopBroadcast(); 
    } 
}

接下来,执行你的脚本,以 1) 部署你的 OFT 合约到 Berachain,2) 使其识别 Sepolia 对应的合约:4o

# FROM: ./layerzero-oft 
 
forge script script/MyOFT.s.sol --rpc-url https://bartio.rpc.berachain.com/ --broadcast 
 
# [Example Output] 
# ##### 80085 
# ✅  [Success]Hash: 0x16cf8daa6f335fb65dedee8e722c01adb45b87aeccad0d6dc751d6c04c466a5f 
# Contract Address: 0x42993d9A691636cbb23C201729b36B5C6e750733 
# Block: 1147280 
# Paid: 0.040444634965884468 ETH (2842719 gas * 14.227447372 gwei) 
#  
# ##### 80085 
# ✅  [Success]Hash: 0xd670e01e028fe50d9e8c323007a777590d202fada28d80d6a9f9973abcb8b607 
# Block: 1147281 
# Paid: 0.000682799744815656 ETH (47666 gas * 14.324670516 gwei)

在你的 .env 文件中将 BERACHAIN_OFT_ADDRESS 更新为你部署的 MyOFT 合约地址。

步骤3:将代币从 Sepolia 桥接到 Berachain

现在,我们将把所有组件连接起来,并将 $UNI 从 Sepolia 桥接到 Berachain。

创建 ./script/Bridge.s.sol 文件,并填入以下内容:

pragma solidity ^0.8.22; 
 
import "forge-std/Script.sol"; 
import {IOFT, SendParam} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol"; 
import {IOAppCore} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/IOAppCore.sol"; 
import {MessagingFee} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol"; 
import {OptionsBuilder} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol"; 
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 
 
interface IAdapter is IOAppCore, IOFT {} 
 
contract SendOFTScript is Script { 
    using OptionsBuilder for bytes; 
 
    uint32 constant BERACHAIN_ENPOINT_ID = 40291; 
    address constant SEPOLIA_UNI_ADDRESS = 
        0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984; 
 
    function run() external { 
        address SEPOLIA_ADAPTER_ADDRESS = vm.envAddress( 
            "SEPOLIA_ADAPTER_ADDRESS" 
        ); 
        address BERACHAIN_OFT_ADDRESS = vm.envAddress("BERACHAIN_OFT_ADDRESS"); 
 
        uint256 privateKey = vm.envUint("PRIVATE_KEY"); 
        vm.startBroadcast(privateKey); 
        address signer = vm.addr(privateKey); 
 
        // Get the Adapter contract instance 
        IAdapter sepoliaAdapter = IAdapter(SEPOLIA_ADAPTER_ADDRESS); 
 
        // Hook up Sepolia Adapter to Berachain's OFT 
        sepoliaAdapter.setPeer( 
            BERACHAIN_ENPOINT_ID, 
            bytes32(uint256(uint160(BERACHAIN_OFT_ADDRESS))) 
        ); 
 
        // Define the send parameters 
        uint256 tokensToSend = 0.0001 ether; // 0.0001 $UNI tokens 
 
        bytes memory options = OptionsBuilder 
            .newOptions() 
            .addExecutorLzReceiveOption(200000, 0); 
 
        SendParam memory sendParam = SendParam( 
            BERACHAIN_ENPOINT_ID, 
            bytes32(uint256(uint160(signer))), 
            tokensToSend, 
            tokensToSend, 
            options, 
            "", 
            "" 
        ); 
 
        // Quote the send fee 
        MessagingFee memory fee = sepoliaAdapter.quoteSend(sendParam, false); 
        console.log("Native fee: %d", fee.nativeFee); 
 
        // Approve the OFT contract to spend UNI tokens 
        IERC20(SEPOLIA_UNI_ADDRESS).approve( 
            SEPOLIA_ADAPTER_ADDRESS, 
            tokensToSend 
        ); 
 
        // Send the tokens 
        sepoliaAdapter.send{value: fee.nativeFee}(sendParam, fee, signer); 
 
        console.log("Tokens bridged successfully!"); 
    } 
}

让我们分解一下这个脚本的作用:

  1. 首先,我们连接到已部署的 Sepolia Adapter 实例。
  2. 然后,我们调用 setPeer 方法,将 Berachain 上的 OFT 合约告知 Adapter。
  3. 定义选项,指定执行者为消息传递支付的 gas 数量(更多内容请阅读此处),准备消息负载,并为该交易请求费用报价。
  4. 我们批准 Adapter 合约支出我们的 $UNI 代币。
  5. 最后,调用 Adapter 的 send 方法,使用消息负载和费用发送交易。

使用以下命令运行脚本:

# FROM: ./layerzero-oft 
 
forge script script/Bridge.s.sol --rpc-url https://rpc.sepolia.org/ --broadcast

等待片刻,LayerZero 执行者处理请求后,我们将在 Berachain 钱包中看到桥接的 $lzUNI 代币!

如何使用 LayerZero V2 将任意代币跨链到 Berachain | 开发者必备

总结

恭喜你,已成功使用 LayerZero OFTs 将现有代币桥接到 Berachain 🎉

若想了解更多有关 OFTs 及跨链消息传递的功能,欢迎查阅 LayerZero 文档。

免责声明:OFT 和 OFT 适配器是为协议开发者提供的解决方案,用于将其协议的代币引入新链。未经授权的现有代币的 OFT 部署不太可能获得支持。

🐻 完整代码库

如果你想查看最终代码并浏览其他指南,请查看 Berachain LayerZero 指南代码

https://github.com/berachain/guides/tree/main/apps/layerzero-oft

🛠️ 想构建更多项目吗?

如果你想在 Berachain 上构建更多项目并查看更多示例,请访问我们的 Berachain GitHub 指南库,其中包含各种实现方式,包括 NextJS、Hardhat、Viem、Foundry 等。

https://github.com/berachain/guides/tree/main

如果你想深入了解细节,请查看我们的 Berachain 文档

https://docs.berachain.com

寻求开发支持?

请务必加入我们的 Berachain Discord 服务器,并查看我们的开发者频道以提出问题。

❤️ 别忘了为这篇文章点赞呀~~ 👏🏼

原创文章,作者:Erica,如若转载,请注明出处:https://www.dappchaser.com/bridge-any-token-to-berachain-with-layerzero-v2-2/

发表评论

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

联系我们

邮件:contact@dappchaser.com

QR code