🏠

Solidity に Ethereum のスマコンのメモを書いておいたのだけど、書いた、スマコンをテストしたりデプロイしたりするのに使うのが Hardhat。長くなったので別記事にすることにしました。これはこれで全然ややこしい。

1 環境構築

npm install --save-dev hardhat
npx hardhat

を実行すると、どうするか聞かれる。 hardhat.config.js が見つかれば、どんなコマンド(task と言うらしい)があるか見れる。そのファイルの中身が下記。

require("@nomiclabs/hardhat-waffle");

// this file contains API_KEYS and the private key for the account;
// do not commit this file!
const secret = require("./secret.json");

const ENDPOINT = `https://rinkeby.infura.io/v3/${secret.INFURA_API_KEY}`;

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.7.3",
  networks: {
    rinkeby: {
      url: ENDPOINT,
      accounts: [`0x${secret.PRIVATE_KEY}`],
    },
  },
};

この networks の中の情報が、スマコンをデプロイするときに必要な情報です。詳細は下記デプロイする箇所参照。

ethers.js と waffles でいいので、下記のライブラリも入れる。

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

なんか chai 入ってるけど…気にしない。

2 最初のコントラクトを書いて、テストをしてみる。

がばがばトークンの内容については、Token.sol参照。テストも書いてあります。

で、これをコンパイルするには、

npx hardhat compile

artifacts ディレクトリに諸々コンパイルされたものが作られています。

でテストは下記実行、 mkdir test して、中に Token.js を入れる、こちらも内容については、Token.sol参照。

npx hardhat test

で test 実行。

3 Test の次は「他のネットワークにデプロイする。」ためのスクリプト

hardhat はスクリプトを介して、ネットワークに対してデプロイする。(他の事もできると思うけど)グローバル変数として、 HRE (Hardhat Runtime Environment) がアクセスできるらしく、ちょくちょく出てくる、 ethers とか artifacts はここから出てくるものだと思う。

async function main() {
    const [deployer] = await ethers.getSigners();
    const contractName = "Token";

    console.log("Deploying contracts with the account:", deployer.address);
    console.log("Account balance:", (await deployer.getBalance()).toString());

    const Token = await ethers.getContractFactory(tokenName);
    const token = await Token.deploy();

    console.log("'%s' address: %s", tokenName, token.address);

    saveForFrontend(token, "Token"); // for using the contract from the frontend
}

で、チュートリアルにはこれでデプロイできると言う話だけど、フロントエンドで使うためには、コントラクトの ABI (ex: Token.json) とそのコントラクトのアドレスが必要になるので、上の最後の関数はそのためのもの、以下はその内容。

function saveForFrontend(token, name) {

  const fs = require("fs");
  const contractsDir = __dirname + "/../frontend/src/contracts";

  if (!fs.existsSync(contractsDir)) {
    fs.mkdirSync(contractsDir);
  }

  fs.writeFileSync(
    contractsDir + "/contract-address.json",
    JSON.stringify({ Token: token.address }, undefined, 2)
  );

  const TokenArtifact = artifacts.readArtifactSync(name);

  fs.writeFileSync(
    contractsDir + "/" + name + ".json",
    JSON.stringify(TokenArtifact, null, 2)
  );
}

で、以上を実行する。

main()
    .then(()=> process.exit(0))
    .catch(()=>{
        console.error(error);
        process.exit(1);
    });

だとして、script を run する時に network を指定するとそのネットワークにデプロイできる。

npx hardhat run scripts/deploy.js --network {NETWORK_NAME}

この引数は hardhat.config.js で設定したやつ。指定しなければ、hardhat のローカルノードにデプロイされる。が、ローカルノードなので、プロセスは生き残らない。(でも console.log で、一応挙動をみることはできる。)

メイン・テストネットワークの URL に関しては、alchemy とか infura なんちゅう、デプロイ代行サービスが用意されている。当たり前だけど、 API_KEY や、 PrivateKey はファイルに書いたり、 git のコミットをしないこと。

ここで、テストネットへのデプロイにも偽 eth が必要なので、それを蛇口 (Faucet) を捻るようにしてできるサービスがあるのだが、なぜか軒並み Ropsten ファセット(蛇口)が機能しなかったので、結局 Rinkeby と言うテストネットで展開してみた。

https://rinkeby.etherscan.io/address/0x51269463f85f77e36e6C11425eC6694f65851449

ここをみると、合計 0.021 eth を蛇口から汲んで、今見ると残高が、0.0203eth となっているので、展開に、0.007eth 必要だったことになります。時価 2600 円くらい!高い。

4 Frontend 開発?

なんか感覚ですが、フロントエンドはフロントエンドで別にレポジトリを作って開発した方がいい気がします…。

Date: 2021-09-01 14:44

Author: Yasushi Sakai

Created: 2021-09-01 Wed 16:54