3MIKAN
仮想通貨

トランザクションがpending・dropped・replacedか判定する方法

tx hash、receipt、status、block、from、nonce、replacement hashを照合し、pending・confirmed・failed・dropped候補・replacedを安全に判定する手順です。

tx hashからreceipt、nonce、replacementをたどりトランザクション状態を判定する図

ウォレットにpendingと出ている、Explorerでtx hashが見つからない、受取先の残高に反映されない。この3つは同じ状態とは限りません。receiptがあればpendingではないため、ウォレットの表示より先にチェーン上の証拠を確認します。

結論:receiptから順に判定する

判定 必要な証拠 読み方
confirmed-success 元hashのreceiptがあり、blockに含まれ、status = success チェーン上では成功。受取側の反映待ちは別問題
confirmed-failed 元hashのreceiptがあり、status = revertedまたはExplorerのFail blockには含まれたが処理は失敗。pendingではない
pending-observed receiptはなく、ExplorerまたはRPCが未採掘transactionを観測 その観測元ではpending。ネットワーク全体の保証ではない
replaced 別hashが同じfrom + nonceで確定 元hashは同じnonceを使えず、置換済み
dropped-candidate receiptなし、複数の観測元でhashなし、nonceも未消費 droppedの候補。再broadcastで再出現し得る
nonce-consumed-unknown receiptなし、latest nonce > tx nonceだが置換hash未特定 何かがnonceを消費済み。replacedと断定せず別hashを探す

Explorerでnot foundになっただけではdroppedを確定できません。RPC障害、index遅延、別chain、別nodeのtransaction pool、wallet内だけの履歴も切り分けます。

tx hashからreceipt、pending観測、同一from・nonceの別hash、複数RPCを順に確認し、confirmed success、failed、pending observed、replaced、dropped candidateへ分岐する図

最初に記録する9項目

画面を更新したりwallet履歴を消したりする前に、次をテキストで保存します。

chainId / network
original tx hash
from
to
nonce
block number(あれば)
receipt status(あれば)
replacement tx hash(あれば)
確認したExplorer・RPC・日時

hashだけでは、別chainで同じ文字列を検索しているミスを除外できません。fromnonceだけでは、どのcallが実行されたか分かりません。tovalue、calldata、token transfer logsも必要に応じて保存します。

1. receiptがあればsuccessかfailedに分ける

Ethereum Execution APIeth_getTransactionReceiptは、transactionがblockへ含まれるまではreceiptを返しません。receiptが得られたら、blockNumberstatusを確認します。

const transaction = await publicClient.getTransaction({ hash })
const receipt = await publicClient.getTransactionReceipt({ hash })

console.table({
  hash: transaction.hash,
  from: transaction.from,
  to: transaction.to,
  nonce: transaction.nonce,
  blockNumber: receipt.blockNumber,
  status: receipt.status, // 'success' | 'reverted'
})

not foundとRPC障害を同じcatchで握りつぶさないでください。viemのTransactionNotFoundErrorTransactionReceiptNotFoundErrorだけを「未検出」として扱い、timeout、rate limit、chain不一致は調査エラーとして止めます。

failedもblockには含まれている

EtherscanのEthereum transaction詳細にFail、block番号、from、to、execution revertedが表示された公開画面
2026年8月28日に確認したEtherscan公開画面。Ethereum mainnetの公開hashで、StatusはFail、blockは25853564、実行結果はexecution revertedでした。個人walletは使用していません。

Failでもblock番号とreceiptは存在します。state変更はrevertしますが、実行に使われたgasは支払われます。revert reason、calldata、logsの読み方はviemで失敗トランザクションを解析するへ分けています。

2. receiptがなければpendingの観測を探す

EtherscanのPending Transactions一覧にtransaction hash、nonce、last seen、gas、from、toが並ぶ公開画面
2026年8月28日のEtherscan Pending Transactions公開画面。表示中のhashは一時的な観測で、撮影後にconfirmed、failed、replaced、droppedのいずれかへ変わる可能性があります。

pending一覧やeth_getTransactionByHashでtransactionが見え、blockNumberとreceiptがまだなければ、そのExplorerまたはnodeではpendingとして観測されています。ただしmempoolは全nodeで完全に同じではありません。

同じfromについて、確定済みとpendingを別々に取得します。

const [latestNonce, pendingNonce] = await Promise.all([
  publicClient.getTransactionCount({ address: from, blockTag: 'latest' }),
  publicClient.getTransactionCount({ address: from, blockTag: 'pending' }),
])
  • latest: 最新の確定stateから見た次のnonce
  • pending: 接続nodeが認識するpendingも考慮した値
  • latest > transaction nonce: そのnonceは確定chain上ですでに消費済み
  • pending > latest: そのnodeが未確定のnonce列を観測している手掛かり

pending値は接続nodeの見え方です。別RPC、Explorer、walletのActivityを時刻付きで照合します。

3. 同じfrom・nonceの別hashが確定したらreplaced

nonceは同じaccountから送るtransactionの実行順です。同一chainで、別hashが同じfrom + nonceを使ってreceiptを持つなら、元hashはreplacedと判断できます。置換側がrevertしていてもnonceは消費されるため、元hashは後から同じnonceで確定できません。

Etherscan公式例で元transactionがDropped and Replacedとなり、別hashが同じFromとnonce 7でSuccessになった比較画面
Etherscan公式解説に掲載された2020年の実画面例。左の元hashと右の確定hashは同じFrom・nonce 7で、元hashにはDropped & Replacedとreplacement hashが表示されています。現在のUIとはレイアウトが異なります。

latest nonceが進んだだけでは、元hashが確定したのか、別hashへ置換されたのかまでは分かりません。送信accountのtransaction履歴、wallet/providerのActivity、replacement hashを探し、両hashのreceiptを保存します。

4. hash未検出はdropped確定ではない

Etherscanでtransaction hash not foundと表示され、別nodeのTX Poolに残る可能性やindex待ちを案内する公開画面
2026年8月28日のEtherscan公開画面。元hashは現在not foundですが、画面自身も別nodeのTX Pool、broadcast待ち、index遅延の可能性を案内しています。

Etherscanのdropped解説でも、nodeごとにpending poolの上限や設定があり、いったん落ちたtransactionが再broadcastされるとpendingへ戻り得ると説明されています。

そのため本記事では、次をすべて満たしてもdropped-candidateと呼びます。

  1. 元hashのreceiptがない
  2. 時間を空けて複数の独立したRPC・Explorerでtransactionを観測できない
  3. latest nonce <= transaction nonceで、対象nonceが確定chain上では未消費
  4. 同じfrom + nonceの確定済み別hashが見つからない
  5. RPC errorや別chain検索を除外した

送信元サービスがprivate relayや独自poolを使う場合もあります。exchange、wallet、RPC providerが送信主体なら、送信記録とreplacement hashをその提供元へ確認します。

speed upとcancelは同じnonceの置換試行

MetaMask公式HelpのSepolia Activity画面でSentがPendingとなりCancelとSpeed upボタンが表示されたExtension UI
MetaMask公式Help掲載のExtension実画面。サンプルのSepolia transactionにPending、Cancel、Speed upが表示されています。3MIKANでは個人walletを開かず、公式掲載画像だけを確認しました。

MetaMask公式Helpの説明では、どちらも元transactionがnetwork上でpendingの間に行う操作です。

  • Speed up: 同じ内容・同じnonceを、より高いfee条件で再送する
  • Cancel: 同じnonceで自分宛て0 ETHなどを送り、元transactionより先に確定させることを試みる

cancelはチェーン上の取り消し命令ではありません。元transactionと置換transactionのどちらが先に採用されるかを競うため、すでにconfirmedのtransactionは戻せず、pendingでも成功保証はありません

置換に失敗しやすい条件

  • 元transactionが先にconfirmedした
  • replacement nonceが元nonceと違う
  • feeの上げ幅が接続nodeのreplacement条件を満たさず、replacement transaction underpricedになった
  • より古いpending nonceが前に詰まっている
  • fromまたはchainが違う
  • feeを払うnative token残高が不足している
  • MetaMask Smart Transactionsやprovider独自の送信経路を通常mempoolと同じ前提で扱った

必要なfee上昇幅はclient、RPC、network条件で変わります。固定率をprotocol保証として扱わず、walletの現在提案、元transactionのmaxFeePerGasmaxPriorityFeePerGas、network状況を確認します。手動nonceを使う場合は、MetaMask公式の案内どおり最も古いpendingから解消し、Smart Transactionsの制約も確認してください。

受取側に反映されない問題はchain状態と分ける

receiptがsuccessでblockに含まれているなら、transactionはもうpendingではありません。次を受取側の問題として調べます。

  • 送ったchainと受取サービスが対応する入金networkは同じか
  • toは案内されたdeposit addressか
  • ERC-20ならTransfer logのtoken address、fromto、amountは正しいか
  • 取引所が必要とするconfirmation数を満たしたか
  • memo / tagなど別項目が必要なchainでは入力が正しいか
  • minimum deposit、maintenance、token contract変更、service側index遅延がないか

反対にreceiptがrevertedなら、受取側へ問い合わせる前に失敗原因を確認します。送金操作そのものの確認はMetaMaskの送金が反映されないときの確認へ戻れます。誤送金の回収可否はchainと受取主体で異なり、本記事は回収を保証しません。

実装でも証拠の優先順位を固定する

アプリや調査用スクリプトへ組み込む場合も、RPCの表示順ではなく、receiptとnonceの証拠を明示的な入力にします。

const state = classifyTransactionEvidence({
  originalReceiptStatus: receipt?.status ?? null,
  replacementReceiptStatus: replacementReceipt?.status ?? null,
  replacementMatchesSenderAndNonce:
    replacement != null &&
    replacement.hash !== original.hash &&
    replacement.from === original.from &&
    replacement.nonce === original.nonce,
  pendingObserved: transaction != null && transaction.blockNumber == null,
  latestNonce: Number(latestNonce),
  transactionNonce: Number(original.nonce),
  missingSourceCount: 0,
})

判定の優先順位は元receipt → 確定replacement → nonce消費 → pending観測 → 複数ソース未検出です。latest nonceが進んでいるのにhashを見つけられないケースを、都合よくdroppedへ分類しません。

調査を終える前のチェックリスト

  • chainId、hash、from、to、nonceを保存した
  • 元hashのtransactionとreceiptを別々に確認した
  • blockとreceipt statusを確認した
  • latestpending nonceを同じfromで比較した
  • 同じfrom・nonceの別hashとreceiptを探した
  • not foundとRPC errorを区別した
  • 受取側の未反映をchain未確定と混同していない
  • speed up / cancel後も両hashのreceiptを確認した
  • wallet履歴のresetや再送前に証拠を保存した

最短ルートは、walletのラベルを信じ切ることではなく、receipt、block、status、from、nonce、replacement hashを順番に固定することです。結論が出ない場合はunknownのまま記録し、送信元providerの情報を追加してから再判定します。

確認した一次情報