Hardhat 本地链卡链?先看是不是关了自动挖矿

Hardhat 本地链跑合约,await tx.wait() 卡住不返回,感觉链死了。看着像 bug,其实基本都是配置问题。

快速定位

一条命令看当前区块号:

cast block-number --rpc-url http://127.0.0.1:8545

没有 cast 就用 curl:

curl -X POST http://127.0.0.1:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

隔几秒再跑一次,区块号不变——链停了。

原因 1:配了 auto: false

hardhat.config.js 里如果有:

networks: {
  hardhat: {
    mining: {
      auto: false,     // 关掉了自动挖矿
      // interval: 5000  // 或者只按间隔挖
    }
  }
}

交易发到内存池后不会被打包,得手动 mine:

await network.provider.send("evm_mine");

或者恢复自动挖矿:

await network.provider.send("evm_setAutomine", [true]);

原因 2:nonce 冲突

之前发过一个低 gas 交易占住了某个 nonce,后面的交易全排在它后面:

cast nonce 0x<address> --rpc-url http://127.0.0.1:8545

解法:发一个相同 nonce、更高 gas 的交易顶掉旧的(cancelTx 模式)。

原因 3:fork 主网时 RPC 挂了

npx hardhat node --fork https://eth-mainnet.g.alchemy.com/v2/xxx

Alchemy 超限、RPC 断线、网络超时,Hardhat 表现得就像卡住。开 debug 日志看:

DEBUG=hardhat* npx hardhat node

会看到”Waiting for chain state”之类的提示。

原因 4:不是链卡,是前端缓存了

Hardhat 每次重启链状态会重置,但前端还拿着旧合约地址、旧 ABI。清理编译产物:

rm -rf cache artifacts
npx hardhat compile
npx hardhat run scripts/deploy.js --network localhost

原因 5:evm_mine 返回 0 不等于失败

有人看到:

await network.provider.send("evm_mine");
// '0'

以为报错了。其实 '0' 是 RPC 的正常返回值,表示成功。区块号会 +1,验证一下:

await ethers.provider.getBlockNumber();

兜底:一键重置

想快速回到初始状态而不重启进程:

await network.provider.request({
  method: "hardhat_reset",
  params: [],
});

链状态、快照、内存池全清。跑测试之间用这个特别方便。

或者最粗暴——Ctrl+C 结束 npx hardhat node,重新起一个。

一句话总结

Hardhat “卡链” 九成是 auto: false 关了自动挖矿。先 evm_setAutomine [true] 或手动 evm_mine 一下,绝大多数情况就通了。