見出し画像

【完全保存版】ChainlinkのCCIPで異なるチェーンにメッセージを送ろう!


0 はじめに

今回は、「Chainlink」「CCIP」を使い、「Sepolia」チェーンから「Mumbai」チェーンに「Hello World」などのメッセージを送ってみます。

そのため、事前に「Sepolia」「Mumbai」テストトークンの取得をお願いします。

・Sepolia

・Mumbai

https://faucet.polygon.technology/

また、「CCIP」では、「LINK」テストトークンも必要なので、下から取得します。

下のように、ウォレットアドレスを貼り付けて、チェックをし、「Send me 20 testnet LINK」を選択します。

https://faucets.chain.link/sepolia

1 「Sepolia」から「Mumbai」にメッセージを送ろう

1 はじめに

本日は、ChainlinkCCIP(Cross-Chain Interoperability Protocol)のデモを行います。

「Sepolia」というチェーンから「Mumbai」というチェーンにメッセージを送付します。

https://docs.chain.link/ccip

そして、下の青い部分に囲まれたところが「CCIP」です。

私たちが意識しなくて良い部分ですが、その仕組みも詳しく公式に書かれております。

2 送り元コントラクトの作成について(Sepolia)

では、まずは送り元のコントラクトを作ってみましょう。

「Deploy the sender contract」「Open in Remix」を選択します。

https://docs.chain.link/ccip/getting-started

「Home」のファイルが開かれるため、「Sender.sol」のファイルを開きます。

下のように、コードが書かれているのが、確認できます。

しかし、エラーが出ているようです。

確認すると、コンパイラのバージョンが異なると出ています。

下の場所でコンパイルのバージョンを確認すると、確かに違うことが確認できます。

こちらを選択して、「0.8.19」のバージョンに変更します。

すると、エラーが消えました。

では、下から、コンパイルを行います。

次に、デプロイを行います。

「ENVIRONMENT」を下のように、「Injected Provider」に変更します。

「Sepolia」のチェーンIDである、「11155111」であることを確認し、下のボタンを押します。

ここで、「ルーター」「LINKトークン」のコントラクトアドレスを設定します。

「LINK」トークンは今回、ガス代として使用します。

なお、アドレスはこちらの部分に記載があります。

https://docs.chain.link/ccip/getting-started

その他、各チェーンでの「LINKトークン」コントラクトアドレス一覧はこちらにあります。

https://docs.chain.link/resources/link-token-contracts

ちなみに、「ルーター」は、下の、左下の部分を設定していました。

ちなみに、チェーンごとのCCIPの一覧は下のように確認することができます。

https://docs.chain.link/ccip/supported-networks#ethereum-sepolia

では、戻ります。

下のように、デプロイ完了しました。

次に、このコントラクトアドレス「LINK」トークンを送付するために、アドレスをコピーします。

メタマスクなどで、LINKトークンを送付します。

下は、「0.1LINK」ですが、もしかすると、足りないかもしれません。

3 送り先コントラクトの作成について(Mumbai)

次に、「Deploy the receiver contract」から「Open in Remix」を選択します。

「Receiver.sol」ファイルを選択すると、このように、コードが記載されています。

下のように、コンパイルを行います。

次に、デプロイを行います。

「mumbai」なので、メタマスクでチェーンを切り替えチェーンID「80001」になっていることを確認します。

こちらで、ルーターのコントラクトアドレスを設定します。

ちなみに、下の画像は「"0x7049…」のように、「"」が誤って入ってしまっていましたね。

最終的にこれはエラーになりました。「0x7049…」から入れるのが正しいです。

ちなみに、こちらが、今回設定するルーターコントラクトアドレスです。

https://docs.chain.link/ccip/getting-started

もしくは、こちらの一覧から取得しても良いと思います。

https://docs.chain.link/ccip/supported-networks#polygon-mumbai

なお、今回設定したのは、下の右側のルーターです。

ルーターを設定し、「mumbai」で下のようにデプロイしました。

4 メッセージを送ってみよう

では、こちらのコントラクトアドレスをコピーして、「Sender」コントラクトからメッセージを送ってみます。

では「Sepolia」「Sender」コントラクトに戻ります。

メタマスクで、チェーンを「Sepolia」へ変更するのを忘れずに設定してください。

「sendMessage」下の矢印を選択します。

ここから、「mumbai」「Receive」コントラクトにメッセージを送ります。

そのため、「mumbai」の宛先と「コントラクトアドレス」、「送るメッセージ」を入力します。

「destinationChainSelector」には、こちらの「Mumbai」「Chain Selector」を設定します。

また、「receive」には、先ほど「mumbai」で作ったコントラクトアドレスを貼り付けます。

できたら、「transact」を実行します。

https://docs.chain.link/ccip/supported-networks#polygon-mumbai

これで、下のように、トランザクションが実行できました。

5 エクスプローラーで確認しよう

確認すると、下のように、「transaction hash」があるので、こちらをコピーします。

こちらをCCIPエクスプローラーで確認します。

すると、下のように、「Waiting for finality」ファイナリティ待ちである旨が表示されます。

https://ccip.chain.link/msg/0x009f65e6960d57cd38526e0646649274da1632d1b384b7125f25b438fbd2f209

メタマスクで、チェーンを「mumbai」に変更し、「Receiver」コントラクト「getLastReceivedMessageDetails」を確認すると、今は下のようになります。

そして、しばらく待つと、エクスプローラーステータス「Success」になります。

私の場合は、10分以上かかりました。

https://ccip.chain.link/msg/0x009f65e6960d57cd38526e0646649274da1632d1b384b7125f25b438fbd2f209

6 メッセージを確認しよう

再び、関数を実行すると、下のように、メッセージが届いていることが確認できました。

2 コードを見てみよう(「Sender」コントラクト)

では、「Sender」コントラクトの中身を見てみましょう。

1 errorとイベント

まずは、下のように残高不足の際の「error」メッセージの送付が完了した時のイベントを書いています。

2 ルーターとトークンの初期化

次に、下のように、「IRouterClient」「LinkTokenInterface」のインターフェースを取得して、初期化をおこなっています。

これでルーターリンクトークンの初期化ができました。

3 sendMessage関数について

次に、こちらの「sendMessage」関数を見てみましょう。

4 メッセージの作成

まず、大まかに、下の部分で、メッセージを作成しています。

具体的には、メッセージとして、こちらの「Client」ライブラリにある、「EVM2AnyMessage」という構造体を作っています。

下のように、受取人(receiver)テキスト(data)手数料のトークン(feeToken)を設定しています。

それぞれ、abi.encodeでエンコードしています。

こちらの「tokenAmounts」も見てみましょう。

(ただ、今回はトークンを送るわけではないので、配列のサイズは「0」になっています。)

ちなみに、下のように、構成としては、トークンアドレス送る量になっていました。

つまり、異なるトークンを同時に送ることができそうだと思いました。(ここは細かく見ていないので、想像です。)

さらに下の部分では、追加の引数(extraArgs)を設定しています。

具体的には、「gasLimit」厳格にするか否か「EVMExtraArgsV1」で設定しています。

そちらに、「CCIP EVMExtraArgsV1」「keccak256」でハッシュ化した先頭の4バイト0x97a657c9)をくっつけて、エンコードしています。

5 手数料の取得

そして、「IRouterClient」インターフェースにある、「getFee」関数で手数料を取得しています。

こちらですね。

6 残高の確認

手数料を取得したので、残高上、問題ないかを確認しています。

「balanceOf」はこのように、「LinkTokenInterface」にあります。

7 手数料のapprove

次に、「approve」を使い、ルーターコントラクト手数料の送付権限を与えています。

これにより、コントラクトが持っている「LINK」トークンのうちの手数料ルーターコントラクトが送れるようになります。

ちなみに、「approve」はこちらです。

8 ccipSend関数について

そして、下の部分で、「ccipSend」を用いて、メッセージを送付し、「メッセージID」を取得しています。

具体的には、下のように、目的先のチェーンのセレクタメッセージを渡しています。

9 イベントの実行

それが終われば、「MessageSent」イベントを発火しています。

10 メッセージIDの取得

そして、最後に「メッセージID」を返しています。

3 コードを見てみよう(「Receiver」コントラクト)

次に、「Receiver」コントラクトを見てみましょう。

1 ルーターの設定

まずは、「constructor」でルーターを設定しています。

こちらになります。

2 _ccipReceive関数について

続いて、メッセージを受け取っているのが、こちらの「_ccipReceive」関数になります。

3 メッセージIDの取得

下のようにして、メッセージIDを取得しています。

なお、メッセージIDテキスト共に、受け取ったら上書きをしているようです。

具体的には、「Client」ライブラリ「Any2EVMMessage」の構造体の、こちらの「messageId」を取得しています。

4 テキストの取得

テキストも同様ですが、下のように、受け取ったものをstringにデコードして、格納しています。

メッセージIDと同様に、「Any2EVMMessage」構造体「data」を取得していました。

5 イベントの実行

そして、最後に受け取った旨の「MessageReceived」イベントを発火しています。

今回は以上です。

サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊