Fusion モードを説明するシリーズの 3 番目の記事では、スワップ解決のオンチェーン コンポーネントに焦点を当てています。
このシリーズの前回の 2 つの記事では、それぞれリゾルバの概念とスワップ解決プロセスのオフチェーン コンポーネントについて説明しました。
中断したところから始めましょう。スワップ解決プロセスでは、リゾルバのバックエンドが、特定のブロックで 1inch リレイ サービスから受信した Fusion 注文を、スワップされた資産の一定量をユーザーに返すことで満たすことを「決定」した段階にあります。次に、スワップ解決プロセスのオンチェーン部分について説明します。ただし、まず、このプロセスの参加者について説明します。
Fusion スワップ実行のオンチェーン部分には、次のブロックチェーン エンティティ間の非常に複雑な相互作用が含まれます。

非常に重要なお知らせ: 場合によっては (常にではありませんが)、リゾルバーは 1 つのバッチで最大 32 個のトークンをフィルします。通常、リゾルバーのワーカー コントラクトには複数のトークン バランスがあり、バックエンドはリレーヤーが提供する「ストリーム」から複数の注文を受け取り、一連のフィルを行うことができます。
次のシナリオを見ていきましょう。
リゾルバーは、リレーヤーから潜在的に利益の出る注文を 3 つ選択して実行します。
100 DAI、最低0.6 WETH
少なくとも100 DAIで0.6 WETH
少なくとも36UNIに対して0.01WBTC
リゾルバのビジネス目標は、ユーザーが少なくとも期待した金額を得られる方法で、3 つのスワップすべてを実行することです。リゾルバの可能な収益戦略は省略し、計算を簡略化して、全体的な考え方を理解できるようにします。
ここで、バックエンドは選択された注文に関する情報をワーカー コントラクトに提供します。次に何が起こるでしょうか?
注意: このチャートは、スワップ解決のオフチェーン コンポーネントに特化した記事のチャートの続きです。ただし、理解を簡単にするために、ステップ 1 から始めます。

ステップ1
ワーカー コントラクト (またはウォレット) は、1inch 決済コントラクトの settleOrders() メソッドを呼び出し、軽量の圧縮バイト形式で注文情報を配信します。calldata および tokensAndAmounts 引数は、この情報を保存するために使用されます。
ここで、いくつか興味深い詳細に気づくかもしれません:
rateBump は見積もり側から提供され、実質的にリターンを決定します。これは、現在のオークション金額と最小オークション金額のパーセンテージ差です。たとえば、rateBump 値が 4_000_000 で、auctionEndAmount (最小リターン) が 500 の場合、現在のオークションの落札金額は 700 になります。
totalFee は、すべてのリゾルバが 1inch Foundation に支払う必要がある料金です (重要: 現在この機能は使用されていません。リゾルバは 1inch Foundation に料金を支払いません)。
limitOrderProtocol は、それぞれの Solidity インターフェースを介して決済コントラクトで宣言されるプロトコルのインスタンスです。決済コントラクトからこのコントラクトを呼び出すために使用されます。

ステップ2
決済コントラクトは、指値注文コントラクトの fillOrderTo() メソッドを呼び出し、リストから 3 つの注文のうちの 1 つのデータ (たとえば、少なくとも 0.6 WETH の 100 DAI) を配信します。
インタラクション - これには、後で実行する必要がある一括注文がさらに 2 つあるという情報が含まれます。
支払う金額または受け取る金額 - 文字通り、支払う金額または受け取る金額。これらの金額のうち、ゼロ以外にできるのは 1 つだけです。makingAmount を設定すると、リゾルバーとして受け取りたい金額を指定します。または、takingAmount を設定すると、リゾルバーとして売りたい金額を決定します。1 つは別の金額に基づいて計算されます。
ターゲット - ソース トークンを受信するワーカー コントラクトのアドレス。

ステップ3〜4
指値注文コントラクトは、ERC20 Solidity インターフェースを使用して、ソース トークン コントラクトを呼び出して、ユーザーからリゾルバーのワーカー コントラクトにスワップ金額を転送します。
人間が判読しにくいアセンブリパーツが calldata を形成し、トークン コントラクトを呼び出します。コントラクトのアセンブリパーツは、ガス効率と複雑なデータの配信のために作成されます。

ステップ5〜6
指値注文コントラクトは、fillOrderInteraction() というメソッドを使用して決済コントラクトにコールバックし、バッチ内の追加注文に関する情報 (以前にインタラクションで受信した情報) を含む interactiveData を送信します。決済側では、コードが interactiveData をデコードして、インタラクションに変換します。
バッチにそれ以上の注文が含まれていない場合 (以下のシナリオ 1)、インタラクションを終了し、リゾルバのワーカー コントラクトを呼び出して注文を解決するように「指示」します。これは、ワーカー コントラクトが IResolver というインターフェイスをインポートするため可能になります。Solidity では、コントラクト間のインタラクションは通常この方法で行われます。ワーカーが行う処理については、以下の手順 16 ~ 17 で説明します。
バッチ内に他の注文が残っている場合、決済コントラクトは指値注文コントラクトを再度呼び出します。2 つのコントラクトは、すべての注文が決済され、すべての資金がユーザーのアカウントから回収されるまで (この例では 100 DAI、0.6 WETH、0.01 WBTC)、データを交換し続けます。

ステップ7
もうすぐ終わりです。ワーカー リゾルバ コントラクトは、1inch 決済および指値注文コントラクトを通じてユーザーからすべての資金を受け取りました。次は、実際に注文を解決するときです。
注文のプロパティは次のとおりです。
注文1: 100 DAI、少なくとも0.6 WETH
注文2: 少なくとも100 DAIで0.6 WETH
注文3: 少なくとも36UNIに対して0.01 WBTC
追加のアクションなしで、注文 1 と注文 2 を文字通り一致させることができるようです。したがって、注文 2 を送信したユーザーから収集した 0.6 WETH を注文 1 を送信したユーザーに安全に送信し、その逆も行います。したがって、3 つの注文のうち 2 つは、ユーザー自身の資金を使用して解決されました。
最後に残った注文は、0.01 WBTC を 36 UNI にスワップするものです。ワーカー コントラクトの残高には UNI がありません。そのため、ワーカー コントラクトは、従来のスワップでユーザーが行うのと同じ方法で、1 インチ アグリゲーション ルーター コントラクトを呼び出します。リゾルバのバックエンドは、アグリゲーション API を呼び出して最適なルートを取得し、それをワーカーに渡して実行することができます。ルーターはこのスワップを実行し、36 UNI をリゾルバに渡します。
この簡略化された例では、リゾルバーは何も稼いでおらず、契約間でデータを転送するためにガスに資金を費やしました。実際には、前述のように、リゾルバーのバックエンドはすべての費用を考慮し、取引がリゾルバーにとって利益があり、クォーターサービスによって提供されるフレームワーク内にとどまっていることを確認します。また、リゾルバーは、スワップがユーザーにとって最大限に利益になるように努めます。
ステップ8~11
さて、ワーカー リゾルバが宛先トークンを取得したら、コールバックに応答して、それらを決済コントラクトに転送する必要があります。しかし、待ってください...なぜトークンをユーザーに直接送信できないのでしょうか?
いいえ、アーキテクチャの実装方法によりできません。このフローのステップ 5 は、決済コントラクトから指値注文コントラクトに呼び出される fillOrderTo() メソッドへのコールバックであることを覚えておいてください。つまり、関数はまだ実行中です。
呼び出し元は決済コントラクトであるため、この構成では注文の受取人と見なされます。したがって、このインスタンスはリゾルバからの応答と転送されたトークンを受信することになっています。次に、指値注文コントラクトに承認を提供し、次に指値注文コントラクトが宛先トークンコントラクトへの transferFrom() を呼び出し、スワップ金額が最終的にユーザーのウォレットに入金されます。これで完了です。
実際のEtherscanの例
最後の演習として、Fusion スワップの実際のケースを確認しましょう。Seawise リゾルバによって解決された 1INCH から DAI へのスワップと、その ERC20 トークン転送です。最適なエクスペリエンスを得るには、下の画像と上の図を相互参照し、手順を一致させる必要があります。

ステップ 4 では、指値注文コントラクトは 1INCH トークン コントラクトの transferFrom() を呼び出して、ソース トークンをメーカー アドレス (0x90…9044) からリゾルバー アドレスに転送します。
ステップ 5 と 6 は ERC20 トークンの転送を伴わないため、このリストには反映されていません。
ステップ 7 では、リゾルバーとしての Seawise が流動性ソースとして Uniswap プール内の 1INCH を DAI にスワップします。
ステップ 8 で、Seawise は DAI を 1 インチ決済契約に転送します。
ステップ 9 と 10 も、リゾルバと 1inch 契約間の内部コールバック応答であるため、ここではスキップされます。
最後に、ステップ 11 で、1inch 決済契約は宛先トークンをメーカーに転送します。
このトランザクションを Etherscan で自由に調べてください:
https://etherscan.io/tx/0x55e621337837f4f69f0c398ad5e9072a24811bbfd8cb2b208d621b940c9689b5
