In the world of Ethereum blockchain development, encountering pending transactions is a common challenge—especially when you're testing on the mainnet. A transaction stuck in the pending state can block subsequent transactions from being processed, causing delays and frustration. This guide walks you through how to programmatically cancel a pending Ethereum transaction using code, so you can regain control of your wallet’s nonce and continue with new operations.
Whether you're a developer testing smart contracts or managing DeFi interactions, understanding how to handle stuck transactions is essential. We’ll cover the logic behind cancellation, required parameters, and provide a working JavaScript implementation using Alchemy and Web3.
Understanding Pending Transactions on Ethereum
When you submit a transaction to the Ethereum network, it enters the mempool—a pool of unconfirmed transactions waiting for miners (or validators in proof-of-stake) to include it in a block. If your gas price is too low, miners may ignore your transaction, leaving it stuck in a pending state for hours or even days.
While you can't truly "delete" a transaction from the blockchain, you can replace it by sending a new transaction with the same nonce but a higher gas fee. This effectively cancels the original one by overriding it.
🔁 Ethereum uses nonces to ensure transaction order. Each transaction must have a unique, sequential nonce. Reusing a nonce with a new transaction replaces the previous one if confirmed first.
Why Cancel a Pending Transaction?
Here are common scenarios where canceling becomes necessary:
- Your transaction has been pending for over 24 hours.
- You set an unreasonably low gas price.
- A new high-priority transaction needs to go through.
- You want to avoid wallet lock-up due to nonce congestion.
Instead of waiting indefinitely, replacing the transaction gives immediate resolution.
👉 Learn how to manage Ethereum transactions like a pro with advanced tools.
Step-by-Step: Canceling a Pending Transaction via Code
Step 1: Gather Transaction Details
To replace a pending transaction, you need its core details:
- From Address: Your wallet address.
- Nonce: The exact nonce of the pending transaction.
- Gas Limit: Usually 21,000 for simple transfers.
- Gas Price: Must be higher than the original to incentivize miners.
You can retrieve this data using Etherscan. Enter your transaction hash, and look for:
From
To
Nonce
Gas Price
Input Data
If the Input Data
field is 0x
, it's a simple ETH transfer.
Step 2: Set Up Your Development Environment
Install required dependencies:
npm install dotenv @alch/alchemy-web3
We'll use Alchemy Web3 for reliable node access and easier integration.
Step 3: Build the Cancellation Transaction
The key idea is to send a zero-value transaction to your own address (or any), with:
value: 0
input: "0x"
(empty data)- Same
nonce
as the pending tx - Higher
gasPrice
This creates a replacement transaction that “cancels” the original.
Example Transaction Object
let tx = {
from: "0xd6cc8a078ef9081ad86210cca052923437f260c5",
to: "0x4bf60761fb54588cad44c146d2e2632763c6cf36",
nonce: 97,
value: 0,
input: "0x",
gas: "21000",
gasPrice: "30000000000", // 30 Gwei
};
💡 Tip: Use ETH Gas Tracker to check current network conditions. Aim for at least 10–20% above average gas prices.
Step 4: Sign and Broadcast the Replacement
Use your private key to sign the transaction locally, then broadcast it via Alchemy.
Full Script Example
import dotenv from "dotenv";
import { createAlchemyWeb3 } from "@alch/alchemy-web3";
dotenv.config();
const web3 = createAlchemyWeb3(process.env.MAINNET_RPC_URL);
const PRIVATE_KEY = process.env.PRO_PRIVATE_KEY;
const PUBLIC_ADDRESS = process.env.PRO_PUBLIC_KEY;
(async () => {
try {
const nonce = await web3.eth.getTransactionCount(PUBLIC_ADDRESS);
let tx = {
from: PUBLIC_ADDRESS,
to: PUBLIC_ADDRESS, // Sending to self is acceptable
nonce: nonce, // Must match pending tx nonce
value: "0",
input: "0x",
gas: "21000",
gasPrice: await web3.eth.getGasPrice(), // Or manually set higher
};
// Override gas price with higher value (e.g., 50 Gwei)
tx.gasPrice = web3.utils.toWei('50', 'gwei');
const signedTx = await web3.eth.accounts.signTransaction(tx, PRIVATE_KEY);
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log("Transaction successful with hash:", receipt.transactionHash);
} catch (error) {
console.error("Error sending transaction:", error);
}
})();
⚠️ Security Note: Never expose your private key in production code. Use environment variables and secure vaults.
Once confirmed, the original pending transaction will disappear from the mempool.
Alternative: Speed Up Instead of Cancel
You can also speed up a transaction using the same method—but instead of zero value and empty data, reuse the original to
, value
, and input
. Just increase the gasPrice
.
This keeps your intent intact while boosting confirmation chances.
👉 Discover powerful blockchain tools that simplify Ethereum development.
Best Practices for Managing Ethereum Transactions
- Monitor Gas Prices: Use real-time dashboards before submitting.
- Use Wallet Features: MetaMask allows built-in speed-up/cancel options.
- Track Nonces: Keep logs of sent transactions to avoid collisions.
- Test First on Testnets: Goerli or Sepolia reduce risk.
- Automate with Scripts: For frequent operations, build reusable tools.
Frequently Asked Questions (FAQ)
Q1: Can I cancel any pending Ethereum transaction?
Yes, as long as it remains unconfirmed. By replacing it with a same-nonce transaction (usually a zero transfer), you can effectively cancel it.
Q2: What happens to the original pending transaction after cancellation?
It gets dropped from the mempool once the replacement is confirmed. Nodes no longer recognize it.
Q3: Do I lose money when canceling a transaction?
Only the gas fee for the replacement transaction. The original ETH amount isn’t lost unless the first tx confirmed.
Q4: Is it safe to use my private key in scripts?
Only if stored securely (via .env
files, hardware wallets, or key management systems). Avoid hardcoding in source files.
Q5: Can I use Infura instead of Alchemy?
Yes. Both provide Ethereum node access. Just replace the provider URL in createAlchemyWeb3()
or use standard Web3
instance.
Q6: Why does my wallet show multiple pending transactions?
This usually means nonces are out of order. Canceling or speeding up the earliest one often resolves the chain.
Final Thoughts
Canceling a stuck Ethereum transaction via code is not only possible—it's a valuable skill for developers and power users. By crafting a zero-value replacement with a higher gas fee, you regain control over your wallet’s flow without waiting indefinitely.
With proper tooling and understanding of nonces and gas mechanics, you can automate and streamline your interaction with the Ethereum network.
Whether you're debugging dApps or managing assets across protocols, mastering transaction lifecycle management puts you ahead in the Web3 ecosystem.
👉 Access developer-friendly platforms to test and deploy blockchain solutions efficiently.