Skip to content

Commit

Permalink
Fix eth_gasPrice RPC method (#1883)
Browse files Browse the repository at this point in the history
* fix rpc methdod

* fix test

* fix test

* added priority fee

* draft logic

* tests

---------

Co-authored-by: Igor Crevar <crewce@gmail.com>
  • Loading branch information
rachit77 and igorcrevar authored Sep 7, 2023
1 parent 3d2e58f commit 75bb8b4
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 17 deletions.
101 changes: 85 additions & 16 deletions jsonrpc/eth_blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/0xPolygon/polygon-edge/blockchain"
"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/helper/hex"
"github.com/0xPolygon/polygon-edge/helper/progress"
"github.com/0xPolygon/polygon-edge/state/runtime"
Expand Down Expand Up @@ -276,42 +277,89 @@ func TestEth_Syncing(t *testing.T) {
})
}

// if price-limit flag is set its value should be returned if it is higher than avg gas price
func TestEth_GetPrice_PriceLimitSet(t *testing.T) {
priceLimit := uint64(100333)
func TestEth_GasPrice_WithLondonFork(t *testing.T) {
const (
baseFee = uint64(10000)
tipCap = uint64(1000)
priceLimit = uint64(10010)
)

store := newMockBlockStore()
store.blocks = []*types.Block{
{
Header: &types.Header{Number: uint64(1)},
},
}
store.maxPriorityFeePerGasFn = func() (*big.Int, error) {
return new(big.Int).SetUint64(tipCap), nil
}

// not using newTestEthEndpoint as we need to set priceLimit
eth := newTestEthEndpointWithPriceLimit(store, priceLimit)

t.Run("returns price limit flag value when it is larger than average gas price", func(t *testing.T) {
t.Run("returns price limit flag value when it is larger than MaxPriorityFee+BaseFee", func(t *testing.T) {
store.baseFee = 0

res, err := eth.GasPrice()
store.averageGasPrice = 0

assert.NoError(t, err)
assert.NotNil(t, res)

assert.Equal(t, argUint64(priceLimit), res)
})

t.Run("returns average gas price when it is larger than set price limit flag", func(t *testing.T) {
store.averageGasPrice = 500000
t.Run("returns MaxPriorityFee+BaseFee when it is larger than set price limit flag", func(t *testing.T) {
store.baseFee = baseFee

res, err := eth.GasPrice()

assert.NoError(t, err)
assert.NotNil(t, res)
assert.Equal(t, argUint64(baseFee+tipCap), res)
})

assert.GreaterOrEqual(t, res, argUint64(priceLimit))
t.Run("returns error if MaxPriorityFeePerGas returns error", func(t *testing.T) {
store.maxPriorityFeePerGasFn = func() (*big.Int, error) {
return nil, runtime.ErrDepth
}

_, err := eth.GasPrice()

assert.ErrorIs(t, err, runtime.ErrDepth)
})
}

func TestEth_GasPrice(t *testing.T) {
func TestEth_GasPrice_WithoutLondonFork(t *testing.T) {
const priceLimit = 100000

store := newMockBlockStore()
store.averageGasPrice = 9999
eth := newTestEthEndpoint(store)
store.forksInTime.London = false
store.blocks = []*types.Block{
{
Header: &types.Header{Number: uint64(1)},
},
}

res, err := eth.GasPrice()
assert.NoError(t, err)
assert.NotNil(t, res)
eth := newTestEthEndpointWithPriceLimit(store, priceLimit)

assert.Equal(t, argUint64(store.averageGasPrice), res)
t.Run("priceLimit is greater than averageGasPrice", func(t *testing.T) {
store.averageGasPrice = priceLimit - 100

res, err := eth.GasPrice()

assert.NoError(t, err)
assert.NotNil(t, res)
assert.Equal(t, argUint64(priceLimit), res)
})

t.Run("averageGasPrice is greater than priceLimit", func(t *testing.T) {
store.averageGasPrice = priceLimit + 100

res, err := eth.GasPrice()

assert.NoError(t, err)
assert.NotNil(t, res)
assert.Equal(t, argUint64(priceLimit+100), res)
})
}

func TestEth_Call(t *testing.T) {
Expand Down Expand Up @@ -406,11 +454,16 @@ type mockBlockStore struct {
averageGasPrice int64
ethCallError error
returnValue []byte
forksInTime chain.ForksInTime
baseFee uint64

maxPriorityFeePerGasFn func() (*big.Int, error)
}

func newMockBlockStore() *mockBlockStore {
store := &mockBlockStore{}
store.receipts = make(map[types.Hash][]*types.Receipt)
store.forksInTime = chain.AllForksEnabled.At(0)

return store
}
Expand Down Expand Up @@ -598,6 +651,22 @@ func (m *mockBlockStore) GetAccount(root types.Hash, addr types.Address) (*Accou
return &Account{Nonce: 0}, nil
}

func (m *mockBlockStore) GetBaseFee() uint64 {
return m.baseFee
}

func (m *mockBlockStore) GetForksInTime(block uint64) chain.ForksInTime {
return m.forksInTime
}

func (m *mockBlockStore) MaxPriorityFeePerGas() (*big.Int, error) {
if m.maxPriorityFeePerGasFn != nil {
return m.maxPriorityFeePerGasFn()
}

return big.NewInt(0), nil
}

func newTestBlock(number uint64, hash types.Hash) *types.Block {
return &types.Block{
Header: &types.Header{
Expand Down
14 changes: 13 additions & 1 deletion jsonrpc/eth_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type ethTxPoolStore interface {

// GetNonce returns the next nonce for this address
GetNonce(addr types.Address) uint64

// returns the current base fee of TxPool
GetBaseFee() uint64
}

type Account struct {
Expand Down Expand Up @@ -393,10 +396,19 @@ func (e *Eth) GetStorageAt(
// GasPrice returns the average gas price based on the last x blocks
// taking into consideration operator defined price limit
func (e *Eth) GasPrice() (interface{}, error) {
// Return --price-limit flag defined value if it is greater than avgGasPrice/baseFee+priorityFee
if e.store.GetForksInTime(e.store.Header().Number).London {
priorityFee, err := e.store.MaxPriorityFeePerGas()
if err != nil {
return nil, err
}

return argUint64(common.Max(e.priceLimit, priorityFee.Uint64()+e.store.GetBaseFee())), nil
}

// Fetch average gas price in uint64
avgGasPrice := e.store.GetAvgGasPrice().Uint64()

// Return --price-limit flag defined value if it is greater than avgGasPrice
return argUint64(common.Max(e.priceLimit, avgGasPrice)), nil
}

Expand Down

0 comments on commit 75bb8b4

Please sign in to comment.