アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

dydxをローカルに構築して遊んでみる。

今回はDefiでおなじみのdydxのv2 protocolである、soloで遊ぶためにローカルでsoloを構築する手順を説明します。
dydx.exchange

マージントレード、デリバティブトレードとして有名なdydxですが、最近プロトコルがバージョンアップされv2 soloとなりv1 expoとは大幅にコントラクトの様相が変わっております。特にマージントレードの幅広い戦略をサポートするために考案されたActionsのプロトコルは非常にメタ化された概念であり、ソースコードからその実態を掴むのは容易ではありません。
そのため、本記事ではdydx soloで追加されたActionsを実際に動かしながら体験するために、dydx soloをローカルに構築する手順を解説します。
なお、本記事ではdydx soloに関する詳しい説明やActionsを利用したマージントレード戦略の具体的な記述方法については解説しないのでご注意ください。

Requirement

以下のライブラリ等はインストールしておいてください。
(表記中のバージョンは実際に僕が試した環境です。)

  • Node.js: v8.16.0 (or higher)
  • solc: 50.5.7
  • git

なお、開設時のコマンドではローカルのnpmモジュールへのパス(./node_module/.bin/)は省いて表記していますのでご注意ください。

1. リポジトリのクローンと依存モジュールのインストール

github.com
まずはじめに、soloのリポジトリをcloneして、依存モジュールをインストールします。

$ git clone https://github.com/dydxprotocol/solo.git
$ cd solo
$ npm install

2. テスト用のノードを立てる

dydx soloのリポジトリではテスト用に各種scriptやtesting専用の便利なコントラクトなどが用意されているので、今回はそれを使います。
なので、scriptの設定にあるport番号とnetworkIdと同じnodeを起動します。
なお、ここではganache nodeのみを使ってください。dydx soloが用意しているtest用のscriptなどではevm_snapshotなどのganache特有のRPCを利用しているため、ganacheのみでしか動かせません。

$ ganache-cli -l 8000000 -p8445 -i 1001 

3. 必要なコントラクトをビルドする

dydx soroが用意しているscriptを利用してコントラクトをビルドします。これで、内部の依存関係を解消しながらコントラクトがビルドされます。

$ npm run build

4. test用のコントラクトをデプロイする

これで、テスト用に用意された便利なメソッドを持つコントラクトがデプロイされます。またこの時に、デプロイ直後の状態にnodeを戻すためのsnapshotも作成されます。

$ npm run deploy_test

5. tsをjsファイルにtranslateする

dydx soloのJSライブラリはTypeScriptで書かれているのでtranslateをする必要があります。なお、この時にローカルnodeにデプロイしたコントラクトのaddressがJSONファイルから読み込まれてハードコードされるので、.tsファイルのtranslateは必ずコントラクトデプロイ後に行う必要があります。

$ npm run build:js

基本的に、ローカルnodeはsnapshot機能を使っていつでもデプロイ直後の状態に戻せますが、もし何らかの不具合等でnodeを再起動して、コントラクトのデプロイからやり直す必要が出た場合には、必ずJSライブラリもtranslateし直してください。そうしないと、コントラクトのアドレスが変わってしまうためうまくJSが実行できなくなります。

6. sample用のコードを書いて実行する

サンプルコードはこちら。
gist.github.com

7. 実行する

$ node sample.js

sampleの最初にawait solo.testing.evm.resetEVM(2)を呼び出しているので、常にクリーンな状態にリセットされてからスクリプトが実行されます。

8. sampleの解説

sampleスクリプトの内容を簡単に解説します。

Marketの設定

sampleスクリプトの17行目の関数で、dydxのマーケットを作成しています。
ソースコード内のtesting.tokenA〜tokenBはsoloがテスト用に用意したちょっと便利なERC20トークンになります。
soloではERC20トークンをMarketを介して扱うため、ここでそのMarketを作っています。対応するMarketが存在しないERC20はdydxで取り扱うことができません。ちなみに、現在dydx soloはmainnetでWETH, DAI, USDCの3つのERC20トークンをサポートしているため、testでもtokenA〜Cまでの3種類のトークンが標準で用意されています。

ERC20トークンの転送許可

ユーザが保有しているERC20トークンをdydx soloを介してトレードするためには、dydx soloコントラクトに対してERC20トークンの転送許可を出す必要があります。62行目にあるこの関数はtokenA〜Cの3つのトークンに対して転送許可を出すための便利メソッドです。

Deposit、Withdraw Action

87行目のこの関数はdydx soloにトークンをデポジットするためのActionを指定されたoperationに対して追加するメソッドです。同様に、111行目のこの関数はWithdraw Actionを追加するメソッドです。

Commit

dydx soloでは1つのトランザクションで複数のActionを発行できます。133行目のこの関数はoperationに追加された複数のActionを実行するためのTransactionをEthereumに対して発行するためのメソッドです。
dydx soloではActionsの処理の最後に担保割れが起きていないかどうかをチェックします。そのため、Actionの途中で担保割れが起きていても問題なく実行されます。最後の担保チェックに成功した場合は全てのActionを実行した結果が記録され、担保チェックに失敗した場合は全てがなかったことにされます。(gas代の消費は除く)

事前セットアップ

main関数の前段ではローカルに立てたnodeへの接続とテスト用のSoloインスタンスの生成、それからサンプルで動かすためのMarketの作成などを行なってます。
Soloを作成する時にtesting: trueオプションを指定することで、各種テスト用の便利なコントラクトやライブラリがロードされます。

メインのAction。1ETHを230DAIを担保にして借りている。

main関数のこの4行がdydx soloでトレードを行うメインの処理になっています。ここではWIthdraw Actionで1ETHを借入し、その担保としてDeposit Actionで230DAIをデポジットしています。
このsampleでは先にWIthdraw Actionが実行され担保がない状態で1ETHの借入を行なっていますが、先ほど説明した通り、dydxではActionsの途中の処理で担保割れが怒ることを許容しているのでこのサンプルは問題なく動作します。

まとめ

dydxではExchangeWrapperを利用して外部のDEXとのオペレーション(BuyやSell)も1つのActionとしてネイティブに行えます。外部のDEXを使うようなsampleを実行したいのであれば、testコードに必要な設定方法などが記述されているので参考にしてみてください。