LoginSignup
3
1

Hardhatを使ってデプロイしたコードを一括で全てEtherscanに登録する

Last updated at Posted at 2023-12-25

Etherscanではコードを登録すると、対象のコントラクトのページにて登録したコードが確認できるようになります。
例えばWBTCだと、下記のページでコードを確認できます。
https://etherscan.io/token/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599#code
全画面_2023_12_24_12_22.png

コードの登録はWebページから1つずつ行うこともできますが、今回はhardhatを利用してデプロイしたコードを一括で全て登録する方法を紹介します。

NPMモジュールをインストールする

hardhatがインストールされているリポジトリで、@nomicfoundation/hardhat-verifyをインストールします。

npm install --save-dev @nomicfoundation/hardhat-verify

古いバージョンの@nomiclabs/hardhat-etherscanというモジュールも存在していますが、deprecatedとなっているので要注意です。

Hardhatのコンフィグを更新する

hardhat.config.tsで@nomicfoundation/hardhat-verifyを読み込みます。

hardhat.config.ts
import "@nomicfoundation/hardhat-verify";

また、コンフィグには以下のようにEtherscanのAPIキーの設定も追加する必要があります。

module.exports = {
  networks: {
    mainnet: { ... }
  },
  etherscan: {
    // https://etherscan.io/ で取得したEtherscanのAPIキー
    apiKey: "YOUR_ETHERSCAN_API_KEY"
  }
};

基本的な使い方

ターミナルでコマンドを実行してコードを登録する場合は、第一引数にコントラクトアドレス、第2引数には対象のコントラクトの引数を指定してnpx hardhat verifyを実行する必要があります。

例えば、コントラクトが

contract Foo {
  constructor (uint x) { ... }
}

の場合、コマンドは

npx hardhat verify --network mainnet DEPLOYED_CONTRACT_ADDRESS 1

となります。

タスクを作成して一括登録する

1. タスクを作る

Hardhatのタスク内でverifyタスクを実行するには、下記のようにrunファンクションでverify:verifyというサブタスクを呼び出す必要があります。

tasks/verify-all-contracts.ts
import { task } from 'hardhat/config';

task(
  'verify-all-contracts',
  'Verify and register the all contracts on Etherscan',
).setAction(async (_, { run }) => {
  const address = "対象のコントラクトアドレス";
  const constructorArguments = "対象のコントラクトのcounstructorに渡す引数";

  // Etherscanにコードを登録する
  await run('verify:verify', {
    address,
    constructorArguments,
  });
});

2. デプロイした全てのコントラクトの一覧を取得する

デプロイした全てのコントラクトの一覧を取得するために、deployments配下のターゲットとなるネットーワークのjsonファイルを全て読み込み、それらに対してそれぞれverify:verifyサブタスクを実行します。
また、前ステップでハードコードされていたaddressdeployments.getで取得した値に置き換えます。

tasks/verify-all-contracts.ts
import fs from 'fs';
import { task } from 'hardhat/config';

task(
  'verify-all-contracts',
  'Verify and register the all contracts on Etherscan',
).setAction(async (_, { deployments, run, network }) => {
  const constructorArguments = "対象のコントラクトのcounstructorに渡す引数";

  // デプロイした全てのコントラクトの一覧を取得する
  const fileNames = fs
    .readdirSync(`deployments/${network.name}`, {
      withFileTypes: true,
    })
    .filter((dirent) => dirent.isFile() && dirent.name.endsWith('.json'))
    .map(({ name }) => name.replace('.json', ''));

  // Etherscanにコードを登録する
  for (const fileName of fileNames) {
    const { address } = await deployments.get(fileName);

    await run('verify:verify', {
      address,
      constructorArguments,
    });
  }

3. constructorの引数のマッピングを作成する。

constructorの引数をファイル名からマッピングできるように、下記のようなオブジェクトを作成し、constructorArgumentsと置き換えます。

const constructorArgumentsMap = {
  Foo: [1],
  Bar: [50, 'string'],
};

最終的なコードはこちら。

tasks/verify-all-contracts.ts
import fs from 'fs';
import { task } from 'hardhat/config';

// constructorの引数のマッピングを定義する
const constructorArgumentsMap = {
  Foo: [1],
  Bar: [50, 'string'],
};

task(
  'verify-all-contracts',
  'Verify and register the all contracts on Etherscan',
).setAction(async (_, { deployments, run, network }) => {
  // デプロイした全てのコントラクトの一覧を取得する
  const fileNames = fs
    .readdirSync(`deployments/${network.name}`, {
      withFileTypes: true,
    })
    .filter((dirent) => dirent.isFile() && dirent.name.endsWith('.json'))
    .map(({ name }) => name.replace('.json', ''));

  // Etherscanにコードを登録する
  for (const fileName of fileNames) {
    const { address } = await deployments.get(fileName);

    const constructorArguments = constructorArgumentsMap[fileName];
    await run('verify:verify', {
      address,
      constructorArguments,
    });
  }

4. タスクをhardhat.config.tsで読み込む

作成したタスクをhardhat.config.tsで以下のように読み込みます。

hardhat.config.ts
import './tasks/verify-all-contracts';

これで作成したタスクがhardhatコマンドで実行できるようになります。

5. コマンドを実行する

下記コマンドで実行し、全てのコントラクトをEtherscanに登録します。

npx hardhat verify-all-contracts --network <任意のネットワーク>

mainnetに登録する場合は、npx hardhat verify-all-contracts --network mainnetとなります。

終わりに

これでいつでもEtherscanに気軽にコードが登録できるようになりました。
コントラクトがProxyパターンだったり、複数のチェーンをサポートしていて何度もコントラクトをデプロイしなければならないケースなどは特にこの一括で登録する方法が役に立つと思うので、ぜひ試してみてください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1