HardhatでHelloWorld


ずっとtruffleを使ってきましたが、主要なサービスのサンプルコードなど、ほぼhardhatな感じなのでHardhatを試してみます。
基本的に[こちらの記事](https://zenn.dev/hid3/articles/b5f17e2167d4f7)を参考にさせていただきました（ありがとうございます）が、私のやりたいことと少し違うところもあるので修正しながら自分で試してみます。

>HardhatはEtherrum上のContractを作成するためのフレームワークです。

## 前提

* macOS上
* nodeインストール済み（18.x）

## 準備

### 作業場の作成と必要モジュールインストール

```bash
cd
mkdir test-hardhat
cd test-hardhat

npm init -y
npm install --save-dev hardhat
```

### プロジェクトの生成

npx hardhatを実行すると以下のような感じの表示が出ます。

```bash
npx hardhat


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

```

Create a JavaScript projectを選択し、後はデフォルトかyesで進めます。

>TypeScriptも使えるんですね（コントラクト自体をTSとかで書けるわけではありません）。


## Contractファイルの作成と記述

contractsの中にファイルを生成。

```bash
touch contracts/Hello.sol
```

最低限の記述をします。

>Ethereum上のコントラクトはSolidityで記述します（JSに似てますが違います）。

```sol:Hello.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract Hello {
    function greet() public pure returns (string memory) {
        return "Hello World";
    }
}
```

>// SPDX-License-Identifier: UNLICENSEDの記述がないと怒られます。

## Deployファイルの作成（編集）

新しくファイルを作ってもいいのですが、すでにscripts/deploy.jsというファイルがあるのでそれを編集します。

>Lock.solをデプロイする記述が書かれているのでその部分は削除します。

```sol:deploy.sol
const hre = require("hardhat");

async function main() {
  const Hello = await hre.ethers.getContractFactory("Hello");
  const hello = await Hello.deploy();

  await hello.deployed();

  console.log(`Deployed to ${hello.address}`);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

## ローカルノードの実行

テスト実行するnodeを起動させてみます。

>truffleだとGanache(CLI)に相当するもの。

```bash
npx hardhat node
```

>testnetやmainnetを利用する場合はINFURAやAlchemy等のノードサービスを利用することになります（もちろん自分でnode立ててもいいです）。

## Deploy

デプロイは以下のようにネットワークとスクリプトを指定して行うようです。

```bash
npx hardhat run --network localhost scripts/deploy.js
```

出力されるデプロイ先アドレスをメモしておきます（実行に必要なため）。

## コントラクトの実行

コンソールを利用して動作確認ができます。
実行には、abiとアドレス情報が必要になります。

* abi: artifacts/contracts/Hello.sol/Hello.json中のapi要素部となります（配列をコピーしておきます）。
* アドレス: 先程出力されたものです。

### コンソールの起動

```bash
npx hardhat console --network localhost
```

### コンソールでの操作

以下のように対話的に変数を設定しながら最終的にgreet()を実行します。

```bash
> const abi = [
     {
       "inputs": [],
       "name": "greet",
       "outputs": [
         {
           "internalType": "string",
           "name": "",
           "type": "string"
         }
       ],
       "stateMutability": "pure",
       "type": "function"
     }
   ]
undefined
> const address = "0x5FbDB2315678afecb367f032d93F642f64180aa3"
undefined
> const hello = await ethers.getContractAt(abi, address)
undefined
> await hello.greet()
'Hello World'
```

## おまけ

### テストしてみる

テストもかけます。
とりあえずファイル生成。testフォルダ中に生成します。

```bash
touch test/Hello.js
```

とりあえずreturn値をチェックするだけ。

```js:test/Hello.js
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Hello Contract", function(){

    it("Shoud return Hello World.",async function(){

        const Hello = await ethers.getContractFactory("Hello");
        const hello = await Hello.deploy();

        await hello.deployed();

        expect(await hello.greet()).to.equal("Hello World");

    });

});
```

テストを実行します。

```bash
npx hardhat test test/Hello.js
```

>npx hardhat test とすると全てのテストが実行される。

テストネットやメインネットでのデプロイについては[こちら](https://qiita.com/zaburo/items/957eabdd4753aa7b3bba)をどうぞ。

## 参考

* https://zenn.dev/hid3/articles/b5f17e2167d4f7
* https://hardhat.org/hardhat-runner/docs/getting-started#quick-start