0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Solidityスマートコントラクト開発をFoundryで始める

0
Posted at

はじめに

Solidityのコントラクト開発は、HardhatとFoundryが主流です。
この記事では、Foundryの開発フローを理解し、実践的な使い方を解説します。

インストール

Foundry は、公式のインストーラ兼バージョンマネージャーである foundryup を使ってインストールします。

foundryup のインストール

foundryupのインストールは以下のコマンドで行います。

curl -L https://foundry.paradigm.xyz | bash

Windowsの場合、Git BashWSLが実行環境となります。
PowerShell や Command Prompt はサポートされていません。

ターミナルの再起動

以下を実行します。

source ~/.bashrc
# または
source ~/.zshrc

Foundry のインストール

以下を実行します。

foundryup

ツール

Foundry をインストールすると、以下の 4 つのツールが利用できるようになります。

ツール 目的
forge スマートコントラクトのビルド、テスト、デバッグ、デプロイ、Verify(検証)
cast コントラクトとの対話、トランザクション送信、チェーンデータの取得
anvil フォーク機能を備えたローカル Ethereum ノードを起動
chisel 高速なプロトタイピングのための Solidity REPL

プロジェクトセットアップ

Foundry のプロジェクトは forge init で初期化します。
初期化後は、すぐに使える標準的なディレクトリ構成が自動的に作成されます。

プロジェクトの作成

既存のディレクトリで初期化する場合は以下を実行します。

ここでは、開発環境をVSCodeとしている為、オプションに--vscodeを付けています。

cd my_project
forge init --vscode

空でないディレクトリで初期化する場合は以下を実行します。

forge init --force --vscode

フォルダ構成

以下がフォルダ構成となります。

my_project/
├─ foundry.toml #プロジェクト設定ファイル
│
├─ src/
│  └─ Counter.sol #サンプルコントラクト
│
├─ test/
│  └─ Counter.t.sol #サンプルテスト
│
├─ script/
│  └─ Counter.s.sol #サンプルスクリプト
│
└─ lib/
   └─ forge-std/ #標準ライブラリ

OpenZeppelinライブラリ追加

ERC20やERC721などのトークン標準、アクセス制御、その他の汎用機能を活用する場合は、OpenZeppelinのライブラリを追加します。
forge install を使うことでも可能ですが、ここではforge soldeer を使ってインストールします。
Soldeer の場合バージョン指定になります。

forge soldeer install @openzeppelin-contracts~5.6.1

インポートは以下のようになります。

import { ERC20 } from "@openzeppelin-contracts-5.6.1/token/ERC20/ERC20.sol";

Upgradeableの場合は以下のコマンドとなります。

forge soldeer install @openzeppelin-contracts-upgradeable~5.6.1

Forge

Forge は、Solidity スマートコントラクトの コンパイル、テスト、デプロイを行うためのツールです。
Foundry における 中核となる開発ツールです。

コントラクトのビルド

Forge は、src/ ディレクトリ内の すべての Solidity ファイルをコンパイルし、
生成された成果物(アーティファクト)を out/ ディレクトリに出力します。

forge build

コンパイラのバージョン

Forge は、コントラクト内の pragma ステートメントから 必要な Solidity のバージョンを自動検出し、対応するコンパイラを 自動的にダウンロードします。
特定のバージョンに固定したい場合は、foundry.toml で明示的に指定できます。

# foundry.toml
[profile.default]
solc_version = "0.8.28"

最適化(Optimization)

本番環境へのデプロイ時は、ガス最適化のためオプティマイザを有効化が必須です。

# foundry.toml
[profile.default]
optimizer = true
optimizer_runs = 200
via_ir = true

※:テスト環境では、via_ir を無効にしておいたほうが良いです。

テスト(Testing)

Forge は、Solidity で記述されたテストを実行します。
テストファイルは test/ ディレクトリに配置し、テスト関数名は test で始める必要があります。

forge test

テストの記述(Writing tests)

Test を継承した テストコントラクトを作成します。

主な規約(Key conventions)

  • テストファイル名は .t.sol で終わる
  • テストコントラクトは forge-std/Test.sol を継承する
  • テスト関数名は test_ または test で始める
  • setUp() は各テストの実行前に毎回呼ばれる

カバレッジ(Coverage)

カバレッジレポートを生成します。

forge coverage

トレース(Traces)

トレースは、テスト実行中に行われたすべての呼び出しをツリー構造で表示します。
これにより、実行フローを理解しやすくなり、失敗時のデバッグに役立ちます。

例:スタックトレース(Stack traces)

forge test -vvv

詳細度レベル(Verbosity levels)

-v フラグを使うことで、Forge が出力する ログの詳細度を制御できます。

フラグ 表示内容
(なし) 成功 / 失敗のサマリーのみ
-v テスト名を表示
-vv テスト中に出力されたログを表示
-vvv 失敗したテストのみトレースを表示
-vvvv すべてのテスト(setUp 含む)のトレースを表示
-vvvvv トレース+ストレージの変更内容を表示

ガス使用量のトラッキング(Gas tracking)

Forge は、コントラクトのガス使用量を追跡し、最適化の検討やガスコストの退行(regression)検知を支援します。

ガスレポート(Gas reports)

すべてのテストに対して ガスレポートを生成するには、以下を実行します。

forge test --gas-report

スクリプト(Scripting)

Forge の スクリプトは、コントラクトのデプロイやオンチェーンでのトランザクション実行を行う Solidity ファイルです。

スクリプトの構成(Script structure)

スクリプトは Script を継承し、run() 関数を実装します。

例)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Script} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";

contract DeployScript is Script {
    function run() public {
        vm.startBroadcast();

        Counter counter = new Counter();
        counter.setNumber(42);

        vm.stopBroadcast();
    }
}

主な要素(Key elements)

  • forge-std/Script.sol を継承する
  • スクリプトファイル名は .s.sol で終わる
  • デプロイ処理は vm.startBroadcast() / vm.stopBroadcast() で囲む

スクリプトの実行(Running scripts)

デプロイのシミュレーション(トランザクションは送信されません)

forge script script/Deploy.s.sol

このコマンドは、実際にはトランザクションを送信せず、デプロイ処理をシミュレーション実行します。

ネットワークに対してトランザクションを送信する場合

forge script script/Deploy.s.sol --broadcast --rpc-url $RPC_URL

--broadcast を指定することで、指定した RPC エンドポイント($RPC_URL)に対して 実際にトランザクションが送信されます。

フォーマット(Formatting)

Forge には、一貫したコードスタイルを強制するためのビルトインフォーマッタが含まれています。

注:VSCodeのファイル保存で自動フォーマットをしている場合、フォーマットと合わせる必要があります。

ファイルのフォーマット

すべての Solidity ファイルをフォーマットします。

forge fmt

変更を加えずにフォーマットをチェックします。

forge fmt --check

設定(Configuration)

フォーマッタの挙動は foundry.toml で設定できます。

# foundry.toml
[fmt]
line_length = 120
tab_width = 4
bracket_spacing = true
int_types = "long"
multiline_func_header = "params_first"
quote_style = "double"
number_underscore = "thousands"
single_line_statement_blocks = "preserve"

主なオプション(Common options)

オプション デフォルト 説明
line_length 120 1 行の最大文字数
tab_width 4 インデントあたりのスペース数
bracket_spacing false 中括弧内のスペース有無 ({ x } / {x})`
int_types "long" uint256 形式か uint 形式か
quote_style "double" "string" / 'string'
number_underscore "preserve" 1_000_000 / 1000000

オプションはフォーマッタのリファレンスを参照

リンティング(Linting)

Forge には、一般的な問題を検出し、ベストプラクティスを強制するためのビルトインリンターが含まれています。

リンターの実行

forge lint

設定(Configuration)

リンターのルールは foundry.toml で設定できます。

# foundry.toml
[lint]
severity = ["high", "med", "low"]
exclude_lints = ["mixed-case-function", "custom-errors"]

severity:実行する lint の重大度レベルを指定します。
exclude_lints:特定の lint ルールを無効化します。

Anvil

Anvil は、開発およびテスト向けの 高速なローカル Ethereum ノードです。
すべて メモリ内で動作し、任意の EVM 互換チェーンからのフォークをサポートしています。

※:ローカル環境でブロックチェーンノードのダミーとして利用可能です。

ローカルノードの起動

anvil

デフォルトアカウント(Default accounts)

Anvil は、開発用アカウントを 10 個生成し、それぞれに 10,000 ETH があらかじめ割り当てられます。

デフォルトのニーモニック(復元フレーズ)は以下のとおりです。

test test test test test test test test test test test junk

アカウントのカスタマイズ

以下のオプションを使って、生成されるアカウントをカスタマイズできます。

  • --accounts:生成するアカウント数を指定
  • --balance:各アカウントの残高を指定
  • --mnemonic:使用するニーモニックを指定

まとめ

開発で扱いそうな機能をひとおおり記載しました。
Foundryは非常に豊富な機能を備えているため、さらに詳しく知りたい場合は公式ドキュメントを参照してください。

公式サイト:https://www.getfoundry.sh/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?