Daily Archive2022-01-22

Dapp Tools

ブロックチェーン技術を使った分散型アプリケーションとしてDappとかdAppとかあらわされますが、Ethereum上で動作するDappの開発言語Solidityのテスト環境としてdapptoolsというものを見つけたの試してみました。

https://github.com/dapphub/dapptools

(下記動画で学習中、テストパターンを与える部分がよくわからなかったので確認してみただけになります。ブロックチェーンは様々な種類があり、それぞれ開発環境も豊富です。それが一気に押し寄せてきた感じがあり、とりあえず気になるものからどんどんためして理解を深めようと思っています。)

動画では、Openzeppelinとか使用している部分もありますが、ここではDapp ToolsといいながらDappとは関係ない純粋にSolidity言語による一般ロジックのテストの部分に注目しています。

環境) VSCode + Ubuntu20.04/WSL/Windows11

インストール

curl -L https://nixos.org/nix/install | sh
. “$HOME/.nix-profile/etc/profile.d/nix.sh”
curl https://dapp.tools/install | sh

初期化

mkdir dapp_test2
cd dapp_test2
dapp init
code .

dappコマンドでファイルは自動生成され、以下の内容に編集します。(*.t.sol がテストコード)

Dapptest2.sol

// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.6; contract Dapptest2 { uint8[] internal arr; function remove(uint8 _index) internal{ require(_index < arr.length, "index out of bound"); for(uint i = _index; i < arr.length - 1 ; i++){ arr[i] = arr[i+1]; } arr.pop(); } }
Code language: JavaScript (javascript)

Dapptest2.t.sol

// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.6; import "ds-test/test.sol"; import "./Dapptest2.sol"; contract Dapptest2Test is Dapptest2, DSTest { Dapptest2 test; //event DebugLogEvent(string); uint8[] private copy; function test_remove(uint8[] memory _arr, uint8 _i) public { /* function test_remove() public { uint[] memory _arr = new uint[](4); _arr[0] = 1; _arr[1] = 2; _arr[2] = 3; _arr[3] = 4; uint _i = 2; */ if(_i >= _arr.length){ return; } arr = _arr; // delete copy; for(uint i=0;i<arr.length;i++){ if(i!=_i){ copy.push(arr[i]); } } remove(_i); assertEq(arr.length, copy.length); for(uint i=0;i<arr.length;i++){ assertEq(arr[i], copy[i]); } //emit DebugLogEvent("-- end --"); } function test_length(uint8[] memory _arr, uint8 _i) public{ if(_i >= _arr.length){ return; } assert(_arr.length == _i); } function setUp() public { test = new Dapptest2(); } function testFail_basic_sanity() public { assertTrue(false); } function test_basic_sanity() public { assertTrue(true); } }
Code language: JavaScript (javascript)

動画ではremove()関数のテストの様子がわかりますが、入力の配列とインデックスに何が与えられているのかわかりづらかったため、test_length()という関数を追加して試してみました。

dapp test –fuzz-runs 10

このコマンドを実行しても上記スクリーンショットのように成功するときもあれば、下記のように失敗するときもあります。

失敗したとき[FAIL]のCounterexampleという部分に、配列とインデックスがでてきますが、毎回違うためランダムに入力データが与えられていることが確認できました。(見やすくするためオリジナルのuint256をuint8に変更)

–fuzz-runsを指定しないと100がデフォルトで与えられるようです。

本来の目的のremove()関数のテストでは、リムーブされたことをテストするのが目的のため、配列やインデックスの数はなんでもいいのでチェックする必要はなく、テストしていないため毎回成功することになります。

VSCodeの環境(Solidity機能拡張あり)でSolidityのテストできる環境をためせたことは有益でした。