From d572d98428e63b898cccd3f081ae13184184e96f Mon Sep 17 00:00:00 2001 From: Levi Schoen Date: Fri, 1 Dec 2023 13:36:40 -0800 Subject: [PATCH] use evm index and tendermint as source of truth when trace status discrepency. --- rpc/backend/tracing.go | 48 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 64aee968ed..e0586f188d 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -18,6 +18,7 @@ package backend import ( "encoding/json" "fmt" + "math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" @@ -125,7 +126,52 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi return nil, err } - return decodedResult, nil + jsonResult, ok := decodedResult.(map[string]interface{}) + + if !ok { + // gracefully fallback to default behavior + return decodedResult, nil + } + + // handle edge cases in differences between traced tx status + // and actual tx status when it was executed as part of a block + // this can happen when + // - tracing a tx succeeds even though when the tx was executed + // the block gas meter became exhausted + if jsonResult["failed"] != transaction.Failed { + // override trace transaction status with actual tx status + jsonResult["failed"] = transaction.Failed + _, exists := jsonResult["error"] + + if !exists { + // use tendermint as source of truth for error message + // and gas usage + query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) + resTxs, err := b.clientCtx.Client.TxSearch(b.ctx, query, false, nil, nil, "") + + if err != nil { + panic(err) + } + + if resTxs.TotalCount != 1 { + // gracefully fallback to default behavior + return decodedResult, nil + } + + txMe := resTxs.Txs[0] + + // using the actual gas used amount for when the tx was executed + jsonResult["gas_used"] = txMe.TxResult.GasUsed + + // TODO: supporting configuring max error string length + // some indexing services (e.g. blockscout) have a character limit + // for the field that stores this data + maxErrorStringLength := math.Min(200, float64(len(txMe.TxResult.Log)-1)) + jsonResult["error"] = txMe.TxResult.Log[0:int64(maxErrorStringLength)] + } + } + + return jsonResult, nil } // TraceBlock configures a new tracer according to the provided configuration, and