1
0

LayerZero V2であらゆるトークンをBerachainにブリッジする [Berachain翻訳]

Posted at

本記事は下記の翻訳となります。
『Bridge any Token to Berachain with LayerZero V2』

image.png

OFT の紹介

Omnichain Fungible Tokens(OFT)は、クロスチェーンアセットのためにLayerZeroによって開拓された新しいトークン規格です。OFT を使用すると、アセットのラッピングや流動性プールの必要なく、異なるブロックチェーン間で代替可能なトークンを転送することができます。また、統一された供給を維持することも可能です。

LayerZero は汎用のクロスチェーンメッセージングプロトコルですが、この記事では、特に OFT のブリッジングアプリケーションに焦点を当てます。

LayerZero V2

LayerZero V2 は 2024 年 1 月に発表され、メッセージの検証と実行を分離することで重要なアップグレードをもたらしました(これらは LayerZero V1 ではリレーヤーを使用してバンドルされていました):

  • アプリケーション所有者は、メッセージペイロードを検証するための分散型検証ネットワーク(DVN)のセットを選択できます。
  • 宛先チェーンでのメッセージの実行はExecutorsによって処理されます。

その他の改善点に加えて、これらの変更により、オムニチェーンアプリの開発者に対してスケーラビリティとカスタマイズ性が向上しました。詳細は、この記事をご覧ください。

この記事では、LayerZero OFT を使用して、Sepolia Testnet から Berachain Testnet に$UNIトークンをブリッジする方法を紹介します。

📋 必要要件

次に進む前に、コンピュータに以下のものがインストールされ、設定されていることを確認してください。

  • Node v20.11.0以上
  • pnpm
  • Berachain bArtio NetworkSepolia Testnetが設定されたウォレット
  • そのウォレットに$BERAまたは Berachain Testnet トークンがあること  — Berachain Faucetを参照してください
  • そのウォレットに Sepolia Testnet の$ETHがあること  — Sepolia Faucetを参照してください
  • Sepolia の$UNIを取得すること  — Uniswapを参照してください(このガイドでは 0.0001 を使用します)

Foundry

このガイドでは Foundry のインストールが必要です。ターミナルウィンドウで次のコマンドを実行してください。

curl -L https://foundry.paradigm.xyz | bash;

foundryup;
# foundryup installs the 'forge' and 'cast' binaries, used later

For more installation instructions, see Foundry’s installation guide. For more details using Foundry on Berachain, see this guide.

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/',
]

インタラクションの概要

コントラクトを書く前に、Sepolia から Berachain への$UNIトークンのブリッジングプロセスに関与するインタラクションについて簡単に説明しましょう:


Overview of Interactions

  1. ユーザーはソースチェーン上で、私たちが作成したOFT Adapter契約に対してブリッジングトランザクションを実行します。
  2. $UNIトークンはOFT Adapterにロックされます。
  3. LayerZero エンドポイント契約は、Destination Chain 上で$UNIトークンを作成するための指示を含むメッセージを送信します。
  4. メッセージは DVN によって検証されます。
  5. エグゼキューターは、Destination Chain 上のエンドポイント契約に対して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 アダプターについての詳細はこちらをご覧ください。

さらに、delegate コントラクトが設定されており、このアドレスに設定の変更などの重要なタスクを処理する権限が与えられています。

次に、ファイル ./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 コントラクトを実装し、デスティネーションチェーン上でトークンの詳細(例: namesymbol)を定義する場所です。再度、delegate が定義されています。

(プロジェクトで生成された src/Counter.soltest/Counter.t.solscript/Counter.s.sol を削除しても構いません)。

デプロイと実行

ステップ 1: OFT アダプタを Sepolia にデプロイする

以下の内容でプロジェクトのルートに/.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();
    }
}

以下のコマンドを実行すると、MyAdapterコントラクトが Sepolia Testnet にデプロイされます。

(オプションでフラグ— etherscan-api-key YOUR_ETHERSCAN_API_KEY — verifyを追加してコントラクトを検証することもできます)。

# 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_ADDRESSMyAdapter デプロイメントのアドレスで更新する。

ステップ 2:OFT を Berachain にデプロイする

次に、./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 ピアコントラクトを認識させます:

# 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_ADDRESSMyOFT` デプロイのアドレスで更新してください。

ステップ 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 アダプターのインスタンスに接続します。
  2. 次に、setPeerを呼び出して、Berachain にある OFT コントラクトの情報をアダプターに伝えます。
  3. オプションを定義して、Executor がメッセージ配信に支払うガス量を設定します(詳細はこちらを参照)。また、メッセージペイロードを準備し、このトランザクションのfee(手数料)の見積もりを要求します。
  4. アダプターコントラクトに対して、私たちの$UNIトークンを使用する権限を与えます。
  5. 最後に、アダプターのsendメソッドを、メッセージペイロードとfeeを引数として呼び出します。

以下のコマンドでスクリプトを実行します:

# FROM: ./layerzero-oft

forge script script/Bridge.s.sol --rpc-url https://rpc.sepolia.org/ --broadcast

しばらくすると、LayerZero の Executor がリクエストを処理し、ブリッジされた $lzUNI トークンが Berachain のウォレットに表示されます!

まとめ

おめでとうございます!LayerZero OFTs を使用して、既存のトークンを Berachain へ成功裏にブリッジしました 🎉

OFTs やクロスチェーンメッセージングが可能にするすべてについてさらに学びたい場合は、ぜひLayerZero のドキュメントをご覧ください。

Disclaimer: OFT と OFT アダプターは、プロトコル開発者が自身のプロトコルのトークンを新しいチェーンに展開するためのソリューションです。既存トークンの非公認 OFT デプロイメントは、サポートを得られる可能性が低いでしょう。


🐻 Full Code Repository

最終的なコードや他のガイドを見たい場合は、Berachain LayerZero Guide Codeを参照してください。
Berachain GitHub Guides Repo
https://github.com/berachain/guides/tree/main/apps/pyth-oracle?ref=berachain.ghost.io

🛠️ さらに開発を進めたいですか?

Berachain でさらに開発を進めたい、より多くの実装例を見たいとお考えですか?私たちBerachain GitHub Guides Repo をぜひご覧ください。このリポジトリには、NextJS、Hardhat、Viem、Foundry など、様々な技術を使用した幅広い実装例が用意されています。

より詳細な情報を探求したい場合は、Berachain ドキュメントをご覧ください。

開発者サポートをお探しですか?

質問をするために、Berachain Discordサーバーに参加し、開発者チャンネルをチェックしてください。

❤️ この記事に対して愛を示すのを忘れないでください 👏🏼



【Sunrise とは】
Sunrise は Proof of Liquidity(PoL)と Fee Abstraction(手数料抽象化)を備えたデータ可用性レイヤーです。 私たちは DA の体験を再構築し、多様なエコシステムからのモジュラー型流動性を活用してロールアップを立ち上げています。

【Social Links】

【お問合せ】
Sunrise へのお問い合わせはこちらから 👉 Google Form

1080x360.jpeg

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0