DeFiでアビトラのコントラクト ~Aave Flash Loan & OrFeed~

Yuya Sugano
20 min readJul 17, 2020

--

Aave V2が既にローンチされています。FlashLoanに変更あり

dydxのFlashloansを活用して 1,271 ETH、約 $355,880 をぶち抜いたフラッシュローン事件以来、dydx/aave/UniswapなどフラッシュローンをサポートするDeFiプロトコルがさらに注目されているように感じます。2020年はDeFi元年と言われていますがEthereum上のDeFiエコシステムが成熟し、さらに新しいDeFiプロトコルや上のレイヤーのアプリケーションが拡充してくる時期でしょう。前回の記事では2/15日のdydxフラッシュローン事件の振り返りと、aaveのフラッシュローン機能をRopstenネットワークでテストしてみました。テストネットのレンディングプールに流動性がなかったために、4000 ETH借りてみることはできなかったのですが、10 ETHをシングルトランザクションで借りて手数料とともに返却できることを確認しました。今回はフラッシュローンの実例を参考にしつつ、フラッシュローンを使ったアビトラのコントラクトを作成してみます。

Photo by Scott Webb from Pexels

目次です。フラッシュローンとは、は前回からの再掲です。

  • フラッシュローンとは
  • フラッシュローンのアビトラの例
  • OrFeedのUIでアビトラやってみる
  • フラッシュローンでアビトラのコード

フラッシュローンとは

通常の金融世界のローンとはお金などの貸し付けのことであり、ユーザは担保を元にお金を借り受けることができます。その返済には利子が伴うことがあります。流動性選好の観点とお金の貯蔵性からマネーを借りる場合には、利子が発生することは避けられません(減価する貨幣などお金の機能を変化させているものは除く)。フラッシュローンとは担保なしで対象資産(暗号資産やトークンなど)を借り受け、その債務の処理と返済を同じ取引(Ethereum上の1つのトランザクション)内で解消することができるDeFiプロトコルの機能のことです。このとき利子は発生せず、手数料が発生する場合があります。この記事ではaaveのFlash Loanを取り扱います。実装は各DeFiプロトコルによって異なるため各プロトコルのドキュメントを確認する必要があります。[1]

Flash Loans are special uncollateralised loans that allow the borrowing of an asset, as long as the borrowed amount (and a fee) is returned before the end of the transaction. There is no real world analogy to Flash Loans.

フラッシュローンは担保なしでマネーを融通することができる点、またトランザクション内で借りたマネーの操作や返済を一挙に行える点が特徴で、以下のような処理・アプリケーションへの応用が考えられています。アビトラはまさにdydxのフラッシュローン事件で応用されており、当該事件では故意に価格差を発生させることでアビトラを成功させシングルトランザクションで裁定解消まで完結しています。

  • Arbitrage(アービトラージ)
  • Refinance loan(ローンの借り換え)
  • Swap collaterals(担保のスワップ)

フラッシュローンはシングルトランザクション内でアビトラの処理や返済(aaveは手数料も支払う必要あり)ができなければ処理はリバートされるため、もし貸し借りが成立したらどうなるだろうという as-if 的世界に見えます。このような取引は現実の取引所や金融資産では行えなかったので『There is no real world analogy to Flash Loans』という説明は非常に的を得ています。フラッシュローンのユースケースの1つであるアービトラージを例に取ってみましょう。ある商品の価格差(同一商品の先物と現物の価格や複数取引所間の価格など複数パターンあり)を認識して裁定取引のポジションを建てた場合、1) 裁定取引の解消に伴うリスク、2) 手数料などで利益が消滅するリスクが存在します。アービトラージを成功させるには複数の取引が必要でその複数の取引に関連する様々な不確実性が存在しています。端的にいうとそれら複数の取引を1つの取引としてDeFiのエコシステムで実行できることがフラッシュローンのメリットだと考えます。さらにフラッシュローンでは担保をデポジットする必要がありません。アトミックなトランザクション内で返済ができれば1億でも10億でも借りられるため、大きな金額をレバレッジすることが可能になります。特に流動性が価格へ大きな影響を持つ暗号資産の場合には、フラッシュローンで大きな金額を借りることが取引に有利に働くことも多いかと思います。

この記事で取り上げているのはフラッシュローンの機能を使用したアプリケーションの中でもArbitrage(アービトラージ)に注目した活用法ですが、フラッシュローン自体は上記のローンの借り換えや担保のスワップなど様々なアプリケーションに応用ができると考えられています。

フラッシュローンのアビトラの例

まずこちらが一番最初に観測されたaaveで実行されたフラッシュローンです。ArbitrageDAOというコントラクトで手数料とトランザクション手数料を除くと数ドル分のDAIのプロフィットとなっています。今ではガス手数料が上昇しているので、同様のアビトラを成功させてもそれほど利益は得られないかもしれません。またSCDのシャットダウンに伴いDAIとSAIのMigrationがMakerプロトコルでできないので同じ手法は行えないようになっています。トランザクションのetherscanリンクです、参考のためこのフラッシュローンで何が行われたか確認してみます。[2]

https://twitter.com/CamiRusso/status/1218640871048056832

見たままですがトランザクションの内容を簡単に説明します。使用しているプロトコルはMaker DAOとUniswapです。レンディングプールから借りたDAIをMaker MigrationのコントラクトでSAIに変換しています。変換したSAIをUniswapでDAIにスワップすることでDAI/SAIの価格差が利益として出現しています。最終的に借りたDAIと0.09%の手数料をレンディングプールへ返却して、9 DAIがプロフィットとしてフラッシュローンのコントラクトへ戻ってきていることが確認できます。これは価格差の発生する可能性があった類似商品を対象としたアビトラと考えられるでしょう。

フラッシュローンがうまくいかずこのトランザクションが成立しない場合には処理自体がすべてリバートされます。フラッシュローン手数料もその場合にはかかりません(トランザクション手数料はかかる)。フラッシュローンによって保有している量以上のDAIをレバレッジできている上に、下手にポジションを持つ必要がないのでリスクも低減されています。[3]

https://etherscan.io/tx/0x4555a69b40fa465b60406c4d23e2eb98d8aee51def21faa28bb7d2b4a73ab1a9

このフラッシュローンは、一般的にSingle collateralのSAIの方が価格が高くなることを利用したアビトラでした。以下のスクリーンショットはDEX Aggregatorである1inch.exchangeのトークンスワップのダッシュボードです。100 DAIは約79 SAIと交換可能であることが分かります。ローンが不要であれば1inch.exchangeのようなDEXを使ったアビトラでも十分やっていけそうです。[5]

https://1inch.exchange/#/DAI/SAI

OrFeedのUIでアビトラやってみる

OrFeedはDeFiのためのオラクルアグリゲーターでUniswapやKyber、Bancorなどのプロトコルからトークンスワップの照会を行えると同時に、arbというTrianglularアービトラージを指示できるメソッドも実装するスマートコントラクトです。オンチェーンだけでなくオフチェーンのデータもChainLinkなどを通じて取得することができます。カスタムオラクルとして自身のオラクルコントラクトをOrFeedへ登録することも可能です。[6]

OrFeed TryOutのUIで0x8316B082621CFedAB95bf4a44a1d4B64a6ffc336にデプロイされているOrFeedの動作を確認できます。[7]

※上記のアドレスは現在のOrFeed 0.2のアドレスですが開発中のOrFeed 0.5ではアドレスが変更される予定です、ベタ書きでアドレスを埋め込むと後から変更できませんので注意してください

Homemade high-reliability oracle aggregator for Ethereum-based DeFi apps that need on and off-chain data, with a bit of streamlined execution functionality in there, as well.

OrFeed TryOutのUIのVenueにプロバイダを指定してQUERYをクリックすることで対象トークンをスワップや交換した場合の交換量を照会できました。以下はUniswapV2におけるETHからDAIとUSDCへのスワップの結果です。ETHの量は100000000000000を指定しています。

uint256 price1 = orfeed.getExchangeRate("ETH", "DAI", "UNISWAPBYSYMBOLV2", 100000000000000);
uint256 price2 = orfeed.getExchangeRate("ETH", "USDC", "UNISWAPBYSYMBOLV2", 100000000000000);
UniswapV2 ETH to DAI and USDC

arbfinderでarbを使用したアービトラージの機会を確認できるようになっています。arbはOrFeedのスマートコントラクトに実装されているメソッドです。arbfinderで『Big arb window』が24時間以内に発生した頻度が分かります。Big arb windowは1分間に+1、-1%の価格変化が1つかもしくは複数の交換所で発生した場合に出現します。つまりボラティリティを発見した時にアービトラージの機会として通知してくれるシステムです。Subscribeするとメールでお知らせもしてくれるのでarbfinderでアビトラしたい方は登録するとよいのではないでしょうか。[8]

Big arb windows are triggered by 1%+ changes in prices on one or more exchanges occurring in less than a 1-minute interval

https://www.orfeed.org/defiarbfinder/#

arbはOrFeedのスマートコントラクトに実装されているメソッドです。Uniswap/Kyber/BancorなどのDEXでTrianglularアービトラージを行うことができます。3 wayのスワップの指示は orfeed.arb('<fund-return-address>', '<liquidity-provider-address>', ["DAI","MKR","USDC"], 5000000000000000000, ["KYBER","UNISWAP","KYBER"]); のように行います。arbをWebでテストできるようにUIを提供するサイトがOrFeed Angleです。[8]

以下の例では10 DAIをMKR、USDCとスワップすることで10.07 USDCが得られるトランザクションをarbで実行することができました。このトランザクションを承認したetherscanの履歴をその下へ貼りつけています。このトランザクションでは10 DAI($10.17)から10.07 USDC($10.08)へスワップできました(ドル建ての実質価格ではマイナスになってしまいました)。トランザクションによってガスコストが高額となるためアービトラージで利益を得るためには価格差とガスコストを考慮したトレード戦略が必要です。

DAI -> MKR -> USDC
https://etherscan.io/tx/0xcff34831903cf24706ccbc7bee2f59ae890fa943def2ed2df1b02cf0f3a1af32
Swap 10 DAI with 10.074 USDC with arb

OrFeedのarbのファンクションをaaveのフラッシュローンのコントラクト内で呼び出すことでトークンスワップを使用したアービトラージが実現可能です。arbを呼び出すフラッシュローンのコントラクトからフラッシュローンの債務返済が行われるためDAIをローンした場合には、最後またDAIへスワップして戻しておく必要があります。例えばDAIからWETH、あるいはUSDCへスワップしてまた再度DAIへ戻さなければいけません。OrFeed Angleでトークンスワップが確認できたので次はaaveのフラッシュローンのコントラクトへOrFeedのarbを組み込んだスマートコントラクトによるアービトラージをやってみたいと思います。

DAI -> WETH -> DAI

フラッシュローンでアビトラのコード

今回作成したgithubリポジトリは以下です。[9]

https://github.com/yuyasugano/flashloan

OrFeedのarbを使ってaaveのフラッシュローンのスマートコントラクトを書いてみたいと思います。aaveのレンディングプールのコントラクト、フラッシュローンのコントラクト、OrFeedのコントラクトが相互に協働します。ちょっと複雑なので流れを簡単に確認してみました。

※メインネットでデプロイしたコントラクトの実行に係るガスコストが高すぎるために本番環境でのフラッシュローンは実行しておりません

  1. executeOperation を実装するフラッシュローンのコントラクトを自身でデプロイします、このコントラクトにaaveのレンディングプールのコントラクトからフラッシュローンを振り込むよう指示します
  2. レンディングプールのコントラクトの _receiver へデプロイしたコントラクトのアドレスを指定してフラッシュローンを実行しますhttps://etherscan.io/address/0x398ec7346dcd622edc5ae82352f02be94c62d119#writeProxyContract
    ※etherscan上からMetaMaskを使って実行することにします
  3. フラッシュローンのコントラクト内のexecuteOperationでarbを使用したアービトラージを実行します、arbを利用してスワップをしたトークンはフラッシュローンのコントラクトへ戻ってきます
  4. フラッシュローンのコントラクトからaaveのレンディングプールへ手数料を含めたトークンを返済します、 transferFundsBackToPoolInternal で債務が返済できない場合はトランザクションが失敗しリバートされます

aaveのレンディングプールのコントラクトからフラッシュローンを実行するので作成するフラッシュローンのコントラクトには executeOperation のみ実装します。このコントラクトは orfeed.arb(address(this), address(this), ["DAI","WETH","DAI"], _amount, ["UNISWAP","UNISWAP","UNISWAP"]); と同等のスワップを実行できるようになっています。このトランザクションが成功しても特にプロフィットは発生いたしません。

次にInfuraを使ってコントラクトをメインネットにデプロイしてみます。ウォレットやガスの設定は truffle.js を見てください。

$ truffle compile
$ truffle migrate --network mainnet

無事デプロイできますた。コントラクトのデプロイに0.02 ETHかかっているのでガチでアビトラを行う場合は、このコントラクトのデプロイコストも検討要ですね。

Deploying 'FlashExecution'
--------------------------
> transaction hash: 0xd9c50cb7f5c898d300aec26ca80e558d08aebfc3bc4fd4e36b2f6b20bd8a3c79
> Blocks: 9 Seconds: 117
> contract address: 0x7581B20c28694cA5541E1C0913d1A58e186D6392
> block number: 10455108
> block timestamp: 1594695183
> account: 0x0000000000000000000000000000000000000000
> balance: 2.9953265243
> gas used: 1047438
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.02094876 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.02094876 ETH

https://etherscan.io/address/0x7581b20c28694ca5541e1c0913d1a58e186d6392

デプロイしたコントラクトのアドレスにフラッシュローン手数料分のDAIを送信しておきましょう。前回の記事でお伝えしたとおりフラッシュローン手数料は借り受けしたトークンでしか払うことができません。

Sent a fee to the contract address

aaveのレンディングプールのコントラクトへMetaMaskで接続してflashLoanを実行することができます。 _receiver はフラッシュローンの受け手のアドレスで executeOperation が実装されているフラッシュローンのコントラクトを指定します。 _reserve にはaaveのERC20トークンのリザーバのアドレスを指定してください。DAIの場合は0x6B175474E89094C44Da98b954EedeAC495271d0Fです。 _amount に借りたい金額を入力してWriteをクリックします。

ここでこのトランザクションの実行に数十ドルかかることが判明したため、実際にこの呼び出しは行いませんでした。ガスコストの負担が高い場合はフラッシュローンと係る取引によるプロフィットがある程度狙えないと実行をためらいますね。というわけでコントラクトの作成までで実行はできておりませんが、この記事の下部に貼ってあるProof SuiteのYoutubeビデオで実演が見れますので参考にしてください。フラッシュローン事件の手法には賛否両論あるのですが、ゼロベースで対象の手法を発見して実現することは簡単ではなく 1,271 ETHという価値はその取引や価格操作を現実に実行できた報酬としては妥当なのではと感じた次第でありました。

記事を作成するにあたり参考にしたYouTubeビデオです。

DeFi on Ethereum (Lesson 5: Finding Arbitrage on Kyber, Uniswap & Bancor)

OrFeedやarbfinderの説明です。『Big arb window』の出現条件やUniswap/Kyber/Bancorなどのトークンスワップでスワップした場合の交換レートの見方について学ぶことができます。

DeFi on Ethereum (Lesson 6: Arbitrage Strategy and Execution)

OrFeed AngleでOrFeedのarbを利用したトークンスワップのやり方が説明されています。OrFeedのUIでアビトラやってみる、はこのビデオの内容を実際に手元で再現してみた内容です。

--

--

Yuya Sugano

Cloud Architect and Blockchain Enthusiast, techflare.blog, Vinyl DJ, Backpacker. ブロックチェーン・クラウド(AWS/Azure)関連の記事をパブリッシュ。バックパッカーとしてユーラシア大陸を陸路横断するなど旅が趣味。