プロフェッショナルなスマートコントラクト開発:SolidityとHardhatによる実践ガイド

Programming tutorial - IT technology blog
Programming tutorial - IT technology blog

Web3開発における重大な責任

伝統的なWeb開発からブロックチェーン開発への転換は、まるでプログラミングを一から学び直すような感覚に近いものです。一般的なCRUDアプリケーションであれば、本番環境のバグは軽微な不都合に過ぎません。コンテナをロールバックするか、5分以内にホットフィックスをプッシュすれば済む話です。

しかし、ブロックチェーンにはそのようなセーフティネットはありません。Ethereumのメインネット上では、コードはイミュータブル(不変)です。たった一つのロジックエラーが、瞬時に何百万ドルものユーザー資金を消失させる可能性があります。2022年のNomad Bridgeのハッキング事件では、単純な設定ミスによって1億9,000万ドルの損失が発生しました。

多くの開発者は、ブラウザベースのエディタであるRemixからスタートします。Remixは10行程度の実験的なコードには適していますが、本番環境レベルの分散型アプリケーション(dApps)に求められるバージョン管理や自動テストスイートが不足しています。ローカル環境への移行はこの問題を解決しますが、同時に新たな摩擦も生じます。秘密鍵の管理、RPCプロバイダーの設定、そしてローカル環境が実際のネットワークを正確に反映しているかの確認といった作業が突然必要になるからです。

なぜ従来のローカル開発は困難なのか

この摩擦は、アーキテクチャの根本的な変化に起因します。私たちは、管理された中央集権的なサーバーから、すべてのトランザクションにコスト(ガス代)がかかる分散型台帳へと移行しています。オンチェーンの状態変更は永続的です。この環境では、多くのWeb開発者が最初は戸惑うような「テスト重視」の考え方が求められます。

二つ目の大きなハードルは断片化です。構造化されたフレームワークがないと、Solidityをコンパイルするために壊れやすいカスタムスクリプトを書いたり、ABIを手動でフロントエンドにコピーしたりすることになります。Hardhatは、スマートコントラクト開発をプロフェッショナルなソフトウェアエンジニアリングとして扱うことで、この問題を解決します。ローカルのEthereumネットワーク、高度なデバッグツール、そしてDevOpsライフサイクル全体を効率化するプラグインエコシステムを提供します。

解決策:プロフェッショナルなHardhatワークフロー

それでは、プロフェッショナルレベルの環境を一から構築してみましょう。「掲示板(Message Board)」コントラクトを作成し、厳格な自動テストを記述し、本番環境へのデプロイ準備を整えます。このローカルサイクルをマスターすることこそが、愛好家と、安全でスケーラブルなdAppsを構築できるエンジニアを分ける境界線となります。

1. 環境構築

マシンにNode.jsがインストールされていることを確認してください。まず、専用のディレクトリを作成し、Hardhatパッケージをインストールします。

mkdir my-dapp && cd my-dapp
npm init -y
npm install --save-dev hardhat

次のコマンドでプロジェクトを初期化します。

npx hardhat

「Create a JavaScript project」を選択します。Hardhatは、Solidityのロジック用のcontracts/、検証スクリプト用のtest/、ネットワーク設定を管理するためのhardhat.config.jsというクリーンなフォルダ構成を生成します。

2. スマートコントラクトの記述

contractsフォルダにMessageBoard.solを作成します。このコントラクトは、ユーザーがブロックチェーン上に文字列を保存できるようにし、その文字列が変更されるたびにイベントを発行します。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract MessageBoard {
    string private message;
    address public owner;

    // メッセージが更新されたときに発行されるイベント
    event MessageUpdated(string newMessage, address updatedBy);

    constructor(string memory initialMessage) {
        message = initialMessage;
        owner = msg.sender;
    }

    // メッセージを更新する関数
    function updateMessage(string memory newMessage) public {
        message = newMessage;
        emit MessageUpdated(newMessage, msg.sender);
    }

    // 現在のメッセージを取得する関数
    function getMessage() public view returns (string memory) {
        return message;
    }
}

このスニペットでは、ストレージ用の状態変数(state variables)と、フロントエンドに通知するためのイベント(events)を使用しています。これらは、あらゆる主要なDeFiプロトコルの構成要素となっています。

3. なぜテストが唯一のセーフティネットなのか

メインネットに触れる前に、ロジックの検証は必須です。HardhatはMochaとChaiを統合しているため、JavaScript開発者にとって移行は容易です。コントラクトの動作を検証するためにtest/MessageBoard.jsを作成します。

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("MessageBoard", function () {
  it("メッセージを更新し、イベントを発行すること", async function () {
    const MessageBoard = await ethers.getContractFactory("MessageBoard");
    const board = await MessageBoard.deploy("Hello World!");
    await board.waitForDeployment();

    expect(await board.getMessage()).to.equal("Hello World!");

    // メッセージの更新とイベントの発行をテスト
    await expect(board.updateMessage("新しいブロックチェーンメッセージ"))
      .to.emit(board, "MessageUpdated")
      .withArgs("新しいブロックチェーンメッセージ", await (await ethers.getSigners())[0].getAddress());
  });
});

npx hardhat testでテストスイートを実行します。自動テストは、バグのあるコントラクトをデプロイし、修正版にユーザーを移行させるためだけに数百ドルのガス代を支払うという悪夢を防いでくれます。

4. ローカルノードへのデプロイ

Hardhatにはローカルブロックチェーンが組み込まれています。実行すると、それぞれ10,000 ETHが事前に入金された20個の仮想アカウントが即座に提供されます。これは、実際のお金を使わずに迅速にプロトタイプを作成するのに最適です。ノードを起動します:

npx hardhat node

別のターミナルで、このローカルネットワークに対してデプロイスクリプトを実行します:

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

5. パブリックテストネット(Sepolia)への移行

ローカルテストに合格したら、Sepoliaテストネットに移動しましょう。これは「価値のない」ETHを使用してEthereumメインネットの環境を模倣したものです。hardhat.config.jsを更新し、Alchemyなどのプロバイダーと秘密鍵を含めるように設定します。

セキュリティ上のヒント: 鍵をハードコードしないでください。秘密鍵が漏洩すると、数秒でウォレットが空になります。.envファイルとdotenvを使用して、機密情報をGitHubに上げないようにしてください。

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.19",
  networks: {
    sepolia: {
      // 環境変数からAPI URLと秘密鍵を読み込む
      url: process.env.ALCHEMY_API_URL,
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};

Hardhatでより良い開発を

Web3での成功は、コードと同じくらいツール選びにかかっています。Hardhatは、Solidity内でのconsole.logの使用など、複雑なロジックのデバッグにおいて救世主となる画期的な機能を提供します。手動デプロイから卒業し、構造化された環境へと移行することで、コードの安全性、検証可能性、そしてプロフェッショナルな品質を確保できます。

ローカル開発サイクルの習得は、新しいブロックチェーンエンジニアにとって最大のハードルです。ローカルで確実に記述、テスト、デプロイができるようになれば、ガス代の最適化や高度なセキュリティ監査といった、業界のより困難な課題に集中できるようになります。

Share: