見出し画像

【保存版】Hardhatによるコントラクトのデプロイ方法について

こんにちは、CryptoGamesの高橋です。

クリスペの会社です。

また、CryptoMaidsのアンバサダーを務めさせていただいております。

始める前に
・秘密鍵を扱うことになります。慣れないうちは、テストアカウントで実施するようにお願いします。秘密鍵の扱いは厳重にお願いします。

・全く同じように実行してもエラーが出ることは多々あります。個々のPCの設定が関係していることが少なくありません。その場合、私では解決ができませんので、ググるなどして、ご自身で解決に向かうようお願いします。

0 事前準備

Hardhatを扱うためにはNode.jsのインストールが必要です。

MacWindowsではやり方が異なりますので、ご自身のPCに応じて、インストールを行ってください。

スクリーンショット 2022-02-21 9.06.50

1 Hardhatのインストール

次のようにしてHardhatのインストールを行いましょう。

mkdir hardhat-tutorial
cd hardhat-tutorial
npm init --yes
npm install --save-dev hardhat

下のようにやってなります。

スクリーンショット 2022-02-21 5.57.02

「npm init --yes」を行うことで、「package.json」というファイルができました。

「npm install --save-dev hardhat」を行うことで依存関係(関係してくるファイルなど)をインストールできました。

2 設定ファイル「hardhat.config.js」を作ろう

Hardhatの肝である、「hardhat.config.js」を作りましょう。

次のコマンドを実行しましょう。

npx hardhat

初回実行時は、次のようになると思います。

スクリーンショット 2022-02-21 6.06.47

「Create an empty hardhat.config.js」を実行して行きましょう。

<ここからは上の画面がでない場合>

ちなみに、すでに作ったことがある方は、下のような状態になると思います。

スクリーンショット 2022-02-21 6.03.15

今回の目的は、あくまでも「hardhat.config.js」ができれば良いので、下のようにファイルを作って行きましょう。

スクリーンショット 2022-02-21 6.17.35

require("@nomiclabs/hardhat-waffle");
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
 solidity: "0.7.3",
};

↑こちらをコピペ

3 便利なプラグインをインストールしよう

とても使い勝手の良いプラグインである

①Ethers.js
②Waffle

インストールしましょう。

npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai

スクリーンショット 2022-02-21 6.25.19

これでインストールができました。

4 コントラクトのファイルを作成しよう

まずは、空のsolidityファイルを作ってみましょう。

下のように「contracts」フォルダと、その中に「Token.sol」というファイルを作ってください。

スクリーンショット 2022-02-21 6.30.04

空のファイルができましたら、公式のサンプルコードを貼り付けましょう。

ざっくりみたところ、「MHT」というトークンを作っていそうですね。

スクリーンショット 2022-02-21 6.34.00

こちらです。

// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity ^0.7.0;

// This is the main building block for smart contracts.
contract Token {
   // Some string type variables to identify the token.
   // The `public` modifier makes a variable readable from outside the contract.
   string public name = "My Hardhat Token";
   string public symbol = "MHT";
   // The fixed amount of tokens stored in an unsigned integer type variable.
   uint256 public totalSupply = 1000000;
   // An address type variable is used to store ethereum accounts.
   address public owner;
   // A mapping is a key/value map. Here we store each account balance.
   mapping(address => uint256) balances;
   /**
    * Contract initialization.
    *
    * The `constructor` is executed only once when the contract is created.
    */
   constructor() {
       // The totalSupply is assigned to transaction sender, which is the account
       // that is deploying the contract.
       balances[msg.sender] = totalSupply;
       owner = msg.sender;
   }
   /**
    * A function to transfer tokens.
    *
    * The `external` modifier makes a function *only* callable from outside
    * the contract.
    */
   function transfer(address to, uint256 amount) external {
       // Check if the transaction sender has enough tokens.
       // If `require`'s first argument evaluates to `false` then the
       // transaction will revert.
       require(balances[msg.sender] >= amount, "Not enough tokens");
       // Transfer the amount.
       balances[msg.sender] -= amount;
       balances[to] += amount;
   }
   /**
    * Read only function to retrieve the token balance of a given account.
    *
    * The `view` modifier indicates that it doesn't modify the contract's
    * state, which allows us to call it without executing a transaction.
    */
   function balanceOf(address account) external view returns (uint256) {
       return balances[account];
   }
}

 ​5 コンパイルしてみよう

では、コントラクトのコードができたので、コンパイルをしてみましょう。

こちらのコードです。

npx hardhat compile

スクリーンショット 2022-02-21 6.37.42

このようになれば、成功です。

6 テストコードを作成しよう

では、コンパイルができたので、次はテストをしてみましょう。

まずは、下のように空のテストファイルを用意します。

スクリーンショット 2022-02-21 6.46.52

では、公式のサンプルコードをコピペしましょう。

スクリーンショット 2022-02-21 6.49.34

大まかには、発行した総トークン量と、発行者が持っている総トークン量が一致しているかを確認するテストです。

↓こちらのコードです。

const { expect } = require("chai");
describe("Token contract", function () {
 it("Deployment should assign the total supply of tokens to the owner", async function () {
   const [owner] = await ethers.getSigners();
   const Token = await ethers.getContractFactory("Token");
   const hardhatToken = await Token.deploy();
   const ownerBalance = await hardhatToken.balanceOf(owner.address);
   expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
 });
});

7 テストを実行しよう

では、テストコードができたので、実際にテストをしてみましょう。

↓こちらのコードを実行しましょう。

npx hardhat test

スクリーンショット 2022-02-21 6.56.32

このようになれば、テスト成功です。

8 コントラクトの実行準備

8ー1 .envのインストール

秘密鍵などのコードへのべたうちは避けたいので、ここでは「dotenv」を使って行きます。

次のようにインストールしましょう。

npm install dotenv --save

スクリーンショット 2022-02-21 7.15.02

8ー2 .gitignoreファイルを設定する(大事!)

重要
前提として、私は、自分で自信を持って操作できるようになるまでは秘密鍵を扱ったコードはGitに上げない方が良いと思っています。
誤って上げてしまった場合、秘密鍵が漏れてしまいます。

私は、上記のように考えておりますが、もし上げた場合に備えて、「.env」ファイルをgitにコミットされないようにします。

スクリーンショット 2022-02-21 7.20.46

上のように「hardhat-tutorial」直下に空の「.gitignore」を作成し、中に「.env」と入力します。

これで、後に作る「.env」というファイルはgitの管理から外れます。

9 コントラクトの実行ファイルを作る

さて、準備ができましたので、デプロイ用の実行ファイルを作って行きます。

Remixの場合「deploy」ボタンを押すだけだったので、面倒だと感じるかもしれません。

しかし、実はファイルで実行することにより、複雑な操作を行うことができるようになるため、後々便利さを実感できると思います。

スクリーンショット 2022-02-21 7.30.07

まずは、上のように「scripts」フォルダとその中に「deploy.js」を作ってみましょう。

できましたら、公式のサンプルコードを貼り付けましょう。

スクリーンショット 2022-02-21 7.35.20

↓こちらです。

async function main() {
 const [deployer] = await ethers.getSigners();
 console.log("Deploying contracts with the account:", deployer.address);
 console.log("Account balance:", (await deployer.getBalance()).toString());
 const Token = await ethers.getContractFactory("Token");
 const token = await Token.deploy();
 console.log("Token address:", token.address);
}
main()
 .then(() => process.exit(0))
 .catch((error) => {
   console.error(error);
   process.exit(1);
 });

10 テストとして、実行しましょう

デプロイ時には、「どのネットワークに」と指定しますが、まずは仮でテストとして実行してみましょう。

npx hardhat run scripts/deploy.js

スクリーンショット 2022-02-21 8.00.53

今回はコントラクトの中身には触れませんが、何やらトークンの発行に成功していそうですね。

11 インフラキーを取得する

これから、Rinkebyネットワークとやり取りをするためのゲートウェイを取得します。

今回はこちらの「Infura」を利用しようと思います。

まずは登録を行ってください。(無料でできます。)

できましたら、下の手順に沿って「Project ID」を取得してください。

スクリーンショット 2022-02-21 8.25.03

「Create New Project」を選択

スクリーンショット 2022-02-21 8.25.17

Product「Ethereum」、名前は任意のもので「Create」

スクリーンショット 2022-02-21 8.25.42

すると、下のようにできました。

こちらの「Project ID」を次のパートで使います。

スクリーンショット 2022-02-21 8.26.56

12 Rinkebyテストネットで実行しましょう。

12ー1 .envファイルを設定しよう

注意 
ここから秘密鍵を扱うことになります。
自分で流れをしっかりと理解し、責任を持って実行ができるまでは、必ずテストアカウントで実行をしてください。
また秘密鍵の扱いには十分ご注意ください。

まずは、「hardhat-tutorial」の直下に「.env」ファイルを作成してください。

スクリーンショット 2022-02-21 8.21.11

ファイルの中に前章で取得したInfuraProject IDと秘密鍵を入れます。

スクリーンショット 2022-02-21 8.42.15

繰り返しになりますが、秘密鍵はテストアカウントのものを使い、扱いには十分気をつけてください。
INFURA_KEY=""
PRIVATE_KEY=""

12ー2 hardhat.config.jsを追記しよう

Hardhatの設定ファイルである、「hardhat.config.js」を下のように書き換えましょう。

これで、dotenvRinkebyネットワークが使えるようになりました。

スクリーンショット 2022-02-21 8.47.21

require("@nomiclabs/hardhat-waffle");
require("dotenv").config();

/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
 solidity: "0.7.3",

 networks: {
   rinkeby: {
     url: "https://rinkeby.infura.io/v3/" + process.env.INFURA_KEY,
     accounts: [`${process.env.PRIVATE_KEY}`],
   },
 },
};

13 Rinkebyで実行しよう

では、準備ができましたので、実行しましょう。

npx hardhat run scripts/deploy.js --network rinkeby

 ​こちらのコードで、Rinkebyネットワークでの実施を指定しています。

スクリーンショット 2022-02-21 8.51.54

このように、うまく実施ができました!

なお、RinkebyのETHがないと失敗しますのでご注意ください。

こちら、参考です。

14 メタマスクで見てみよう

では、実際にできたかをメタマスクで見てみましょう。

今回はトークンを作るコントラクトでした。

スクリーンショット 2022-02-21 8.58.04

下に、先ほどできたコントラクトアドレスなどを入れます。

スクリーンショット 2022-02-21 8.58.43

「Import Tokens」を選択すると。。

スクリーンショット 2022-02-21 8.58.50

できました!

スクリーンショット 2022-02-21 8.58.57

これで、無事にHardhatを使って、実際のデプロイを行うことができました!

今回は以上です。

サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊