Closed 0xsomewherecat closed 3 years ago
@0xMotoko こちら、Definition of Doneの認識合わせをさせてください。
このIssueにおける"mock contract"は、ChainLinkやTellorのふりをして、それっぽい任意数値を返してくるコントラクトをつくってdeployしましょう、ということで合っていますか?
なぜそうするかというと、デモにリアル感をもたせるために数字が定期的に更新されるようにしたいから。(=Chainlink/TellorのRinkeby contractとつないでもあまり数字が動かないかも、ということ)
実装としては、contracts/PriceFeed.solの中身をつくって、プライス取得用contractをmock contractにする。 ・mock contractのインターフェースはChainlink/Tellorのものに準拠させる。 ・後続フェーズで、プライス取得用contractの向き先をChainlink/Tellorのものにする。
認識ずれているところや、気をつけるべき点などありましたらご教示ください。
このIssueはmock contract作成に関わるものなので、PriceFeed.sol実装は別Issueを切った方が良さそうです。 → #16 を起票しました。
Def of Done相違ないです。
もっと言えばPricwFeed.solが読むChainLinkMock.solは初期価格と前回価格をstateとして持ちつつ、価格取得関数では前回価格にランダムにプラスマイナスをかけて返却し、ついでその値を前回価格に上書きするものが良かろうと思います。
取得時に
カオスエンジニアリングとして、
フィード切り替えのテストになる。
フィードバックありがとうございます!解像度あがりました。着手します。
今週末にv1を完成させることを目標に進めています。
下記のような構成を想定しています。変更した方がよい点がありましたらご教示ください。
※こちらの点について、yamatoの方にいれた方がよい、などあればご指摘ください。
・ChainlinkMockのインターフェースは、latestRoundData()にならう https://docs.chain.link/docs/price-feeds-api-reference/#latestrounddata
・Tellorのインターフェースは、getCurrentValue()にならう https://docs.tellor.io/tellor/integration/introduction
yamatoのcpntracts/mock配下に置いて大丈夫ですよ〜。smockが発明される前まではテスト用コントラクトの量はもっと多かったので、かわいいもんです。
(2)(3)よいと思います
ChainlinkMock v1をcontracts/mock配下に置きました。(ライブラリの改良が進んだのですね!)
Motokoさんのフィードバックを元に、下記のような仕様としました。 ・価格を呼ぶ度に、0~1%の範囲で前回価格から変動。(0.1%刻み。変動量・変動の方向+-はランダムに決定) ・1%変化が10回起きると、10回目に前回価格から51%変動。(切替テスト用)
なお、ChainlinkのlatestRoundData()はview関数なのですが、mock関数は内部stateをいじるためviewではありません。
Test caseは、依存性の解決がうまくできておらず試行錯誤中です。
行った手順: ・最新のyamatoコードをpull。ローカルの.envを編集 ・npm install ・npm run compile →正常完了 ・npm run test →下記エラーが発生
FAIL unittest test/unit/CurrencyOS.test.ts ● Test suite failed to run
Cannot find module 'hardhat/internal/hardhat-network/stack-traces/revert-reasons' from 'node_modules/@eth-optimism/smock/dist/src/smockit/binding.js'
Require stack: node_modules/@eth-optimism/smock/dist/src/smockit/binding.js node_modules/@eth-optimism/smock/dist/src/smockit/smockit.js node_modules/@eth-optimism/smock/dist/src/smockit/index.js node_modules/@eth-optimism/smock/dist/src/index.js test/unit/CurrencyOS.test.ts
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
at Object.<anonymous> (node_modules/@eth-optimism/smock/src/smockit/binding.ts:3:1)
package-lock.jsonを削除してから再度npm iするとどうでしょう?
キャッシュ対策としてはpackage-lock.jsonはそのままにして以下を行ってからnpm i
を試すのも手です。
npm cache clean
するhardhatとかtruffleのようなCLIツールはnpmのグローバル領域にインストールしている場合もありますよね。もしそうならそちらも念のためチェックですね。localの方が優先されるはずですが。 この手の問題を予防するためには、CIにてコンテナのようなクリーンな環境下でのビルドチェックを走らせて担保&壊れたのを検出できるのが一番だと思っています。
ありがとうございます! こちら、MotokoさんにDMでもお付き合い頂き解決しました。
hardhatのバージョンずれと、typechain dirをproject rootに作成する必要がある、という点がポイントでした。
私の場合、hardhatが2.6.0になってしまっていました。TeaTwoさんご指摘の、global領域にインストールしたものが使われるようなコマンドを誤って実行してしまっていた可能性があります。Repoを入れ直し、npm iすることで直りました。
テストケース書きから参加してくれるSolidity初心者などがきた時に有用になると思われますので、yamato README.mdに手順を追記します。
LiquityのPriceFeed.solの実装的にChainlinkMock.sol に decimals()
latestRoundData(uint256)
が欲しい感じなので、追加おねがいします 🙏
承知しました!
decimals()は戻り値のprecisionをチェックするためですね。
latestRoundData(uint256)とお書きになった方は、 getRoundData(uint80 _roundId)の意図と理解しました。(roundIdを指定して過去のプライスを取り寄せる関数で、こちらもLiquityの実装で使われている)
decimals(), getRoundData(uint80 _roundId)を追加します。
追加完了しました。
テスト用Mockなので、過去の全ラウンドのデータを保持するよう実装しました。(変な挙動があった場合のdebugに有用…)
Liquity実装が使うのは1つ前のroundDataだけなので、ガス代が気になる環境で動かすことがあればprevious round分だけをもつように変更します。
メモ残課題: ・Chainlink JPY/USD対応。(コンストラクタでシンボル渡して、price初期値とdecimalを制御?) ・Tellor ETH/JPY mock作成。
Chainlink Mockについて、コンストラクタで通貨を指定できるようにしました。
RinkebyにデプロイしたMockコントラクト: Chainlink Mock (ETH/USD) 0x81CE5a8399e49dCF8a0ce2c0A0C7015bb1F042bC Chainlink Mock (JPY/USD) 0x6C4e3804ddFE3be631b6DdF232025AC760765279 ※特にみられて困る機能ではないですが、ソースpublish済みのためDiscord project-feedに流れた通知は削除しました。
メモ: ・51%の変動が起きると価格がリアルなものから離れすぎる。こうした場合に、価格を戻したり任意の値をセットできるよう、setPriceToDefault()とsetPrice(price)関数を追加する。
メモ: ・setPriceToDefault()とsetPrice(price)関数を追加した。 ・TellorMockの実装が完了。 ・READMEに、Rinkebyの各種Mockコントラクトのアドレスを記録。(※Chainlink Mockは、価格セット関数追加前のversion。QAをした上で、最新版をデプロイする)
ToDo: ・テストケースの実装。
先日のhardhatの依存問題について、今さらながら原因らしきところに気がつきました。
package.jsonのnpmスクリプトでnpx
が使われていますが、これはかなりトリッキーです。
package.jsonにhardhatを記述してローカルにインストールしているので、npxを外して"hardhat deploy --network rinkeby"
だけで十分です。
npxはターミナルでパッと試したいときに使うお便利ツールで、ローカルに該当パッケージがインストールされてなくてもできちゃうスゴイやつです。逆にいうとローカルのlockファイルは気にしないしnode_modulesに無くても動けちゃいます。これが依存ずれの原因だったのではないかなと疑われますし、今後のためにも外した方が良いと思います。
rollupも同じです。
いろいろ触ってみてのフィードバックを共有させてください!
以上です。
※ EIP1559対応の関係でフォルダ構造をいじっているのと、再度npm iが必要な点、ご留意ください ※2 npxの件、修正中です。ご指摘助かります! ※3 上記フィードバック、「デモ環境でのMockの安定性確保」としてissue切ってもいいかもしれません
フィードバックありがとうございます!
デモ環境で不特定多数の人に叩かれる前提での設計が不足しておりました。具体的なアドバイス大変助かります。
3についてですが、これは、①価格を変動させるトリガーと②51%変動を発生させるトリガーの両方をblock.numberベースのものにした方がよさそう、というサジェスチョンと理解しました。そうすれば、不特定多数のユーザが同時にこの関数を呼んでも値動きはコントロールされたものになる。(内容、同意です!)
こちらの内容、別issue切りますね。→ #27 起票しました。
※1 TeaTwoさん、npxの挙動について勉強になりました!ありがとうございます。 ※2 TellorMockのつくりでお手間をかけてしまった様子ですみません。requireが通らないと、ガス代が暴走するのですね。
@0xMotoko かなり時間がかかってしまいましたが、単体テスト実装まで完了しましたのでDoneに移動します。お手数ですが、レビューをお願いできますでしょうか。(ツールと動作環境にはなれることができました)
メモ: ・blocknumberを用いて、1 blockに一度のみ価格を動かせるようにした。(あまりにも急な/高頻度の価格更新を避ける) ・ETH価格の更新にかかわる関数はonlyOwnerとした。
考慮点: ・現状、全通貨ペアにおいて一度の価格更新の変動幅を-1%~1% (0.1%刻み)としている。これは、デモなのである程度大きめに動いてもよしとするか、MainnetのChainlinkのdeviation triggerに合わせた方がよいか(例:ETH/USDであれば-0.5%~0.5%)。 ※Tellorの方は、miningを依頼するuserがTRBでincentiviseする構造になっており、特定の周期・変動幅で必ず価格更新が起きるものではない仕様のため、Chainlinkの変動幅に合わせればよいかと思われます。
問題なさそうです。 node-scheduler
などで自動化して動かしながら調整しましょう!
https://github.com/DeFiGeek-Community/yamato/commit/132d71cdf85f7f53df1cf18caff400fa4977ec55
早速のご確認ありがとうございます!
Memo from 0xMotoko: ・RinkebyにChainLink/Tellorの任意数値を定期的に返してくるmock contractを設置(デモにリアル感を持たせるため)……… タスク移譲可 予想3人日