読了時間:38分
概要
Hyperliquidは、2つのレイヤーを1つの統合された状態の下に組み合わせたものです。その2つとは、署名付きアクションを介してアクセスされる超低遅延のオーダーブックエンジン「HyperCore」と、標準的なSolidity開発に対応した完全なEVM互換ネットワーク「HyperEVM」です。
Chainlink CCIPは、バーン・アンド・ミントの仕組みを用いて、チェーン間の資産ブリッジを可能にします。Hyperliquid内では、HyperCore(HIP-1)資産とそのHyperEVM表現との間の変換は、ネイティブのプロトコルフローによって処理されます。
このガイドでは、Foundry を使用して HIP-1 アセットに対応する HyperEVM トークンをラップし、CCIP を利用してそのトークンを HyperEVM と BNB Smart Chain (BSC) の間でブリッジします。
主な業務内容
- HIP-1アセットにリンクされたHyperEVMトークンのラッパーコントラクトを作成する
- HyperEVM および BSC 上で CCIP トークンプールをデプロイおよび設定する
- 展開済みのトークンおよびプール契約をオンチェーンで確認する
- Foundryスクリプトを使用して、HyperEVMとBSC間でCCIP転送を実行する
必要なもの
- Node.js v22 以降およびパッケージマネージャー(npm、yarn、または pnpm)がインストールされていること
- HyperEVMメインネットおよびBinance Smart ChainメインネットがMetaMaskに追加されました
- HyperEVMおよびBinance Smart Chain向けのQuicknodeエンドポイント
- Solidityおよび Foundryの使用経験
このガイドでは、各チェーンのメインネットを使用しています。これは、本稿執筆時点で、HyperEVMテストネットではChainlink CCIPが利用できないためです。十分にご注意いただき、損失を許容できる範囲の資金のみをご利用ください。
開発環境のセットアップ
Foundryを使用して、スマートコントラクトのコンパイル、デプロイ、および操作を行います。Foundry をまだインストールしていない場合は、ターミナルで次のコマンドを実行してインストールしてください:
curl -L https://foundry.paradigm.xyz | bash
画面の指示に従ってください。その後、以下の機能をご利用いただけるようになります。 foundryup Foundry をインストールするためのコマンドです。このコマンドは、変更が反映されるよう、新しいターミナルセッションで実行してください。 PATH 変数。
foundryup
このガイドで扱うプロジェクトを保存するため、ローカルに新しいフォルダを作成する必要があります。ここでは「hyperevm_ccip」という名前を付けますが、お好きな名前で構いません。ターミナルで以下のコマンドを実行してフォルダを作成し、コードエディタでそのフォルダに移動してください。このガイドでは、VS Code を使用します。
forge init hyperevm_ccip
cd hyperevm_ccip
code .
この時点で、設定は次のような状態になっているはずです:

素晴らしい!これで「Foundry」プロジェクトの構造が整いました。次に、 .env プロジェクトフォルダのルートにあるファイルです。ここには、秘密鍵やRPC URLなどの環境変数を保存します。このファイルの形式は以下の通りです。 .env ファイルは次のような形式になるはずです:
HYPEREVM_RPC="your_hyperevm_rpc_url"
BSC_RPC="BSCのRPC URL"
PRIVATE_KEY="あなたの秘密鍵"
ETHERSCAN_API_KEY="あなたの_etherscan_api_key"
これらの変数がそれぞれ何を指すのか、またそれらをどのように取得するのかについては、後ほど説明します。次のステップは、デフォルトのものを削除することです。 src/Counter.sol 契約および script/Counter.s.sol Foundryが自動的に生成するスクリプトです。このガイドではこれらを使用しません。あるいは、ターミナルで以下のコマンドを実行して、これらのファイルを削除することもできます:
rm src/Counter.sol
rm script/Counter.s.sol
また、以下の設定を行う必要があります。 foundry.toml プロジェクトフォルダのルートにあるファイルに、Solidityコンパイラに関する重要な設定や、これから使用するimport文のリマッピングを記述します。その内容は以下の通りです。 foundry.toml ファイルは次のような形式になるはずです:
[プロフィール.デフォルト]
src = "src"
out = "out"
libs = ["lib"]
optimizer = true
optimizer_runs = 200
再マッピング = [
'@chainlink/contracts-ccip/=node_modules/@chainlink/contracts-ccip/',
'@chainlink/contracts/=node_modules/@chainlink/contracts/',
]
fs_permissions = [{ アクセス = "読み書き", path = "./" }]
このファイルには、以下の内容を追加しました。 オプティマイザー スマートコントラクトのデプロイを最適化するための設定。その fs_permissions このエントリにより、Foundryはプロジェクトディレクトリ内のファイルを読み書きできるようになります。この 再マッピング 各項目は、このガイドで使用するChainlinkコントラクトのパッケージのパスです。次に、これらのパッケージをインストールします。
依存関係のインストール
このガイドでは、2つのChainlinkコントラクトパッケージを使用します: @chainlink/contracts-ccip そして @chainlink/contracts. 1つ目のパッケージには、今後やり取りを行うことになるCCIPの中核となるコントラクトと、デプロイする予定のCCIPトークンプール用コントラクトが含まれています。2つ目のパッケージには、カスタマイズされた ERC20 Chainlinkのクロスチェーン転送要件を満たす契約。
また、以下の設置も行う予定です。 @layerzerolabs/hyperliquid-composer このパッケージは、HyperEVM上でのトランザクションのガス制限を引き上げるために使用されます。HyperEVMには、 マルチブロックアーキテクチャ これは、ガス制限が200万ガス単位の小さなブロックと、ガス制限が3,000万ガス単位の大きなブロックで構成されています。小さなブロックのブロック時間は1秒、大きなブロックのブロック時間は1分です。デフォルトでは、HyperEVM上のアカウントは、小さなブロックのガス制限に準拠したトランザクションのみ送信できます。このパッケージを利用することで、大きなブロックに収まるよう、より高いガス制限を持つトランザクションをアカウントから送信できるようになります。
これらのパッケージをインストールするには、お好みのパッケージマネージャーを使用して、以下のコマンドを入力してください:
- npm
- 糸
npm install @chainlink/contracts-ccip @chainlink/contracts @layerzerolabs/hyperliquid-composer
yarn add @chainlink/contracts-ccip @chainlink/contracts @layerzerolabs/hyperliquid-composer
素晴らしい!このガイドで使用する依存関係を正常にインストールできました。次に、設定ファイルに記述する必要がある環境変数について説明します。 .env ファイル。
環境変数
Quicknode エンドポイント
まず、HyperEVM および BSC 用の適切な RPC エンドポイントを取得する必要があります。これらは以下の場所から入手できます。 Quicknode. 無料トライアルに登録し、新しいマルチチェーン・エンドポイントを作成して、各チェーンのHTTPS URLをコピーするだけです。対応するURLを HYPEREVM_RPC そして BSC_RPC あなたの .env ファイル。
Etherscan API
次に、[ ] のプロフィールページにアクセスして、 Etherscan 「API KEYS」タブに移動してください。アカウントをお持ちでない場合は、作成してください こちら. ここでは、オンチェーンでスマートコントラクトを検証するために必要なAPIキーを作成します。APIキーをコピーして、 ETHERSCAN_API_KEY あなたの .env ファイル。
秘密鍵
最後に、MetaMaskを開き、アカウントのいずれかの秘密鍵をコピーしてください。秘密鍵の確認方法については、こちらの短い記事をご覧ください。 ガイド. この秘密鍵を PRIVATE_KEY あなたの .env ファイル。
これで、あなたの .env これでファイルにデータが入力されたはずです。この設定プロセスの最後のステップは、MetaMaskウォレットに適切なネットワークを追加することです。
MetaMaskへのネットワークの追加
MetaMaskウォレットに、HyperEVMメインネットおよびBinance Smart Chainメインネットのネットワークを追加する予定です。これらのネットワークを追加する最も簡単な方法は、以下のページにアクセスすることです。 hyperevmscan.io そして bscscan.com そして、[ 追加 ページの左下にあるボタン。これにより、ネットワークがMetaMaskウォレットに追加されます:

おめでとうございます!このガイドに従って開発環境の設定が完了しました。次のステップは、HyperCoreからHyperEVMへHIP-1アセットをブリッジすることです。
HyperCoreからHyperEVMへの移行
ここでは、HyperCoreからHyperEVMへHIP-1資産をブリッジします。このプロセスでは、HIP-1資産を対応するHyperEVMトークンに変換します。このガイドでは、Hyperliquidのネイティブエコシステムコインである「HYPE」を使用します。まず、Hyperliquidの取引画面にアクセスし、MetaMaskでログインして開始してください。
まだHYPEコインをお持ちでない場合は、ArbitrumメインネットからHyperliquidにUSDCを入金し、取引インターフェースのスポット市場でHYPEと交換することで入手できます:

HYPEを入手したら、HyperEVMへのブリッジに進むことができます。これを行うには、チャートの下にあるページ下部の「EVMとの送受信」ボタンをクリックしてください。ブリッジしたいHYPEの数量を入力し、「確認」をクリックするだけです。

HYPEとHyperEVMの橋渡し
素晴らしい!HyperCoreからHyperEVMへのHYPEのブリッジに成功しました。これで、MetaMask上でHyperEVMネットワーク上のHYPEの残高を確認できるようになっているはずです。次に、Chainlinkのクロスチェーン転送要件に準拠したHYPE用のラッパーコントラクトを作成していきます。
HYPE用のラッパー契約の作成
Chainlink CCIP を使用して HyperEVM と BSC 間の HYPE をブリッジするには、Chainlink のクロスチェーン転送要件に準拠したラッパーコントラクトを作成する必要があります。これには、HyperEVM 上の既存の HYPE アセットをラップする新しい ERC20 トークンコントラクトと、BSC 上の対応する ERC20 トークンコントラクトを作成することが含まれます。
私たちは、 Quicknodeをめぐる騒ぎ 記号付きのトークン qWHYPE. 以下のコマンドを入力して、 src プロジェクトディレクトリ内のフォルダに、以下のコードを貼り付けてください。
- ファイルを作成する
- コード
touch src/qWHYPE.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol";
contract qWHYPE is BurnMintERC20 {
event Deposit(address indexed account, uint256 amount);
event Withdraw(address indexed account, uint256 amount);
constructor() BurnMintERC20("Quicknode Wrapped HYPE", "qWHYPE", 18, 0, 0) {}
function deposit() public payable {
_mint(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) external {
_burn(msg.sender, amount);
payable(msg.sender).transfer(amount);
emit Withdraw(msg.sender, amount);
}
}
ラッパー契約の理解
それでは、このコードを詳しく見ていきましょう。 qWHYPE.sol 契約。この契約では、 BurnMintERC20 ~からの契約 @chainlink/contracts このパッケージは、トークンの発行および焼却に必要な機能を提供します。ユーザーがHYPEをコントラクトに預け入れると、コントラクトはそのユーザーのアドレスに対して同額のqWHYPEトークンを発行します。逆に、ユーザーがqWHYPEトークンを引き出すと、コントラクトはそのトークンを焼却し、対応する額のHYPEをユーザーのアドレスに返還します。
この特定のコントラクトは、HyperEVMネットワーク上にデプロイされます。BSC上では、ベースとなるコントラクトをデプロイする予定です。 BurnMintERC20 追加の機能は必要ないため、直接契約を締結します。次のセクションでは、スクリプトを使用して両方の契約を展開します。
ファウンダリー・スクリプトの書き方
スマートコントラクトのデプロイや操作を行うために、いくつかのFoundryスクリプトを作成します。このセクションでは、各スクリプトについて詳しく解説するため、いくつかのパートに分けて説明します。以下のスクリプトを作成し、この順序で実行していきます:
| スクリプト名 | 説明 |
|---|---|
DeployTokens.s.sol | HyperEVM上にqWHYPEコントラクトとベースをデプロイします BurnMintERC20 BSC上の契約 |
DeployPools.s.sol | HyperEVMとBSCの両方にCCIPトークンプール契約を展開します |
SetupAdmin.s.sol | 各チェーンの CCIP 契約について、管理者ロールを登録および設定する |
ConfigurePools.s.sol | 各CCIPトークンプール間のクロスチェーン転送を行うための設定を行います |
DepositAndTransferTokens.s.sol | qWHYPEコントラクトに少量のHYPEを預け入れ、qWHYPEトークンを鋳造した後、BSCへのクロスチェーン転送を実行する |
TransferTokens.s.sol | qWHYPEトークンのクロスチェーン送金を、どちらの方向からも実行する |
前提条件
スクリプトを記述する前に、デプロイされたコントラクトのアドレスを追跡する仕組みと、スクリプト全体で使用する共通の定数を格納するファイルを用意しておく必要があります。
以下のコマンドを実行して、必要なファイルを作成してください:
touch script/Constants.s.sol
mkdir -p script/output
touch script/output/deployments.json
ここでは、 deployments.json 各チェーン上でデプロイされたコントラクトのアドレスを追跡するためのファイル。
以下が Constants.s.sol ファイルは次のような形式になるはずです:
クリックしてコードを展開
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script} from "forge-std/Script.sol";
contract Constants is Script {
struct CCIPConstants {
uint64 chainSelector;
address router;
address rmnProxy;
address tokenAdminRegistry;
address registryModuleOwnerCustom;
string nativeCurrencySymbol;
}
function getCCIPConstants(uint256 chainId) public pure returns (CCIPConstants memory) {
if(chainId == 999) {
return CCIPConstants({
chainSelector: 2442541497099098535,
router: 0x13b3332b66389B1467CA6eBd6fa79775CCeF65ec,
rmnProxy: 0x07f15e9813FBd007d38CF534133C0838f449ecFA,
tokenAdminRegistry: 0xcE44363496ABc3a9e53B3F404a740F992D977bDF,
registryModuleOwnerCustom: 0xbAb3aBB5F29275065F2814F1f4B10Ffc1284fFEf,
nativeCurrencySymbol: "HYPE"
});
} else if (chainId == 56) {
return CCIPConstants({
chainSelector: 11344663589394136015,
router: 0x34B03Cb9086d7D758AC55af71584F81A598759FE,
rmnProxy: 0x9e09697842194f77d315E0907F1Bda77922e8f84,
tokenAdminRegistry: 0x736Fd8660c443547a85e4Eaf70A49C1b7Bb008fc,
registryModuleOwnerCustom: 0x47Db76c9c97F4bcFd54D8872FDb848Cab696092d,
nativeCurrencySymbol: "BNB"
});
}
revert("Chain not supported");
}
}
スクリプトメニュー
- DeployTokens.s.sol
- DeployPools.s.sol
- SetupAdmin.s.sol
- ConfigurePools.s.sol
- DepositAndTransferTokens.s.sol
- TransferTokens.s.sol
このスクリプトは、 qWHYPE HyperEVMおよびその基盤に関する契約 BurnMintERC20 BSC上の契約。以下の場所に新しいファイルを作成します。 スクリプト プロジェクトディレクトリ内の、名前が DeployTokens.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/DeployTokens.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script, console} from "forge-std/Script.sol";
import {qWHYPE} from "../src/qWHYPE.sol";
import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol";
contract DeployTokens is Script {
string internal constant OUTPUT_PATH = "script/output/deployments.json";
/// forge script script/DeployTokens.s.sol:DeployTokens
function run() external {
// Load env vars
bytes memory hyperevm = bytes(vm.envString("HYPEREVM_RPC"));
bytes memory bsc = bytes(vm.envString("BSC_RPC"));
uint256 pk = vm.envUint("PRIVATE_KEY");
// Check if env vars are set
require(hyperevm.length != 0, "HYPEREVM_RPC not set");
require(bsc.length != 0, "BSC_RPC not set");
// print deployer address
address deployer = vm.addr(pk);
console.log("Deployer address:", deployer);
// Deploy on both chains
address hyperAddr = deployOn(hyperevm, deployer, pk);
address bscAddr = deployOn(bsc, deployer, pk);
// Write deployed addresses to JSON file
string memory obj = vm.serializeString("deployments", "qWHYPE_hyperevm", vm.toString(hyperAddr));
obj = vm.serializeString("deployments", "qWHYPE_bsc", vm.toString(bscAddr));
vm.writeJson(obj, OUTPUT_PATH);
}
function deployOn(bytes memory rpc, address deployer, uint256 pk) internal returns (address) {
vm.selectFork(vm.createFork(string(rpc)));
vm.startBroadcast(pk);
string memory chainName = getChainName(block.chainid);
address tokenAddr = address(block.chainid == 999 ? new qWHYPE() : new BurnMintERC20("Quicknode Wrapped HYPE", "qWHYPE", 18, 0, 0));
console.log("\nDeployed qWHYPE to:", tokenAddr, "on", chainName);
BurnMintERC20(tokenAddr).grantMintAndBurnRoles(deployer);
console.log("Granted minter and burner roles on", chainName, "qWHYPE to:", deployer);
vm.stopBroadcast();
return tokenAddr;
}
function getChainName(uint256 chainId) internal pure returns (string memory) {
if (chainId == 56) return "\x1b[36mBSC Mainnet\x1b[0m";
else if (chainId == 999) return "\x1b[32mHyperEVM Mainnet\x1b[0m";
else revert("Unsupported chain ID");
}
}
DeployTokens スクリプトの理解
このスクリプトでは、まずRPC URLと秘密鍵の環境変数を読み込みます。次に、 deployOn RPC URL、デプロイ先のアドレス、および秘密鍵をパラメータとして受け取る関数。この関数は、指定されたチェーンのフォークを作成し、渡された秘密鍵を使用してトランザクションのブロードキャストを開始し、以下のいずれかをデプロイします。 qWHYPE 契約(HyperEVM上)またはベース BurnMintERC20 (BSC上の)コントラクト。デプロイ後、デプロイ元アドレスに対して、デプロイされたトークンコントラクトにおけるミントおよびバーンの権限が付与されます。
このスクリプトは、HyperEVMとBSCの両方にCCIPトークンプール契約をデプロイします。 スクリプト プロジェクトディレクトリ内の、名前が DeployPools.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/DeployPools.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script} from "forge-std/Script.sol";
import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol";
import {IBurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol";
import {BurnMintTokenPool} from "@chainlink/contracts-ccip/contracts/pools/BurnMintTokenPool.sol";
import {Constants} from "./Constants.s.sol";
contract DeployPools is Script {
string internal constant OUTPUT_PATH = "script/output/deployments.json";
/// forge script script/DeployPools.s.sol:DeployPools
function run() external {
// Load env vars
bytes memory hyperevm = bytes(vm.envString("HYPEREVM_RPC"));
bytes memory bsc = bytes(vm.envString("BSC_RPC"));
uint256 pk = vm.envUint("PRIVATE_KEY");
// Check if env vars are set
require(hyperevm.length != 0, "HYPEREVM_RPC not set");
require(bsc.length != 0, "BSC_RPC not set");
// Read deployed token addresses from JSON
string memory json = vm.readFile(OUTPUT_PATH);
address tokenHyp = vm.parseJsonAddress(json, ".qWHYPE_hyperevm");
address tokenBsc = vm.parseJsonAddress(json, ".qWHYPE_bsc");
// Fetch CCIP constants
Constants constants = new Constants();
Constants.CCIPConstants memory cfgHyp = constants.getCCIPConstants(999);
Constants.CCIPConstants memory cfgBsc = constants.getCCIPConstants(56);
// Create forks up front
uint256 hyperFork = vm.createFork(string(hyperevm));
uint256 bscFork = vm.createFork(string(bsc));
// Deploy pool on HyperEVM
vm.selectFork(hyperFork);
vm.startBroadcast(pk);
address poolHyp = address(new BurnMintTokenPool(IBurnMintERC20(tokenHyp), 18, new address[](0), cfgHyp.rmnProxy, cfgHyp.router));
BurnMintERC20(tokenHyp).grantMintAndBurnRoles(poolHyp);
vm.stopBroadcast();
// Deploy pool on BSC
vm.selectFork(bscFork);
vm.startBroadcast(pk);
address poolBsc = address(new BurnMintTokenPool(IBurnMintERC20(tokenBsc), 18, new address[](0), cfgBsc.rmnProxy, cfgBsc.router));
BurnMintERC20(tokenBsc).grantMintAndBurnRoles(poolBsc);
vm.stopBroadcast();
// Write deployed addresses to JSON file
string memory out = vm.serializeString("deployments", "qWHYPE_hyperevm", vm.toString(tokenHyp));
out = vm.serializeString("deployments", "qWHYPE_bsc", vm.toString(tokenBsc));
out = vm.serializeString("deployments", "qWHYPE_pool_hyperevm", vm.toString(poolHyp));
out = vm.serializeString("deployments", "qWHYPE_pool_bsc", vm.toString(poolBsc));
vm.writeJson(out, OUTPUT_PATH);
}
}
DeployPools スクリプトの理解
このスクリプトでは、まずRPC URLと秘密鍵の環境変数を読み込みます。次に、デプロイされたトークンのアドレスを deployments.json 前のスクリプトで作成されたファイル。HyperEVM と BSC の両方に必要な CCIP 定数を、 定数 契約。
これらの定数には、Chainlinkが各チェーンにデプロイした中核となるCCIPコントラクト(Router、TokenAdminRegistry、RegistryModuleOwnerCustomなど)や、プールのデプロイに必要なRiskManagementNetwork(RMN)プロキシアドレスが含まれます。 Routerはクロスチェーンメッセージのルーティングを担当し、TokenAdminRegistryはトークンアドレスとそれぞれのプールとのマッピングを管理し、RegistryModuleOwnerCustomはさまざまな所有権パターンにおけるトークン管理者の登録に使用され、RMNプロキシはクロスチェーンメッセージのRMN署名の検証に使用されます。
これらの定数を用いて、 BurnMintTokenPool 両方のチェーン上の契約に対し、それぞれのトークン契約におけるミントおよびバーンの役割を付与します。最後に、 deployments.json デプロイされたトークンプールのアドレスが記載されたファイル。
このスクリプトは、各チェーンのCCIPレジストリ契約にデプロイしたトークンの管理者を登録します。以下の場所に新しいファイルを作成してください。 スクリプト プロジェクトディレクトリ内の、名前が SetupAdmin.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/SetupAdmin.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script, console} from "forge-std/Script.sol";
import {TokenAdminRegistry} from "@chainlink/contracts-ccip/contracts/tokenAdminRegistry/TokenAdminRegistry.sol";
import {RegistryModuleOwnerCustom} from "@chainlink/contracts-ccip/contracts/tokenAdminRegistry/RegistryModuleOwnerCustom.sol";
import {Constants} from "./Constants.s.sol";
contract SetupAdmin is Script {
string internal constant OUTPUT_PATH = "script/output/deployments.json";
/// forge script script/SetupAdmin.s.sol:SetupAdmin
function run() external {
// Load env vars
bytes memory hyperevm = bytes(vm.envString("HYPEREVM_RPC"));
bytes memory bsc = bytes(vm.envString("BSC_RPC"));
uint256 pk = vm.envUint("PRIVATE_KEY");
// Check if env vars are set
require(hyperevm.length != 0, "HYPEREVM_RPC not set");
require(bsc.length != 0, "BSC_RPC not set");
// Read deployed token addresses
string memory json = vm.readFile(OUTPUT_PATH);
address tokenHyp = vm.parseJsonAddress(json, ".qWHYPE_hyperevm");
address tokenBsc = vm.parseJsonAddress(json, ".qWHYPE_bsc");
// Fork both chains up front
uint256 hyperFork = vm.createFork(string(hyperevm));
uint256 bscFork = vm.createFork(string(bsc));
// Do HyperEVM
vm.selectFork(hyperFork);
_registerAndAccept(tokenHyp, pk);
// Do BSC
vm.selectFork(bscFork);
_registerAndAccept(tokenBsc, pk);
}
function _registerAndAccept(address token, uint256 pk) internal {
Constants constants = new Constants();
Constants.CCIPConstants memory cfg = constants.getCCIPConstants(block.chainid);
address ownerCustomModule = cfg.registryModuleOwnerCustom;
address tokenAdminRegistry = cfg.tokenAdminRegistry;
string memory chainName = _getChainName(block.chainid);
vm.startBroadcast(pk);
// Register admin on RegistryModuleOwnerCustom (msg.sender becomes pending admin)
RegistryModuleOwnerCustom(ownerCustomModule).registerAdminViaGetCCIPAdmin(token);
console.log("Proposed admin via OwnerCustom on", chainName);
// Accept the admin role from the pending admin
TokenAdminRegistry tokenAdminRegistryContract = TokenAdminRegistry(tokenAdminRegistry);
TokenAdminRegistry.TokenConfig memory config = tokenAdminRegistryContract.getTokenConfig(token);
address pendingAdmin = config.pendingAdministrator;
require(pendingAdmin == vm.addr(pk), "Pending admin mismatch");
tokenAdminRegistryContract.acceptAdminRole(token);
console.log("Successfully registered and accepted admin role for token on", chainName, ": ", token);
vm.stopBroadcast();
}
function _getChainName(uint256 chainId) internal pure returns (string memory) {
if (chainId == 56) return "BSC";
if (chainId == 999) return "HyperEVM";
return "Unknown";
}
}
SetupAdmin スクリプトの理解
このスクリプトでは、まずRPC URLと秘密鍵の環境変数を読み込みます。次に、デプロイされたトークンのアドレスを deployments.json ファイル。これらのトークンアドレスは、CCIPレジストリ契約が各トークンの管理者を取得し、それぞれのチェーンに登録するために必要となります。
CCIPトークンの管理者を登録するには、2つの手順があります。まず、 RegistryModuleOwnerCustom 契約が呼び出されます。この契約は、トークンの新しい管理者を提案するために使用されます。現在の管理者は、 getCCIPAdmin 当サイトの qWHYPE 契約により、その者が保留中の管理者となります。その RegistryModuleOwnerCustom は、 TokenAdminRegistry 新しい管理者を提案するための契約。この状態はその後、 TokenConfig のstruct TokenAdminRegistry 契約。そして最後のステップは、 TokenAdminRegistry 契約が呼び出され、から検出された保留中の管理者から管理者ロールを受け入れます。 TokenConfig 指定されたトークンに対して。
なぜトークンの管理者の登録が、このような複雑な2段階のプロセスで行われるのか、不思議に思われるかもしれません。なぜ単に管理者を直接 TokenAdminRegistry 契約? この設計選択にはいくつかの理由があります:
- セキュリティの強化:2段階承認プロセスにより、現在の管理者が新しい管理者を審査・承認してから、任命が確定するようになっています。
- マルチシグ対応:管理者の変更案を提案し、その後承認することで、マルチシグウォレット(例:Safe)に対応しています。
- 所有形態:以下の方法により、CCIPの所有モデルと互換性があります
getCCIPOwnerまた、OpenZeppelinの「Ownable」スタイルの所有権機能などにより、既存のさまざまなトークンの導入が可能になります。
このスクリプトは、CCIPトークンプール間でクロスチェーン転送が行えるよう設定を行います。以下のディレクトリに新しいファイルを作成してください。 スクリプト プロジェクトディレクトリ内の、名前が ConfigurePools.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/ConfigurePools.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script, console} from "forge-std/Script.sol";
import {TokenAdminRegistry} from "@chainlink/contracts-ccip/contracts/tokenAdminRegistry/TokenAdminRegistry.sol";
import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol";
import {RateLimiter} from "@chainlink/contracts-ccip/contracts/libraries/RateLimiter.sol";
import {Constants} from "./Constants.s.sol";
contract ConfigurePools is Script {
struct Params {
address localToken;
address localPool;
address tokenAdminRegistry;
uint64 remoteSelector;
address remotePool;
address remoteToken;
uint256 pk;
string chainName;
}
string internal constant OUTPUT_PATH = "script/output/deployments.json";
/// forge script script/ConfigurePools.s.sol:ConfigurePools
function run() external {
// Load env vars
bytes memory hyperevm = bytes(vm.envString("HYPEREVM_RPC"));
bytes memory bsc = bytes(vm.envString("BSC_RPC"));
uint256 pk = vm.envUint("PRIVATE_KEY");
require(hyperevm.length != 0, "HYPEREVM_RPC not set");
require(bsc.length != 0, "BSC_RPC not set");
// Load deployed addresses
string memory json = vm.readFile(OUTPUT_PATH);
address tokenHyp = vm.parseJsonAddress(json, ".qWHYPE_hyperevm");
address tokenBsc = vm.parseJsonAddress(json, ".qWHYPE_bsc");
address poolHyp = vm.parseJsonAddress(json, ".qWHYPE_pool_hyperevm");
address poolBsc = vm.parseJsonAddress(json, ".qWHYPE_pool_bsc");
// Preload constants for both chains
Constants constants = new Constants();
Constants.CCIPConstants memory cfgHyp = constants.getCCIPConstants(999);
Constants.CCIPConstants memory cfgBsc = constants.getCCIPConstants(56);
// Forks
uint256 hyperFork = vm.createFork(string(hyperevm));
uint256 bscFork = vm.createFork(string(bsc));
// Configure HyperEVM pool and registry
vm.selectFork(hyperFork);
Params memory pHyp = Params({
localToken: tokenHyp,
localPool: poolHyp,
tokenAdminRegistry: cfgHyp.tokenAdminRegistry,
remoteSelector: cfgBsc.chainSelector,
remotePool: poolBsc,
remoteToken: tokenBsc,
pk: pk,
chainName: "HyperEVM"
});
_setPoolAndApplyChainUpdates(pHyp);
// Configure BSC pool and registry
vm.selectFork(bscFork);
Params memory pBsc = Params({
localToken: tokenBsc,
localPool: poolBsc,
tokenAdminRegistry: cfgBsc.tokenAdminRegistry,
remoteSelector: cfgHyp.chainSelector,
remotePool: poolHyp,
remoteToken: tokenHyp,
pk: pk,
chainName: "BSC"
});
_setPoolAndApplyChainUpdates(pBsc);
}
function _setPoolAndApplyChainUpdates(Params memory p) internal {
// Set pool in TokenAdminRegistry (maps token -> pool)
vm.startBroadcast(p.pk);
TokenAdminRegistry(p.tokenAdminRegistry).setPool(p.localToken, p.localPool);
console.log("setPool set on ", p.localPool);
// Configure pool with remote chain, pool, rate limits
TokenPool pool = TokenPool(p.localPool);
TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1);
// Encode remote pool addresses (single entry)
bytes[] memory remotePoolAddressesEncoded = new bytes[](1);
remotePoolAddressesEncoded[0] = abi.encode(p.remotePool);
chainUpdates[0] = TokenPool.ChainUpdate({
remoteChainSelector: p.remoteSelector,
remotePoolAddresses: remotePoolAddressesEncoded,
remoteTokenAddress: abi.encode(p.remoteToken),
outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}),
inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0})
});
// No removals, apply chain updates
uint64[] memory chainSelectorRemovals = new uint64[](0);
pool.applyChainUpdates(chainSelectorRemovals, chainUpdates);
console.log("Chain update applied to pool at address:");
console.log(p.localPool);
vm.stopBroadcast();
}
}
ConfigurePools スクリプトの理解
このスクリプトでは、まずRPC URLと秘密鍵に関する環境変数を読み込みます。次に、デプロイされたトークンとプールのアドレスを deployments.json ファイル。HyperEVM と BSC の両方について、必要な CCIP 定数を 定数 契約。これらの定数には、 TokenAdminRegistry 各トークンのプールを設定するために必要なアドレスとチェーンセレクタ。
我々は、 パラメータ 各プールを設定するために必要なすべてのパラメータを格納する構造体。これにより可読性が向上するだけでなく、Solidityでの「スタックが深すぎる」というエラーを防ぐのにも役立ちます。これを setPool の関数 TokenAdminRegistry 各トークンをそれぞれのプールにマッピングする契約。次に、 applyChainUpdates の関数 TokenPool 契約。この例では、簡略化のためレート制限を無効にしていますが、本番環境では、必要に応じて適切なレート制限を設定することができます。
このスクリプトは、qWHYPEコントラクトに少量のHYPEを預け入れ、qWHYPEトークンを鋳造した後、BSCへのクロスチェーン転送を実行します。以下の場所に新しいファイルを作成してください。 スクリプト プロジェクトディレクトリ内の、名前が DepositAndTransferTokens.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/DepositAndTransferTokens.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script, console} from "forge-std/Script.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol";
import {Constants} from "./Constants.s.sol";
import {qWHYPE} from "../src/qWHYPE.sol";
contract DepositAndTransferTokens is Script {
string internal constant OUTPUT_PATH = "script/output/deployments.json";
/// forge script script/DepositAndTransferTokens.s.sol:DepositAndTransferTokens
function run() external {
// Load env vars
bytes memory hyperevm = bytes(vm.envString("HYPEREVM_RPC"));
bytes memory bsc = bytes(vm.envString("BSC_RPC"));
uint256 pk = vm.envUint("PRIVATE_KEY");
require(hyperevm.length != 0, "HYPEREVM_RPC not set");
require(bsc.length != 0, "BSC_RPC not set");
// Read deployed token addresses
string memory json = vm.readFile(OUTPUT_PATH);
address tokenHyp = vm.parseJsonAddress(json, ".qWHYPE_hyperevm");
// Create forks and select HyperEVM (source)
uint256 hyperFork = vm.createFork(string(hyperevm));
vm.selectFork(hyperFork);
// Resolve CCIP constants for source and destination
Constants constants = new Constants();
Constants.CCIPConstants memory cfgHyp = constants.getCCIPConstants(999);
Constants.CCIPConstants memory cfgBsc = constants.getCCIPConstants(56);
address router = cfgHyp.router;
uint64 destinationChainSelector = cfgBsc.chainSelector;
address sender = vm.addr(pk);
// Amount to wrap and transfer: 0.01 HYPE -> 0.01 qWHYPE (18 decimals)
uint256 amount = 0.01 ether;
vm.startBroadcast(pk);
// Deposit HYPE to mint qWHYPE on HyperEVM
qWHYPE(tokenHyp).deposit{value: amount}();
console.log("Deposited and minted qWHYPE amount");
console.log(amount);
// Approve router to spend qWHYPE
IERC20(tokenHyp).approve(router, amount);
console.log("Approved router to spend qWHYPE");
// Build CCIP EVM2AnyMessage for token transfer
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({token: tokenHyp, amount: amount});
Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 0});
bytes memory extraArgsBytes = Client._argsToBytes(extraArgs);
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(sender),
data: abi.encode(),
tokenAmounts: tokenAmounts,
feeToken: address(0), // pay fees in native
extraArgs: extraArgsBytes
});
// Route via CCIP using native token for gas
IRouterClient routerClient = IRouterClient(router);
require(routerClient.isChainSupported(destinationChainSelector), "Dest chain not supported");
uint256 fee = routerClient.getFee(destinationChainSelector, message);
console.log("Estimated fee (native)", fee);
bytes32 messageId = routerClient.ccipSend{value: fee}(destinationChainSelector, message);
console.log("CCIP messageId");
console.logBytes32(messageId);
vm.stopBroadcast();
}
}
DepositAndTransferTokens スクリプトの理解
このスクリプトでは、まずRPC URLと秘密鍵に関する環境変数を読み込みます。次に、デプロイされたトークンのアドレスを deployments.json ファイル。HyperEVMチェーンのフォークを作成します。これが、クロスチェーン転送のソースチェーンとなります。
HyperEVM と BSC の両方に必要な CCIP 定数を、 定数 契約。これらの定数には、 ルーター クロスチェーンメッセージの送信に必要なアドレスとチェーンセレクター。預け入れおよび送金したいHYPEの量を指定します。この例では0.01 HYPEです。
私たちはこれを 預金 の関数 qWHYPE HYPEを預け入れることでqWHYPEトークンを鋳造する契約を締結します。次に、RouterがqWHYPEトークンを使用できるように承認します。その後、 Client.EVM2AnyMessage クロスチェーン送金の詳細(受信者アドレス、トークンの数量、および追加の引数など)を含む構造体。
最後に、私たちは ccipSend Routerコントラクト上の関数を使用して、送信元チェーンのネイティブトークン(HYPE)で必要な手数料を支払い、クロスチェーンメッセージを送信します。このスクリプトは、推定手数料とCCIP転送のメッセージIDをログに記録します。このメッセージIDを使用することで、 Chainlink CCIP エクスプローラー.
このスクリプトは、qWHYPEトークンのクロスチェーン転送をどちらの方向からも実行します。 スクリプト プロジェクトディレクトリ内の、名前が TransferTokens.s.sol そして、以下のコードをそこに貼り付けてください。
クリックしてコードを展開
ファイルを作成します:
touch script/TransferTokens.s.sol
以下のコードをファイルに貼り付けてください:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Script, console} from "forge-std/Script.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol";
import {Constants} from "./Constants.s.sol";
// Transfer-only script: does NOT deposit. Assumes caller holds qWHYPE on source chain.
contract TransferTokens is Script {
string internal constant OUTPUT_PATH = "script/output/deployments.json";
uint256 internal constant AMOUNT = 0.01 ether;
/// forge script script/TransferTokens.s.sol:TransferTokens --sig 'run(string)' <to-bsc | to-hyperevm>
function run(string memory to) external {
bool toBsc = _eq(to, "to-bsc");
require(toBsc || _eq(to, "to-hyperevm"), "to must be 'to-bsc' or 'to-hyperevm'");
_run(toBsc);
}
function run() external {
string memory to = vm.envOr("TO", string(""));
require(bytes(to).length != 0, "Set TO or use run(string)");
bool toBsc = _eq(to, "to-bsc");
require(toBsc || _eq(to, "to-hyperevm"), "to must be 'to-bsc' or 'to-hyperevm'");
_run(toBsc);
}
function _run(bool toBsc) internal {
// Validate RPCs and select source fork
require(bytes(vm.envString("HYPEREVM_RPC")).length != 0, "HYPEREVM_RPC not set");
require(bytes(vm.envString("BSC_RPC")).length != 0, "BSC_RPC not set");
vm.selectFork(vm.createFork(toBsc ? vm.envString("HYPEREVM_RPC") : vm.envString("BSC_RPC")));
// Resolve router and destination selector
address router = (new Constants()).getCCIPConstants(block.chainid).router;
uint64 destSelector = (new Constants()).getCCIPConstants(toBsc ? 56 : 999).chainSelector;
// Source token address
address srcToken = toBsc
? vm.parseJsonAddress(vm.readFile(OUTPUT_PATH), ".qWHYPE_hyperevm")
: vm.parseJsonAddress(vm.readFile(OUTPUT_PATH), ".qWHYPE_bsc");
// Start broadcasting
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
// Approve router to spend qWHYPE
IERC20(srcToken).approve(router, AMOUNT);
console.log("Approved router to spend qWHYPE");
// Build token amounts
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({token: srcToken, amount: AMOUNT});
// Send via CCIP using native gas as fee
require(IRouterClient(router).isChainSupported(destSelector), "Dest chain not supported");
uint256 fee = IRouterClient(router).getFee(
destSelector,
Client.EVM2AnyMessage({
receiver: abi.encode(vm.addr(vm.envUint("PRIVATE_KEY"))),
data: abi.encode(),
tokenAmounts: tokenAmounts,
feeToken: address(0),
extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0}))
})
);
console.log("Estimated fee (native)");
console.log(fee);
console.log("CCIP messageId");
console.logBytes32(
IRouterClient(router).ccipSend{value: fee}(
destSelector,
Client.EVM2AnyMessage({
receiver: abi.encode(vm.addr(vm.envUint("PRIVATE_KEY"))),
data: abi.encode(),
tokenAmounts: tokenAmounts,
feeToken: address(0),
extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0}))
})
)
);
vm.stopBroadcast();
}
function _eq(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
TransferTokensスクリプトの理解
このスクリプトでは、まずターミナルから渡された引数が以下のいずれかであるかどうかを確認します。 to-bsc または to-hyperevm、これは転送の方向を示しています。これに基づき、適切なソースチェーン(HyperEVM または BSC)のフォークを作成します。そして、 定数 契約。これらの定数には、 ルーター クロスチェーンメッセージを送信するために必要なアドレスとチェーンセレクタ。
転送する qWHYPE の量を一定値(この例では 0.01 qWHYPE)として設定します。Router が私たちの qWHYPE トークンを使用することを承認し、 Client.EVM2AnyMessage クロスチェーン送金の詳細(受信者アドレス、トークンの数量、および追加の引数など)を含む構造体。
最後に、私たちは ccipSend Routerコントラクト上の関数を使用して、送信元チェーンのネイティブトークン(HYPEまたはBNB)で必要な手数料を支払い、クロスチェーンメッセージを送信します。このスクリプトは、推定手数料とCCIP転送のメッセージIDをログに記録します。このメッセージIDを使用すると、 Chainlink CCIP エクスプローラー.
素晴らしい!これで、CCIPトークンプールのデプロイと設定、およびHyperEVMとBSC間のqWHYPEトークンのクロスチェーン転送を行うために必要なスクリプトをすべて作成しました。次のセクションでは、これらのスクリプトを実行していきます。
スクリプトの実行
必要なスクリプトをすべて作成したので、これらを順番に実行して、CCIPトークンプールをデプロイおよび設定し、qWHYPEトークンのクロスチェーン転送を行うことができます。
先ほど、Hyperliquidのマルチブロックアーキテクチャについて説明しました。小さいブロックでは最大2Mのガスが使用されますが、大きいブロックでは最大30Mのガスを使用できます。私たちのコントラクトデプロイメントトランザクションは、間違いなく2Mのガス制限を超えるため、まずアカウントで大きいブロックを使用できるように設定する必要があります。これを行うには、ターミナルで次のコマンドを実行してください:
source .env
npx @layerzerolabs/hyperliquid-composer set-block --size big --network mainnet --private-key $PRIVATE_KEY
秘密鍵をコマンドラインで直接指定することは、シェルの履歴に記録される可能性があるため、お勧めしません。機密情報を扱う際は、常に環境変数や安全な方法を使用してください!
お使いのウォレットがHyperCoreに登録されていない場合、このコマンドは次のエラーで失敗する可能性があります。 ユーザーまたはAPIウォレットが存在しません。 ウォレットを登録するには、Hyperliquidで入金または取引を行っていることを確認してください。もし以下の手順に従った場合は、 HyperCoreからHyperEVMへの移行 そうです、お持ちのウォレットはすでに登録済みです!
素晴らしい!これで、私たちのアカウントではより大きなブロックを使用できるようになりました。それでは、 DeployTokens.s.sol スクリプト:
forge script script/DeployTokens.s.sol:DeployTokens --broadcast --verify --verifier etherscan
このコマンドを実行すると、トークンがHyperEVMネットワークとBSCネットワークの両方にデプロイされます。ターミナルにはデプロイの進行状況が表示され、トランザクションが確認されるとトランザクションハッシュが表示されます。 --放送 このフラグは、トランザクションをネットワークに送信したいことを示し、一方、 --検証 そして --検証ツール:Etherscan flags は、デプロイ後に hyperevmscan.io および bscscan.com で当社のコントラクトを自動的に検証します。また、あなたの deployments.json ファイルには、デプロイされたコントラクトのアドレスが書き込まれています。ターミナルの出力は、次のようなものになるはずです:

次に、以下の方法を使用して、CCIPトークンプールをデプロイします。 DeployPools.s.sol スクリプト:
forge script script/DeployPools.s.sol:DeployPools --broadcast --verify --verifier etherscan
このコマンドを実行すると、トークンプールがHyperEVMネットワークとBSCネットワークの両方にデプロイされます。前の手順と同様に、ターミナルにデプロイの進行状況が表示され、トランザクションが確認されるとトランザクションハッシュが表示されます。 deployments.json ファイルには、デプロイされたプールのアドレスが反映されます。ターミナルの出力は、次のようなものになるはずです:

次に、以下の方法を使用して、トークンの管理画面を設定します。 SetupAdmin.s.sol スクリプトを使用して、プールを設定し、 ConfigurePools.s.sol スクリプト。以下のコマンドを使用すると、両方のスクリプトを順番に実行できます:
forge script script/SetupAdmin.s.sol:SetupAdmin --broadcast
forge script script/ConfigurePools.s.sol:ConfigurePools --broadcast
前の手順と同様に、トランザクションが確認されると、トランザクションのハッシュを含む同様のターミナル出力が表示されます。
初のクロスチェーン送金
最後に、以下の方法を用いて、HyperEVMからBSCへqWHYPEトークンのクロスチェーン転送を行います。 DepositAndTransferTokens.s.sol スクリプト:
forge script script/DepositAndTransferTokens.s.sol:DepositAndTransferTokens --broadcast
このコマンドを実行すると、HyperEVM上でqWHYPEを鋳造するためにHYPEが預け入れられ、その後、qWHYPEトークンがBSCへ転送されます。転送の進行状況はターミナルに表示され、トランザクションが確認されるとトランザクションハッシュが表示されます。また、転送のCCIPメッセージIDも表示されます。このIDを使用すると、Chainlink CCIP Explorer上で転送のステータスを追跡できます。ターミナルには、以下のようにメッセージIDが表示されます:
- ターミナルの出力
- CCIP Explorer
- HyperEVM エクスプローラー
- BSC Explorer
CCIPメッセージIDが表示されたターミナルの出力
クロスチェーン転送のステータスを表示するCCIP Explorer
転送取引の詳細を表示するHyperEVM Explorer
受信した送金取引の詳細を表示するBSC Explorer
では、その qWHYPE BSC上でトークンを受領しました。MetaMaskウォレットを開き、BSCネットワークに切り替えて、 qWHYPE あなたのアカウントにあるアドレスを使用してトークンを deployments.json 鍵を含むファイル qWHYPE_bsc. トークンのインポートについてサポートが必要な場合は、MetaMaskのガイドに従ってください こちら. ウォレットの残高が 0.01 qWHYPE トークンになっているはずですので、クロスチェーン転送が成功したことが確認できます!
あらゆる方向への転送
その TransferTokens.s.sol このスクリプトを使用すると、HyperEVMとBSCの間でqWHYPEトークンを双方向に転送できます。転送の方向は、以下のいずれかを指定することで設定できます。 to-bsc または to-hyperevm スクリプトを実行する際の引数として指定します。たとえば、qWHYPEトークンをBSCからHyperEVMに転送するには、次のコマンドを実行します:
forge script script/TransferTokens.s.sol:TransferTokens --broadcast --sig 'run(string)' 'to-hyperevm'
出力結果は、最初のクロスチェーン転送時と同様で、トランザクションハッシュとCCIPメッセージIDが表示されます。このメッセージIDをChainlink CCIP Explorerに貼り付けると、逆方向の転送が表示されます:

結論
おめでとうございます!Chainlink CCIP を使用して Hyperliquid でトークンのブリッジを行う方法を無事に習得しました。独自の ERC-20 トークンをデプロイし、CCIP トークンプールを設定し、HyperEVM と BSC 間で qWHYPE トークンのクロスチェーン転送を実行しました。
今後の手順
クロスチェーンブリッジが正常に動作するようになったので、設定をさらに改善・カスタマイズすることができます。以下にいくつかのアイデアを紹介します:
- Hyperliquid Bridge UI:React や Vue.js などのフレームワークを使用して、ブリッジ用のユーザーフレンドリーなインターフェースを構築します。これにより、ユーザーはコマンドラインツールを使用することなく、ブリッジを簡単に操作できるようになります。
- レート制限: 不正利用を防止し、公平な利用を確保するために、トークンプールにレート制限を導入してください。レート制限の設定は、
ConfigurePools.s.solスクリプト。 - 追加のチェーンの実装:Chainlink CCIPがサポートする追加のチェーンに対応できるよう、ブリッジを拡張してください。このガイドに記載されている手順に従って、他のチェーン上でトークンプールをデプロイおよび設定することができます。CCIPディレクトリで、レーンおよびサポートされているチェーンを確認してください。
- その他のHIP-1資産のラップ化:HYPEの場合と同様の手順に従い、Hyperliquid上で他のHIP-1資産用のラップトークンを追加で作成・展開することができます。唯一の違いは、資産ごとにラップ用ERC-20コントラクトを作成する必要があるという点です。これにより、ユーザーはHyperEVMと他のチェーン間で、より幅広い資産をブリッジできるようになります。
その他の参考資料
- Hyperliquid ドキュメント
- Quicknode Hyperliquid ガイド
- Quicknode Hyperliquid ドキュメント
- 『ファウンドリー・ブック』
- 動画:Hyperliquid HyperEVMとは何か、そしてその始め方
行き詰まったり質問がある場合は、Discordまでお気軽にご連絡ください。X(@Quicknode)やTelegramの告知チャンネルをフォローして、最新情報をチェックしてください。
皆様からのフィードバックを心よりお待ちしております!❤️
このドキュメントについてご意見やご質問がございましたら、ぜひお知らせください。皆様からのご連絡を心よりお待ちしております!