今後、分散型取引所(DEX)の発展は必要不可欠でありさまざまなDEXに関するプロジェクトが立ち上がっています。
DEXにおいてベースとなる課題はやはりブロックチェーン自体のスケーリングがあげられますが、フロントランニングもよく問題提起されることが多くなっています。
そこで、今回は、DEXのプロトコルである0x protocolにおけるフロントランニングの概要と緩和策について解説していきます。
0xの基本的な仕組みを前提としていくのでこちらの記事も併せてご覧ください。
参考:分散型取引所(DEX)で高速かつ安価な取引を目指す「0xプロジェクト」とは
フロントランニングとは
DEXにおけるフロントランニングとは、攻撃対象のオーダーより高いgas priceを設定するなどして、攻撃者のオーダーを先回りして処理してしまうことで、相手により不利なレートでの取引を強制させることです。
例えば、アリスがトレーダーでボブがフロントランナーである以下のような状況を考えます。
- アリスが10ZRXを10KNCに交換するオーダーをDEXに送ります。(10ZRX→10KNC)つまり、このオーダーが処理されるとZRX:KNC=1:1のレートで処理されることになります。
- ボブはイーサリアムのpending transaction poolをウォッチしており、上記のオーダートランザクションを確認した後、より高いgas priceで同じオーダーを送ります。つまり、ボブも10ZRXを10KNCに交換するオーダー(10ZRX→10KNC)を出します。
- マイナーはより多くの手数料報酬を得るためにより高いgasのトランザクションを優先してブロックに取り込んでいきます。なので、フロントランニングしたボブのオーダーが先に通ってしまうことになります。
- 0xの場合、アリスの(本来のレートでの)オーダーは失敗しgasを消費します。
- ボブのオーダー処理により最適なレートがZRX:KNC=1:0.9に変動してしまいます。
- なので、アリスは10ZRXをKNC交換をするためにはこのより不利なレートでの取引を強いられてしまいます。(10ZRX→9KNC)
- 攻撃者ボブがフロントランニングして得た10KNCを他のユーザーの不利なレートでのオーダーに当てることで理論的に1KNCを得られてしまうことになります。
DEXにおける基本的なフロントランニングのプロセスは上記のようになります。
0xの場合、プロセス6以降、フロントランニングされた後にオーダーを再度出すかどうかはテイカーのアリス次第になります。(オーダー処理は失敗してもアリスはgasを支払わなければなりません。)
一方、Bancorのような価格が動的に計算されるDEXでは、十分に高いトークン量の場合、攻撃者ボブがこのフロントランニング攻撃で利益を得られ、アリスが不利なレートでのトレードを強制されてしまうことになります。
また、以上は、他のユーザーによるフロントランニングのプロセスですがフロントランナーがマイナーになるとさらに対処が難しくなります。
マイナーによるフロントランニング
イーサリアムネットワークにブロードキャストされたトランザクションはクライアントによる検証がされると、pending transaction poolに割り当てられます。
このpoolは次回以降のブロックに取り込むべきトランザクションのpoolであり、ブロックを生成するマイナーは自由にそのpending transaction poolから好きなトランザクションをピックアップしてブロックに含めることができます。
基本的に、マイナーは自身のgas fee報酬を最大化するためにgas priceの高いトランザクションからブロックに取り込んでいくことになるので、上記のプロセスではこのpending transaction poolをウォッチしておき、より高いgas priceを設定したオーダートランザクションを送信することでブロックチェーンの仕様上、先回りしてしまうことができるのです。
なので、このことを考えると、上記のプロセスでは攻撃者アリスは他のトレーダーを想定していましたが、アリスはマイナーにもなりえます。つまり、攻撃者自身がマイナーであればそのブロックに取り込むトランザクションの順番はgas priceに限らず自由なので、より高いgas priceを設定することなく確実に自身のフロントランニング・トランザクションを優先して処理することができてしまうのです。
このマイナーによるフロントランニングはより対策がしにくい問題となっています。例えば、トレーダーによるフロントランニングであれば、オーダーに一定のgas limitを定めておき、それ以上のgas priceは設定できないようにしておけば、ユーザーがそのgas limit最大限にgasを設定することで、攻撃者が回り込めないようにする、などの対処をすることができます。
しかし、マイナーによるフロントランニングでは上述したようにgas priceに関係なく自由にトランザクションの順序付けができてしまうのでこの方法では対処することができないのです。
結論から言うと、DEXにおけるフロントランニングに対して明確な対処法は考えられていません。しかし、いくつかの緩和策が提案されおり、ここでは0xで考えられているフロントランニングの緩和策について紹介していきます。
フロントランニングの緩和策
Airswapスタイル(P2P交渉)
0xのオーダーブックは基本的にオープンであり、どのオーダーに対しても任意のテイカーがfillすることができます。これにより、流動性プールがオープンであり他の取引所やdAppsが直接オーダーにアクセスすることができるようになっています。
このパブリックオープンなオーダーの性質がそもそものフロントランニングを引き起こす原因となっているのです。
なので、例えば、もしオーダーに特定のtakerAddressが定められていて、そのテイカーのみしかそのオーダーをfillすることができない、というようにしておけば他のユーザーはそのオーダーに対してフロントランニングすることができなくなります。
これがまさにAirswapのメカニズムであり、メイカーとテイカーのP2Pの交渉によりレートが決まりオーダーが生成されるので、他のユーザーがフロントランニングをする余地がありません。
なぜなら、オーダーにメイカーとテイカーのアドレスが定められた上で署名がされるので、その定められたテイカーのみしかオーダーをfillすることができないからです。(0xでもオプショナルにテイカーのアドレスを定めることができます)
しかし、欠点として以下のようなことが挙げられます。
- このような両者の事前交渉が必要なことがUX的なデメリット(少額の取引には向いていない)
- メイカーがオンラインでそれぞれのトレードの交渉に応じなければならない
- クローズドな流動性プールになってしまう
Commit – Revealスキーム
上記のP2P交渉スキームでは、クローズドな流動性プールができてしまうことが大きな問題でした。パブリックオープンなオーダーブックを保ちながら、フロントランニングに対処するひとつの方法としてCommit-Revealスキームがあげられます。
フロントランニングは誰でもfillするすることができるオーダーのトランザクションがpending transaction poolにあり、それを攻撃者のフロントランナーが先回りしてfillしてしまうことにより起こります。
これに対処するために、テイカーは2ステップのトランザクション送信を行い、最初のCommitトランザクションでhash(secret, hash(order))を送ります。secretはテイカー任意の値であり、commitしたテイカーのみがrevealできるようにする値です。また、orderはハッシュ化されているので外部からはどのorderに対してcommitしているのかは分かりません。
このcommitトランザクションがブロックに取り込まれてから、テイカーは次にrevealトランザクションでsecretと実際のorderを送ることで取引の処理が行われます。
このように実際のオーダー処理の前にcommitフェーズを組み込むことで、実際にオーダー処理を行うrevealフェーズのトランザクションをpending transaction poolでウォッチしていても、commitしていないフロントランナーの攻撃を防ぐことができます。
具体的な手順をまとめると以下のようになります。
- テイカーはオーダーブックからfillしたいオーダーについてのhash(secret, hash(order))とsecurity depositを乗せてトランザクションを送信します。デポジットは一定の時間内にrevealするとテイカーに返ってくるので、revealするインセンティブを与えていることになります。
- このcommitトランザクションは0xプロトコルのCommit Revealスマートコントラクトに送信され、記録されることになります。
- commitトランザクションがブロックに含まれたことを確認したら、テイカーは実際のorderを明らかにしcommit時のsecretとともにrevealトランザクションを送信します。外部ユーザーはpending trasanction poolをウォッチしrevealトランザクションから特定のオーダーを確認することができますが、そのオーダーに対してcommitしていないのでフロントランニングすることはできません。
- Commit Revealコントラクトがrevealトランザクションを送り、secretが一致していたら実際のExchangeコントラクトにオーダーが送られ実際の取引が実行されることになります。
ただ、このようなcommit-revealスキームの欠点としては、偶然、オーダーが被って送信されてしまうことへの対処ができないことやより多くのgas feeが必要になることなどがあげられます。
特定のオーダーに対するフロントランニング攻撃はこのスキームで防ぐことができますが、偶然オーダー処理が被ってしまう現象は防ぐことができません。実際、commitとrevealのトランザクションに時間的なスパンがあるのでトランザクションのcollisionが起こる確率は高くなってしまいます。
テイカーはトランザクションを2回送信する必要があるのでより多くのgas feeを支払う必要がある上に、commitとrevealの時間差送信はUX的に悪い影響を与えます。
Trade Execution Coordinators(TEC)
0xにおいてフロントランニングを防ぐもうひとつの方法が、テイカーがオーダーをオンチェーンに送る前にTrade Execution Coordinators(TEC)を置くという方法です。
TECによって署名されたオーダーのみがオンチェーンで取引処理できることになります。逆に、TECの署名がついていない場合は、オンチェーン処理でfailすることになります。
このTECがフロントランニングやオーダーの被りはないか監視してくれるので、フロントランニングなどの問題は起こらなくなります。つまり、プロセスの流れとしてはテイカー→TEC→オンチェーンとなります。
ただ、当然問題となってくるのがこのTECがどのような主体が行うのかということです。例えば、以下のような主体が考えられます。
- それぞれのリレイヤー
- 信頼できるハードウェア
- random beaconによるトークンホルダーからのランダムな選出
以上のように、オーダーブックをパブリックオープンに保ちながらフロントランニングの問題を解決しようとする方法はいくつか考えられますが、それぞれにメリット・デメリットがあり決定的な解決策は得られていないのが現状です。
ただ、当然DEXの取引量が増えるにつれて、フロントランニングのような脆弱性は防ぐ必要がありますし、上述したようなオーダーの被り(collision)も増えてくるので何らかの対策が必要になってくるはずです。
- Front-running, Griefing and the Perils of Virtual Settlement (Part 1)
- Front-running, Griefing and the Perils of Virtual Settlement (Part 2)
- Implementing Ethereum trading front-runs on the Bancor exchange in Python
Gunosyブロックチェーンブログでも記事を書いているのでこちらもよろしくお願いします!