Skip to content

Commit

Permalink
reset lastBaseFee if fee config changes (#241)
Browse files Browse the repository at this point in the history
* reset lastBaseFee if fee config changes

* comments / lint

* update test to use require

* remove todo
  • Loading branch information
darioush authored Aug 30, 2022
1 parent 343a664 commit 5bfb71e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
15 changes: 12 additions & 3 deletions eth/gasprice/gasprice.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,12 @@ func (oracle *Oracle) suggestDynamicFees(ctx context.Context) (*big.Int, *big.In
return nil, nil, err
}

var feeLastChangedAt *big.Int
var (
feeLastChangedAt *big.Int
feeConfig commontype.FeeConfig
)
if oracle.backend.ChainConfig().IsFeeConfigManager(new(big.Int).SetUint64(head.Time)) {
_, feeLastChangedAt, err = oracle.backend.GetFeeConfigAt(head)
feeConfig, feeLastChangedAt, err = oracle.backend.GetFeeConfigAt(head)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -333,7 +336,13 @@ func (oracle *Oracle) suggestDynamicFees(ctx context.Context) (*big.Int, *big.In
tipResults []*big.Int
baseFeeResults []*big.Int
)

// if the fee config has changed in this block, use the new base fee
// if it is higher than this block's base fee.
if feeLastChangedAt != nil && feeLastChangedAt.Uint64() == number {
if lastBaseFee.Cmp(feeConfig.MinBaseFee) < 0 {
lastBaseFee = feeConfig.MinBaseFee
}
}
// iterates backwards until enough blocks are sent or until the block number that fee last changed at
for sent < oracle.checkBlocks && number > 0 && (feeLastChangedAt == nil || feeLastChangedAt.Uint64() < number) {
go oracle.getBlockTips(ctx, number, result, quit)
Expand Down
66 changes: 65 additions & 1 deletion eth/gasprice/gasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ import (
"github.com/ava-labs/subnet-evm/core/rawdb"
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/core/vm"
"github.com/ava-labs/subnet-evm/ethdb"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"github.com/stretchr/testify/require"
)

const testHead = 32
Expand All @@ -53,6 +56,7 @@ var (
)

type testBackend struct {
db ethdb.Database
chain *core.BlockChain
pending bool // pending block available
}
Expand Down Expand Up @@ -148,7 +152,7 @@ func newTestBackend(t *testing.T, config *params.ChainConfig, numBlocks int, gen
if _, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("Failed to insert chain, %v", err)
}
return &testBackend{chain: chain}
return &testBackend{chain: chain, db: db}
}

func (b *testBackend) MinRequiredTip(ctx context.Context, header *types.Header) (*big.Int, error) {
Expand Down Expand Up @@ -467,3 +471,63 @@ func TestSuggestGasPricePreAP3(t *testing.T) {
t.Fatal(err)
}
}

// Regression test to ensure the last estimation of base fee is not used
// for the block immediately following a fee configuration update.
func TestSuggestGasPriceAfterFeeConfigUpdate(t *testing.T) {
require := require.New(t)
config := Config{
Blocks: 20,
Percentile: 60,
}

// create a chain config with fee manager enabled at genesis with [addr] as the admin
chainConfig := *params.TestChainConfig
chainConfig.FeeManagerConfig = precompile.NewFeeManagerConfig(big.NewInt(0), []common.Address{addr})

// create a fee config with higher MinBaseFee and prepare it for inclusion in a tx
signer := types.LatestSigner(params.TestChainConfig)
highFeeConfig := chainConfig.FeeConfig
highFeeConfig.MinBaseFee = big.NewInt(28_000_000_000)
data, err := precompile.PackSetFeeConfig(highFeeConfig)
require.NoError(err)

// before issuing the block changing the fee into the chain, the fee estimation should
// follow the fee config in genesis.
backend := newTestBackend(t, &chainConfig, 0, func(i int, b *core.BlockGen) {})
oracle, err := NewOracle(backend, config)
require.NoError(err)
got, err := oracle.SuggestPrice(context.Background())
require.NoError(err)
require.Equal(chainConfig.FeeConfig.MinBaseFee, got)

// issue the block with tx that changes the fee
genesis := backend.chain.Genesis()
engine := backend.chain.Engine()
blocks, _, err := core.GenerateChain(&chainConfig, genesis, engine, backend.db, 1, 0, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{1})

// admin issues tx to change fee config to higher MinBaseFee
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: chainConfig.ChainID,
Nonce: b.TxNonce(addr),
To: &precompile.FeeConfigManagerAddress,
Gas: chainConfig.FeeConfig.GasLimit.Uint64(),
Value: common.Big0,
GasFeeCap: chainConfig.FeeConfig.MinBaseFee, // give low fee, it should work since we still haven't applied high fees
GasTipCap: common.Big0,
Data: data,
})
tx, err = types.SignTx(tx, signer, key)
require.NoError(err, "failed to create tx")
b.AddTx(tx)
})
require.NoError(err)
_, err = backend.chain.InsertChain(blocks)
require.NoError(err)

// verify the suggested price follows the new fee config.
got, err = oracle.SuggestPrice(context.Background())
require.NoError(err)
require.Equal(highFeeConfig.MinBaseFee, got)
}

0 comments on commit 5bfb71e

Please sign in to comment.