day22. hardhat – デプロイ –

Hardhat自体はデプロイの機能は提供していませんが、hardhat-deployなどのプラグインを用いるとデプロイのタスクを容易に作成することができます。ここでは、実際のデプロイスクリプトについて解説します。 day17で実装したFundingコントラクトを実装するためのスクリプトを見ていきます。

Hardhat自体はデプロイの機能は提供していませんが、hardhat-deployなどのプラグインを用いるとデプロイのタスクを容易に作成することができます。ここでは、実際のデプロイスクリプトについて解説します。
day17で実装したFundingコントラクトを実装するためのスクリプトを見ていきます。

TOC

デプロイスクリプト

早速ですが、実際のデプロイスクリプトの例を見てみます。

TypeScript
// deploy/01-deploy-funding.ts
import { HardhatRuntimeEnvironment } from "hardhat/types"
import { DeployFunction } from "hardhat-deploy/types"
import { developmentChains } from "../helpder-hardhat-config"
import { networkConfig } from "../helpder-hardhat-config"
import verify from "../scripts/verify"

const deployFunding: DeployFunction = async function (
    hre: HardhatRuntimeEnvironment,
) {
    const { getNamedAccounts, deployments, network } = hre
    const { deploy, log } = deployments
    const { deployer } = await getNamedAccounts()

    log("-----------------------------------------------------")
    log("Deploying Funding and waiting for confirmations...")
    const funding = await deploy("Funding", {
        from: deployer,
        args: [],
        log: true,
        waitConfirmations: networkConfig[network.name].blockConfirmations || 0,
    })
    log(`Funding deployed at ${funding.address}`)
    if (
        !developmentChains.includes(network.name) &&
        process.env.ETHERSCAN_API_KEY
    ) {
        await verify(funding.address, [])
    }
}

export default deployFunding

deployFunding.tags = ["all", "funding"]

このスクリプトでは、Fundingというコントラクトをデプロイしています。デプロイには、deploy関数を使っています。

hre, getNamedAccounts, deployments, network

11行目のコードのhreHardhatRuntimeEnvironment)はhardhat/typesでエクスポートされているもので、Hardhatの実行環境を表します。このhreという変数を通じて、Hardhatの実行環境で提供される機能にアクセスすることができます。例えば、左側で定義されている3つの変数は、このhreで定義されているプロパティ(機能)を表しています。

TypeScript
// deploy/01-deploy-funding.ts (抜粋)
    const { getNamedAccounts, deployments, network } = hre
  • getNamedAccounts: hardhat-deployプラグインが提供する関数で、設定ファイル(hardhat.config.ts)で名前を付けたアカウントのリストを取得します。各ネットワークに対して名前付きアカウントを設定することができ、これを使うことでスクリプトの中でアカウントを簡単に参照することができます。例えば、デプロイするアカウントをdeployerとして設定した場合、getNamedAccountsを使って{ deployer }という形でアカウントを取得できます。
  • deployments: hardhat-deployプラグインが提供するオブジェクトで、デプロイ関連の操作を行うためのメソッドを提供します。具体的には、スマートコントラクトのデプロイ (deployメソッド)、デプロイ済みのスマートコントラクトの取得 (getメソッド)、デプロイ済みのすべてのスマートコントラクトの取得 (allメソッド)、などが可能です。また、デプロイ中の内容をコンソール出力するための関数、logも含まれます。
  • network: は現在選択されているネットワークとその設定に関連する情報や機能を提供します。name(ネットワーク名)、 config(ネットワークの設定: RPC URL, chain idなど。詳細はday21も参照すると分かりやすいです。)

上記を踏まえて、11、12行目を参照すると実際にgetNamedAccounts, deploymentsからそれぞれ、deploy, deployerを取得しています。deployは実際にデプロイを行うための処理を実行する関数で、deployerは、deployを実行する際に利用するユーザーです(そして、このアカウントは、設定ファイルで定義しています。day21の51行目以降のnamedAccountsの箇所)。

TypeScript
// deploy/01-deploy-funding.ts (抜粋)
    const { deploy, log } = deployments
    const { deployer } = await getNamedAccounts()

deploy関数

実際のデプロイは16行目で行われています。これまでで読み込んだdeploy関数が実際に実行されている箇所になります。

TypeScript
// deploy/01-deploy-funding.ts (抜粋)
    const funding = await deploy("Funding", {
        from: deployer,
        args: [],
        log: true,
        waitConfirmations: networkConfig[network.name].blockConfirmations || 0,
    })

deploy関数では、次に記載するような引数を取得します。

  • name: デプロイするコントラクトの名前です。これは一意でなければならず、特定のコントラクトのデプロイメントを参照するために使用されます。
  • from: トランザクションを送信するアカウントのアドレスです。このアカウントがコントラクトのデプロイメントに必要なガスを支払います。
  • args: コントラクトのコンストラクタに渡す引数の配列です。つまり、開発したスマートコントラクトのコンストラクタの仕様に併せて、引数を定義します。
  • log: trueに設定すると、デプロイメントの詳細がコンソールにログとして出力されます。
  • waitConfirmations: ブロックチェーンでは、該当のトランザクションがブロックに含まれ、ネットワークによって検証されると、「確認」されたことになります。この設定項目は、確認の数を指定します(確認が多いほど、そのトランザクションが改ざんされる可能性は低くなります。しかし、多くの確認を待つことは、それだけデプロイメントが完了するまでの時間を長くする)

veirfy

次のソースは、Etherscanに検証を依頼している箇所になります。実際に、検証を依頼しているのは、verify関数の部分になりますが、これは、別のファイルとして、scriptsの下にverify.tsというファイルを配置して使っています。

TypeScript
// deploy/01-deploy-funding.ts (抜粋)
    if (
        !developmentChains.includes(network.name) &&
        process.env.ETHERSCAN_API_KEY
    ) {
        await verify(funding.address, [])
    }
TypeScript
// scripts/verify.ts
import { run } from "hardhat"

const verify = async (contractAddress: string, args: any[]) => {
    console.log("Verifying contract...")
    try {
        await run("verify:verify", {
            address: contractAddress,
            constructorArguments: args,
        })
    } catch (e: any) {
        if (e.message.toLowerCase().includes("already verified")) {
            console.log("Already verified!")
        } else {
            console.log(e)
        }
    }
}

export default verify

7行目のrun関数は、hardhatによって提供されるもので、hardhatのタスクを実行することができます。Hardhatのタスクをプログラム的に実行するための関数です。Hardhatには、コンパイルやテスト、デプロイなどのための標準的なタスクがいくつか含まれており、これらのタスクはhardhatコマンドラインツールを使って手動で実行することができます。しかし、これらのタスクをスクリプト内から直接呼び出すこともできます。それがrun関数の役割です。

基本的な使用方法は以下のような形式となります。上記の例では、検証(verify:verify)タスクを実行しています。引数としては、デプロイしたコントラクトのアドレスとコントラクトのコンストラクターの引数を取ります(17行目でデプロイした結果としてデプロイしたコントラクトを取得していますが(funding)、funding.addressとすることでデプロイしたコントラクトのアドレスが取得できます)。

TypeScript
await hre.run('taskName', taskArguments)

run関数を実行する部分は、try~catchで囲われており、tryで試行しているrun関数の実行がうまく行かなかった場合、catch以降でエラーを取得し、コンソールへのエラー出力を行っています。

export

TypeScript
// deploy/01-deploy-funding.ts (抜粋)
export default deployFunding

deployFunding.tags = ["all", "funding"]

TypeScriptのexport文は、モジュールから関数、オブジェクト、値、型などをエクスポート(公開)するために使います。これにより、他のモジュールからimport文を使ってエクスポートしたエンティティを利用することができます。上記の例では、先に定義されているdeployFunding関数を公開し、利用できるようにしています。

続けて次の部分では、デプロイを実行する際のオプションを定義しています。オプションとして--tags allとした場合、allのタグがついている関数が実行されます。--tags fundingとした場合、fundingのタグがついている関数が実行されます(例えば、複数のデプロイスクリプトからデプロイが構成されている場合、全て実行するか、特定のデプロイスクリプトだけ実行するかといったことを指定することができます)。

デプロイスクリプトの実行

次に実際にローカルでデプロイを実行してみます。

Zsh
# console
% yarn hardhat deploy --network hardhat --tags all
yarn run v1.22.19
$ /Users/username/code/token-village/funding/node_modules/.bin/hardhat deploy --tags all
Generating typings for: 1 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 6 typings!
Compiled 1 Solidity file successfully
-----------------------------------------------------
Deploying Funding and waiting for confirmations...
deploying "Funding" (tx: 0xbc444ca6c542123b21a0f1a3515a8d8f2f43b980f8e747417596779369851eda)...: deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3 with 538126 gas
Funding deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3
  Done in 6.67s.
%

デプロイは次のような形式で実行することができます。

Zsh
% yarn hardhat deploy --network Network-Name [--tags Tag-Name]

networkオプションには、ネットワーク(ローカル(hardhat)、テストネット(sepoliaなど)、メインネット(mainnet))を指定します。mainnet以外のネットワークについては、hardhat.config.tsで定義されている必要があります(設定については、day21参照)。

ご意見をお聞かせください!

web3チュートリアルシリーズについてのご意見を是非お聞かせください。

この記事、または、web3チュートリアル全体について、是非、あなたのご意見をお聞かせください。
アンケートはこちらからご回答いただけます。

無料相談承ります

ITの専門家が無料相談を受け付けます。web3以外のテーマでもOKです。

オンラインでの無料相談を承っています。ご希望の方は、お問い合わせフォームよりご連絡ください。
ITの専門家があなたのご質問にお答えいたします。

Let's share this post !

Author of this article

After joining IBM in 2004, the author gained extensive experience in developing and maintaining distributed systems, primarily web-based, as an engineer and PM. Later, he founded his own company, designing and developing mobile applications and backend services. He is currently leading a Tech team at a venture company specializing in robo-advisory.

Comments

To comment

CAPTCHA


TOC