1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Hardhat】ガス代0のネットワークへデプロイする際に「insufficient funds for transfer」エラーが出たときの対処法

Posted at

はじめに

Hardhatでスマートコントラクトをデプロイしようとした際に、下記のエラーによりデプロイに失敗する場合があります。

Error: insufficient funds for transfer

これはトランザクションの送信者(署名者)のトークン残高が、ガス代(+送金額)を賄えない場合に発生します。

しかし、自分の場合はガス代が0となっているネットワークへデプロイしようとした際に発生しました。
「ガス代0なのにガス代不足!?」と当初はかなり困惑しました…。

Layer2や独自チェーンの中には、トランザクションのガス代が0になる設計のものがあります。
今回は同じような状況となった方を対象に、自分がデプロイに成功した際の対処方法を記載していきます。

開発環境

hardhat 2.24.1
秘密鍵等の機密保持のためdotenvを使用

対処法

※ネットワークによっては下記の対処法でも解決しない可能性がありますのでご了承ください。

対処法1:デプロイスクリプトにてgasLimitを調整する

deploy.ts
import { ethers } from "hardhat";

async function main() {
    // ガス上限の設定
    const block = await ethers.provider.getBlock("latest"); // デプロイ時に指定したネットワークの最新ブロックを取得
    const blockGasLimit = block?.gasLimit.valueOf() as bigint;
    const gasLimit = blockGasLimit - 100000n;   // 100000 gasの余裕を持たせる

    // コントラクトのデプロイ
    const testContract = await ethers.deployContract(
        "TestContract", 
        { gasLimit: gasLimit }  // ネットワークによっては設定が必要
    );
    await testContract.waitForDeployment();
    console.log(`testContract deployed to: ${testContract.target}`);
}

main().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});

ethers.deployContractのオプションであるgasLimitへ適当に十分な値を入れて試してみたのですが、自分の環境ではデプロイに失敗していました。
そのため、ネットワークの最新ブロックのgasLimitを取得し、少し余裕を持たせた値を設定することで、ネットワークの制限内に収めることができ、デプロイに成功しました。

対処法2:networks設定でgasPrice: 0を指定する

process.envは.envファイルからの参照です

hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import 'dotenv/config';

const config: HardhatUserConfig = {
  solidity: "0.8.0",
  typechain: {
    outDir: 'frontend/types',
    target: 'ethers-v6',
    alwaysGenerateOverloads: false, 
  },
  networks: {
    targetNetwork: {
      url: `${process.env.TARGET_NETWORK_URL}`,
      accounts: [`0x${process.env.TARGET_NETWORK_PRIVATE_KEY}`],
      gasPrice: 0, // ガス価格を明示的に 0 に設定
    },
  },
};

export default config;

hardhat.config.tsへ設定したネットワーク情報へgasPrice: 0を追加し、
ガス代ゼロでトランザクションを送信できる環境を構築することでもデプロイが成功しました。

注意点
gasPrice: 0を設定しても、ノード側がそれを許容していないとトランザクションが拒否されることがあるようです。
Issue #6519では、「gasPriceが0でも、送信者の残高が0だとトランザクションが失敗する」的なことが報告されているので、ガス代がゼロでも送信者に十分な残高が必要なケースがあるということになります。

対処法3?:ネイティブトークンの残高を確認する

案外抜けている可能性が無きにしも非ずなので一応記載。
.envファイルに設定した秘密鍵のアカウントにトークンが十分な量あるか確認しておきましょう。


一応、いずれの方法もデプロイ時のコマンドに特筆すべきことはありません。
>npx hardhat run --network targetNetwork scripts/deploy.ts

さいごに

この記事を書くにあたってガス代0なのにガス代不足エラーが出る根本的理由を調べてみたのですが、
・トランザクション作成時に、署名者の残高チェックが行われる
・gasPriceが0でも、gasLimitが極端に高いと「内部的に必要な残高がある」と判断されることがある
…からっぽいです。
ガス代が0でもgasLimitが高すぎると、Hardhat側で「残高不足」と判定されてしまうってことですね。
要はEVMの設計とツールの実装の“ズレ”からくる現象と思っておきましょう!
なのでサービス開発者だけではどうにもならん場合もあります。


まだまだweb3系のエラーに対する記事は多くないので、ピンポイントで困っている方にこの記事が引っかかれば幸いです。

1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?