Blocknative with Flashbotsで mempoolと戯れる #1
MEV(旧 Miner Extractable Value、現 Maximal Extractable Value)はEthereumなどのブロックチェーンで主にマイナーがトランザクションを任意に含めたり、除外したり、並べ替えたりすることを通じて得られる利益とされています。Flashbotsの登場でSearchersはトランザクションの入札を直接マイナーへ支払うことができるようになりました。
BlocknativeのmempoolエクスプローラによってSearchersは、オンチェーンとして確定する以前の状態をmempoolから確認することができるようになります。Flashbots Auctionと組み合わせることで、アービトラージなどのトランザクションをmempoolの情報と統合してMEV Relayersへ送出することができるようになりました。本記事ではまずBlocknativeのエクスプローラからmempoolを確認します。
次にBlocknative’s mempool APIやSDKを活用してアービトラージの機会を検出するようなスクリプトの作成を検討します。Blocknative’s mempool APIとflashbots private relayを利用したアービトラージのスマートコントラクトの例は以降の記事でリサーチおよび疑似コードの作成をすることとしたいと思います。※本記事はEthereumブロックチェーンやMEVに関する前提知識を必要とします
Disclaimer
This article is not either an investment advice or a recommendation or solicitation to buy or sell any investment and should not be used in the evaluation of the merits of making any investment decision. It should not be relied upon for accounting, legal or tax advice or investment recommendations. The contents reflected herein are subject to change without being updated. This article was written for educational and entertaining purpose only.
目次
- MEVとFlashbots
- Mempoolを見ることの意味
- Mempoolエクスプローラを見る
- Mempool SDKでアービトラージ
MEVとFlashbots
通常のEthereumのトランザクションプールでは、ユーザはトランザクションをブロックチェーンのネットワークにブロードキャストし、実行したいトランザクションに対して支払うガス価格を指定します。マイナーは受け取ったトランザクションを集め、ガス価格順などでオーダーを並び替え、トランザクション手数料を最大化しようとするブロックを作成します。このメカニズムはEnglish auctionとall-pay auctionの中間であると説明されており、3つの問題点があると説明されています。[1]
※Flashbots AlphaからFlashbots Auctionへ名前が変更されています。
- 通常のトランザクションプールのオープンな性質は、トランザクションのオーダリングの入札バトルを引き起こし、ネットワークの輻輳やガス価格の変動の原因となります。これは洗練されていないネットワーク参加者に不利益をもたらす可能性があります。
- all-pay auctionの性質から失敗したビッドはチェーン上でリバートされます。これは不必要なブロックスペースの消費を発生させ、実行リスクのため入札者が入札の価格を低くし、最終的には人為的なブロックスペースの不足とマイナーのリワードの減少につながります。
- ガス価格に依存しているため、入札者はブロックの最上位のオーダーに制限され、きめ細かい注文設定を実現できません。このことによって、入札に勝つ可能性を高めるためスパムなどの代替の戦略が行われ、デットウェイト損失がさらに増加します。
Flashbots Auctionは、上記のようなメカニズムではなく first-price sealed-bid auction を採用しています。ユーザはビッドに失敗した場合に手数料を支払う必要がなく、入札内容と取引注文の詳細をプライベートな通信チャネルで伝えることができます。このメカニズムによってマイナーのペイオフを最大化できると同時に、特定のMEVの価値に関する価格発見のための効率的な機会を提供することができるようになりました。[2]
Flashbots AuctionによってSearchersはトランザクションを通常のEthereumネットワークにブロードキャストすることなく、MEV-geth(PoSへ移行後ではMEV-boost)へ送出することで内容をピアトゥピアネットワークから見えなくすることができます。手数料をマイナーの coinbase
アドレスへ直接支払い、ガスの支払いを行わないように設定できるため、これによりトランザクションの成功を条件としてやり取りを行うことができるため、失敗した入札に対して支払う必要もなくなります。
Flashbots AuctionやFlashbotsのサービスの目的はMEVを民主化しオープンにすることでした。MEVは大規模なハッシュレートにアクセスできる一部のダークプールに限定されていたり、大口トレーダーと一部マイナー間の一方的なオフチェーンの取引を通じて、少数のプレーヤーに集中化されてます。MEVを民主化することで、パーミッションレス・分散性という特性を侵害せずにプレイヤーは低レベルな金融プリミティブに平等にアクセスできるようになります。
参考文献 [3]
Mempoolを見ることの意味
Flashbotsを利用することでMEVを活用したアービトラージと通常のDapps利用および送金のトランザクションは分離され、結果としてマイナー手数料は最適化されると同時にガス価格は安定してきます。アービトラージのトランザクションは通常のノードへ送出されず、プライベートネットワーク経由でマイナーの coinbase
アドレスへ直接届けられます。
ユーザとしては以下のようなケースでFlashbotsを利用する可能性があると紹介されています。
- アービトラージやリクイデーションボットなどの用途でブロックスペースへ早くまたリスクフリーなアクセスが必要となるようなケース(典型的なボットのユースケース)
- 送出するトランザクションにおいてフロントランニングに対する防衛が必要なケース(UniswapなどのDEXのアドバンスドなユーザ)
- Dappsにおけるアカウントアブストラクションやガスレストランザクション等の発展的なユースケース
FlashbotsのMediumのパブリケーションに、Flashbotsのインフラを使用したMEV抽出やアービトラージの実際のトランザクションが紹介されています。またFlashbotsを使用した高額な手数料のトランザクションはこのTwitter Botで情報収集できるのでフォローしておくと便利です。以下の例では101.112 ETHものトランザクション手数料をマイナーへ直接支払っています。
2021年の3月30日にUniswap V2に上場した$MARSHの流動性提供を検知して大量購入し、売り抜けることで利益を上げたトランザクションです。ボットで新規の流動性供給を監視および検知できるようにしていたものと考えられます。250 WETHで$MARSHを購入し、それらを売却することで莫大な利益を上げています。トランザクション手数料は0 Ethでマイナーへ直接101.112 ETHを送金しています。これが今現在最も高額なマイナーへの直接支払いのようです。
その他のMEVを活用したアービトラージ事例やサンドウィッチ攻撃およびサルモネラ菌コントラクトなどのトピックについてこちらに以前まとめています。[4]
Flashbots AuctionによってMEVへのアクセスができるようになるわけですが、依然としてアービトラージなどの裁定取引には情報の非対称性による一部のユーザの優位性が残っています。それがmempoolへのアクセスです。プロフィッタブルなアービトラージのトランザクションを成功させるには 1) トランザクションをより早く、もしくはノード近傍から送出、2) アービトラージの機会をいち早く検出、の両方もしくは片方を最適化していくことが基本となってきます。
mempool(gethではトランザクションプールの呼称)へのアクセスが可能となることで既にステートとして確定しているオンチェーンデータではなく、ペンディングトランザクションなどインザフライの情報をもとにアービトラージの機会を探ることができるようになります。よってアービトラージの機会を早く検出することができ、フロントランニングやバックランニングの成功確率がより高まります。
MEVによって利益を得たいSearchersにとってはmempoolへのアクセスが死活問題です。mempoolは各マイナーのインメモリに滞留しているものなので、マイナーおよび一部の特権的なユーザしか従来はアクセスすることができませんでした。BlocknativeはmempoolエクスプローラやAPI、SDK等を開発し一般のユーザが簡単にmempoolの情報へアクセスできるようなインフラを提供しています。[5]
Blocknativeの主なサービスの一覧です。
mempoolは各ノードのインメモリ内に存在する情報であるため、世界中のノードそれぞれが別の情報を持っています。ブロックとしてトランザクションが確定するまで、ノードの設定(ガス設定やmempoolのサイズ制限など)によってmempoolの内容はおのおの異なっている状態です。あるノードがピアへトランザクションを送出する際にもそれらのトランザクションは置きかえられたり、キャンセルされたりする可能性が存在します。
BlocknativeはEthereum、Binance、xDai、Bitcoinなどのノードのグローバル ネットワークを運用することで、新しいトランザクションを発生起点の近くで検出することができ、グローバルピアツーピアネットワーク全体での情報伝播を監視します。さらには様々なクライアントタイプ、複数の設定などクライアントノードの多様性を持たせることでグローバルなmempoolの条件として正確な視点を提供できるように努めているとのことです。[6] [7]
Mempoolエクスプローラを見る
Blocknative Mempool Explorerは数万から数十万あるといわれるmempoolのトランザクションに関するインサイトを提供することが可能です。またその3倍から5倍の数存在すると言われているスマートコントラクト間のやり取りとある内部トランザクション(Internal Transactions)もその対象に含まれます。
Mempoolエクスプローラは、Blocknativeのグローバルインフラによるリアルタイムなトランザクションデータフィードを提供します。特定のウォレットやスマートコントラクトアドレスをサブスクライブするだけでイベントをフィルターすることができ、トレードやDappsに必要なデータだけフィードすることが可能です。[8]
まずはmempoolエクスプローラをブラウザで見て、どのようなデータフィードが取得できるかおよびフィルターできるかを見てみましょう。Mempool Explorerへアクセスして、サインアップします。ログインするとサブスクライブの設定を行うことができる画面へ遷移します。
以下がmempoolエクスプローラのデフォルトのUIで、ネットワークはEtehereumメインネットに設定されています。Watch top DEXes for pending transactionsをクリックしてライブサンプルを見てみました。イベントは最大50個まで出て停止します。
最後の50個目に出力されたトランザクションを見てみます。ステータスはpendingでUniswap V3: Router 2のコントラクトの呼び出しであることが分かります。"2022-11-03T07:22:39.258Z"
がpending時点でのタイムスタンプ、Etherscan上でオンチェーンとなったトランザクションを見るとタイムスタンプは Nov-03-2022 07:22:47 AM + UTC
となっていることから、pending状態であったトランザクションが8秒後にはオンチェーンに取り込まれて記録されていることが読み取れます(Etherscanの記録時間)。
※出力の長いフィールドは内容を省略しています
{
"status": "pending",
"monitorId": "nethermind_1_a1_prod",
"monitorVersion": "0.117.1",
"pendingTimeStamp": "2022-11-03T07:22:39.258Z",
"pendingBlockNumber": 15887979,
"hash": "0x03d8f2f8023226bf0ed010b176eaec3347af230890483aacf97410256893245b",
"from": "0x4871de2F75464A6cf57463601b2F1F4e90dC2E6A",
"to": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"value": "0",
"gas": 266881,
"nonce": 148,
"blockHash": null,
"blockNumber": null,
"v": "0x1",
"r": "0xc76b98f7e5b63018606a911d925f5f78977fda2abb0bed5bdd7fa50b433573fd",
"s": "0xc31238e7dafafef4ae647a0d372241366c332ce48c98136188b8ca18314ae62",
"input": "0x<xxx>",
"type": 2,
"maxFeePerGas": "21004227538",
"maxFeePerGasGwei": 21,
"maxPriorityFeePerGas": "1500000000",
"maxPriorityFeePerGasGwei": 1.5,
"transactionIndex": null,
"asset": "",
"estimatedBlocksUntilConfirmed": 1,
"watchedAddress": "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",
"direction": "incoming",
"counterparty": "0x4871de2F75464A6cf57463601b2F1F4e90dC2E6A",
"serverVersion": "0.151.4",
"eventCode": "txPool",
"timeStamp": "2022-11-03T07:22:39.258Z",
"dispatchTimestamp": "2022-11-03T07:22:39.331Z",
"system": "ethereum",
"network": "main",
"contractCall": {
"contractType": "multicall",
"contractAddress": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"methodName": "multicall",
"params": {
"deadline": "1667461931",
"data": [
"0x<xxx>",
"0x<xxx>"
]
},
"subCalls": [
{
"data": {
"methodName": "swapExactTokensForTokens",
"params": {
"amountIn": "7917217719057997015383",
"amountOutMin": "255484197500943703",
"path": [
"0xe4815AE53B124e7263F08dcDBBB757d41Ed658c6",
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
"to": "0x0000000000000000000000000000000000000002"
}
},
"contractType": "Uniswap V3: Router 2"
},
{
"data": {
"methodName": "unwrapWETH9",
"params": {
"amountMinimum": "255484197500943703",
"recipient": "0x4871de2F75464A6cf57463601b2F1F4e90dC2E6A"
}
},
"contractType": "Uniswap V3: Router 2"
}
]
}
}
新規のサブスクリプションの作成は対象となるウォレットやコントラクトアドレスを入力するだけです。Subscription Filtersで特定のフィールドの条件によるフィルタを、Subscription Selectsを使用してフィルターしたイベントの特定のフィールドのみを表示できます。またMempoolエクスプローラはカスタムコントラクトABIをサポートしているため、トランザクション入力をオンザフライでデコードおよびフィルタリングすることができるように設定できます。
以下の画像の例はUniswap Auto Routerのコントラクトアドレスに対するイベントに対して、statusがpendingのイベントのみをフィルタしstatus、timestamp、hash、contractCall.methodName、contractCall.contractType、contractCall.subCalls.data.methodNameのみをストリームに表示するように設定しています。SaveをクリックするとDefault API Keyを使用してサブスクリプションが保存されます。
mempoolエクスプローラのストリームはwebhookを使用することで、任意のフロントエンドやバックエンドのインフラへ送出することができます。シンプルな用途としてSlackチャンネルやDiscordサーバ、またTelegramへ情報を連携することができます。簡単なモニタリング用途であればこの機能で十分でしょう。
カスタムABIの統合方法やwebhookの使用方法はYouTubeで説明されています。アカウントページのDefault API Keyや追加した別のAPI Keyにwebhookの設定を行うだけでフィルタしたストリームをSlackチャンネルなどへ流すことができます。Mempool APIを使用するとwebhookの操作・設定をAPI経由で実行可能です。[9]
Mempool Explorer [#1] — Walk Through & Quickstart (Updated MPEX UI)
Mempool Explorer [#2] — How To Work With Custom ABIs
Mempool Explorer [#3] — Composability Via Webhooks
Mempool SDKでアービトラージ
Mempool Explorerでデータフィードを定義してリアルタイムにmempoolの情報を見ることができることが分かりました。またwebhookを利用してデータフィードを受け取ることができることが分かりました。本章では、Mempoolエクスプローラで設定したAPI KeyをエクスポートしてMempool SDKで使用してみたいと思います。
具体的にはmempoolのデータをフィルターし、ペンディングトランザクションの情報を統合することでFlashbotsを使用したアービトラージ戦略を実行できそうか検討します。まずはMempoolエクスプローラのAccountからAdd new API keyをクリックして新規のAPI Keyを作成します。次にこのAPI Keyにサブスクリプションを設定します。
mempoolで監視するトランザクションはUniswapなどAMMの流動性プールのバランスの変化としましょう。ある流動性プールAにおいてトークンAからトークンBのスワップが発生するとき、他のDEXの流動性プールB(同じトークンペア)ではこの価格影響を受けていないと仮定します。このスワップが次のブロックで取り込まれるとき、トークンAは流動性プールAでは安くなるためトークンAを流動性プールBでトークンBへとスワップして、流動性プールAで交換したトークンBをトークンAへとスワップする戦略が成り立ち得ます。
mempoolである流動性プールAにおけるトークンAからトークンBへのスワップのトランザクションを検知することができれば、次のブロックでこのトランザクションが取り込まれるときと同時に上記のようなプロフィッタブルなアービトラージのトランザクションを同じブロック高でMEV RelayersへFlashbots Bundleとして送出できます。※ここでは流動性プールでのスリッページや手数料は考慮していません、よって現実的に成り立つような戦略とは限らないことをご了承ください
次に具体的にどのスマートコントラクトをサブスクライブして、どのようなデータフィードをモニタリングするかを検討しましょう。まずUniswap Auto Router、SushiSwap Routerのスマートコントラクトをサブスクライブして、Global Filtersでpending-simulationを設定します。
EthereumメインネットのUniswap Auto RouterやSushiSwap RouterではSimulated Eventsがサポートされます。pending-simulationをフィルターすることで対象のスマートコントラクトと内部トランザクションによる現時点のブロックハイトへの効果をシミュ―レーションした結果を受け取ることができるようになります。
Simulated Eventsが検知できるBlocknative Simulation Platformについて説明を追加します。Simulation Platformはサブスクライブされているスマートコントラクトによる内部トランザクションの影響を可視化します。Blocknativeによって最適化されたEthereumノードによって内部トランザクションはトレースされ、以下の2つのルールによってシミュ―レーションの適格性が評価されます。[10] [11]
- トランザクションがスマートコントラクトへ送信され、内部トランザクションの発生する可能性があるか
- トランザクションに市場性があるかどうか(市場性のあるトランザクションは、次のブロックに入るのに競争力を持つガス価格を持つかどうかで評価されます)
上記の条件が満たされた場合に、Simulation Platformは保留中のシミュレーションされたペイロードをデータフィードに配信します。トランザクションがシミュレートされたブロックの高さは、pendingBlockNumberとしてペイロードに表示されます。
pending-simulationのステータスのトランザクションによって、サブスクライブしているペンディングトランザクションのコントラクトの呼び出しによって発生する内部トランザクションに関するペイロードがデータフィードに出力されます。
またサブスクライブしているアドレスが内部トランザクションの一部ではあるものの、ベースペイロードの from
もしくは to
のアドレスに一致しない場合にも当該ペイロードは internalTransactions
の構造を含むことができます。
internalTransactions
およびnetBalanceChanges
のペイロードがpending-simulationのステータスのトランザクションでは出力されますが、今回注目したいのは netBalanceChanges
のペイロードです。これは関連する内部トランザクションによるバランスの変化を補足することができます。
Uniswap Auto RouterやSushiSwap Routerに対するコントラクトコールによる内部トランザクションによって流動性プールのバランスも変化します。ペンディングトランザクションに対する netBalanceChanges
ペイロードを監視することで現時点のブロック高から、mempoolに入っているスワップによる流動性プールのバランスの変化の予測をモニタリングできます。つまり次ブロックにおいて取り込まれる可能性があり、そのことによって発生するであろう流動性プールのバランス変化をペンディングブロック高において知ることができます。※ただしBlocknativeによって説明されるとおりシミュレーションは”speculative execution”、つまり推測的な実行です。トランザクションはオンチェーン上で初めて確定します
"netBalanceChanges": Object
netBalanceChangesのオブジェクトは内部トランザクションに関連する各アドレスに対するエントリの配列で成り立っています。以下のようなデータ構造です。具体的なpending-simulationの例を以下で見てみましょう。
"netBalanceChanges": [
{
"address": String,
"balanceChanges": [
{
"delta": String,
"asset": {
"contractAddress": String
"symbol": String,
"type": String
},
"breakdown": [
{
"amount": String,
"counterparty": String
},
...
]
}
]
},
...
]
https://gist.github.com/yuyasugano/867d19f995c5fc8cb16d02106676c18d
上記のgistは以下のUniswap V3 Routerを使用したHEXからWETHへのスワップがpending-simulationとして検知されたJSONデータです。HEXというトークン 44145.92889310を0.973422865283299445 WETHへと交換しています。各コントラクト間の内部トランザクションは internalTransactions
のペイロードにシミュレーションされています。 netBalanceChanges
の配列は順番にHEX/WETHの流動性プール、Uniswap V3 Router、トランザクションの送信者、そしてWETHのコントラクトアドレスのバランス変化を表しています。
ここで注目したいのはHEX/WETHの流動性プールのバランス変化です。Uniswap V3 Router上でHEXからWETHへスワップされるとき、HEXは相対的にUniswap上で安くなるため、HEXをSushiSwapでWETHへスワップしUniswapでWETHからHEXへとスワップするトランザクションを次ブロック向けに送出することでHEXのアービトラージを狙うことができます。これはシミュレーション結果に基づくもので他のアクターよりも早い段階でこのアービトラージの機会に気が付くことができるはずです。
"netBalanceChanges": [
{
"address": "0x9e0905249ceefffb9605e034b534544684a58be6",
"balanceChanges": [
{
"delta": "-973422865283299445",
"asset": {
"type": "erc20",
"symbol": "WETH",
"contractAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"breakdown": [
{
"counterparty": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"amount": "-973422865283299445"
}
]
},
{
"delta": "4414592889310",
"asset": {
"type": "erc20",
"symbol": "HEX",
"contractAddress": "0x2b591e99afe9f32eaa6214f7b7629768c40eeb39"
},
"breakdown": [
{
"counterparty": "0x4065149108A615930114Bb511818fc0909AA9269",
"amount": "4414592889310"
}
]
}
]
},
{
"address": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"balanceChanges": [
{
"delta": "973422865283299445",
"asset": {
"type": "erc20",
"symbol": "WETH",
"contractAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"breakdown": [
{
"counterparty": "0x9e0905249ceefffb9605e034b534544684a58be6",
"amount": "973422865283299445"
}
]
}
]
},
{
"address": "0x4065149108A615930114Bb511818fc0909AA9269",
"balanceChanges": [
{
"delta": "-4414592889310",
"asset": {
"type": "erc20",
"symbol": "HEX",
"contractAddress": "0x2b591e99afe9f32eaa6214f7b7629768c40eeb39"
},
"breakdown": [
{
"counterparty": "0x9e0905249CeEFfFB9605E034b534544684A58BE6",
"amount": "-4414592889310"
}
]
},
{
"delta": "973422865283299445",
"asset": {
"type": "ether",
"symbol": "ETH"
},
"breakdown": [
{
"counterparty": "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",
"amount": "973422865283299445"
}
]
}
]
},
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"balanceChanges": [
{
"delta": "-973422865283299445",
"asset": {
"type": "ether",
"symbol": "ETH"
},
"breakdown": [
{
"counterparty": "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",
"amount": "-973422865283299445"
}
]
}
]
}
]
netBalanceChanges
ペイロードにおける流動性プールのバランス変化の条件は以下のようにまとめることができると思います。簡単に表現すると netBalanceChanges
の各要素の中でどれが流動性プールのものであるかを判別できれば良いということになるでしょう。
address
がtransaction.from
やtransaction.to
と一致しないnetBalanceChanges.balanceChanges.length
が2つであるnetBalanceChanges.balanceChanges
の2つの要素のasset.contractAddress
が存在する(またcontractAddress
は実際のERC20のスマートコントラクトのアドレスである)
さらに今回モニタリングしているUniswap Auto Router、SushiSwap Routerのいずれかにおいて流動性プールのバランス変動を検知した際に、対向のAMMにおいても対象のトークンペアの流動性プールが存在するかを判別しなければなりません。
前述のmempoolエクスプローラで見たUniswap V3 Router上のHEXとWETHのスワップの場合、SushiSwap Routerを利用してアービトラージをしようとするとSushiSwapのAMM上にもHEX/WETHの流動性プールがあらかじめ存在していることが前提条件となります。
前置きが長くなりましたがこれからnode.jsのSDKを使用して上記の条件を満たすpending-simulationのステータスのトランザクションを抽出するスクリプトを書いていきます。mempoolエクスプローラでサブスクリプション設定ファイルおよびSDK設定ファイルをエクスポートして、SDKからイニシャライズできます。SDKのイニシャライズ方法は以下を参考にしました。
手順
- サブスクリプションの設定をmempoolエクスプローラで実施
- サブスクリプション設定ファイル(configuration.json)およびSDK設定ファイル(sdk-setup.js)をエクスポート
- Mempool SDKとエクスポートしたファイルを使用してコーディング
まずMempoolエクスプローラからUniswap Auto RouterとSushiSwap Routerをサブスクライブして設定を新規に作成したAPI Keyに保存します。またグローバルフィルターにpending-simulationのステータスを追加しました。ここではBlocknative-MEVという名前のAPI Keyにサブスクリプションを保存しています。
mempoolエクスプローラの縦の3点ボタンを押下して、Export Configurationをクリックすると configuration.json
sdk-setup.js
をダウンロードすることができます。エクスポートしたファイルをMempool SDKで設定ファイルとして使用することで、簡単にフィルターしたイベントを取得するスクリプトを記述できます。
configuration.json
sdk-setup.js
をMempool SDKを使用するプロジェクト内で使用します。作成したスクリプト index.js
はgithubへリポジトリとして内容をまとめました。実行するとコンソール上に以下のような結果が表示されます。USDC、USDTやETH/WETHなどの流動性ペアのスワップの結果と対向のAMMに存在する流動性プールのアドレスが表示されます。
https://github.com/yuyasugano/blocknative-mev [13]
$ node index.js
Transaction pending block at 15932172: counter party is 0xcc444e2Cf1a68255A6001fe0953a42A3c5361168
Index: 0, Address: 0xcc444e2Cf1a68255A6001fe0953a42A3c5361168
Index: 1, Address: 0xaf119546a2391F0D2d3deCb5eda6D54b75367380
Token USDC: -693197670, Token WETH: 573722685245977209
Liquidity Pool exists at 0x397FF1542f962076d0BFE58eA045FfA2d347ACa0
Transaction pending block at 15932172: counter party is 0x411693000cb076778097fE3A420e4B8C41FeBeDa
Index: 0, Address: 0x11b815efb8f581194ae79006d24e0d814b7697f6
Transaction pending block at 15932172: counter party is 0x395A74BB9d0Cd4DD4A7208dD5d4Eb8E9Ca92E75e
Index: 0, Address: 0x395A74BB9d0Cd4DD4A7208dD5d4Eb8E9Ca92E75e
Index: 1, Address: 0x7610301d5d6A56EdBDC353cF65fe6C30Ea091F00
Token USDT: -1210658042, Token ETH: 1000000000000000000
Liquidity Pool exists at 0x06da0fd433C1A5d7a4faa01111c044910A184553
...
Transaction pending block at 15932228: counter party is 0x8e36ba811cdd78f900022C0Fe195aa5278DDDFc0
Index: 0, Address: 0x9a772018fbd77fcd2d25657e5c547baff3fd7d16
Index: 1, Address: 0x8e36ba811cdd78f900022C0Fe195aa5278DDDFc0
Index: 2, Address: 0x7858e59e0c01ea06df3af3d20ac7b0003275d4bf
Token USDT: -988056836, Token USDC: 987705063
Liquidity Pool exists at 0xD86A120a06255Df8D4e2248aB04d4267E23aDfaA
bitFlyer Advent Calendar 2022の記事 #1 として、今回はここまでとします。目的としていたBlocknative’s mempool APIやSDKを活用してアービトラージの機会を検出するスクリプトを作成できました。記事が長くなったため flashbots private relayを利用したアービトラージのスマートコントラクトへの応用は次の記事でリサーチおよび疑似コードの作成として発行です。次はBlocknativeのFlashbotsに関する記事を参考にします。[14]
おわり
本記事ではMEVとFlashbotsについておさらいした後に、mempoolへのアクセスにアービトラージの発見の優位性が残っていること、アービトラージの機会を早く捉えるためにmempoolの情報、またBlocknativeのpending-simulationのトランザクション情報などが有益であることを確認しました。また実際にpending-simulationのステータスのトランザクションから、アービトラージの機会と考えられるような流動性プールのバランスの変化をオンチェーン確定に先んじて取得するスクリプトを作成しました。
FlashbotsによってMEVが民主化されたように、多くの人がBlocknativeのインフラを使用し始めるにつれて、Blocknativeを使用するボット内での競争・競合が激化してくる点に注意してください。すでにpending-simulationのトランザクションを見てアービトラージを行う単純なボットは賞味期限切れと見てよいでしょう。Blocknativeを利用してプロフィットを生み出すようなアービトラージを行うには現段階からもう一工夫必要かと思われます。
本記事が少しでも暗黒森林の探索のお役に立ちましたら幸いです。
References
- [1] Flashbots Alpha ~Flashbots Bundleの作り方編~
- [2] Flashbots Auction — How does it work?
- [3] Ethereumの暗黒森林とMEVそしてFlashbots
- [4] Flashbots Alpha ~Flashbots Arbitrageサンプルの手引き~
- [5] Blocknative — Blockchain events before they happen
- [6] What is the Mempool? — Your intro to In-Flight Transactions
- [7] 8 Lessons to Help You Master the Mempool
- [8] Mempool Explorer
- [9] Mempool API
- [10] Understanding Ethereum Transaction Simulation — And Why It Matters
- [11] Introducing Simulation Platform: A Net-New Capability for the Ethereum Ecosystem
- [12] Mempool SDK — Initialize the Library
- [13] yuyasugano/blocknative-mev
- [14] Blocknative — How to Use Blocknative with Flashbots