Skip to content

[F-2026-17775] - Inconsistent log reporting for failed derived transactions across JSON-RPC endpoints#19

Merged
0xNilesh merged 6 commits into
audit-fixesfrom
audit/receipt-log-consistency-fix
Jun 11, 2026
Merged

[F-2026-17775] - Inconsistent log reporting for failed derived transactions across JSON-RPC endpoints#19
0xNilesh merged 6 commits into
audit-fixesfrom
audit/receipt-log-consistency-fix

Conversation

@AryaLanjewar3005

Copy link
Copy Markdown
Collaborator

[F-2026-17775] - Inconsistent log reporting for failed derived transactions across JSON-RPC endpoints

Problem

When a derived EVM transaction fails (EVM reverts but the Cosmos transaction succeeds — a scenario enabled by the inbound handler swallowing EVM errors), two RPC endpoints behaved inconsistently:

  • GetTransactionLogs — already returned nil for failed transactions via an explicit res.Failed guard. Correct.
  • GetTransactionReceipt — unconditionally called TxLogsFromEvents and included any EventTypeTxLog events found in the block results, regardless of the EVM execution outcome.

Because the pre-fix DerivedEVMCallWithData emitted EventTypeTxLog events even for reverted executions ("ghost logs"), GetTransactionReceipt would return non-empty logs for a transaction whose EVM outcome was a revert. This misrepresents the transaction to clients and breaks EVM semantics (failed transactions must yield no logs).

Root Cause

The failure had two contributing layers:

  1. Execution layer (x/vm/keeper/call_evm.go): EventTypeTxLog was emitted unconditionally, including for reverted derived transactions (fixed separately in bloom-block-issue.md).
  2. RPC layer (rpc/backend/tx_info.go): GetTransactionReceipt did not consult res.Failed before parsing logs from block-result events. If ghost log events existed in the block results, they were silently included in the receipt.

Fix

Execution layer (defense-in-depth, bloom-block-issue.md)

EventTypeTxLog emission and bloom/log-size updates in DerivedEVMCallWithData are now gated on !res.Failed(), so ghost log events are never written for reverted executions.

RPC layer (rpc/backend/tx_info.go)

GetTransactionReceipt now checks res.Failed before calling TxLogsFromEvents:

// Before
msgIndex := int(res.MsgIndex)
logs, err := TxLogsFromEvents(blockRes.TxsResults[res.TxIndex].Events, msgIndex)
if err != nil {
    b.logger.Debug("failed to parse logs", "hash", hexTx, "error", err.Error())
}

// After — failed transactions yield no logs, consistent with GetTransactionLogs
var logs []*ethtypes.Log
if !res.Failed {
    msgIndex := int(res.MsgIndex)
    var err error
    logs, err = TxLogsFromEvents(blockRes.TxsResults[res.TxIndex].Events, msgIndex)
    if err != nil {
        b.logger.Debug("failed to parse logs", "hash", hexTx, "error", err.Error())
    }
}

Integration tests (rpc/backend/tx_info_test.go)

TestFailedTxLogsConsistency covers three scenarios for a failed EVM transaction (EVM reverted, Cosmos tx succeeded) whose block results contain ghost EventTypeTxLog events:

  1. GetTransactionLogs returns nil — early return on res.Failed, no RPC calls needed.
  2. GetTransactionReceipt returns empty logs — ghost events in block results are ignored; receipt["logs"] is [][]*ethtypes.Log{}.
  3. Consistency — both endpoints agree: GetTransactionLogs returns nil and GetTransactionReceipt returns empty logs for the same transaction.

Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • tackled an existing issue or discussed with a team member
  • left instructions on how to review the changes
  • targeted the main branch

@github-actions github-actions Bot added the tests label Jun 10, 2026
@0xNilesh 0xNilesh merged commit 4e1260c into audit-fixes Jun 11, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants