本記事は下記の翻訳となります。
『Bridge any Token to Berachain with LayerZero V2』
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 NetworkとSepolia 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
依存関係のインストール
LayerZeroとOpenZeppelinのツールに関連するいくつかの依存関係を利用しますので、以下のコマンドでインストールしてください:
# 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
トークンのブリッジングプロセスに関与するインタラクションについて簡単に説明しましょう:
- ユーザーはソースチェーン上で、私たちが作成した
OFT Adapter
コントラクトに対してブリッジのトランザクションを実行します。 -
$UNI
トークンはOFT Adapter
にロックされます。 - LayerZero エンドポイント契約は、Destination Chain 上で
$UNI
トークンを作成するための指示を含むメッセージを送信します。 - メッセージは DVN によって検証されます。
- エグゼキューターは、Destination Chain 上のエンドポイント契約に対して
lzReceive()
を呼び出し、メッセージを受け取ります。 -
$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
コントラクトを実装し、デスティネーションチェーン上でトークンの詳細(例: name
、symbol
)を定義する場所です。再度、delegate
が定義されています。
(プロジェクトで生成された src/Counter.sol
、test/Counter.t.sol
、script/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_ADDRESS
を MyAdapter
デプロイメントのアドレスで更新する。
ステップ 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_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!");
}
}
- まず、デプロイされた Sepolia アダプターのインスタンスに接続します。
- 次に、
setPeer
を呼び出して、Berachain にある OFT コントラクトの情報をアダプターに伝えます。 - オプションを定義して、Executor がメッセージ配信に支払うガス量を設定します(詳細はこちらを参照)。また、メッセージペイロードを準備し、このトランザクションの
fee
(手数料)の見積もりを要求します。 - アダプターコントラクトに対して、私たちの
$UNI
トークンを使用する権限を与えます。 - 最後に、アダプターの
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 Discordサーバーに参加し、開発者チャンネルをチェックしてください。
❤️ この記事に対して愛を示すのを忘れないでください 👏🏼
【Sunrise とは】
Sunrise は Proof of Liquidity(PoL)と Fee Abstraction(手数料抽象化)を備えたデータ可用性レイヤーです。 私たちは DA の体験を再構築し、多様なエコシステムからのモジュラー型流動性を活用してロールアップを立ち上げています。
【Social Links】
【お問合せ】
Sunrise へのお問い合わせはこちらから 👉 Google Form