Skip to main content
This page covers the most common errors you may encounter while developing on StableNet Testnet, along with their causes and fixes.

”replacement transaction underpriced”

What it means: You are trying to replace a pending transaction with the same nonce, but the new transaction’s fees are not high enough to displace the original. Fix: Use both --gas-price and --priority-gas-price with the higher reference values:
cast send <CONTRACT> "methodName()" \
  --rpc-url https://api.test.stablenet.network \
  --private-key $PRIVATE_KEY \
  --gas-price 80000000000000 \
  --priority-gas-price 35000000000000
For Hardhat / ethers.js, pass both fields explicitly:
{
  maxPriorityFeePerGas: ethers.parseUnits("35000", "gwei"), // 35000000000000 wei
  maxFeePerGas: ethers.parseUnits("80000", "gwei"),         // 80000000000000 wei
}
The 35,000 Gwei / 80,000 Gwei values are field-tested reference values for StableNet Testnet. They are not official protocol specifications — adjust based on observed mempool conditions.

”NativeCoinAdapter: transfer amount exceeds balance”

What it means: Your wallet balance is not enough to cover both the transfer amount and the estimated gas cost. The NativeCoinAdapter uses the same balance for gas and for WKRC transfers. Fix: Lower your gas price and retry. High maxFeePerGas values inflate the gas reservation during estimation, leaving less balance available for the transfer.
cast send $WKRC \
  "approve(address,uint256)" $CONTRACT $AMOUNT \
  --rpc-url https://api.test.stablenet.network \
  --private-key $PRIVATE_KEY \
  --priority-gas-price 27600000000000
Do not raise --priority-gas-price above 27,600 Gwei when calling WKRC system contract methods unless necessary. Higher values increase the gas reservation and can trigger this error during estimation.

Transaction timeout (cast / Hardhat)

What it means: cast returned a timeout error, or waitForDeployment() / tx.wait() appears to hang. This does not mean the transaction failed. What to do: Wait 1–2 minutes. Your transaction is already in the mempool and will be confirmed once a block includes it. Block time on StableNet is ~1 second, but mempool propagation can add latency.
Do not cancel and resubmit with the same nonce. Doing so creates a nonce conflict and may result in a “replacement transaction underpriced” error. Check the Explorer to confirm whether your transaction is pending or already confirmed.

maxFeePerGas not set — transaction rejected

What it means: You set maxPriorityFeePerGas but omitted maxFeePerGas. On StableNet, maxFeePerGas defaults to 0 when not specified, which causes the transaction to be rejected even if the priority fee is correct. Fix: Always specify both fields together:
const tx = await wallet.sendTransaction({
  to: "0xRecipientAddress",
  value: ethers.parseEther("1.0"),
  maxPriorityFeePerGas: ethers.parseUnits("27600", "gwei"),
  maxFeePerGas: ethers.parseUnits("80000", "gwei"),
});

npx hardhat init fails or behaves unexpectedly

What it means: Hardhat v3 changed npx hardhat init to an interactive-only flow that may not scaffold a standard JavaScript project correctly in all environments. Fix: Install Hardhat v2 explicitly:
npm install --save-dev hardhat@2
npx hardhat init
Select “Create a JavaScript project” when prompted. Hardhat v2 is fully compatible with StableNet Testnet.

import dotenv/config fails on Node.js v20+

What it means: On Node.js v20 and later, import 'dotenv/config' or require('dotenv').config() may cause import resolution errors depending on your module setup. Fix: Use the built-in --env-file flag instead of the dotenv package:
node --env-file=.env your-script.js
Your .env file format stays the same:
PRIVATE_KEY=your_private_key_here
The --env-file flag is available in Node.js v20.6.0 and later. If you are on an older version, use dotenv as normal.

viem privateKeyToAccount — invalid private key

What it means: privateKeyToAccount requires a hex string that starts with 0x. If your .env file stores the key without the prefix (e.g., PRIVATE_KEY=abc123...), viem will throw an invalid key error. Fix: Prepend 0x when passing the environment variable:
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`);
Your .env file should store the key without the 0x prefix:
PRIVATE_KEY=your64hexcharsprivatekey
Alternatively, store the key with the 0x prefix in .env (PRIVATE_KEY=0x...) and pass it directly as process.env.PRIVATE_KEY. Pick one convention and be consistent across your project.

Next Steps

Foundry Quickstart

Deploy a WKRC payment contract with Foundry.

Hardhat Guide

Configure Hardhat and deploy contracts on StableNet.

SDK Guide

Connect with ethers.js or viem and interact with WKRC.