🌟

Foundry使ったスマートコントラクト開発の所感

2022/09/24に公開

はじめに

Foundryの概要と簡単な使用感をhardhatとの比較を交えて書いていきます。

現状、solidity開発のどういうケースだと使えそうか?に対する答えを出そうと思います。

Foundryとは

Crypto VCのParadigm が開発した、Rust製のsolidity開発ツールです。

https://book.getfoundry.sh

https://github.com/foundry-rs/foundry

※現状の主なsolidityスマートコントラクト開発ツール

  • テストが js or ts

    • truffle
    • hardhat
  • ブラウザで簡単

    • remix
  • 実装もテストもsolidity

    • Foundry <-- NEW!!

特徴

速い

rust製ということもあり、コンパイル・テストがめちゃくちゃ速いです。具体的な数字は、hardhat との比較で後で記述します。

git submodules 依存関係の管理

hardhatやtruffleではnpmでパッケージの管理を行いますが、
foundry のcli, forgeでは git submodulesを使っています。

fuzzing test

fuzzing test がネイティブで実装されています。

trace

テスト実行時に、verbosityのレベルが五段階用意されています。

forge test -vv
forge test -vvv
forge test -vvvv
forge test -vvvvv

使用するCLI一覧

  • Forge

    • package インストール
    • テスト実行
    • コントラクトdeploy・verify
  • Anvil

    • ローカルノード立ち上げ
  • Cast

    • スマートコントラクトのcall
    • read transaction

hardhatと比べて

良い

  • コンパイル・テストが速い

githubに,スピードテストの結果がdapptoolsと比較されています。

また、uniswap-v3coreのコンパイル結果もhardhatと比較されてグラフになっています。

  • 言語のスイッチングコストない

hardhatでは、コントラクト実装はsolidity, テストの際はjsもしくはts と、別の言語へのスイッチングコストがありますが、foundryはコントラクトもテストもsolidityです。

  • fuzzing test

先ほどの特徴でも説明しましたが、ネイティブで実装されています。

token.t.sol
// fuzzing testしたい値を関数に引数として追加する
function testMint(uint256 amount) public {
        vm.prank(creator);
        reconeToken.mint(user, amount);
        assertEq(reconeToken.balanceOf(user), amount);
    }
  • hardhatではプラグイン必要な機能がネイティブで実装されている

消費するgas量が相対的にわかる

trace形式
[<Gas Usage>] <Contract>::<Function>(<Parameters>)
    ├─ [<Gas Usage>] <Contract>::<Function>(<Parameters>)
    │   └─ ← <Return Value>
    └─ ← <Return Value>
terminal
$ forge test -vvvvv
Traces:
  [72583] EmitContractTest::testExpectEmit() 
    ├─ [33287] → new ExpectEmit@"0xce71…c246"
    │   └─ ← 166 bytes of code
    ├─ [0] VM::expectEmit(true, true, false, true) 
    │   └─ ← ()
    ├─ emit Transfer(from: EmitContractTest: [0xb4c79dab8f259c7aee6e5b2aa729821864227e84], to: 0x0000000000000000000000000000000000000539, amount: 1337)
    ├─ [1940] ExpectEmit::t() 
    │   ├─ emit Transfer(from: EmitContractTest: [0xb4c79dab8f259c7aee6e5b2aa729821864227e84], to: 0x0000000000000000000000000000000000000539, amount: 1337)
    │   └─ ← ()

悪い

  • 学習コスト少し高い

jsやtsに比べて、dapps開発以外で、solidity使ってテストを書くことがないことと、foundryにネイティブで存在するライブラリの使い方を覚える必要があるため、テスト書くときに多少のコストがかかります。

foundryのdapptoolsに影響を受けて開発されたので、似たようなメソッドがあるので、もし以前に使ったことあれば書きやすいかもです。

  • プラグインが少ない

やはりすでにさまざまなプロトコルで採用されている hardhat よりも、プラグインの数がかなり少ないです。

  • 記事少ない

単純に使ってる人がまだ少ないのでいろんなケースで使用された記事や、日本語の記事も少ないです。

使用感

  • コンパイルやテストがサクサク終わるので気持ち良い
  • テスト書くとき、「フロント、ノードからコントラクト操作」というよりも「VM直接いじっている」感覚がある
  • testファイルは'.t.sol', test関数名は'test....', script実行ファイルは'.s.sol'にする必要がある等、ファイル名や関数名に対しての一貫したルールがあって個人的には好き

その他 foundry でできること

  • upgradeable contractの実装
  • 実際のチェーンをローカルノードにフォークしてテスト
  • differential testing

最後に

使えそうか?どういうユースケースで?

基本的には、まだhardhatでの開発で良いのではないかといった感じです。

  • 実際のコントラクト実装には、hardhatほどのプラグインの豊富さと使用者の少なさ、ネット上の記事の少なさ的にはまだ採用するには早い
  • 既存のhardhat開発を置き換えるのは難しい。使うとしても、新規で開発する
  • 構造がシンプルなコントラクトを作成する際に使用できそう

参考資料

https://book.getfoundry.sh
https://github.com/foundry-rs/foundry
https://tech.fracton.ventures/entry/2022/08/23/135902
https://tech.fracton.ventures/entry/2022/08/10/132957
https://qiita.com/oishun/items/808994e0aea83cf08d7b
https://yamenmerhi.medium.com/foundry-vs-hardhat-918c55e47add
https://zenn.dev/razokulover/articles/574eb471e6db1c
https://zenn.dev/pokena/scraps/a4b23e687e15ad

Discussion