Repository: harmony-one/harmony
Pull request #4844: Fix effective gas price for rpc getTransactionReceipt
Author: login: Frozen
Created: 2025-02-07T00:00:11Z | Merged: 2025-03-26T08:29:08Z

Fixed issue with effective gas price panic. Covered wth tests.


Diff:
diff --git a/core/types/receipt.go b/core/types/receipt.go
index 6207332d4e..0f9068c345 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -43,6 +43,9 @@ const (
 
 	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
 	ReceiptStatusSuccessful = uint64(1)
+
+	// DefaultEffectiveGasPrice is the default effective gas price for a transaction.
+	DefaultEffectiveGasPrice = 100 * 1e9
 )
 
 // Receipt represents the results of a transaction.
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 590c99b8b8..cede163a86 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -25,16 +25,15 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/harmony-one/harmony/internal/params"
-
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/hexutil"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/rlp"
-
 	"github.com/harmony-one/harmony/crypto/hash"
 	common2 "github.com/harmony-one/harmony/internal/common"
+	"github.com/harmony-one/harmony/internal/params"
 	staking "github.com/harmony-one/harmony/staking/types"
+	errs "github.com/pkg/errors"
 )
 
 // no go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
@@ -531,7 +530,7 @@ func (tx *Transaction) SenderAddress() (common.Address, error) {
 	}
 	addr, err := Sender(signer, tx)
 	if err != nil {
-		return common.Address{}, err
+		return common.Address{}, errs.WithMessage(err, "failed to extract sender address")
 	}
 	return addr, nil
 }
diff --git a/rosetta/services/tx_operation_test.go b/rosetta/services/tx_operation_test.go
index 06dc4278b6..328e2539d1 100644
--- a/rosetta/services/tx_operation_test.go
+++ b/rosetta/services/tx_operation_test.go
@@ -7,23 +7,31 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/harmony-one/harmony/hmy/tracers"
-
 	"github.com/coinbase/rosetta-sdk-go/types"
 	ethcommon "github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/crypto"
-
 	hmytypes "github.com/harmony-one/harmony/core/types"
 	"github.com/harmony-one/harmony/core/vm"
 	"github.com/harmony-one/harmony/hmy"
+	"github.com/harmony-one/harmony/hmy/tracers"
 	internalCommon "github.com/harmony-one/harmony/internal/common"
 	"github.com/harmony-one/harmony/internal/params"
 	"github.com/harmony-one/harmony/rosetta/common"
+	rpcV2 "github.com/harmony-one/harmony/rpc/harmony/v2"
 	"github.com/harmony-one/harmony/staking"
 	stakingTypes "github.com/harmony-one/harmony/staking/types"
 	"github.com/harmony-one/harmony/test/helpers"
 )
 
+// GetMessageFromStakingTx gets the staking message, as seen by the rpc layer
+func GetMessageFromStakingTx(tx *stakingTypes.StakingTransaction) (map[string]interface{}, error) {
+	rpcStakingTx, err := rpcV2.NewStakingTransaction(tx, ethcommon.Hash{}, 0, 0, 0, true)
+	if err != nil {
+		return nil, err
+	}
+	return types.MarshalMap(rpcStakingTx.Msg)
+}
+
 func TestGetStakingOperationsFromCreateValidator(t *testing.T) {
 	gasLimit := uint64(1e18)
 	createValidatorTxDescription := stakingTypes.Description{
@@ -46,7 +54,7 @@ func TestGetStakingOperationsFromCreateValidator(t *testing.T) {
 	if err != nil {
 		t.Fatal(err.Error())
 	}
-	metadata, err := helpers.GetMessageFromStakingTx(tx)
+	metadata, err := GetMessageFromStakingTx(tx)
 	if err != nil {
 		t.Fatal(err.Error())
 	}
@@ -187,7 +195,7 @@ func TestGetStakingOperationsFromDelegate(t *testing.T) {
 	if err != nil {
 		t.Fatal(err.Error())
 	}
-	metadata, err := helpers.GetMessageFromStakingTx(tx)
+	metadata, err := GetMessageFromStakingTx(tx)
 	if err != nil {
 		t.Fatal(err.Error())
 	}
@@ -323,7 +331,7 @@ func TestGetStakingOperationsFromUndelegate(t *testing.T) {
 	if err != nil {
 		t.Fatal(err.Error())
 	}
-	metadata, err := helpers.GetMessageFromStakingTx(tx)
+	metadata, err := GetMessageFromStakingTx(tx)
 	if err != nil {
 		t.Fatal(err.Error())
 	}
@@ -397,7 +405,7 @@ func TestGetStakingOperationsFromCollectRewards(t *testing.T) {
 	if err != nil {
 		t.Fatal(err.Error())
 	}
-	metadata, err := helpers.GetMessageFromStakingTx(tx)
+	metadata, err := GetMessageFromStakingTx(tx)
 	if err != nil {
 		t.Fatal(err.Error())
 	}
@@ -458,7 +466,7 @@ func TestGetStakingOperationsFromEditValidator(t *testing.T) {
 	if err != nil {
 		t.Fatal(err.Error())
 	}
-	metadata, err := helpers.GetMessageFromStakingTx(tx)
+	metadata, err := GetMessageFromStakingTx(tx)
 	if err != nil {
 		t.Fatal(err.Error())
 	}
diff --git a/rpc/harmony/eth/types.go b/rpc/harmony/eth/types.go
index 120129f45d..46bae77b56 100644
--- a/rpc/harmony/eth/types.go
+++ b/rpc/harmony/eth/types.go
@@ -140,6 +140,14 @@ func NewReceipt(senderAddr common.Address, tx *types.EthTransaction, blockHash c
 		receipt.Logs[i].TxHash = ethTxHash
 	}
 
+	var effectiveGasPrice hexutil.Big = hexutil.Big(*big.NewInt(types.DefaultEffectiveGasPrice))
+	if receipt.EffectiveGasPrice != nil {
+		//e := hexutil.Big(*new(big.Int).Set(receipt.EffectiveGasPrice))
+		//effectiveGasPrice = &e
+		//effectiveGasPrice = hexutil.Big(*receipt.EffectiveGasPrice)
+		effectiveGasPrice = hexutil.Big(*receipt.EffectiveGasPrice)
+	}
+
 	fields := map[string]interface{}{
 		"blockHash":         blockHash,
 		"blockNumber":       hexutil.Uint64(blockNumber),
@@ -152,7 +160,7 @@ func NewReceipt(senderAddr common.Address, tx *types.EthTransaction, blockHash c
 		"contractAddress":   nil,
 		"logs":              receipt.Logs,
 		"logsBloom":         receipt.Bloom,
-		"effectiveGasPrice": hexutil.Big(*receipt.EffectiveGasPrice),
+		"effectiveGasPrice": effectiveGasPrice,
 	}
 
 	// Assign receipt status or post state.
diff --git a/rpc/harmony/eth/types_test.go b/rpc/harmony/eth/types_test.go
new file mode 100644
index 0000000000..210f70afb1
--- /dev/null
+++ b/rpc/harmony/eth/types_test.go
@@ -0,0 +1,45 @@
+package eth
+
+import (
+	"math/big"
+	"testing"
+
+	common2 "github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/hexutil"
+	"github.com/harmony-one/harmony/core/types"
+	"github.com/harmony-one/harmony/internal/common"
+	"github.com/stretchr/testify/require"
+)
+
+func asInt(i any) *big.Int {
+	if s, ok := i.(hexutil.Big); ok {
+		return s.ToInt()
+	}
+	panic("<failed to convert>")
+}
+
+func TestNewReceipt(t *testing.T) {
+	var (
+		senderAddr         = common.Address{}
+		tx                 = &types.EthTransaction{}
+		blockHash          = common2.Hash{}
+		blockNumber uint64 = 1
+		blockIndex  uint64 = 1
+		receipt            = &types.Receipt{}
+		r                  = make(map[string]interface{})
+		err         error
+	)
+
+	t.Run("effectiveGasPrice", func(t *testing.T) {
+		r, err = NewReceipt(common2.Address(senderAddr), tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+		require.EqualValues(t, big.NewInt(types.DefaultEffectiveGasPrice), asInt(r["effectiveGasPrice"]))
+
+		rec := &types.Receipt{
+			EffectiveGasPrice: big.NewInt(1),
+		}
+		r, err = NewReceipt(common2.Address(senderAddr), tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+		require.EqualValues(t, big.NewInt(1), asInt(r["effectiveGasPrice"]))
+	})
+}
diff --git a/rpc/harmony/v1/types.go b/rpc/harmony/v1/types.go
index fa9369f4d2..988fc058f0 100644
--- a/rpc/harmony/v1/types.go
+++ b/rpc/harmony/v1/types.go
@@ -191,6 +191,16 @@ type TxReceipt struct {
 	EffectiveGasPrice hexutil.Big    `json:"effectiveGasPrice"`
 }
 
+// GetEffectiveGasPrice returns the effective gas price of the tx receipt
+func (s TxReceipt) GetEffectiveGasPrice() hexutil.Big {
+	return s.EffectiveGasPrice
+}
+
+// GetContractAddress returns the contract address of the tx receipt
+func (s TxReceipt) GetContractAddress() common.Address {
+	return s.ContractAddress
+}
+
 // StakingTxReceipt represents a staking transaction receipt that will serialize to the RPC representation.
 type StakingTxReceipt struct {
 	BlockHash         common.Hash    `json:"blockHash"`
@@ -209,6 +219,16 @@ type StakingTxReceipt struct {
 	EffectiveGasPrice hexutil.Big    `json:"effectiveGasPrice"`
 }
 
+// GetEffectiveGasPrice returns the effective gas price of the staking tx receipt
+func (s StakingTxReceipt) GetEffectiveGasPrice() hexutil.Big {
+	return s.EffectiveGasPrice
+}
+
+// GetContractAddress returns the contract address of the staking tx receipt
+func (s StakingTxReceipt) GetContractAddress() common.Address {
+	return s.ContractAddress
+}
+
 // CxReceipt represents a CxReceipt that will serialize to the RPC representation of a CxReceipt
 type CxReceipt struct {
 	BlockHash   common.Hash  `json:"blockHash"`
@@ -304,11 +324,13 @@ func NewTransaction(
 	return result, nil
 }
 
+type Receipt interface{}
+
 // NewReceipt returns a transaction OR staking transaction that will serialize to the RPC
 // representation.
 func NewReceipt(
 	tx interface{}, blockHash common.Hash, blockNumber, blockIndex uint64, receipt *types.Receipt,
-) (interface{}, error) {
+) (Receipt, error) {
 	plainTx, ok := tx.(*types.Transaction)
 	if ok {
 		return NewTxReceipt(plainTx, blockHash, blockNumber, blockIndex, receipt)
@@ -346,6 +368,11 @@ func NewTxReceipt(
 		}
 	}
 
+	var effectiveGasPrice = hexutil.Big(*big.NewInt(types.DefaultEffectiveGasPrice))
+	if receipt.EffectiveGasPrice != nil {
+		effectiveGasPrice = hexutil.Big(*receipt.EffectiveGasPrice)
+	}
+
 	// Declare receipt
 	txReceipt := &TxReceipt{
 		BlockHash:         blockHash,
@@ -361,7 +388,7 @@ func NewTxReceipt(
 		To:                receiver,
 		Root:              receipt.PostState,
 		Status:            hexutil.Uint(receipt.Status),
-		EffectiveGasPrice: hexutil.Big(*receipt.EffectiveGasPrice),
+		EffectiveGasPrice: effectiveGasPrice,
 	}
 
 	// Set empty array for empty logs
@@ -390,6 +417,11 @@ func NewStakingTxReceipt(
 		return nil, err
 	}
 
+	var effectiveGasPrice hexutil.Big = hexutil.Big(*big.NewInt(types.DefaultEffectiveGasPrice))
+	if receipt.EffectiveGasPrice != nil {
+		effectiveGasPrice = hexutil.Big(*receipt.EffectiveGasPrice)
+	}
+
 	// Declare receipt
 	txReceipt := &StakingTxReceipt{
 		BlockHash:         blockHash,
@@ -404,7 +436,7 @@ func NewStakingTxReceipt(
 		Type:              hexutil.Uint64(tx.StakingType()),
 		Root:              receipt.PostState,
 		Status:            hexutil.Uint(receipt.Status),
-		EffectiveGasPrice: hexutil.Big(*receipt.EffectiveGasPrice),
+		EffectiveGasPrice: effectiveGasPrice,
 	}
 
 	// Set empty array for empty logs
@@ -721,3 +753,25 @@ func NewStakingTransactionFromBlockIndex(b *types.Block, index uint64) (*Staking
 	}
 	return NewStakingTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time().Uint64(), index)
 }
+
+type getEffectiveGasPrice interface {
+	GetEffectiveGasPrice() hexutil.Big
+}
+
+type getContractAddress interface {
+	GetContractAddress() common.Address
+}
+
+func MustReceiptEffectivePrice(receipt Receipt) hexutil.Big {
+	if s, ok := receipt.(getEffectiveGasPrice); ok {
+		return s.GetEffectiveGasPrice()
+	}
+	panic(fmt.Sprintf("<failed to convert, i(%T) does not support GetEffectiveGasPrice interface>", receipt))
+}
+
+func MustContractAddress(receipt Receipt) common.Address {
+	if s, ok := receipt.(getContractAddress); ok {
+		return s.GetContractAddress()
+	}
+	panic(fmt.Sprintf("<failed to convert, i(%T) does not support getContractAddress interface>", receipt))
+}
diff --git a/rpc/harmony/v1/types_test.go b/rpc/harmony/v1/types_test.go
new file mode 100644
index 0000000000..2a9ceaae68
--- /dev/null
+++ b/rpc/harmony/v1/types_test.go
@@ -0,0 +1,108 @@
+package v1
+
+import (
+	"math/big"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/harmony-one/harmony/core/types"
+	staking "github.com/harmony-one/harmony/staking/types"
+	stakingTypes "github.com/harmony-one/harmony/staking/types"
+	"github.com/harmony-one/harmony/test/helpers"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+var (
+	oneBig     = big.NewInt(1e18)
+	tenOnes    = new(big.Int).Mul(big.NewInt(10), oneBig)
+	twelveOnes = new(big.Int).Mul(big.NewInt(12), oneBig)
+	gasPrice   = big.NewInt(10000)
+)
+
+func TestNewReceipt(t *testing.T) {
+	var (
+		FaucetPriKey, _                     = crypto.GenerateKey()
+		to                                  = common.Address{}
+		nonce                        uint64 = 1
+		gasLimit                            = uint64(1e18)
+		blockHash                           = common.Hash{}
+		blockNumber                  uint64 = 1
+		blockIndex                   uint64 = 1
+		receipt                             = &types.Receipt{}
+		r                            any
+		err                          error
+		createValidatorTxDescription = stakingTypes.Description{
+			Name:            "SuperHero",
+			Identity:        "YouWouldNotKnow",
+			Website:         "Secret Website",
+			SecurityContact: "LicenseToKill",
+			Details:         "blah blah blah",
+		}
+		payloadMaker = func() (stakingTypes.Directive, interface{}) {
+			fromKey, _ := crypto.GenerateKey()
+			return stakingTypes.DirectiveCreateValidator, stakingTypes.CreateValidator{
+				Description:        createValidatorTxDescription,
+				MinSelfDelegation:  tenOnes,
+				MaxTotalDelegation: twelveOnes,
+				ValidatorAddress:   crypto.PubkeyToAddress(fromKey.PublicKey),
+				Amount:             tenOnes,
+			}
+		}
+	)
+	t.Run("effectiveGasPrice-transaction", func(t *testing.T) {
+		unsigned := types.NewTransaction(nonce, to, 0, big.NewInt(0), 0, big.NewInt(0), nil)
+		tx, _ := types.SignTx(unsigned, types.HomesteadSigner{}, FaucetPriKey)
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+
+		price := MustReceiptEffectivePrice(r)
+		require.EqualValues(t, big.NewInt(types.DefaultEffectiveGasPrice), price.ToInt())
+
+		rec := &types.Receipt{
+			EffectiveGasPrice: big.NewInt(1),
+		}
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+
+		effectivePrice := MustReceiptEffectivePrice(r)
+		assert.EqualValues(t, "0x1", effectivePrice.String())
+	})
+	t.Run("effectiveGasPrice-staking", func(t *testing.T) {
+		unsigned, err := helpers.CreateTestStakingTransaction(payloadMaker, nil, 0, gasLimit, gasPrice)
+		tx, _ := staking.Sign(unsigned, stakingTypes.NewEIP155Signer(unsigned.ChainID()), FaucetPriKey)
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+
+		receiptEffectivePrice := MustReceiptEffectivePrice(r)
+		assert.EqualValues(t, big.NewInt(types.DefaultEffectiveGasPrice), receiptEffectivePrice.ToInt())
+
+		rec := &types.Receipt{
+			EffectiveGasPrice: big.NewInt(1),
+		}
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+
+		mustReceiptEffectivePrice := MustReceiptEffectivePrice(r)
+		assert.EqualValues(t, "0x1", mustReceiptEffectivePrice.String())
+	})
+	t.Run("contract-address", func(t *testing.T) {
+		unsigned := types.NewTransaction(nonce, to, 0, big.NewInt(0), 0, big.NewInt(0), nil)
+		tx, _ := types.SignTx(unsigned, types.HomesteadSigner{}, FaucetPriKey)
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+		require.EqualValues(t, receipt.ContractAddress, MustContractAddress(r))
+
+		rec := &types.Receipt{
+			ContractAddress: common.BytesToAddress([]byte{0x1}),
+		}
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+		require.EqualValues(t, rec.ContractAddress, MustContractAddress(r))
+	})
+	t.Run("unknown-receipt", func(t *testing.T) {
+		_, err := NewReceipt(nil, blockHash, blockNumber, blockIndex, receipt)
+		require.Error(t, err)
+	})
+}
diff --git a/rpc/harmony/v2/types.go b/rpc/harmony/v2/types.go
index 74060f9c99..8e0ef819cb 100644
--- a/rpc/harmony/v2/types.go
+++ b/rpc/harmony/v2/types.go
@@ -221,6 +221,11 @@ type TxReceipt struct {
 	EffectiveGasPrice uint64         `json:"effectiveGasPrice"`
 }
 
+// GetEffectiveGasPrice returns the effective gas price of the tx receipt
+func (s TxReceipt) GetEffectiveGasPrice() uint64 {
+	return s.EffectiveGasPrice
+}
+
 // StakingTxReceipt represents a staking transaction receipt that will serialize to the RPC representation.
 type StakingTxReceipt struct {
 	BlockHash         common.Hash       `json:"blockHash"`
@@ -239,6 +244,11 @@ type StakingTxReceipt struct {
 	EffectiveGasPrice uint64            `json:"effectiveGasPrice"`
 }
 
+// GetEffectiveGasPrice returns the effective gas price of the staking tx receipt
+func (s StakingTxReceipt) GetEffectiveGasPrice() uint64 {
+	return s.EffectiveGasPrice
+}
+
 // CxReceipt represents a CxReceipt that will serialize to the RPC representation of a CxReceipt
 type CxReceipt struct {
 	BlockHash   common.Hash `json:"blockHash"`
@@ -334,10 +344,13 @@ func NewTransaction(
 	return result, nil
 }
 
+// Receipt represents a transaction OR staking transaction that will serialize to the RPC representation
+type Receipt interface{}
+
 // NewReceipt returns a transaction OR staking transaction that will serialize to the RPC representation
 func NewReceipt(
 	tx interface{}, blockHash common.Hash, blockNumber, blockIndex uint64, receipt *types.Receipt,
-) (interface{}, error) {
+) (Receipt, error) {
 	plainTx, ok := tx.(*types.Transaction)
 	if ok {
 		return NewTxReceipt(plainTx, blockHash, blockNumber, blockIndex, receipt)
@@ -374,6 +387,10 @@ func NewTxReceipt(
 			return nil, err
 		}
 	}
+	var effectiveGasPrice uint64 = types.DefaultEffectiveGasPrice
+	if receipt.EffectiveGasPrice != nil {
+		effectiveGasPrice = receipt.EffectiveGasPrice.Uint64()
+	}
 
 	// Declare receipt
 	txReceipt := &TxReceipt{
@@ -390,7 +407,7 @@ func NewTxReceipt(
 		To:                receiver,
 		Root:              receipt.PostState,
 		Status:            uint(receipt.Status),
-		EffectiveGasPrice: (*receipt.EffectiveGasPrice).Uint64(),
+		EffectiveGasPrice: effectiveGasPrice,
 	}
 
 	// Set optionals
@@ -426,6 +443,11 @@ func NewStakingTxReceipt(
 		return nil, err
 	}
 
+	var effectiveGasPrice uint64 = types.DefaultEffectiveGasPrice
+	if receipt.EffectiveGasPrice != nil {
+		effectiveGasPrice = receipt.EffectiveGasPrice.Uint64()
+	}
+
 	// Declare receipt
 	txReceipt := &StakingTxReceipt{
 		BlockHash:         blockHash,
@@ -440,7 +462,7 @@ func NewStakingTxReceipt(
 		Type:              tx.StakingType(),
 		Root:              receipt.PostState,
 		Status:            uint(receipt.Status),
-		EffectiveGasPrice: (*receipt.EffectiveGasPrice).Uint64(),
+		EffectiveGasPrice: effectiveGasPrice,
 	}
 
 	// Set empty array for empty logs
@@ -803,3 +825,27 @@ func NewStakingTransactionFromBlockIndex(b *types.Block, index uint64) (*Staking
 	}
 	return NewStakingTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time().Uint64(), index, true)
 }
+
+type getEffectiveGasPrice interface {
+	GetEffectiveGasPrice() uint64
+}
+
+type getContractAddress interface {
+	GetContractAddress() common.Address
+}
+
+// MustReceiptEffectivePrice getter for effective gas price
+func MustReceiptEffectivePrice(receipt Receipt) uint64 {
+	if s, ok := receipt.(getEffectiveGasPrice); ok {
+		return s.GetEffectiveGasPrice()
+	}
+	panic(fmt.Sprintf("<failed to convert, i(%T) does not support GetEffectiveGasPrice interface>", receipt))
+}
+
+// MustContractAddress getter for contract address
+func MustContractAddress(receipt Receipt) common.Address {
+	if s, ok := receipt.(getContractAddress); ok {
+		return s.GetContractAddress()
+	}
+	panic(fmt.Sprintf("<failed to convert, i(%T) does not support getContractAddress interface>", receipt))
+}
diff --git a/rpc/harmony/v2/types_test.go b/rpc/harmony/v2/types_test.go
new file mode 100644
index 0000000000..22757e50af
--- /dev/null
+++ b/rpc/harmony/v2/types_test.go
@@ -0,0 +1,82 @@
+package v2
+
+import (
+	"math/big"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/harmony-one/harmony/core/types"
+	staking "github.com/harmony-one/harmony/staking/types"
+	"github.com/harmony-one/harmony/test/helpers"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+var (
+	oneBig     = big.NewInt(1e18)
+	tenOnes    = new(big.Int).Mul(big.NewInt(10), oneBig)
+	twelveOnes = new(big.Int).Mul(big.NewInt(12), oneBig)
+	gasPrice   = big.NewInt(10000)
+)
+
+func TestNewReceipt(t *testing.T) {
+	var (
+		FaucetPriKey, _                     = crypto.GenerateKey()
+		to                                  = common.Address{}
+		gasLimit                            = uint64(1e18)
+		nonce                        uint64 = 1
+		blockHash                           = common.Hash{}
+		blockNumber                  uint64 = 1
+		blockIndex                   uint64 = 1
+		receipt                             = &types.Receipt{}
+		r                            any
+		err                          error
+		createValidatorTxDescription = staking.Description{
+			Name:            "SuperHero",
+			Identity:        "YouWouldNotKnow",
+			Website:         "Secret Website",
+			SecurityContact: "LicenseToKill",
+			Details:         "blah blah blah",
+		}
+		payloadMaker = func() (staking.Directive, interface{}) {
+			fromKey, _ := crypto.GenerateKey()
+			return staking.DirectiveCreateValidator, staking.CreateValidator{
+				Description:        createValidatorTxDescription,
+				MinSelfDelegation:  tenOnes,
+				MaxTotalDelegation: twelveOnes,
+				ValidatorAddress:   crypto.PubkeyToAddress(fromKey.PublicKey),
+				Amount:             tenOnes,
+			}
+		}
+	)
+
+	t.Run("effectiveGasPrice-transaction", func(t *testing.T) {
+		unsigned := types.NewTransaction(nonce, to, 0, big.NewInt(0), 0, big.NewInt(0), nil)
+		tx, _ := types.SignTx(unsigned, types.HomesteadSigner{}, FaucetPriKey)
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+		require.EqualValues(t, uint64(types.DefaultEffectiveGasPrice), MustReceiptEffectivePrice(r))
+
+		rec := &types.Receipt{
+			EffectiveGasPrice: big.NewInt(1),
+		}
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+		require.EqualValues(t, 1, MustReceiptEffectivePrice(r))
+	})
+	t.Run("effectiveGasPrice-staking", func(t *testing.T) {
+		unsigned, err := helpers.CreateTestStakingTransaction(payloadMaker, nil, 0, gasLimit, gasPrice)
+		tx, _ := staking.Sign(unsigned, staking.NewEIP155Signer(unsigned.ChainID()), FaucetPriKey)
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, receipt)
+		require.NoError(t, err)
+		require.EqualValues(t, types.DefaultEffectiveGasPrice, MustReceiptEffectivePrice(r))
+
+		rec := &types.Receipt{
+			EffectiveGasPrice: big.NewInt(1),
+		}
+		r, err = NewReceipt(tx, blockHash, blockNumber, blockIndex, rec)
+		require.NoError(t, err)
+		assert.EqualValues(t, 1, MustReceiptEffectivePrice(r))
+	})
+}
diff --git a/test/helpers/transaction.go b/test/helpers/transaction.go
index 9367a957da..fcff192f58 100644
--- a/test/helpers/transaction.go
+++ b/test/helpers/transaction.go
@@ -4,12 +4,8 @@ import (
 	"crypto/ecdsa"
 	"math/big"
 
-	"github.com/coinbase/rosetta-sdk-go/types"
-	ethcommon "github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/crypto"
-
 	hmytypes "github.com/harmony-one/harmony/core/types"
-	rpcV2 "github.com/harmony-one/harmony/rpc/harmony/v2"
 	stakingTypes "github.com/harmony-one/harmony/staking/types"
 )
 
@@ -32,15 +28,6 @@ func CreateTestStakingTransaction(
 	return stakingTypes.Sign(tx, stakingTypes.NewEIP155Signer(tx.ChainID()), key)
 }
 
-// GetMessageFromStakingTx gets the staking message, as seen by the rpc layer
-func GetMessageFromStakingTx(tx *stakingTypes.StakingTransaction) (map[string]interface{}, error) {
-	rpcStakingTx, err := rpcV2.NewStakingTransaction(tx, ethcommon.Hash{}, 0, 0, 0, true)
-	if err != nil {
-		return nil, err
-	}
-	return types.MarshalMap(rpcStakingTx.Msg)
-}
-
 // CreateTestTransaction creates a pre-signed transaction
 func CreateTestTransaction(
 	signer hmytypes.Signer, fromShard, toShard uint32, nonce, gasLimit uint64,


Reviews:
user: login: sophoah
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T04:36:38Z
user: login: sophoah
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T04:40:39Z
user: login: mur-me
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-14T09:14:14Z
user: login: GheisMohammadi
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-02-20T02:20:56Z
user: login: Frozen
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-03T17:24:10Z
user: login: mur-me
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T12:05:21Z
user: login: mur-me
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-20T12:06:02Z
user: login: Frozen
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T01:01:01Z
user: login: mur-me
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-21T08:42:15Z

Review comments:
diff_hunk: @@ -390,6 +417,11 @@ func NewStakingTxReceipt(
 		return nil, err
 	}
 
+	effectiveGasPrice := *big.NewInt(0)
+	if receipt.EffectiveGasPrice != nil {
path: rpc/harmony/v1/types.go
user: login: sophoah
body: We should add an `else` clause to prevent the RPC to returns an effective gas price of 0. Not sure what edge case we are going to have in this case.
created_at: 2025-02-14T04:36:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -346,6 +368,11 @@ func NewTxReceipt(
 		}
 	}
 
+	effectiveGasPrice := *big.NewInt(0)
+	if receipt.EffectiveGasPrice != nil {
path: rpc/harmony/v1/types.go
user: login: sophoah
body: We should add an `else` clause to prevent the RPC to returns an effective gas price of 0. Not sure what edge case we are going to have in this case.
created_at: 2025-02-14T04:40:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -390,6 +417,11 @@ func NewStakingTxReceipt(
 		return nil, err
 	}
 
+	effectiveGasPrice := *big.NewInt(0)
+	if receipt.EffectiveGasPrice != nil {
path: rpc/harmony/v1/types.go
user: login: mur-me
body: Hey @Frozen I've tested against old and new transactions against testnet RPC and found that rn we still have 2 behaviors:
* old transactions have "effectiveGasPrice": 0
* new transactions have effectiveGasPrice==gasUsed

Can we make the same behavior `effectiveGasPrice==gasUsed` for the old transactions? 

created_at: 2025-02-14T09:14:14Z
author_association: COLLABORATOR
diff_hunk: @@ -390,6 +417,11 @@ func NewStakingTxReceipt(
 		return nil, err
 	}
 
+	effectiveGasPrice := *big.NewInt(0)
+	if receipt.EffectiveGasPrice != nil {
path: rpc/harmony/v1/types.go
user: login: Frozen
body: updated to return effectiveGasPrice==gasUsed if no value for effectiveGasPrice
created_at: 2025-03-03T17:24:10Z
author_association: COLLABORATOR
diff_hunk: @@ -43,6 +43,9 @@ const (
 
 	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
 	ReceiptStatusSuccessful = uint64(1)
+
+	// DefaultEffectiveGasPrice is the default effective gas price for a transaction.
+	DefaultEffectiveGasPrice = 100
path: core/types/receipt.go
user: login: mur-me
body: Hey @Frozen, I believe @sophoah mean 100GWEI which is `100000000000` as int or `0x174876e800` as hex

Proof:
```
$ curl -d '{
  "jsonrpc":"2.0",
  "method":"hmy_gasPrice",
  "params":[],
  "id":1
}' -H 'Content-Type:application/json' -X POST 'https://api.s0.b.hmny.io'
```
Response: `{"jsonrpc":"2.0","id":1,"result":"0x174876e800"}`

And
```
$ curl -d '{
  "jsonrpc":"2.0",
  "method":"hmyv2_gasPrice",
  "params":[],
  "id":1
}' -H 'Content-Type:application/json' -X POST 'https://api.s0.b.hmny.io'
```
Response `{"jsonrpc":"2.0","id":1,"result":100000000000}`
created_at: 2025-03-20T12:05:16Z
author_association: COLLABORATOR
diff_hunk: @@ -43,6 +43,9 @@ const (
 
 	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
 	ReceiptStatusSuccessful = uint64(1)
+
+	// DefaultEffectiveGasPrice is the default effective gas price for a transaction.
+	DefaultEffectiveGasPrice = 100
path: core/types/receipt.go
user: login: mur-me
body: What I have right now is `100` as v2 and `0x64` as hex for v1 
created_at: 2025-03-20T12:06:02Z
author_association: COLLABORATOR
diff_hunk: @@ -43,6 +43,9 @@ const (
 
 	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
 	ReceiptStatusSuccessful = uint64(1)
+
+	// DefaultEffectiveGasPrice is the default effective gas price for a transaction.
+	DefaultEffectiveGasPrice = 100
path: core/types/receipt.go
user: login: Frozen
body: updated to 100 gwei
created_at: 2025-03-21T01:01:01Z
author_association: COLLABORATOR

PR comments:
user: login: sophoah
created_at: 2025-02-18T08:07:54Z
body: @Frozen 
author_association: CONTRIBUTOR
user: login: Frozen
created_at: 2025-02-25T16:41:11Z
body: returns `nil` by default
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-03T12:28:00Z
body: Hey @Frozen, can you please explain why can't we have the same behavior as Ethereum has for transactions before EIP-1559?

~I've checked numerous sources and all them saying that pre-London(eip1559) transactions should have `gasUsed == effectiveGasUsed`~

I've checked numerous sources and all them saying that pre-London(eip1559) transactions should have `gasPrice == effectiveGasPrice` 

For example:
* https://github.com/ethereum/go-ethereum/issues/29202#issuecomment-1997056266
* `gasPrice now interpreted as maxFeePerGas before the tx is mined and effectiveGasPrice after it's mined (for EIP-1559 txs). This field is deprecated (no EOL set yet) for EIP-1559 transactions.` per https://hackmd.io/@timbeiko/1559-json-rpc

author_association: COLLABORATOR
user: login: Frozen
created_at: 2025-03-04T04:27:14Z
body: updated to return effectiveGasPrice==gasUsed if no value for effectiveGasPrice
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-04T11:47:03Z
body: > updated to return effectiveGasPrice==gasUsed if no value for effectiveGasPrice

Thanks, I'll install this version to the testnet RPC node and verify how will it work 
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-04T13:08:38Z
body: Hey @Frozen, sorry, but I've mistakenly mentioned `gasUsed == effectiveGasUsed` instead of `GasPrice==effectiveGasPrice`, all the source links mentioned are correct, sorry for this   
author_association: COLLABORATOR
user: login: Frozen
created_at: 2025-03-12T23:16:32Z
body: updated to return nil if value is not set
author_association: COLLABORATOR
user: login: Frozen
created_at: 2025-03-12T23:17:33Z
body: Eth Receipt does not contains GasPrice field, so it's better to return nil insted of GasPrice value
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-17T08:32:06Z
body: @Frozen, please rebase on the latest dev :pray: 
author_association: COLLABORATOR
user: login: sophoah
created_at: 2025-03-17T09:46:14Z
body: @Frozen let's fix the effective gas price to 100.
author_association: CONTRIBUTOR
user: login: Frozen
created_at: 2025-03-18T20:11:23Z
body: > @Frozen, please rebase on the latest dev 🙏

Done
author_association: COLLABORATOR
user: login: Frozen
created_at: 2025-03-18T20:59:57Z
body: > @Frozen let's fix the effective gas price to 100.

updated to return 100 as default value
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-21T08:41:55Z
body: Thanks @Frozen, I've installed your branch on the testnet and run regression test suite for the old transactions and now all the tests passed:
```
test_effective_gas_price_regression.py::test_effective_gas_price[eth-staking_call-0xfc78151506dfa4b2f01b5bacac698203348a92eb70fd2b8179b51897a580e26c] PASSED  [  8%]
test_effective_gas_price_regression.py::test_effective_gas_price[eth-smart_contract_call-0x5df75796f9a563d0cd84d8bf86d62f5bbeb696d63b656cf7b659ec3244ff4c1f] PASSED [ 16%]
test_effective_gas_price_regression.py::test_effective_gas_price[eth-coin_transfer-0x174a4ff5073ee5e811e117e9ee950f382dcb388aa50bac45f75e9f50aa051c15] PASSED [ 25%]
test_effective_gas_price_regression.py::test_effective_gas_price[eth-latest-retrived_from_blockscout] PASSED                                                  [ 33%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmy-staking_call-0xfc78151506dfa4b2f01b5bacac698203348a92eb70fd2b8179b51897a580e26c] PASSED  [ 41%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmy-smart_contract_call-0x5df75796f9a563d0cd84d8bf86d62f5bbeb696d63b656cf7b659ec3244ff4c1f] PASSED [ 50%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmy-coin_transfer-0x174a4ff5073ee5e811e117e9ee950f382dcb388aa50bac45f75e9f50aa051c15] PASSED [ 58%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmy-latest-retrived_from_blockscout] PASSED                                                  [ 66%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmyv2-staking_call-0xfc78151506dfa4b2f01b5bacac698203348a92eb70fd2b8179b51897a580e26c] PASSED [ 75%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmyv2-smart_contract_call-0x5df75796f9a563d0cd84d8bf86d62f5bbeb696d63b656cf7b659ec3244ff4c1f] PASSED [ 83%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmyv2-coin_transfer-0x174a4ff5073ee5e811e117e9ee950f382dcb388aa50bac45f75e9f50aa051c15] PASSED [ 91%]
test_effective_gas_price_regression.py::test_effective_gas_price[hmyv2-latest-retrived_from_blockscout] PASSED                                                [100%]
```
author_association: COLLABORATOR
user: login: mur-me
created_at: 2025-03-21T08:43:53Z
body: Let's also merge https://github.com/harmony-one/harmony-test/pull/38 after merge of this PR :pray: 
author_association: COLLABORATOR