day20. hardhat – 開発環境のセットアップ(プロジェクト編) –

hardhat – 開発環境のセットアップ(プロジェクト編)

Day 19では、Hardhatを用いた開発を行うための共通のセットアップを行いました。それに続くものとして、本ガイドでは、各プロダクト(プロジェクト)に対して行うセットアップについて解説します。

TOC

セットアップ手順

セットアップの際には、前回と同様に、ターミナル等のコンソール(コマンドライン)上でコマンドを入力して行います。次のものが、新しくプロジェクトをはじめる際に行う初期のセットアップ手順になります。
それぞれのコマンドの意味については、#以降のコメントに記載しているとおりです。hardhatの初期設定においては、JavascriptまたはTypescriptのいずれかを選択の上、先に進めますが、ここではTypescriptを選択します。

Zsh
% mkdir funding           # フォルダーを作成する
% cd funding              # 作成したフォルダーに移動する
% yarn init               # パッケージ管理の初期化処理を行う(package.json=設定ファイルを作成する)
  yarn init v1.22.19      # 以下のそれぞれの質問について記入。Enterだけ叩いて省略でも良い
  question name (funding): funding
  question version (1.0.0): 0.0.1
  question description: crowdfunding web3 application
  question entry point (index.js): 
  question repository url: 
  question author: 
  question license (MIT): 
  question private: 
% yarn add --dev @nomicfoundation/hardhat-ethers @nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers ethers @nomiclabs/hardhat-etherscan @nomiclabs/hardhat-waffle chai ethereum-waffle hardhat hardhat-contract-sizer hardhat-deploy hardhat-gas-reporter prettier prettier-plugin-solidity solhint solidity-coverage dotenv @typechain/ethers-v6 @typechain/hardhat @types/chai @types/node ts-node typechain typescript # 利用するライブラリーを追加する(Typescriptの場合。Javascriptの場合、dotenvより後ろを削除)
% yarn hardhat            # hardhatの初期設定を行う。以下の質問に回答する(後ろ2つはEnterだけでも良い)
   What do you want to do? · Create a TypeScript project
   Hardhat project root: · /Users/username/code/funding
   Do you want to add a .gitignore? (Y/n) · y
% code .                  # VS Codeを立ち上げる

yarn addコマンドでは、利用するライブラリーを指定して、導入しています。あとから、package.jsonで追加したライブラリーを確認することができます。次のものが、実際のpackage.jsonのサンプル(上記のコマンドで追加した結果)です。scriptsセクションについては、手動で記載しているものです(コマンドのショートカットになります)。

JSON
{
  "name": "funding",
  "version": "0.0.1",
  "description": "crowdfunding web3 application",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@nomicfoundation/hardhat-ethers": "^3.0.4",
    "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
    "@nomiclabs/hardhat-etherscan": "^3.1.7",
    "@nomiclabs/hardhat-waffle": "^2.0.6",
    "@typechain/ethers-v6": "^0.4.3",
    "@typechain/hardhat": "^8.0.2",
    "@types/chai": "^4.3.5",
    "@types/node": "^20.4.2",
    "chai": "^4.3.7",
    "dotenv": "^16.3.1",
    "ethereum-waffle": "^3.0.0", //*
    "ethers": "^6.6.4",
    "hardhat": "^2.17.0",
    "hardhat-contract-sizer": "^2.10.0",
    "hardhat-deploy": "^0.11.34",
    "hardhat-gas-reporter": "^1.0.9",
    "prettier": "^3.0.0",
    "prettier-plugin-solidity": "^1.1.3",
    "solhint": "^3.4.1",
    "solidity-coverage": "^0.8.4",
    "ts-node": "^10.9.1",
    "typechain": "^8.3.0",
    "typescript": "^5.1.6"
  }, 
  "scripts": {
    "test": "yarn hardhat test",
    "test:staging": "yarn hardhat test --network sepolia",
    "lint": "yarn solhint 'contracts/*.sol'",
    "lint:fix": "yarn solhint 'contracts/*.sol' --fix",
    "format": "yarn prettier --write .",
    "coverage": "yarn hardhat coverage"
  }
}

ライブラリー(パッケージ)を追加する方法には、以下の2つの方法があります。
1. yarn add (yarn add –dev) <パッケージ名> で直接コマンドで導入する。
2. package.jsonに対象のパッケージ名を記入し、yarn install を実施する。
package.jsonを記入する際には、dependenciesまたは、devDependenciesのセクションに追加します。後者は開発の際にだけ用いるライブラリーを指定するセクションです。

上記のバージョンと異なる場合には、この先のガイドではエラーが発生する場合があります。例えば、筆者が試した際のエラーとしては、ethereum-waffleのバージョンは4以降のものがインストールされましたが、これだとテストの章でエラーとなります。このため、パッケージを3.0.0と決め打ちで指定しています。
1. package.jsonのethereum-waffleのバージョンを編集
2. node_modules フォルダを削除
3. yarn install の実行

主要なライブラリーとその役割

prettier

prettierはコードフォーマッターの1つです。コードフォーマッターとは、プログラムのコードを自動的に整形するソフトウェアのことで、フォーマットを統一的で一貫性のあるスタイルに整え、可読性、メンテナンス性を向上させます。

.prettierrcというファイルによって、フォーマットする際の設定を定義することができます。以下のものは、.prettierrcの実例で、今回はこの設定を適用します。

JSON
// .prettierrc
{
    "tabWidth": 4, // タブ(インデント)の文字数(半角スペース4文字分)
    "useTabs": false, // インデントにタブを使うかどうか(使わない。タブではなく、半角スペースを使う)
    "semi": false, // 文末にセミコロンを付けるかどうか(付けない)
    "singleQuote": false // 文字列にシングルクォートを使うかどうか(使わない。ダブルクォートが使われる)
}

また、.prettierignoreというファイルによって、フォーマットを行わないファイルを定義することが可能です。次のものが実例で、同様にこの設定を適用します。例えば、node_modulesはyarn(やnpm)によってインストールされるライブラリー群で、これらは直接修正したりすることを想定していないので、対象外としています。他のディレクトリー、ファイルについても同様です。

Zsh
# .prettierignore
node_modules
package.json
img
artifacts
cache
coverage
.env
.*
README.md
coverage.json

dotenv

dotenvは、開発者が環境変数を.envファイルからロードできるようにするためのモジュールです。この.envファイルはプロジェクトのルートディレクトリに配置することが一般的です。

環境変数は、アプリケーションが実行される環境に依存する設定値を格納するために使用されます。例えば、プライベートキーやAPIキーなどがあります。これらの値は通常、ソースコードから分離して管理されます。その理由としては、設定値が環境(開発、テスト、本番など)によって異なる可能性があるため、また、機密情報(プライベートキーやAPIキー)をソースコードに含めるとセキュリティ上のリスクが生じるためです。

Zsh
# .env
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR-API-KEY
PRIVATE_KEY=a301a301a301a301a301a301a301a301a301a301a301a301a301a301a301a301
ETHERSCAN_API_KEY=THISISEXAMPLEKEY000000999999992222
COINMARKETCAP_API_KEY=fabc0000-0000-0abc-0000-999999999999
UPDATE_FRONT_END=true

上記のような.envファイルがある場合、後述のhardhat.config.tsの例ですが、次のような形(process.env.ETHERSCAN_API_KEY)で.envファイルに定義されている変数を使うことが可能です。

TypeScript
// hardhat.config.ts
import "dotenv/config" // dotenvを冒頭でimportすると、
...
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY // process.env.変数名 で値を読み込める
...
etherscan: {
  apiKey: ETHERSCAN_API_KEY, // 値の入った変数をそのまま使う
},
...

chai

chaiは、アサーションライブラリーの1つです。アサーションライブラリーとは、プログラムの特定の部分が期待通りに動作していることを確認するためのツールです。

次の例では、9行目で、引数2つを比較しています(前者がコントラクトの関数を実行して得られる結果で、後者が期待している値です)。比較の結果、2つが同じであれば、trueとなり、期待通りの動きをしていると判断できます。
このようにコントラクトが期待通りの結果かを確認するために使われます(単体テスト、統合テストなどのテストで使われるツールになります)。

TypeScript
// sample ts file
const {assert, expect} = from "chai" // assert関数、expect関数を使えるようにする
...
describe("fund", function() {
...
  it("Updates the amount funded data structure", async () => {
    await funding.fund({ value: ethers.utils.parseEther("1") })
    const response = await fundding.s_addressToAmountFunded(deployer.address)
    assert.equal(response.toString(), ethers.utils.parseEther("1").toString()) // 引数の1つ目と2つ目を比較し、値が同じかどうかをチェックする
  })
}

solhint

SolhintはSolidity言語のための静的コード解析ツール(リンター)です。リンターとは、プログラムコードを解析して、プログラムのエラー、バグおよび疑わしい形になっている可能性がある箇所を検出するためのツールです。
Solhintは次のような特徴を持っています。

  • スタイルガイドの強制:Solhintは一貫したコードスタイルを強制し、コードの読みやすさとメンテナンス性を向上させます。
  • セキュリティチェック:Solhintは、一般的なセキュリティ問題を防ぐためのルールを提供します。
  • パフォーマンスチェック:不必要なコストを発生させる可能性のあるコードを検出します。
  • ベストプラクティスの強制:ブロックチェーンとスマートコントラクト開発のベストプラクティスを強制します。

solhintの設定は、.solhint.json、また対象外ファイルの指定は、.solhintignoreに、それぞれ記載することで、設定を有効にできます。

Zsh
# console
% yarn solhint --init # Solhintを初期化する(.solhint.jsonが作られる
% touch .solhintignore # .solhintignoreを手動で作る(空のファイルが作られる)
JSON
// .solhint.json
{
  "extends": "solhint:recommended", // Solhintの推奨ルールを適用する
  "rules": {
    "compiler-version": ["error", "^0.8.0"], // コンパイラーのバージョンとして、0.8.0以上を指定、満たさない場合にはエラーとする
    "func-visibility": ["warn", { "ignoreConstructors": true }] // 関数の定義において、public, privateなどのビジビリティを省略した場合には、Warning(警告)を出す。コンストラクターにこのルールは適用しない。
  }
}

Solhintのルールの一覧

Zsh
# .solhintignore
node_modules
contracts/test

実際にSolhintを実行した例が次のものですが、ここでは、warning(警告)が3つ出ていますが、エラーは特に出ていません(内容的には、変数名がmixedCase(小文字・大文字の両方を使う)というメッセージですが、例えば14行目の変数名がs_fundersになっていますが、これをsFundersにすると警告は消えます。この変数名は分かりやすくするために意図的にこのようにネーミングしているものなので、ここでは無視します)。

Zsh
# console
% yarn solhint contracts/Funding.sol # Funding.solをリンターにかける
yarn run v1.22.19
$ /Users/someone/code/token-village/funding/node_modules/.bin/solhint contracts/Funding.sol

contracts/Funding.sol
  14:5  warning  Variable name must be in mixedCase    var-name-mixedcase
  15:5  warning  Variable name must be in mixedCase    var-name-mixedcase
  16:5  warning  Variable name must be in mixedCase    var-name-mixedcase

 3 problems (0 errors, 3 warnings)

  Done in 0.95s.

solidity-coverage

solidity-coverageはスマートコントラクト用のコードカバレッジ分析ツールです。コードカバレッジとは、テストスイートがコードのどの部分を実行したかを示す指標で、一般的にはテストがどれだけのコードをカバーしているかをパーセンテージで示します。これはソフトウェアのテスト品質を評価するのに役立ちます。

hardhat.config.ts(hardhatの設定ファイル)に次の一文を入れて、実行可能となります。

TypeScript
// hardhat.config.ts
import "solidity-coverage";

次のものが実行例です。ここでは、まだテストを何も定義していないので、カバレッジ(どのくらいテストが実行されているかを示す割合)が0になります。

Zsh
# console
% yarn hardhat coverage
yarn run v1.22.19
$ /Users/someone/code/funding/node_modules/.bin/hardhat coverage

Version
=======
> solidity-coverage: v0.8.4

...

--------------|----------|----------|----------|----------|----------------|
File          |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
--------------|----------|----------|----------|----------|----------------|
 contracts/   |        0 |        0 |        0 |        0 |                |
  Funding.sol |        0 |        0 |        0 |        0 |... 49,53,57,63 |
  Lock.sol    |        0 |        0 |        0 |        0 |... 27,28,30,32 |
--------------|----------|----------|----------|----------|----------------|
All files     |        0 |        0 |        0 |        0 |                |
--------------|----------|----------|----------|----------|----------------|

scriptの定義(package.json)

package.jsonscriptsのセクションによく使うコマンドのショートカットを定義することが可能です。
例えば、次の例のような定義がある場合、前述のyarn hardhat coverageは、yarn coverage だけで同じコマンドが実行されます。

JSON
// package.json
 ...
  "scripts": {
    "test": "yarn hardhat test",
    "test:staging": "yarn hardhat test --network sepolia",
    "lint": "yarn solhint 'contracts/*.sol'",
    "lint:fix": "yarn solhint 'contracts/*.sol' --fix",
    "format": "yarn prettier --write .",
    "coverage": "yarn hardhat coverage"
  }
}

ディレクトリー構造

hardhatでは、特定のディレクトリー構造が強制されるわけではありませんが、本ガイドでの構造としては、次に示すものを採用しています。*が付いているディレクトリー、ファイルは、システムが利用するものです。

Zsh
.
├── artifacts/*       # コンパイル後のコントラクトとそのメタデータが保存される場所
├── cache/*           # Hardhatがビルドキャッシュを保存する場所
├── contracts/        # スマートコントラクトのソース(.sol)ファイルが格納される
├── deploy/           # deployを行うためのスクリプトを格納する
├── node_modules/*    # npm(yarn)パッケージがインストールされる場所
├── scripts/          # スクリプト(タスクなど)が格納される
├── test/             # テストファイル(.js または .ts)が格納される
├── utils/            # デプロイの際に共通で使うユーティリティ用のスクリプトを格納する
├── .env              # 環境変数の定義を行うファイル
├── .gitignore        # git(ソース管理ツール)で管理対象外のファイルを定義するファイル
├── .prettierrc       # prettierの設定ファイル
├── .prettierignore   # prettierで対象外とするファイルを定義するファイル
├── .solhint.json     # solhintの設定ファイル
├── .solhintignore    # solhintで対象外とするファイルを定義するファイル
├── hardhat.config.ts # Hardhatの設定ファイル
├── package.json      # プロジェクトのnpm(yarn)設定ファイル
└── yarn.lock*        # yarnを利用すると自動的に生成されるファイル(直接編集を行わない)

ご意見をお聞かせください!

web3チュートリアルシリーズについてのご意見を是非お聞かせください。

この記事、または、web3チュートリアル全体について、是非、あなたのご意見をお聞かせください。
アンケートはこちらからご回答いただけます。

無料相談承ります

ITの専門家が無料相談を受け付けます。web3以外のテーマでもOKです。

オンラインでの無料相談を承っています。ご希望の方は、お問い合わせフォームよりご連絡ください。
ITの専門家があなたのご質問にお答えいたします。

Let's share this post !

Author of this article

After joining IBM in 2004, the author gained extensive experience in developing and maintaining distributed systems, primarily web-based, as an engineer and PM. Later, he founded his own company, designing and developing mobile applications and backend services. He is currently leading a Tech team at a venture company specializing in robo-advisory.

Comments

To comment

CAPTCHA


TOC