Skip to content

Commit

Permalink
eupgrade: lowering the base fee (#604)
Browse files Browse the repository at this point in the history
* eupgrade: base definitions

* updates

* nit: consistently use EUpgrade for replace later

* update test configs

* refactor json genesis specs in vm_test.go

* set min base fee at EUpgrade

* nit: comment

* Update params/config.go

Signed-off-by: Darioush Jalali <[email protected]>

* add ut

* nit:  comment

---------

Signed-off-by: Darioush Jalali <[email protected]>
  • Loading branch information
darioush authored Jul 29, 2024
1 parent 0b6c492 commit 49ad954
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 6 deletions.
4 changes: 4 additions & 0 deletions consensus/dummy/dynamic_fees.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var (
ApricotPhase4MinBaseFee = big.NewInt(params.ApricotPhase4MinBaseFee)
ApricotPhase4MaxBaseFee = big.NewInt(params.ApricotPhase4MaxBaseFee)
ApricotPhase3InitialBaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee)
EUpgradeMinBaseFee = big.NewInt(params.EUpgradeMinBaseFee)

ApricotPhase4BaseFeeChangeDenominator = new(big.Int).SetUint64(params.ApricotPhase4BaseFeeChangeDenominator)
ApricotPhase5BaseFeeChangeDenominator = new(big.Int).SetUint64(params.ApricotPhase5BaseFeeChangeDenominator)
Expand All @@ -45,6 +46,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, timestamp uin
isApricotPhase3 = config.IsApricotPhase3(parent.Time)
isApricotPhase4 = config.IsApricotPhase4(parent.Time)
isApricotPhase5 = config.IsApricotPhase5(parent.Time)
isEUpgrade = config.IsEUpgrade(parent.Time)
)
if !isApricotPhase3 || parent.Number.Cmp(common.Big0) == 0 {
initialSlice := make([]byte, params.DynamicFeeExtraDataSize)
Expand Down Expand Up @@ -177,6 +179,8 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, timestamp uin

// Ensure that the base fee does not increase/decrease outside of the bounds
switch {
case isEUpgrade:
baseFee = selectBigWithinBounds(EUpgradeMinBaseFee, baseFee, nil)
case isApricotPhase5:
baseFee = selectBigWithinBounds(ApricotPhase4MinBaseFee, baseFee, nil)
case isApricotPhase4:
Expand Down
27 changes: 27 additions & 0 deletions consensus/dummy/dynamic_fees_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func testRollup(t *testing.T, longs []uint64, roll int) {
Expand Down Expand Up @@ -537,3 +538,29 @@ func TestCalcBlockGasCost(t *testing.T) {
})
}
}

func TestDynamicFeesEUpgrade(t *testing.T) {
require := require.New(t)
header := &types.Header{
Number: big.NewInt(0),
}

timestamp := uint64(1)
extra, nextBaseFee, err := CalcBaseFee(params.TestEUpgradeChainConfig, header, timestamp)
require.NoError(err)
// Genesis matches the initial base fee
require.Equal(params.ApricotPhase3InitialBaseFee, nextBaseFee.Int64())

timestamp = uint64(10_000)
header = &types.Header{
Number: big.NewInt(1),
Time: header.Time,
BaseFee: nextBaseFee,
Extra: extra,
}
_, nextBaseFee, err = CalcBaseFee(params.TestEUpgradeChainConfig, header, timestamp)
require.NoError(err)
// After some time has passed in the EUpgrade phase, the base fee should drop
// lower than the prior base fee minimum.
require.Less(nextBaseFee.Int64(), params.ApricotPhase4MinBaseFee)
}
6 changes: 3 additions & 3 deletions core/txpool/blobpool/blobpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ func init() {

// overrideMinFee sets the minimum base fee to 1 wei for the duration of the test.
func overrideMinFee(t *testing.T) {
orig := dummy.ApricotPhase4MinBaseFee
dummy.ApricotPhase4MinBaseFee = big.NewInt(1)
t.Cleanup(func() { dummy.ApricotPhase4MinBaseFee = orig })
orig := dummy.EUpgradeMinBaseFee
dummy.EUpgradeMinBaseFee = big.NewInt(1)
t.Cleanup(func() { dummy.EUpgradeMinBaseFee = orig })
}

// testBlockChain is a mock of the live chain for testing the pool.
Expand Down
8 changes: 8 additions & 0 deletions core/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type TxPool struct {
quit chan chan error // Quit channel to tear down the head updater

gasTip atomic.Pointer[big.Int] // Remember last value set so it can be retrieved
minFee atomic.Pointer[big.Int] // Remember last value set so it can be retrieved (in tests)
reorgFeed event.Feed
}

Expand Down Expand Up @@ -270,9 +271,16 @@ func (p *TxPool) SetGasTip(tip *big.Int) {
}
}

// MinFee returns the current minimum fee enforced by the transaction pool.
func (p *TxPool) MinFee() *big.Int {
return new(big.Int).Set(p.minFee.Load())
}

// SetMinFee updates the minimum fee required by the transaction pool for a
// new transaction, and drops all transactions below this threshold.
func (p *TxPool) SetMinFee(fee *big.Int) {
p.minFee.Store(new(big.Int).Set(fee))

for _, subpool := range p.subpools {
subpool.SetMinFee(fee)
}
Expand Down
1 change: 1 addition & 0 deletions params/avalanche_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
ApricotPhase4BaseFeeChangeDenominator uint64 = 12
ApricotPhase5TargetGas uint64 = 15_000_000
ApricotPhase5BaseFeeChangeDenominator uint64 = 36
EUpgradeMinBaseFee int64 = GWei

DynamicFeeExtraDataSize = 80
RollupWindow uint64 = 10
Expand Down
2 changes: 1 addition & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ type ChainConfig struct {
// Note: EIP-4895 is excluded since withdrawals are not relevant to the Avalanche C-Chain or Subnets running the EVM.
DurangoBlockTimestamp *uint64 `json:"durangoBlockTimestamp,omitempty"`
// EUpgrade on the Avalanche network. (nil = no fork, 0 = already activated)
// It activates Cancun (TODO) and modifies the min base fee (TODO).
// It activates Cancun and reduces the min base fee.
EUpgradeTime *uint64 `json:"eUpgradeTime,omitempty"`

// Cancun activates the Cancun upgrade from Ethereum. (nil = no fork, 0 = already activated)
Expand Down
31 changes: 30 additions & 1 deletion plugin/evm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,12 +703,41 @@ func (vm *VM) initializeChain(lastAcceptedHash common.Hash) error {
// Set the gas parameters for the tx pool to the minimum gas price for the
// latest upgrade.
vm.txPool.SetGasTip(big.NewInt(0))
vm.txPool.SetMinFee(big.NewInt(params.ApricotPhase4MinBaseFee))
vm.setMinFeeAtEUpgrade()

vm.eth.Start()
return vm.initChainState(vm.blockChain.LastAcceptedBlock())
}

// TODO: remove this after EUpgrade is activated
func (vm *VM) setMinFeeAtEUpgrade() {
now := vm.clock.Time()
if vm.chainConfig.EUpgradeTime == nil {
// If EUpgrade is not set, set the min fee according to the latest upgrade
vm.txPool.SetMinFee(big.NewInt(params.ApricotPhase4MinBaseFee))
return
} else if vm.chainConfig.IsEUpgrade(uint64(now.Unix())) {
// If EUpgrade is activated, set the min fee to the EUpgrade min fee
vm.txPool.SetMinFee(big.NewInt(params.EUpgradeMinBaseFee))
return
}

vm.txPool.SetMinFee(big.NewInt(params.ApricotPhase4MinBaseFee))
vm.shutdownWg.Add(1)
go func() {
defer vm.shutdownWg.Done()

wait := utils.Uint64ToTime(vm.chainConfig.EUpgradeTime).Sub(now)
t := time.NewTimer(wait)
select {
case <-t.C: // Wait for EUpgrade to be activated
vm.txPool.SetMinFee(big.NewInt(params.EUpgradeMinBaseFee))
case <-vm.shutdownChan:
}
t.Stop()
}()
}

// initializeStateSyncClient initializes the client for performing state sync.
// If state sync is disabled, this function will wipe any ongoing summary from
// disk to ensure that we do not continue syncing from an invalid snapshot.
Expand Down
48 changes: 47 additions & 1 deletion plugin/evm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/utils/timer/mockable"
"github.com/ava-labs/avalanchego/utils/units"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/components/chain"
Expand Down Expand Up @@ -113,6 +114,12 @@ var (
return &cpy
}

activateEUpgrade = func(cfg *params.ChainConfig, eUpgradeTime uint64) *params.ChainConfig {
cpy := *cfg
cpy.EUpgradeTime = &eUpgradeTime
return &cpy
}

genesisJSONApricotPhase0 = genesisJSON(params.TestLaunchConfig)
genesisJSONApricotPhase1 = genesisJSON(params.TestApricotPhase1Config)
genesisJSONApricotPhase2 = genesisJSON(params.TestApricotPhase2Config)
Expand Down Expand Up @@ -281,7 +288,24 @@ func GenesisVM(t *testing.T,
*atomic.Memory,
*commonEng.SenderTest,
) {
vm := &VM{}
return GenesisVMWithClock(t, finishBootstrapping, genesisJSON, configJSON, upgradeJSON, mockable.Clock{})
}

// GenesisVMWithClock creates a VM instance as GenesisVM does, but also allows
// setting the vm's time before [Initialize] is called.
func GenesisVMWithClock(
t *testing.T,
finishBootstrapping bool,
genesisJSON string,
configJSON string,
upgradeJSON string,
clock mockable.Clock,
) (chan commonEng.Message,
*VM, database.Database,
*atomic.Memory,
*commonEng.SenderTest,
) {
vm := &VM{clock: clock}
vm.p2pSender = &commonEng.FakeSender{}
ctx, dbManager, genesisBytes, issuer, m := setupGenesis(t, genesisJSON)
appSender := &commonEng.SenderTest{T: t}
Expand Down Expand Up @@ -4065,3 +4089,25 @@ func TestParentBeaconRootBlock(t *testing.T) {
})
}
}

func TestMinFeeSetAtEUpgrade(t *testing.T) {
require := require.New(t)
now := time.Now()
eUpgradeTime := uint64(now.Add(1 * time.Second).Unix())

genesis := genesisJSON(
activateEUpgrade(params.TestEUpgradeChainConfig, eUpgradeTime),
)
clock := mockable.Clock{}
clock.Set(now)

_, vm, _, _, _ := GenesisVMWithClock(t, false, genesis, "", "", clock)
initial := vm.txPool.MinFee()
require.Equal(params.ApricotPhase4MinBaseFee, initial.Int64())

require.Eventually(
func() bool { return params.EUpgradeMinBaseFee == vm.txPool.MinFee().Int64() },
5*time.Second,
1*time.Second,
)
}

0 comments on commit 49ad954

Please sign in to comment.