Skip to content

evmrpc: include reverts in *ExcludeTraceFail discriminator (CON-296)#3450

Open
wen-coding wants to merge 1 commit into
mainfrom
wen/revert_false_in_is_panic_or_synthetic
Open

evmrpc: include reverts in *ExcludeTraceFail discriminator (CON-296)#3450
wen-coding wants to merge 1 commit into
mainfrom
wen/revert_false_in_is_panic_or_synthetic

Conversation

@wen-coding
Copy link
Copy Markdown
Contributor

Summary

isPanicOrSyntheticTx excluded any Status==0 receipt from the *ExcludeTraceFail endpoints, which conflates two cases:

  • Ante failures — tx never reached the VM, no trace exists, can't be traced
  • In-VM failures (reverts, OOG, EIP-7623 floor) — tx ran in the VM and produced a complete trace

evmrpc/README.md's Tracing Failure Management Endpoints section describes the target as the first set only — txs "included in blocks but not executed." Reverts have a real trace; they should stay in. The pre-#3402 trace-based path also kept them (filtered on trace.Error, which is empty for reverts).

Discriminator

Receipt fields are sufficient. WriteReceipt (x/evm/keeper/receipt.go) sets EffectiveGasPrice = msg.GasPrice for any tx that reached the VM. The ante-deferred receipt path (x/evm/keeper/abci.go) writes a stub receipt with EffectiveGasPrice = 0. isReceiptFromAnteError already encodes this check, and it's the same helper filterTransactions uses for block endpoints — so block and tx *ExcludeTraceFail now agree on what they filter.

// before
exclude := receipt.TxType == evmtypes.ShellEVMTxType || receipt.Status == 0
// after
exclude := receipt.TxType == evmtypes.ShellEVMTxType || isReceiptFromAnteError(sdkctx, receipt)

Test coverage

The existing single-case test was anchored to TestPanicTxHash, whose receipt had EffectiveGasPrice: 1000000 — by the correct discriminator that's a revert, mislabelled as a panic. The test passed only because the over-strict mapping happened to exclude it for the wrong reason.

Aligned the fixture with its name (real ante-failure receipt: EffectiveGasPrice=0, VmError="nonce too high") and replaced the single assertion with a table pinning the matrix:

Fixture Receipt shape Expected
TestPanicTxHash (now ante) EffectiveGasPrice=0, nonce-error VmError excluded
TestSyntheticTxHash TxType=ShellEVMTxType excluded
TestNonPanicTxHash (revert) Status=0, EffectiveGasPrice>0 included

The "revert is included" case is the one that catches future regressions in this direction.

Backward compat

#3402 introduced the over-strict mapping (May 2026). It's on main only — git branch -r --contains eb17459e5 | grep release/v6 returns nothing — so no released version exposes the over-strict behavior. This fix lands before #3402 reaches any release branch.

Test plan

  • gofmt -s -l clean
  • go build ./evmrpc/... clean
  • go test ./evmrpc/ -count=1 passes (22s)
  • New test matrix passes 100/100 with -count=100
  • Confirmed revert_is_included fails with the fix reverted ("Should not be: transaction is panic tx"), passes with the fix

🤖 Generated with Claude Code

isPanicOrSyntheticTx mapped Status==0 to "exclude", which conflates
two different things: ante failures (tx never reached the VM) and
in-VM failures like reverts (tx ran and produced a real trace). Per
the README's Tracing Failure Management Endpoints section, the target
is the first set only — txs "included in blocks but not executed."
Reverts have a trace and should stay in.

Receipt fields carry enough signal to discriminate. WriteReceipt
populates EffectiveGasPrice from msg.GasPrice for any tx that reached
the VM; the ante-deferred receipt path in abci.go leaves it zero.
isReceiptFromAnteError already encodes that check and is already used
by filterTransactions, so block and tx *ExcludeTraceFail now agree on
what they filter.

The existing test was anchored to TestPanicTxHash, whose receipt had
EffectiveGasPrice=1000000 — i.e., a revert mislabelled as a panic.
Aligned the fixture with its name (real ante-failure receipt) and
replaced the single assertion with a table that pins the discriminator
across ante failure / synthetic / revert. The "revert is included"
case is what catches future regressions in this direction.

PR #3402 introduced the over-strict mapping; it hasn't been released
yet, so no integrator is depending on the current behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cursor
Copy link
Copy Markdown

cursor Bot commented May 16, 2026

PR Summary

Medium Risk
Changes the filtering logic for *ExcludeTraceFail receipt/trace endpoints, which can alter what transactions clients see and may impact downstream tooling expectations; logic is still localized and backed by new tests.

Overview
Fixes the *ExcludeTraceFail discriminator to only exclude untraceable transactions. isPanicOrSyntheticTx now excludes synthetic txs and ante/pre-state failures (via isReceiptFromAnteError) instead of excluding all Status==0 receipts, so VM-executed failures like reverts/OOG remain eligible for tracing.

Improves correctness across upgrades and hardens edge cases. The discriminator now evaluates isReceiptFromAnteError using the receipt’s own block context (for pre/post v5.8.0 behavior) and treats receipts with an invalidly large BlockNumber as excluded.

Updates fixtures and expands test coverage. Test receipts are adjusted to represent true ante failures (including a pre-v5.8.0 case), and TestGetTransactionReceiptExcludeTraceFail becomes a table-driven matrix asserting ante-failure excluded, synthetic excluded, revert included, and pre-v5.8.0 ante-failure excluded.

Reviewed by Cursor Bugbot for commit baab70c. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedMay 16, 2026, 9:59 PM

@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

❌ Patch coverage is 60.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.26%. Comparing base (823a78d) to head (baab70c).

Files with missing lines Patch % Lines
evmrpc/tracers.go 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3450      +/-   ##
==========================================
- Coverage   59.29%   59.26%   -0.04%     
==========================================
  Files        2125     2120       -5     
  Lines      175629   175168     -461     
==========================================
- Hits       104144   103818     -326     
+ Misses      62404    62298     -106     
+ Partials     9081     9052      -29     
Flag Coverage Δ
sei-chain-pr 66.17% <60.00%> (?)
sei-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
evmrpc/tracers.go 70.71% <60.00%> (-0.40%) ⬇️

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fa94814. Configure here.

Comment thread evmrpc/tracers.go
wen-coding added a commit that referenced this pull request May 16, 2026
Cursor Bugbot caught a real divergence on PR #3450 between
filterTransactions and isPanicOrSyntheticTx. isReceiptFromAnteError
branches on ctx.ClosestUpgradeName() — pre-v5.8.0 receipts have
EffectiveGasPrice=0 but empty VmError, and only the pre-v5.8.0 branch
catches them. filterTransactions passes ctxProvider(block.Block.Height),
which picks the correct branch for old blocks. isPanicOrSyntheticTx
was passing ctxProvider(LatestCtxHeight), so on a current chain it
always landed on the post-v5.8.0 branch and let pre-v5.8.0 ante
failures slip through.

Pull the block-height context off receipt.BlockNumber and pass that
to isReceiptFromAnteError — same call site shape as filterTransactions.

Pinned the behavior with a new test fixture (TestPreV580AnteTxHash:
EffectiveGasPrice=0, no VmError, block 99) and extended the test
ctxProvider so block 99 returns a pre-v5.8.0 upgrade name and
LatestCtxHeight returns a post-v5.8.0 one. semver.Compare("", "v5.8.0")
returns -1, so without the explicit LatestCtxUpgradeName the buggy
LatestCtxHeight path would coincidentally pass — the test fixture
makes the divergence visible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@wen-coding wen-coding force-pushed the wen/revert_false_in_is_panic_or_synthetic branch from baab70c to fa94814 Compare May 16, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant