はじめに
Hardhatでスマートコントラクトをデプロイしようとした際に、下記のエラーによりデプロイに失敗する場合があります。
Error: insufficient funds for transfer
これはトランザクションの送信者(署名者)のトークン残高が、ガス代(+送金額)を賄えない場合に発生します。
しかし、自分の場合はガス代が0となっているネットワークへデプロイしようとした際に発生しました。
「ガス代0なのにガス代不足!?」と当初はかなり困惑しました…。
Layer2や独自チェーンの中には、トランザクションのガス代が0になる設計のものがあります。
今回は同じような状況となった方を対象に、自分がデプロイに成功した際の対処方法を記載していきます。
開発環境
hardhat 2.24.1
秘密鍵等の機密保持のためdotenvを使用
対処法
※ネットワークによっては下記の対処法でも解決しない可能性がありますのでご了承ください。
対処法1:デプロイスクリプトにてgasLimit
を調整する
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ファイルからの参照です
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系のエラーに対する記事は多くないので、ピンポイントで困っている方にこの記事が引っかかれば幸いです。