Pending State
When a transaction is submitted to the Ethereum network, it first goes into the pending status, waiting to be executed by the nodes. A transaction can be in the pending state for a longer duration if the gas price is set very low in the transaction and the nodes are busy processing other higher gas price transactions.
During the pending state, the transaction initiator is allowed to change the transaction fields at any time. They can do so by sending another transaction with the same nonce.
Prerequisite Readings
Mempool Architecture
Ontomir EVM vs Ethereum
In Ethereum, pending blocks are generated as they are queued for production by miners. These pending blocks include pending transactions that are picked out by miners, based on the highest reward paid in gas. This mechanism exists as block finality is not possible on the Ethereum network. Blocks are committed with probabilistic finality, which means that transactions and blocks become less likely to become reverted as more time (and blocks) passes.
Ontomir EVM is designed differently as it uses CometBFT consensus which provides instant finality for transactions. While there is no concept of "pending blocks" that can be reorganized, Ontomir EVM implements an experimental EVM mempool that provides Ethereum-compatible pending state functionality.
EVM-Compliant Mempool
The experimental EVM mempool introduces a two-tiered system that brings Ethereum-like pending state behavior to Ontomir EVM:
Transaction States
Transactions with correct nonces that are immediately executable. These are in the public mempool, broadcast to peers, and ready for block inclusion. Transactions with future nonces (nonce gaps) that are stored locally. These wait for earlier transactions to execute before being promoted to pending.
Key Differences from Traditional Ontomir
Nonce Gap Handling: Unlike traditional Ontomir chains that reject out-of-order transactions, the EVM mempool queues them locally until gaps are filled.
Fee-Based Priority: Both EVM and Ontomir transactions compete fairly based on their effective tips rather than FIFO ordering:
EVM transactions: Priority =
gas_tip_capormin(gas_tip_cap, gas_fee_cap - base_fee)Ontomir transactions: Priority =
(fee_amount / gas_limit) - base_fee
Transaction Replacement: Supports replacing pending transactions with higher fee versions using the same nonce, enabling "speed up" functionality common in Ethereum wallets.
Pending State Queries
With the experimental EVM mempool, pending state queries now reflect a more Ethereum-compatible view:
Transaction Pool Inspection
The mempool provides dedicated RPC methods to inspect pending and queued transactions:
Returns counts of pending and queued transactions:
```json
{
"pending": "0x10", // 16 pending transactions
"queued": "0x5" // 5 queued transactions
}
```Returns detailed information about all transactions in the pool, organized by account and nonce. Provides human-readable summaries of transactions for debugging.
See the JSON-RPC Methods documentation for complete details.
Pending State Behavior
When making queries with "pending" as the block parameter:
Balance Queries: Reflect the account balance after all pending transactions from that account are applied
Nonce Queries: Return the next available nonce considering all pending transactions
Gas Estimates: Account for pending transactions that may affect gas costs
Pending state queries are subjective to each node's local mempool view. Different nodes may return different results based on their transaction pool contents.
JSON-RPC Calls Supporting Pending State
The following RPC methods support the "pending" block parameter:
eth_getBalance- Get balance considering pending transactionseth_getTransactionCount- Get next nonce considering pending transactionseth_getBlockTransactionCountByNumber- Count pending transactionseth_getBlockByNumber- Get pending block informationeth_getTransactionByHash- Retrieve pending transactionseth_getTransactionByBlockNumberAndIndex- Access specific pending transactionseth_sendTransaction- Submit new transactions
Additionally, the txpool_* namespace provides specialized methods for mempool inspection:
txpool_status- Get pool statisticstxpool_content- View all pool transactionstxpool_contentFrom- Filter by addresstxpool_inspect- Human-readable summaries
Practical Examples
Monitoring Transaction Status
// Check if transaction is pending
const tx = await provider.getTransaction(txHash);
if (tx && !tx.blockNumber) {
console.log("Transaction is pending");
// Check pool status
const poolStatus = await provider.send("txpool_status", []);
console.log(`Pool has ${poolStatus.pending} pending, ${poolStatus.queued} queued`);
}Handling Nonce Gaps
// Send transactions with nonce gaps (they'll be queued)
await wallet.sendTransaction({nonce: 100, ...}); // Executes immediately
await wallet.sendTransaction({nonce: 102, ...}); // Queued (gap at 101)
await wallet.sendTransaction({nonce: 101, ...}); // Fills gap, both executeTransaction Replacement
// Speed up a pending transaction
const originalTx = await wallet.sendTransaction({
nonce: 100,
gasPrice: parseUnits("20", "gwei")
});
// Replace with higher fee
const fasterTx = await wallet.sendTransaction({
nonce: 100, // Same nonce
gasPrice: parseUnits("30", "gwei") // Higher fee
});Architecture Details
For a detailed understanding of how the pending state is managed:
See Mempool Architecture for the two-tier system design
Review Transaction Flow for state transitions
Check Integration Guide for implementation details
最后更新于
