From e0d4a463c72125fae470cb8aacf3bf7daec0734f Mon Sep 17 00:00:00 2001 From: blindchaser Date: Wed, 20 Nov 2024 12:35:13 -0500 Subject: [PATCH 1/8] feat: fill failed tx receipt missing fields with block data --- evmrpc/tx.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index 9d773c8720..45896a3157 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -53,6 +53,40 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. } return nil, err } + // Check if the transaction has failed and used 0 gas + if receipt.TxType == 0 && receipt.GasUsed == 0 { + // Get the block + height := int64(receipt.BlockNumber) + block, err := blockByNumberWithRetry(ctx, t.tmClient, &height, 1) + if err != nil { + return nil, err + } + + // Find the transaction in the block + for _, tx := range block.Block.Txs { + etx := getEthTxForTxBz(tx, t.txConfig.TxDecoder()) + if etx != nil && etx.Hash() == hash { + // Get the signer + signer := ethtypes.MakeSigner( + types.DefaultChainConfig().EthereumConfig(t.keeper.ChainID(sdkctx)), + big.NewInt(height), + uint64(block.Block.Time.Unix()), + ) + from, _ := ethtypes.Sender(signer, etx) + + // Update receipt with correct information + receipt.From = from.Hex() + receipt.To = etx.To().Hex() + receipt.TxType = uint32(etx.Type()) + receipt.GasUsed = etx.Gas() + receipt.EffectiveGasPrice = etx.GasPrice().Uint64() + receipt.Status = uint32(ethtypes.ReceiptStatusFailed) + receipt.ContractAddress = "" + + break + } + } + } height := int64(receipt.BlockNumber) block, err := blockByNumberWithRetry(ctx, t.tmClient, &height, 1) if err != nil { From b6f4015e24bb90d90e9ba05e46b4601709741eda Mon Sep 17 00:00:00 2001 From: blindchaser Date: Wed, 20 Nov 2024 13:53:16 -0500 Subject: [PATCH 2/8] improve logic --- evmrpc/tx.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index 45896a3157..dff4db7c9e 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -53,7 +53,7 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. } return nil, err } - // Check if the transaction has failed and used 0 gas + // Fill in the receipt if the transaction has failed and used 0 gas if receipt.TxType == 0 && receipt.GasUsed == 0 { // Get the block height := int64(receipt.BlockNumber) @@ -76,12 +76,17 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. // Update receipt with correct information receipt.From = from.Hex() - receipt.To = etx.To().Hex() + if etx.To() != nil { + receipt.To = etx.To().Hex() + receipt.ContractAddress = "" + } else { + receipt.To = "" + // For contract creation transactions, calculate the contract address + receipt.ContractAddress = crypto.CreateAddress(from, etx.Nonce()).Hex() + } receipt.TxType = uint32(etx.Type()) receipt.GasUsed = etx.Gas() - receipt.EffectiveGasPrice = etx.GasPrice().Uint64() receipt.Status = uint32(ethtypes.ReceiptStatusFailed) - receipt.ContractAddress = "" break } From 79c51b6e724ebc673dce7463bb75320b5229bd06 Mon Sep 17 00:00:00 2001 From: blindchaser Date: Wed, 20 Nov 2024 16:08:53 -0500 Subject: [PATCH 3/8] set gasUsed=0 --- evmrpc/tx.go | 1 - 1 file changed, 1 deletion(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index dff4db7c9e..d28b7d30ef 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -85,7 +85,6 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. receipt.ContractAddress = crypto.CreateAddress(from, etx.Nonce()).Hex() } receipt.TxType = uint32(etx.Type()) - receipt.GasUsed = etx.Gas() receipt.Status = uint32(ethtypes.ReceiptStatusFailed) break From 92a44bd860e2b145c33a0eebd39e48429afb8b9b Mon Sep 17 00:00:00 2001 From: blindchaser Date: Wed, 20 Nov 2024 16:30:59 -0500 Subject: [PATCH 4/8] debug: gasUsed --- evmrpc/tx.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index d28b7d30ef..eb6aa6eb2c 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "log" + "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/accounts" @@ -54,6 +56,7 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, err } // Fill in the receipt if the transaction has failed and used 0 gas + log.Printf("[DEBUG] receipt info: %+v", receipt) if receipt.TxType == 0 && receipt.GasUsed == 0 { // Get the block height := int64(receipt.BlockNumber) @@ -86,7 +89,8 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. } receipt.TxType = uint32(etx.Type()) receipt.Status = uint32(ethtypes.ReceiptStatusFailed) - + receipt.GasUsed = 0 + log.Printf("[DEBUG] GetTransactionReceipt gasUsed: %d", receipt.GasUsed) break } } @@ -316,7 +320,7 @@ func encodeReceipt(receipt *types.Receipt, decoder sdk.TxDecoder, block *coretyp } bloom := ethtypes.Bloom{} bloom.SetBytes(receipt.LogsBloom) - + log.Printf("[DEBUG] encodeReceipt gasUsed: %d", receipt.GasUsed) fields := map[string]interface{}{ "blockHash": bh, "blockNumber": hexutil.Uint64(receipt.BlockNumber), From abc45194c369b1fc602a51e345a0354fd5cc587d Mon Sep 17 00:00:00 2001 From: blindchaser Date: Wed, 20 Nov 2024 18:56:12 -0500 Subject: [PATCH 5/8] remove log --- evmrpc/tx.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index eb6aa6eb2c..04e9ea24ff 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -8,8 +8,6 @@ import ( "strings" "time" - "log" - "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/accounts" @@ -56,7 +54,6 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, err } // Fill in the receipt if the transaction has failed and used 0 gas - log.Printf("[DEBUG] receipt info: %+v", receipt) if receipt.TxType == 0 && receipt.GasUsed == 0 { // Get the block height := int64(receipt.BlockNumber) @@ -90,7 +87,6 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. receipt.TxType = uint32(etx.Type()) receipt.Status = uint32(ethtypes.ReceiptStatusFailed) receipt.GasUsed = 0 - log.Printf("[DEBUG] GetTransactionReceipt gasUsed: %d", receipt.GasUsed) break } } @@ -320,7 +316,6 @@ func encodeReceipt(receipt *types.Receipt, decoder sdk.TxDecoder, block *coretyp } bloom := ethtypes.Bloom{} bloom.SetBytes(receipt.LogsBloom) - log.Printf("[DEBUG] encodeReceipt gasUsed: %d", receipt.GasUsed) fields := map[string]interface{}{ "blockHash": bh, "blockNumber": hexutil.Uint64(receipt.BlockNumber), From 711c345c14b66f1ae879fbb8f8428f784159711e Mon Sep 17 00:00:00 2001 From: blindchaser Date: Thu, 21 Nov 2024 10:38:18 -0500 Subject: [PATCH 6/8] fix status check --- evmrpc/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index 04e9ea24ff..e7e043f673 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -54,7 +54,7 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, err } // Fill in the receipt if the transaction has failed and used 0 gas - if receipt.TxType == 0 && receipt.GasUsed == 0 { + if receipt.Status == 0 && receipt.GasUsed == 0 { // Get the block height := int64(receipt.BlockNumber) block, err := blockByNumberWithRetry(ctx, t.tmClient, &height, 1) From 0f8c9449b8f6b2c0a74e9a99114745fb911db9ed Mon Sep 17 00:00:00 2001 From: blindchaser Date: Thu, 21 Nov 2024 13:03:40 -0500 Subject: [PATCH 7/8] unit test --- evmrpc/tx_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/evmrpc/tx_test.go b/evmrpc/tx_test.go index b41c07f2cf..e2d1896bf3 100644 --- a/evmrpc/tx_test.go +++ b/evmrpc/tx_test.go @@ -243,3 +243,49 @@ func TestGetVMError(t *testing.T) { resObj = sendRequestGood(t, "getVMError", "0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872f") require.Equal(t, "not found", resObj["error"].(map[string]interface{})["message"]) } + +func TestGetTransactionReceiptFailedTx(t *testing.T) { + fromAddr := "0x5b4eba929f3811980f5ae0c5d04fa200f837df4e" // Use the actual address from the block + + // Create a failed receipt with 0 gas used for a contract creation transaction + failedReceipt := &types.Receipt{ + Status: 0, // failed status + GasUsed: 0, + BlockNumber: 8, + TransactionIndex: 0, + TxHashHex: "0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e", + From: fromAddr, // Use the actual from address + } + + // Mock the receipt in the keeper + txHash := common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e") + EVMKeeper.MockReceipt(Ctx, txHash, failedReceipt) + + // Create JSON-RPC request + body := "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e\"],\"id\":\"test\"}" + + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body)) + require.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + + res, err := http.DefaultClient.Do(req) + require.Nil(t, err) + + resBody, err := io.ReadAll(res.Body) + require.Nil(t, err) + + resObj := map[string]interface{}{} + require.Nil(t, json.Unmarshal(resBody, &resObj)) + resObj = resObj["result"].(map[string]interface{}) + + // Verify the receipt was filled with correct information for failed tx + require.Equal(t, "0x0", resObj["status"].(string)) // Failed status + require.Equal(t, "0x0", resObj["gasUsed"].(string)) // 0 gas used + require.Equal(t, "0x8", resObj["blockNumber"].(string)) + require.Equal(t, "0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e", resObj["transactionHash"].(string)) + require.Equal(t, fromAddr, resObj["from"].(string)) + + // For contract creation transaction + require.Equal(t, "0x0000000000000000000000000000000000010203", resObj["to"].(string)) + require.Nil(t, resObj["contractAddress"]) +} From 16fac14883f185e14c8d9245bbad7c95da3bd848 Mon Sep 17 00:00:00 2001 From: blindchaser Date: Thu, 21 Nov 2024 13:15:40 -0500 Subject: [PATCH 8/8] update comment --- evmrpc/tx.go | 1 + 1 file changed, 1 insertion(+) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index e7e043f673..d4d450e3ad 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -54,6 +54,7 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, err } // Fill in the receipt if the transaction has failed and used 0 gas + // This case is for when a tx fails before it makes it to the VM if receipt.Status == 0 && receipt.GasUsed == 0 { // Get the block height := int64(receipt.BlockNumber)