👷‍♂️

【Solidity】Hardhatの環境構築(入門)

2023/04/10に公開

はじめに

突然ですが、今週のETH Global Tokyo頑張りましょう!ということで…

Solidityのスマートコントラクト開発でHardhatをよく利用しますよね🚧

毎回流れ作業になってるんですが、2週間ぐらい空くと「えー…っと」と手が止まって、Notionの個人用に残してる開発ノートを見返さなきゃいけなくなります。ノート自体があまり整理されていないので探すのが面倒です。

したがって、今回は自分の整理も含めて、パパっと開発環境を整えるメモを残しておこうと思います。

コードの説明ではなく、手順の方法を記載していきますので、はじめての方でも参考になると思います!(ならなかったらごめんなさい🙇)

前提

前提知識

下記の知識はあるものとして説明します。バージョンが合わない場合は、それぞれバージョンを確認してみてください。

  • WSL2
  • EVM
  • Node.js
  • npm
bash
$ npm -v
$ node -v

Node.jsとnpmの導入

もしNode.jsもnpmもインストールされていない!って方はこちらの記事が参考になります!

https://kinsta.com/jp/blog/how-to-install-node-js/

環境構築

1. ディレクトリ作成

test-contractというディレクトリを作成してみます。

bash
mkdir test-contract
cd test-contract

2. 初期化

初期化を行って、package.jsonを準備します。今回はデフォルト値を使います。

bash
npm init -y

https://docs.npmjs.com/cli/v9/commands/npm-init

3. Hardhatの導入

  1. npmでhardhatパッケージをインストールする
bash
npm install hardhat --save-dev
  1. インストールが終わったら下記のコマンドを実行する
bash
npx hardhat
  1. プロジェクトを作成する
    今回はJavaScriptを採用し、すべてエンターを押していきます。各自選択してください。
bash
888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

Welcome to Hardhat v2.13.0

? What do you want to do? … 
▸ Create a JavaScript project
  Create a TypeScript project
  Create an empty hardhat.config.js
  Quit
✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /home/username/test-contract
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y
  1. ファイルを確認する
    ここまでで下記のような構造ができていると思います。
Tree
test-contract
├── contracts
│   └── Lock.sol
├── node_modules
├── scripts
│   └── deploy.js
├── test
│   └── Lock.js
├── .gitignore
├── hardhat.config.js
├── package-lock.json
├── package.json
└── README.md
  1. コンパイルしてテストを実行する
    動作を確認してみます。
bash
$ npx hardhat compile
Compiled 1 Solidity file successfully
bash
$ npx hardhat test

  Lock
    Deployment
      ✔ Should set the right unlockTime (1248ms)
      ✔ Should set the right owner
      ✔ Should receive and store the funds to lock
      ✔ Should fail if the unlockTime is not in the future
    Withdrawals
      Validations
        ✔ Should revert with the right error if called too soon
        ✔ Should revert with the right error if called from another account
        ✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
      Events
        ✔ Should emit an event on withdrawals
      Transfers
        ✔ Should transfer the funds to the owner

  9 passing (1s)

https://hardhat.org/hardhat-runner/docs/guides/project-setup

https://github.com/NomicFoundation/hardhat

4. .envファイルの設定

テストネットへデプロイする際にウォレットの秘密鍵やノードプロバイダーのAPI KEYが必要になりますので、.envファイルにて環境変数を管理していきます。

  1. npmでdotenvパッケージをインストールする
bash
npm install dotenv --save-dev
  1. Hardhatプロジェクト直下に.envファイルを作成する
Tree
test-contract
├── artifacts
├── cache
├── contracts
│   └── Lock.sol
├── scripts
│   └── deploy.js
├── test
│   └── Lock.js
├── .env <--- Creation
├── .gitignore
├── hardhat.config.js
├── package-lock.json
├── package.json
└── README.md
  1. .envファイルに必要な項目を入力する
    PRIVATE_KEYには利用するウォレットの秘密鍵を入力します。次に、ノードプロバイダーは今回はalchemyを採用しますので、ALCHEMY_KEYにはHTTPSのAlchemy API URLを入力します。ついでに.envファイルの設定の例を記入する.env.exampleファイルも作成しておくと便利です。
.env
PRIVATE_KEY = "YOUR_PRIVATE_KEY"
ALCHEMY_KEY = "https://network.g.alchemy.com/v2/your-api-key"
.env.example
PRIVATE_KEY = ""
ALCHEMY_KEY = ""


Create and Deploy your Smart Contract using Hardhat

https://www.infura.io/

https://www.alchemy.com/

5. hardhat.config.jsファイルの設定

hardhat.config.jsを開き、Goerliを想定する設定を記入していきます。各自、利用するネットワークを記入してください。

solidityのバージョンはコントラクトで指定したバージョンを記入します。

また、ライブラリを導入した際に設定をこちらに記入していくことになります。

hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.18",
  networks: {
    goerli: {
      url: process.env.ALCHEMY_KEY,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
};

https://hardhat.org/hardhat-runner/docs/config

ライブラリの導入

その他、必要なライブラリを導入していきます。

hardhat-gas-reporterの導入

スマートコントラクトをデプロイする際のガス代やそれぞれの関数を実行した際のガス代を計測してくれるHardhat用のガスレポーターです。

npx hardhat testを実行するとガス使用料を計算してくれます。とても便利です。

bash
npm install hardhat-gas-reporter --save-dev

https://github.com/cgewecke/hardhat-gas-reporter

OpenZeppelinの導入

OpenZeppelinは精査された安全なスマートコントラクトを提供するオープンなライブラリです。必要に応じてインストールします。ご覧の通り、利用も非常に簡単です。

bash
npm install @openzeppelin/contracts
Example.sol
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

https://docs.openzeppelin.com/contracts/4.x/

https://github.com/OpenZeppelin/openzeppelin-contracts

デプロイ

scripts/deploy.jsを書き上げて、ネットワークに合わせて下記のコマンドを実行します。

template
npx hardhat run scripts/deploy.js --network your-network
Goerli
npx hardhat run scripts/deploy.js --network goerli
Mainnet
npx hardhat run scripts/deploy.js --network mainnet

https://hardhat.org/hardhat-runner/docs/guides/deploying#deploying-your-contracts

検証

GoerliのEtherscanを想定してみます。下記の画面のように緑のチェックマークがEtherscanで表示されれば成功です。

1. hardhat-etherscanの導入

bash
npm install @nomiclabs/hardhat-etherscan

https://github.com/NomicFoundation/hardhat/tree/main/packages/hardhat-etherscan

2. Etherscanで検証する

  1. Etherscan.ioからAPIを取得する
  2. .envファイルにETHERSCAN_KEYとして記載する
.env
PRIVATE_KEY = ""
ALCHEMY_KEY = ""
ETHERSCAN_KEY = "YOUR_ETHERSCAN_API_KEY"
  1. hardhat.config.jsファイルに設定を追記する
hardhat.config.js
module.exports = {
  networks: {
    mainnet: { ... }
  },
  etherscan: {
    // Your API key for Etherscan
    // Obtain one at https://etherscan.io/
    apiKey: process.env.ETHERSCAN_KEY
  }
};
  1. 下記に従って検証のコマンドを実行する
    A. 対象となるコントラクトのconstructorがない、もしくは引数がない場合
    B. 対象となるコントラクトのconstructorに引数がある場合
TypeA.sol
contract TypeA is ERC721 {
    constructor() ERC721("Gm NFT", "GMNFT") {}
    ...
}
TypeB.sol
contract TypeB is ERC721 {
    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {}
    ...
}

A. constructorがない、もしくは引数がない場合

template
npx hardhat verify --network goerli your-contract-address
example
npx hardhat verify --network goerli 0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e

B. constructorに引数がある場合

  1. args.jsファイルを作成する
Tree
test-contract
├── artifacts
├── cache
├── contracts
│   └── Lock.sol
├── scripts
│   └── deploy.js
├── test
│   └── Lock.js
├── .env
├── .gitignore
├── args.js <---
├── hardhat.config.js
├── package-lock.json
├── package.json
└── README.md
  1. スマートコントラクトのconstructorに対応する引数を入力する
args.js
module.exports = [
    "Argument 1",
    "Argument 2",
    "Argument 3",
]
  1. 検証のコマンドを実行する
template
npx hardhat verify --network goerli your-contract-address --constructor-args args.js
example
npx hardhat verify --network goerli 0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e --constructor-args args.js

まとめ

初心者でもかなり簡単にスマートコントラクトをデプロイすることができたと思います!

今週はETH Global Tokyoがありますので、皆さんでガシガシコードを書いて頑張っていきましょう!

会場で見かけたらぜひ声をかけてくださーい!@yuk6ra

https://ethglobal.com/events/tokyo

参考文献

https://github.com/NomicFoundation/hardhat
https://github.com/cgewecke/hardhat-gas-reporter
https://github.com/OpenZeppelin/openzeppelin-contracts
https://github.com/NomicFoundation/hardhat/tree/main/packages/hardhat-etherscan
https://www.alchemy.com/
https://www.infura.io/
https://goerlifaucet.com/
https://faucet.quicknode.com/drip

GitHubで編集を提案

Discussion