Symbolとイーサリアム間のクロスチェーンスワップ⚓︎
2つの当事者であるアリスとボブは、互いを信頼したり仲介者を使用したりすることなく、0.01 ETH(イーサリアム上)と1 XYM(Symbol上)を交換したいと考えています。
トークンは2つの異なるブロックチェーン上に存在するため、直接の転送は不可能です。 両方のトークンがSymbol上にある場合、この交換は アトミックスワップ のチュートリアルで示されているように、単一の アグリゲートトランザクション で行えます。 トークンは異なるチェーン上に存在するため、代わりに クロスチェーンスワップ を使用してスワップを調整する必要があります。
このチュートリアルでは、イーサリアム上の HTLC スマートコントラクトとSymbolのネイティブトランザクションを使用して、チェーン間でこのトークンスワップを実行する方法を示します。
両方のチェーンとやり取りするために、このチュートリアルではSymbol SDKとイーサリアムクライアントライブラリを使用します。
サポートされているチェーン
このチュートリアルではSymbolとイーサリアム間のスワップを実演していますが、Symbolのシークレットロックの仕組みは、HTLCをサポートする任意のブロックチェーンで機能します。
HTLCプロトコル、タイミングの制約、および制限の背景については、クロスチェーンスワップ の概念ページを参照してください。
前提条件⚓︎
始める前に、以下のことを確認してください。
- 開発環境をセットアップする。 開発環境のセットアップを参照してください。
- アリス用とボブ用に、2つのSymbol アカウント を作成する。 秘密鍵からのアカウントの作成を参照してください。
- ボブのアカウントで、シークレットロックのトランザクション手数料とロックされる金額を支払うためのXYMを取得する。 フォーセットからテストネット資金を取得するを参照してください。
- アリス用とボブ用に、2つのイーサリアムアカウントを作成する。
Foundry の
cast wallet newコマンド、またはMetaMaskなどの任意のイーサリアムウォレットを使用できます。 -
ガス代を支払うために両方のイーサリアムアカウントにSepoliaテストネットETHを用意し、HTLCに資金を供給するのに十分な額をアリスのアカウントに用意する。 Sepolia ETHは、Google Cloud faucet またはその他のイーサリアムテストネットフォーセットから取得できます。
-
使用する言語のイーサリアムライブラリをインストールする。
完全なコード⚓︎
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
イーサリアムHTLCコントラクト⚓︎
このチュートリアルでは、Symbolのシークレットロックの相手側として、イーサリアム上にデプロイされたサンプルのHTLCコントラクトを使用します。 コントラクトのソースは hashed-timelock-contract-ethereum リポジトリで入手できます。
教育目的のみ
本番環境で使用されるコントラクトは、タイミングが双方のセキュリティにとって重要であるため、ロックとコントラクトの有効期限を慎重に調整する必要があります。
コントラクトは3つの主要なメソッドを提供します。
newContract(address receiver, bytes32 hashlock, uint timelock): 受信者、ハッシュロック、およびタイムロックとしてのUnixタイムスタンプを使用して新しいHTLCを作成します。 SymbolのSecretLockTransactionV1に相当します。withdraw(bytes32 contractId, bytes proof): 受信者がハッシュロックと一致する証明を提供することで、資金を請求できるようにします。 SymbolのSecretProofTransactionV1に相当します。refund(bytes32 contractId): タイムロックの期限切れ後に資金を作成者に返金します。 Symbolでは、シークレットロックの期限が切れると自動的に返金が行われます。
コントラクトはSepoliaテストネットのアドレス 0xd58e030bd21c7788897aE5Ea845DaBA936e91D2B にデプロイされています。
コードの解説⚓︎
アリスとボブはそれぞれ両方のチェーンにアカウントを持つ必要があります。アリスはイーサリアムでETHをロックしてSymbolでXYMを請求し、一方ボブはSymbolでXYMをロックしてイーサリアムでETHを請求します。 アリスが開始者です。彼女はランダムな秘密(証明)を生成し、その暗号化ハッシュ(ハッシュロック)を計算し、それを条件としてイーサリアム上で自身のETHをロックします。 次に、ボブは同じハッシュロックを使用してSymbolで自身のXYMをロックします。これにより、証明を公開することでのみ、どちらの側のロックも解除できるようになります。
コードは以下の4つのステップを順番に実行します。
- アリスがイーサリアムでETHをロックする: イーサリアムのHTLCコントラクト内で、ハッシュロックによって保護されます。 この時点ではアリスだけが知っている、一致する証明によってのみロックを解除できます。
- ボブがSymbolでXYMをロックする: 同じハッシュロックを使用して、
SecretLockTransactionV1を作成します。 - アリスがSymbolでXYMを請求する:
SecretProofTransactionV1を通じて証明を公開することで、証明がSymbol上で誰でも見れる状態になります。 - ボブがイーサリアムでETHを請求する: Symbolからアリスの証明を読み取り、イーサリアムHTLCコントラクトの
withdrawを呼び出します。
実際には、アリスとボブはそれぞれ別のマシンで自分のパートを実行します。 このチュートリアルでは、分かりやすくするために両方の側を1つのスクリプトにまとめています。
コードでは、転送チュートリアルで説明されているのと同じパターンに従って、ネットワークの時刻や手数料を取得したり、トランザクションをアナウンスしたり、承認をポーリングしたりするためのヘルパー関数を定義しています。
このチュートリアルではステップ間でトランザクションの ファイナリティ を待ちませんが、本番環境への実装ではロールバック関連のリスクを防ぐために必ず待機する必要があります。
アカウントのセットアップ⚓︎
ALICE_XYM_PRIVATE_KEY と BOB_XYM_PRIVATE_KEY 環境変数はSymbolの鍵を設定し、 ALICE_ETH_PRIVATE_KEY と BOB_ETH_PRIVATE_KEY はイーサリアムの鍵を設定します。
便宜上、事前に資金が提供されたテストキーがデフォルトとして提供されていますが、これらは保守されておらず、資金が枯渇する可能性があります。
アリス:証明とハッシュロックの生成⚓︎
スワップの開始者として、アリスはランダムな32バイトの値を証明として生成します。 次に、ダブルSHA-256を使用してそれをハッシュ化し、ハッシュロックを生成します。
ダブルSHA-256アルゴリズムが選択されているのは、Symbol( hash_256 として)とイーサリアムのHTLCコントラクトの両方でサポートされているためです。
スワップを機能させるには、両方のチェーンで同じアルゴリズムを使用することが不可欠です。
その他のハッシュアルゴリズム
Symbolは、シークレットロック用に他のハッシュアルゴリズムもサポートしています。
利用可能なすべての値については、 LockHashAlgorithm を参照してください。
ステップ1. アリス:イーサリアムでETHをロックする⚓︎
アリスはイーサリアムHTLCコントラクトの newContract を呼び出し、ボブのために0.01 ETHをロックします。
- 受信者: ボブのイーサリアムアドレス。
- ハッシュロック: 証明の二重SHA-256ハッシュ。この時点ではアリスだけが証明を知っています。
- タイムロック: ボブがスワップを完了しなかった場合にアリスがETHを回収できるようになる、72時間後のUnixタイムスタンプ。
- 値: トランザクションとともに送信される0.01 ETH。
トランザクションレシートには、このHTLCを識別する contractId を含む LogHTLCNew イベントが含まれています。
ボブは後でETHを引き出すためにこの contractId が必要になります。
ステップ2. ボブ:Symbolでシークレットロックを作成する⚓︎
ボブはまず、 getContract を使用してイーサリアムHTLCコントラクトをクエリし、アリスが使用したハッシュロックを取得します。
ロック前の検証
ボブは自身の資金をロックする前に、コントラクトの詳細すべて(金額、受信者、タイムロック)を検証する必要があります。 このチュートリアルでは、簡単にするためにハッシュロックのみを読み取っています。
次に、ボブはSymbolで SecretLockTransactionV1 を作成し、同じハッシュロックを使用してアリスのために1 XYMをロックします。
- 受信者: アリスのSymbolアドレス。
- モザイク: 1 XYM(可分性6の
1_000000アトミック単位として表現)。 -
期間: 5760ブロック(30秒のブロック時間で約48時間)。
タイムロックの順序
この期間は、アリスの72時間のイーサリアムタイムロックより短くなければなりません。 そうしないと、アリスは自分のETHを返金しても、ボブのXYMを請求できる可能性があります。 2つの間のギャップは十分に大きくなければなりません。これは、アリスがぎりぎりで証明を公開した場合でも、ボブがイーサリアムで引き出すことを可能にする安全マージンです。 安全上の考慮事項を参照してください。
-
ハッシュロック(
secretフィールド): イーサリアムのコントラクトから取得したハッシュロック。 - ハッシュアルゴリズム (Hash algorithm):
hash_256(二重SHA-256)。もう一方のチェーンのHTLCで使用されているアルゴリズムと一致する必要があります。
ステップ3. アリス:SymbolでXYMを請求する⚓︎
ボブのシークレットロックが承認され、それが予想される金額、ハッシュロック、受信者、およびタイムロックと一致することをアリスが検証したら、彼女は証明を公開することによってSymbol上でロックされたXYMを請求します。
彼女は以下を使用して SecretProofTransactionV1 を作成します。
- 受信者: アリス自身のSymbolアドレス(ボブのシークレットロックで設定されたのと同じアドレス)。
- ハッシュロック(
secretフィールド): シークレットロックで使用されたのと同じハッシュロック。 - ハッシュアルゴリズム:
hash_256(シークレットロックと一致する必要があります)。 - 証明: アリスが生成した元のランダムなバイト。
このトランザクションがアナウンスされて承認されると、アリスはボブがロックしていた1 XYMを受け取り、証明はSymbolブロックチェーン上で誰でも見れる状態になります。 ボブ(または誰でも)はトランザクションデータからそれを読み取れます。
ステップ4. ボブ:イーサリアムでETHを引き出す⚓︎
ボブは、アリスからトランザクションハッシュをもらう必要なしに、オンチェーンでアリスの証明を発見します。
wait_for_secret_proof ヘルパーは、アリスのアドレスと type=16978 (SecretProofTransactionV1) でフィルタリングされた /transactions/confirmed GET エンドポイントをポーリングし、 transaction.secret をボブ自身のハッシュロックと照合して正しいエントリを選び出し、そこから transaction.proof を読み取ります。
ハッシュロックは各スワップに固有の32バイトのランダムなバイトであるため、過去にアリスが他のシークレット証明を投稿していたとしても、このスワップの証明トランザクションのみが一致します。
証明が取得されると、ボブはイーサリアムHTLCコントラクトの withdraw を2つの引数とともに呼び出します。
- コントラクトID: アリスがETHをロックしたときに発行された
LogHTLCNewイベントからのHTLC識別子。 - 証明: アリスがSymbol上で公開した証明。
引き出し期限
ボブは、アリスのイーサリアムタイムロックが期限切れになる前にこのステップを完了する必要があります。
期限が切れると、アリスはイーサリアムのコントラクトで refund を呼び出してETHを回収できてしまいます。
このイーサリアムトランザクションが承認されると、ボブはアリスの0.01 ETHを受け取り、スワップが完了します。 アリスはステップ3の終わりにすでにボブの1 XYMを受け取っています。
出力⚓︎
以下に示す出力は、プログラムの一般的な実行例に対応しています。
出力の重要なポイント:
- 行 9-10: アリスは証明とハッシュロックを生成します。証明は、アリスが公開するまで秘密にしておく必要があります。
- 行 15: イーサリアムでのアリスのETHロックが承認されます。
- 行 16: HTLCコントラクトIDは、アリスのイーサリアムロックを識別します。ボブはこれを使用してハッシュロックをクエリし、後で引き出します。
- 行 19: ボブは
getContractを使用して、イーサリアムコントラクトからハッシュロックを取得します。 - 行 50: ボブのSymbolシークレットロックが承認されます。これで、アリスはXYMを請求できるようになります。
- 行 70: アリスはシークレット証明トランザクションに証明を含めます。アナウンスされると、Symbol上で誰でも見れる状態(パブリック)になります。
- 行 80: アリスのシークレット証明が承認されます。アリスは1 XYMを受け取ります。
- 行 87: ボブは、Symbol上で承認されたアリスのトランザクションから公開された証明を取得し、それを使用してイーサリアムで引き出しを行います。
- 行 89: ボブのイーサリアムでの引き出しが承認されます。 ボブはアリスの0.01 ETHを受け取り、スワップが完了します。
出力に表示されたハッシュを使用して、各ネットワークのブロックエクスプローラーでトランザクションを確認できます。
- イーサリアム: ロックおよび引き出しトランザクション用の Sepolia Etherscan。
- Symbol: シークレットロックおよびシークレットプルーフトランザクション用の Symbol Testnet Explorer。
結論⚓︎
このチュートリアルでは、以下の方法を示しました。
| ステップ | 関連ドキュメント |
|---|---|
| 証明とハッシュロックの生成 | LockHashAlgorithm |
| イーサリアムでETHをロックする | イーサリアムHTLCコントラクト |
| Symbolでシークレットロックを作成する | SecretLockTransactionV1 |
| Symbolで証明を公開する | SecretProofTransactionV1 |
| イーサリアムでETHを引き出す | イーサリアムHTLCコントラクト |
次のステップ⚓︎
このチュートリアルは簡略化された例です。 本番環境でクロスチェーンスワップを使用する前に、テキストブックの安全上の考慮事項を確認してください。