From a8296542ee019c8754724e012c74229647166a06 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:54:33 +0530 Subject: [PATCH 1/9] fixed trace_transaction (yet to test) --- rpc/backend/blocks.go | 25 +++++++++++ rpc/backend/tracing.go | 95 +++++++++++++++++++++++++++++++++++------- 2 files changed, 104 insertions(+), 16 deletions(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index d69babbd5..7e2c43b9f 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -335,6 +335,31 @@ func (b *Backend) parseDerivedTxFromAdditionalFields( ethMsg.From = additional.Sender.Hex() return ethMsg } +func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( + additional *rpctypes.TxResultAdditionalFields, +) *evmtypes.MsgEthereumTx { + recipient := additional.Recipient + t := ethtypes.NewTx(ðtypes.LegacyTx{ + Nonce: additional.Nonce, + Data: additional.Data, + Gas: additional.GasUsed, + To: &recipient, + GasPrice: nil, + Value: additional.Value, + V: big.NewInt(27), + R: big.NewInt(1), + S: big.NewInt(1), + }) + ethMsg := &evmtypes.MsgEthereumTx{} + err := ethMsg.FromEthereumTx(t) + if err != nil { + b.logger.Error("can not create eth msg", err.Error()) + return nil + } + ethMsg.Hash = additional.Hash.Hex() + ethMsg.From = additional.Sender.Hex() + return ethMsg +} // HeaderByNumber returns the block header identified by height. func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) { diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 3788ff88d..2432c2884 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -18,7 +18,7 @@ import ( // and returns them as a JSON object. func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (interface{}, error) { // Get transaction by hash - transaction, _, err := b.GetTxByEthHash(hash) + transaction, additional, err := b.GetTxByEthHash(hash) if err != nil { b.logger.Debug("tx not found", "hash", hash) return nil, err @@ -46,19 +46,54 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } var predecessors []*evmtypes.MsgEthereumTx - for _, txBz := range blk.Block.Txs[:transaction.TxIndex] { - tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) + // for _, txBz := range blk.Block.Txs[:transaction.TxIndex] { // (block.Block.Txs[res.TxIndex] + // tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) + // if err != nil { + // b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) + // continue + // } + // for _, msg := range tx.GetMsgs() { + // ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + // if !ok { + // continue + // } + + // predecessors = append(predecessors, ethMsg) + // } + // } + for i := 0; i < int(transaction.TxIndex); i++ { + _, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(i)) if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) + b.logger.Debug("failed to get tx by index", + "height", blk.Block.Height, + "index", i, + "error", err.Error()) continue } - for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - continue + + if txAdditional != nil { + // Handle synthetic EVM transaction + ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) + if ethMsg != nil { + predecessors = append(predecessors, ethMsg) } + continue + } - predecessors = append(predecessors, ethMsg) + // Fallback: decode as normal Cosmos tx + tx, err := b.clientCtx.TxConfig.TxDecoder()(blk.Block.Txs[i]) + if err != nil { + b.logger.Debug("failed to decode transaction in block", + "height", blk.Block.Height, + "index", i, + "error", err.Error()) + continue + } + + for _, msg := range tx.GetMsgs() { + if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + predecessors = append(predecessors, ethMsg) + } } } @@ -70,18 +105,46 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi // add predecessor messages in current cosmos tx index := int(transaction.MsgIndex) // #nosec G115 + for i := 0; i < index; i++ { - ethMsg, ok := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx) - if !ok { + msg := tx.GetMsgs()[i] + + // Check if it’s a normal Ethereum tx + if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + predecessors = append(predecessors, ethMsg) + continue + } + + // Check if it’s a synthetic tx (custom Msg type) + // We need to fetch additional info for synthetic tx reconstruction + _, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(transaction.TxIndex)) + if err != nil { + b.logger.Debug("failed to get tx additional info", "error", err.Error()) continue } - predecessors = append(predecessors, ethMsg) + + if txAdditional != nil { + ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) + if ethMsg != nil { + predecessors = append(predecessors, ethMsg) + } + } } + var ethMessage *evmtypes.MsgEthereumTx + var ok bool - ethMessage, ok := tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx) - if !ok { - b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx)) - return nil, fmt.Errorf("invalid transaction type %T", tx) + if additional == nil { + ethMessage, ok = tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx) + if !ok { + b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx.GetMsgs()[transaction.MsgIndex])) + return nil, fmt.Errorf("invalid transaction type %T", tx.GetMsgs()[transaction.MsgIndex]) + } + } else { + ethMessage = b.parseDerivedTxFromAdditionalFieldsForTrace(additional) + if ethMessage == nil { + b.logger.Error("failed to get derived eth msg from additional fields") + return nil, fmt.Errorf("failed to get derived eth msg from additional fields") + } } nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) From 23f8d3c46c2bf085751961b16fa1d38a1d7c9ab5 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:57:14 +0530 Subject: [PATCH 2/9] fixed predecessor issue --- rpc/backend/blocks.go | 2 +- rpc/backend/tracing.go | 19 ++++++++++++++++++- rpc/backend/tx_info.go | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 7e2c43b9f..93df253ad 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -344,7 +344,7 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( Data: additional.Data, Gas: additional.GasUsed, To: &recipient, - GasPrice: nil, + GasPrice: big.NewInt(2500000), Value: additional.Value, V: big.NewInt(27), R: big.NewInt(1), diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 2432c2884..d174528cd 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -23,6 +23,8 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi b.logger.Debug("tx not found", "hash", hash) return nil, err } + fmt.Println("stage 1 (additionals) : ", additional) + fmt.Println("stage 2 (transaction) : ", transaction) // check if block number is 0 if transaction.Height == 0 { @@ -34,6 +36,11 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi b.logger.Debug("block not found", "height", transaction.Height) return nil, err } + fmt.Println("checking Block : ", blk) + fmt.Println("transaction : ", transaction) + fmt.Println("Transaction_index", transaction.TxIndex) + fmt.Println("Transaction_index", transaction.EthTxIndex) + fmt.Println("checking Blocks inside : ", blk.Block.Txs) // check tx index is not out of bound if len(blk.Block.Txs) > math.MaxUint32 { @@ -96,32 +103,38 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } } } + fmt.Println("stage 3 (block predecessors) : ", predecessors) tx, err := b.clientCtx.TxConfig.TxDecoder()(blk.Block.Txs[transaction.TxIndex]) if err != nil { b.logger.Debug("tx not found", "hash", hash) return nil, err } + fmt.Println("decoded transaction (target) : ", tx.GetMsgs()[transaction.MsgIndex]) // add predecessor messages in current cosmos tx index := int(transaction.MsgIndex) // #nosec G115 + fmt.Println("checking index", index) for i := 0; i < index; i++ { msg := tx.GetMsgs()[i] + fmt.Println("predecessor number", i) // Check if it’s a normal Ethereum tx if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { + fmt.Println("what! it is actually evm type mesage") predecessors = append(predecessors, ethMsg) continue } // Check if it’s a synthetic tx (custom Msg type) // We need to fetch additional info for synthetic tx reconstruction - _, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(transaction.TxIndex)) + _, txAdditional, err := b.GetTxByEthHashAndMsgIndex(hash, i) if err != nil { b.logger.Debug("failed to get tx additional info", "error", err.Error()) continue } + fmt.Println("subMsg additional : ", txAdditional) if txAdditional != nil { ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) @@ -130,6 +143,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } } } + fmt.Println("stage 4 (block+cosmostx predecessors) : ", predecessors) var ethMessage *evmtypes.MsgEthereumTx var ok bool @@ -146,6 +160,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi return nil, fmt.Errorf("failed to get derived eth msg from additional fields") } } + fmt.Println("actual_message after parseDervied", ethMessage) nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) if !ok { @@ -182,6 +197,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi if err != nil { return nil, err } + // fmt.Println("stage 5 (trace result) : ", traceResult) // Response format is unknown due to custom tracer config param // More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered @@ -190,6 +206,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi if err != nil { return nil, err } + // fmt.Println("stage 6 (decoded trace result) : ", decodedResult) return decodedResult, nil } diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 889922f4b..7c0635de4 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -424,6 +424,26 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*types.TxResult, *rpctypes.T return txResult, txAdditional, nil } +func (b *Backend) GetTxByEthHashAndMsgIndex(hash common.Hash, index int) (*types.TxResult, *rpctypes.TxResultAdditionalFields, error) { + if b.indexer != nil { + txRes, err := b.indexer.GetByTxHash(hash) + if err != nil { + return nil, nil, err + } + return txRes, nil, nil + } + + // fallback to tendermint tx indexer + query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) + txResult, txAdditional, err := b.queryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { + return txs.GetTxByMsgIndex(index) + }) + if err != nil { + return nil, nil, errorsmod.Wrapf(err, "GetTxByEthHash %s", hash.Hex()) + } + return txResult, txAdditional, nil +} + // GetTxByTxIndex uses `/tx_query` to find transaction by tx index of valid ethereum txs func (b *Backend) GetTxByTxIndex(height int64, index uint) (*types.TxResult, *rpctypes.TxResultAdditionalFields, error) { int32Index := int32(index) //#nosec G115 -- checked for int overflow already From 421162eece9df2ba1738c417a1f9d9932edac74b Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:23:10 +0530 Subject: [PATCH 3/9] Removed Debug logs --- rpc/backend/tracing.go | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index d174528cd..2e068333a 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -23,8 +23,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi b.logger.Debug("tx not found", "hash", hash) return nil, err } - fmt.Println("stage 1 (additionals) : ", additional) - fmt.Println("stage 2 (transaction) : ", transaction) // check if block number is 0 if transaction.Height == 0 { @@ -36,11 +34,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi b.logger.Debug("block not found", "height", transaction.Height) return nil, err } - fmt.Println("checking Block : ", blk) - fmt.Println("transaction : ", transaction) - fmt.Println("Transaction_index", transaction.TxIndex) - fmt.Println("Transaction_index", transaction.EthTxIndex) - fmt.Println("checking Blocks inside : ", blk.Block.Txs) // check tx index is not out of bound if len(blk.Block.Txs) > math.MaxUint32 { @@ -53,21 +46,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } var predecessors []*evmtypes.MsgEthereumTx - // for _, txBz := range blk.Block.Txs[:transaction.TxIndex] { // (block.Block.Txs[res.TxIndex] - // tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) - // if err != nil { - // b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) - // continue - // } - // for _, msg := range tx.GetMsgs() { - // ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) - // if !ok { - // continue - // } - - // predecessors = append(predecessors, ethMsg) - // } - // } for i := 0; i < int(transaction.TxIndex); i++ { _, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(i)) if err != nil { @@ -103,38 +81,29 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } } } - fmt.Println("stage 3 (block predecessors) : ", predecessors) tx, err := b.clientCtx.TxConfig.TxDecoder()(blk.Block.Txs[transaction.TxIndex]) if err != nil { b.logger.Debug("tx not found", "hash", hash) return nil, err } - fmt.Println("decoded transaction (target) : ", tx.GetMsgs()[transaction.MsgIndex]) // add predecessor messages in current cosmos tx index := int(transaction.MsgIndex) // #nosec G115 - fmt.Println("checking index", index) for i := 0; i < index; i++ { msg := tx.GetMsgs()[i] - fmt.Println("predecessor number", i) - // Check if it’s a normal Ethereum tx if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { - fmt.Println("what! it is actually evm type mesage") predecessors = append(predecessors, ethMsg) continue } - - // Check if it’s a synthetic tx (custom Msg type) - // We need to fetch additional info for synthetic tx reconstruction + // Fetch additional data for predecessors _, txAdditional, err := b.GetTxByEthHashAndMsgIndex(hash, i) if err != nil { b.logger.Debug("failed to get tx additional info", "error", err.Error()) continue } - fmt.Println("subMsg additional : ", txAdditional) if txAdditional != nil { ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) @@ -143,7 +112,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } } } - fmt.Println("stage 4 (block+cosmostx predecessors) : ", predecessors) var ethMessage *evmtypes.MsgEthereumTx var ok bool @@ -160,7 +128,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi return nil, fmt.Errorf("failed to get derived eth msg from additional fields") } } - fmt.Println("actual_message after parseDervied", ethMessage) nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) if !ok { @@ -197,7 +164,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi if err != nil { return nil, err } - // fmt.Println("stage 5 (trace result) : ", traceResult) // Response format is unknown due to custom tracer config param // More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered @@ -206,7 +172,6 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi if err != nil { return nil, err } - // fmt.Println("stage 6 (decoded trace result) : ", decodedResult) return decodedResult, nil } From 79018a1306d521192e9decf507831aec7f074a11 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:40:41 +0530 Subject: [PATCH 4/9] removed hardcoded gasPrice from parseDerivedTxFromAdditionalFieldsForTrace --- rpc/backend/blocks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 93df253ad..7e2c43b9f 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -344,7 +344,7 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( Data: additional.Data, Gas: additional.GasUsed, To: &recipient, - GasPrice: big.NewInt(2500000), + GasPrice: nil, Value: additional.Value, V: big.NewInt(27), R: big.NewInt(1), From f5900f126a8474c890eeab5c7d010c123f63f476 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:04:18 +0530 Subject: [PATCH 5/9] fixed v, r and s Error --- rpc/backend/blocks.go | 7 +++-- x/vm/keeper/grpc_query.go | 58 +++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 949c59664..b3e91f014 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -348,9 +348,9 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( To: &recipient, GasPrice: nil, Value: additional.Value, - V: big.NewInt(27), - R: big.NewInt(1), - S: big.NewInt(1), + V: big.NewInt(0), + R: big.NewInt(0), + S: big.NewInt(0), }) ethMsg := &evmtypes.MsgEthereumTx{} err := ethMsg.FromEthereumTx(t) @@ -358,6 +358,7 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( b.logger.Error("can not create eth msg", err.Error()) return nil } + fmt.Println("ludwig : ", additional) ethMsg.Hash = additional.Hash.Hex() ethMsg.From = additional.Sender.Hex() return ethMsg diff --git a/x/vm/keeper/grpc_query.go b/x/vm/keeper/grpc_query.go index 4c7c0028d..ec988cc1f 100644 --- a/x/vm/keeper/grpc_query.go +++ b/x/vm/keeper/grpc_query.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -487,10 +488,18 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ for i, tx := range req.Predecessors { ethTx := tx.AsTransaction() - msg, err := ethTx.AsMessage(signer, cfg.BaseFee) - if err != nil { - continue + + var msg ethtypes.Message + // if tx is not unsigned, from field should be derived from signer, which can be done using AsMessage function + if !isUnsigned(ethTx) { + msg, err = ethTx.AsMessage(signer, cfg.BaseFee) + if err != nil { + continue + } + } else { + msg = unsignedTxAsMessage(common.BytesToAddress(req.Msg.GetFrom()), ethTx, cfg.BaseFee) } + txConfig.TxHash = ethTx.Hash() txConfig.TxIndex = uint(i) //nolint:gosec // G115 // won't exceed uint64 // reset gas meter for each transaction @@ -515,7 +524,7 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ _ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig) } - result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig) + result, _, err := k.traceTx(ctx, cfg, txConfig, signer, common.BytesToAddress(req.Msg.GetFrom()), tx, req.TraceConfig, false, tracerConfig) if err != nil { // error will be returned with detail status from traceTx return nil, err @@ -582,7 +591,7 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) ethTx := tx.AsTransaction() txConfig.TxHash = ethTx.Hash() txConfig.TxIndex = uint(i) //nolint:gosec // G115 // won't exceed uint64 - traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true, nil) + traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, common.BytesToAddress(tx.GetFrom()), ethTx, req.TraceConfig, true, nil) if err != nil { result.Error = err.Error() } else { @@ -608,6 +617,7 @@ func (k *Keeper) traceTx( cfg *statedb.EVMConfig, txConfig statedb.TxConfig, signer ethtypes.Signer, + from common.Address, tx *ethtypes.Transaction, traceConfig *types.TraceConfig, commitMessage bool, @@ -620,9 +630,15 @@ func (k *Keeper) traceTx( err error timeout = defaultTraceTimeout ) - msg, err := tx.AsMessage(signer, cfg.BaseFee) - if err != nil { - return nil, 0, status.Error(codes.Internal, err.Error()) + var msg ethtypes.Message + // if tx is not unsigned, from field should be derived from signer, which can be done using AsMessage function + if !isUnsigned(tx) { + msg, err = tx.AsMessage(signer, cfg.BaseFee) + if err != nil { + return nil, 0, status.Error(codes.Internal, err.Error()) + } + } else { + msg = unsignedTxAsMessage(from, tx, cfg.BaseFee) } if traceConfig == nil { @@ -722,3 +738,29 @@ func (k Keeper) Config(_ context.Context, _ *types.QueryConfigRequest) (*types.Q return &types.QueryConfigResponse{Config: config}, nil } + +func isUnsigned(ethTx *ethtypes.Transaction) bool { + r, v, s := ethTx.RawSignatureValues() + + return (r == nil && v == nil && s == nil) || (r.Int64() == 0 && v.Int64() == 0 && s.Int64() == 0) +} +func unsignedTxAsMessage(fromAddress common.Address, tx *ethtypes.Transaction, baseFee *big.Int) ethtypes.Message { + gasPrice := new(big.Int).Set(tx.GasPrice()) + // If baseFee provided, set gasPrice to effectiveGasPrice. + if baseFee != nil { + gasPrice = math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap()) + } + return ethtypes.NewMessage( + fromAddress, + tx.To(), + tx.Nonce(), + tx.Value(), + tx.Gas(), + gasPrice, + tx.GasFeeCap(), + tx.GasTipCap(), + tx.Data(), + tx.AccessList(), + false, + ) +} From 14d899fc44430195c09665e7b69f6dbb2b231856 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Fri, 5 Dec 2025 16:07:18 +0530 Subject: [PATCH 6/9] gas buffer added to parseDerivedTxFromAdditionalForTrace --- rpc/backend/blocks.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index b3e91f014..2fad85a27 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -341,10 +341,12 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( additional *rpctypes.TxResultAdditionalFields, ) *evmtypes.MsgEthereumTx { recipient := additional.Recipient + + gas := additional.GasUsed + 10000 // buffer t := ethtypes.NewTx(ðtypes.LegacyTx{ Nonce: additional.Nonce, Data: additional.Data, - Gas: additional.GasUsed, + Gas: gas, To: &recipient, GasPrice: nil, Value: additional.Value, @@ -358,7 +360,6 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( b.logger.Error("can not create eth msg", err.Error()) return nil } - fmt.Println("ludwig : ", additional) ethMsg.Hash = additional.Hash.Hex() ethMsg.From = additional.Sender.Hex() return ethMsg From 1bdb7fd14606d67a86b1bf8637b402ce6ddd6ede Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Mon, 8 Dec 2025 11:18:19 +0530 Subject: [PATCH 7/9] added gasLimit emission event --- rpc/backend/blocks.go | 6 +++++- rpc/types/events.go | 10 ++++++++++ rpc/types/types.go | 1 + x/vm/keeper/call_evm.go | 1 + x/vm/types/events.go | 1 + 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 2fad85a27..b1d552123 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -342,7 +342,11 @@ func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( ) *evmtypes.MsgEthereumTx { recipient := additional.Recipient - gas := additional.GasUsed + 10000 // buffer + // for transactions before v31 this value was mistakenly used for Gas field + gas := additional.GasUsed + if additional.GasLimit != nil { + gas = *additional.GasLimit + } t := ethtypes.NewTx(ðtypes.LegacyTx{ Nonce: additional.Nonce, Data: additional.Data, diff --git a/rpc/types/events.go b/rpc/types/events.go index 97c45c239..c03f82222 100644 --- a/rpc/types/events.go +++ b/rpc/types/events.go @@ -74,6 +74,7 @@ type ParsedTx struct { Recipient common.Address Sender common.Address Nonce uint64 + GasLimit uint64 Data []byte } @@ -233,6 +234,7 @@ func ParseTxIndexerResult( GasUsed: parsedTx.GasUsed, Data: parsedTx.Data, Nonce: parsedTx.Nonce, + GasLimit: &parsedTx.GasLimit, }, nil } return &types.TxResult{ @@ -285,6 +287,7 @@ func ParseTxBlockResult( GasUsed: parsedTx.GasUsed, Data: parsedTx.Data, Nonce: parsedTx.Nonce, + GasLimit: &parsedTx.GasLimit, }, nil } return &types.TxResult{ @@ -411,6 +414,13 @@ func fillTxAttribute(tx *ParsedTx, key, value string) error { } tx.Nonce = nonce + case evmtypes.AttributeKeyTxGasLimit: + gasLimit, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return err + } + tx.GasLimit = gasLimit + case evmtypes.AttributeKeyTxData: hexBytes, err := hexutil.Decode(value) if err != nil { diff --git a/rpc/types/types.go b/rpc/types/types.go index e2a3dee58..4d42ea724 100644 --- a/rpc/types/types.go +++ b/rpc/types/types.go @@ -40,6 +40,7 @@ type TxResultAdditionalFields struct { GasUsed uint64 `json:"gasUsed"` Nonce uint64 `json:"nonce"` Data []byte `json:"data"` + GasLimit *uint64 `json:"gasLimit"` } // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction diff --git a/x/vm/keeper/call_evm.go b/x/vm/keeper/call_evm.go index 286508bae..341c30d35 100644 --- a/x/vm/keeper/call_evm.go +++ b/x/vm/keeper/call_evm.go @@ -289,6 +289,7 @@ func (k Keeper) DerivedEVMCallWithData( attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxData, hexutil.Encode(msg.Data()))) // adding nonce for more info in rpc methods in order to parse derived txs attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxNonce, strconv.FormatUint(nonce, 10))) + attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxGasLimit, strconv.FormatUint(gasCap, 10))) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeEthereumTx, diff --git a/x/vm/types/events.go b/x/vm/types/events.go index 5e2681af2..489635e41 100644 --- a/x/vm/types/events.go +++ b/x/vm/types/events.go @@ -17,6 +17,7 @@ const ( AttributeKeyTxType = "txType" AttributeKeyTxLog = "txLog" AttributeKeyTxNonce = "txNonce" + AttributeKeyTxGasLimit = "txGasLimit" AttributeKeyTxData = "txData" // tx failed in eth vm execution From 41ffc10a500e630bf52d77551795c0041b7a4682 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 19 Dec 2025 16:06:40 +0530 Subject: [PATCH 8/9] refactor: renamed parseDerivedTxFromAdditionalFieldsForTrace method --- rpc/backend/blocks.go | 25 ------------------------- rpc/backend/tracing.go | 8 ++++---- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index b1d552123..97121354e 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -316,31 +316,6 @@ func (b *Backend) parseDerivedTxFromAdditionalFields( additional *rpctypes.TxResultAdditionalFields, ) *evmtypes.MsgEthereumTx { recipient := additional.Recipient - t := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: additional.Nonce, - Data: additional.Data, - Gas: additional.GasUsed, - To: &recipient, - GasPrice: nil, - Value: additional.Value, - V: big.NewInt(0), - R: big.NewInt(0), - S: big.NewInt(0), - }) - ethMsg := &evmtypes.MsgEthereumTx{} - err := ethMsg.FromEthereumTx(t) - if err != nil { - b.logger.Error("can not create eth msg", err.Error()) - return nil - } - ethMsg.Hash = additional.Hash.Hex() - ethMsg.From = additional.Sender.Hex() - return ethMsg -} -func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace( - additional *rpctypes.TxResultAdditionalFields, -) *evmtypes.MsgEthereumTx { - recipient := additional.Recipient // for transactions before v31 this value was mistakenly used for Gas field gas := additional.GasUsed diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 12170509c..04b405bcc 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -40,7 +40,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi // check tx index is not out of bound if len(blk.Block.Txs) > math.MaxUint32 { - return nil, fmt.Errorf("tx count %d is overfloing", len(blk.Block.Txs)) + return nil, fmt.Errorf("tx count %d is overflowing", len(blk.Block.Txs)) } txsLen := uint32(len(blk.Block.Txs)) // #nosec G115 -- checked for int overflow already if txsLen < transaction.TxIndex { @@ -61,7 +61,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi if txAdditional != nil { // Handle synthetic EVM transaction - ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) + ethMsg := b.parseDerivedTxFromAdditionalFields(txAdditional) if ethMsg != nil { predecessors = append(predecessors, ethMsg) } @@ -109,7 +109,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } if txAdditional != nil { - ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional) + ethMsg := b.parseDerivedTxFromAdditionalFields(txAdditional) if ethMsg != nil { predecessors = append(predecessors, ethMsg) } @@ -125,7 +125,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi return nil, fmt.Errorf("invalid transaction type %T", tx.GetMsgs()[transaction.MsgIndex]) } } else { - ethMessage = b.parseDerivedTxFromAdditionalFieldsForTrace(additional) + ethMessage = b.parseDerivedTxFromAdditionalFields(additional) if ethMessage == nil { b.logger.Error("failed to get derived eth msg from additional fields") return nil, fmt.Errorf("failed to get derived eth msg from additional fields") From db5fa5af4ba6e1dbd0bc99ad2a8f9d4101443159 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Mon, 22 Dec 2025 16:27:52 +0530 Subject: [PATCH 9/9] fix: Issue with trace function skipping Msg's other than MsgEthereumTx --- rpc/backend/tracing.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 04b405bcc..564297aca 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -50,7 +50,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi var predecessors []*evmtypes.MsgEthereumTx for i := 0; i < int(transaction.TxIndex); i++ { - _, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(i)) + transaction, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(i)) if err != nil { b.logger.Debug("failed to get tx by index", "height", blk.Block.Height, @@ -78,9 +78,26 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi continue } - for _, msg := range tx.GetMsgs() { + index := int(transaction.MsgIndex) + for j := 0; j < index; j++ { + msg := tx.GetMsgs()[j] + // Check if it’s a normal Ethereum tx if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok { predecessors = append(predecessors, ethMsg) + continue + } + // Fetch additional data for predecessors + _, txAdditionalMsg, err := b.GetTxByEthHashAndMsgIndex(hash, j) + if err != nil { + b.logger.Debug("failed to get tx additional info", "error", err.Error()) + continue + } + + if txAdditionalMsg != nil { + ethMsg := b.parseDerivedTxFromAdditionalFields(txAdditionalMsg) + if ethMsg != nil { + predecessors = append(predecessors, ethMsg) + } } } }