day23. hardhat – デプロイ結果の確認 –

day22では、デプロイまで実行しました。このガイドでは、デプロイされたコントラクトへの操作を実際に行い、正しくデプロイされていることを確認していきます。

day22では、デプロイまで実行しました。このガイドでは、デプロイされたコントラクトへの操作を実際に行い、正しくデプロイされていることを確認していきます。

TOC

デプロイ結果の確認

確認するためには、以下のものが必要となります。

  1. ローカルネット: hardhatによって提供されるローカルネットワーク環境です。hardhatのコマンドを実行するとすぐに利用可能な状態になります。2のデジタルウォレットからこのネットワークにある情報を閲覧できるようにするために、ローカルネット向けのRPCノードの設定をMetamaskで行います。
  2. デジタルウォレット(Metamask): ローカルネットは擬似的なアカウントが用意されます。各アカウントのETH残高を確認するためにデジタルウォレットにアカウント情報をインポートします。これによって、各操作の結果、ETH残高がどのように推移するかを確認することができます。
  3. 確認用スクリプト: 開発したコントラクトの関数を呼び出すためのスクリプトで、hardhatから実行することが可能です。Fundingコントラクトを例にすると、fund(投資)を実行したり、withdraw(引き出し)を実行したりするためのものです。

確認のためのローカル環境設定

まずは、前項の1, 2の設定(確認環境の準備)を行います。

ローカルネット向けRPCノードの設定

利用しているブラウザのMetamaskのプラグインから、設定 > ネットワーク > ネットワークを追加を順番に選択します。

設定 > ネットワーク > ネットワークを追加 を順番に選択します。

続けて表示される画面でネットワークを手動で追加を選択し、次の画像のような情報を入力します。これらはローカルネットにおけるRPCノードの設定情報になります。URLはローカルネットのRPCノードのURL、チェーンIDも同様にローカルネット上のものです。

続けて表示される画面でネットワークを手動で追加を選択し、次の画像のような情報を入力します。これらはローカルネットにおけるRPCノードの設定情報になります。URLはローカルネットのRPCノードのURL、チェーンIDも同様にローカルネット上のものです。

ローカルネットの起動

ローカルネットは、hardhatによって提供されます。次の形式のコマンドをコンソール上で実行すると、起動します。

Zsh
% yarn hardhat node

ローカルネットのアカウント情報のimport

ローカルネットを起動すると、次の画像のように複数のアカウントが自動でセットアップされます。これらのアカウントの情報を見るすべはこのままではないので、Metamaskから見れるようにする必要があります。

ローカルネットでノードを起動すると、複数のアカウントが自動でセットアップされます

そのためには、コンソールに表示されるアカウントのプライベートキーをMetamask上でインポートする必要があります。例えば、Account #0および#1のPrivate Keyの値をインポートします。

Metamaskでアカウントをインポートします。この画面の次でコンソール上に表示されたPrivate Keyを貼り付けます。

確認用スクリプト

ここでは、2つの確認用スクリプトを開発します。
対象のコントラクトは、day17で実装したものになります。

  1. fund.ts: fund関数を実行するスクリプト。実行するアカウントの残高がfundの金額分引かれる。
  2. withdraw.ts: withdraw関数を実行するスクリプト。コントラクトをデプロイしたオーナーのみ実行でき、コントラクトの残高をすべて引き落とすことができる。

fund.ts

TypeScript
// scripts/fund.ts
const { ethers, getNamedAccounts, deployments } = require("hardhat");

async function main() {
    const {user} = await getNamedAccounts()
    console.log(deployer)
    
    const funding = await ethers.getContract("Funding", user)
    const fundingAddress = await funding.getAddress()
    console.log(`Got contract Funding at ${fundingAddress}`)
    console.log("Funding contracct...")
    const txnResponse = await funding.fund({
        value: ethers.parseEther("1"),
    })
    await txnResponse.wait()
    console.log("Funded!")
}


main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error)
    process.exit(1)
  })
TypeScript
// scripts/fund.ts(抜粋)
    const { user} = await getNamedAccounts()

day22同様に、importしたgetNamedAccounts関数を使って、hardhat.config.tsに設定されているアカウント情報を取得します。今回は、userの方を取得します(アカウントリストの1番目が設定されています)。

TypeScript
// scripts/fund.ts(抜粋)
    const funding = await ethers.getContract("Funding", user)
    const fundingAddress = await funding.getAddress()

getContract関数は、コントラクト名と実行ユーザーの2つの引数を取ります。すでにday22でデプロイしたFundingコントラクトのインスタンスをuserアカウントで実行するために取得します。
このコントラクトのアドレスを取得した場合は、取得したコントラクトfunding変数からgetAddressを実行すると得ることができます。

TypeScript
// scripts/fund.ts(抜粋)
    const txnResponse = await funding.fund({
        value: ethers.parseEther("1"),
    })
    await txnResponse.wait()

取得したコントラクトのインスタンス(funding変数)からは、元々のスマートコントラクトで定義されている関数やメンバーを呼ぶことができます。fund関数は、day17にもある通り、Funding.solで定義されている関数になります。

ここで{ value: ethers.parseEther("1") }は、fund関数に送られるEtherの量を指定します。このコードでは、1 Etherをfund関数に送っています。ethers.parseEther()関数は、Etherの数をWei(Etherの最小単位)の形のBigNumberに変換します。

txnResponse.wait()は、トランザクションがマイニングされるのを待つことを表します。

※ Funding.solのfund関数では引数は定義されていないですが、送金額をこのように指定することが可能です。これは、Solidityにおいては、msg.sender(送信者)やmsg.value(送信する金額)といった変数は、グローバル変数として定義されているためです。そのため、関数を定義する際には、これらの変数は明示的に定義する必要はありません。

TypeScript
// scripts/fund.ts(抜粋)
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error)
    process.exit(1)
  })

この部分のコードは、main()関数の実行が成功したかどうかに応じてプロセスの終了コードを決定するものです。

  • main().then(() => process.exit(0)): これは、main()関数が成功裏に終了した場合に実行されます。ここでは、終了コード0を返しています。シェルスクリプトやコマンドラインアプリケーションでは、終了コード0は成功を意味します。
  • main().catch((error) => { console.error(error); process.exit(1); }): これは、main()関数が何らかの理由でエラーを投げた場合に実行されます。エラー情報はコンソールに出力され、その後終了コード1でプロセスが終了します。終了コード1は一般的にエラーを示します。

withdraw.ts

TypeScript
// scripts/withdraw.ts
import { error } from "console"

const { ethers, getNamedAccounts } = require("hardhat")

async function main() {
    const {deployer} = await getNamedAccounts()
    const funding = await ethers.getContract("Funding", deployer)
    const fundingAddress = await funding.getAddress()
    console.log(`Get contract funding at ${fundingAddress}`)
    console.log("Withdrawing from contract...")
    const txnResponse = await funding.withdraw()
    await txnResponse.wait()
    console.log("Got it back!")
}

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

コードとしては、fund.tsと同じ機能を使ったものばかりになります。実行する際は、deployerアカウント(コントラクトをデプロイしたオーナーと同一)を使っています。

確認スクリプトの実行

ローカルネットを起動させた状態で、同じくVS Codeのコンソールからスクリプトを実行します。

  1. fund.tsを実行する(user(アカウント#1)から1 ETHがコントラクトに送付される)。
    アカウント#1の残高が減少している(実行の前後でMetamaskで残高を確認する)
  2. withdraw.tsを実行する(deployer(アカウント#0)によってコントラクトからコントラクトの残高が引き出される)。
    アカウント#0の残高が増加している(実行の前後でMetamaskで残高を確認する)

スクリプトの実行は以下のような形式で行うことができます。runに続けて、スクリプト名を指定し、また、networkオプションに続けてネットワーク名を指定します。ここでは、ローカルネットでの実行なので、ローカルホストを指定します。

Zsh
yarn hardhat run scripts/withdraw.ts --network localhost

以下に、fund.tsの実行例を示します。

VS Codeのコンソールからfund.tsを実行
fund.ts実行後のMetamask画面

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

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