From 6c1a8c7df833456b94cdb669f7bec74ce80f57a9 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 17 Oct 2023 16:39:41 -0700 Subject: [PATCH] Change EIP 1559 Denominator with Canyon --- cmd/evm/internal/t8ntool/transition.go | 2 +- consensus/misc/eip1559/eip1559.go | 9 ++--- consensus/misc/eip1559/eip1559_test.go | 48 +++++++++++++++++++++++++- core/chain_makers.go | 4 +-- core/state_processor_test.go | 2 +- core/txpool/blobpool/blobpool.go | 4 +-- core/txpool/blobpool/blobpool_test.go | 2 +- core/txpool/legacypool/legacypool.go | 2 +- eth/gasprice/feehistory.go | 2 +- graphql/graphql.go | 2 +- internal/ethapi/api.go | 2 +- miner/worker.go | 2 +- params/config.go | 11 ++++-- params/superchain.go | 5 +-- 14 files changed, 75 insertions(+), 22 deletions(-) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 600bc460f7..78e7928fc2 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -355,7 +355,7 @@ func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { BaseFee: env.ParentBaseFee, GasUsed: env.ParentGasUsed, GasLimit: env.ParentGasLimit, - }) + }, env.Timestamp) return nil } diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 5e5d8a7e3f..a66298af69 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -47,7 +47,7 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade return errors.New("header is missing baseFee") } // Verify the baseFee is correct based on the parent header. - expectedBaseFee := CalcBaseFee(config, parent) + expectedBaseFee := CalcBaseFee(config, parent, header.Time) if header.BaseFee.Cmp(expectedBaseFee) != 0 { return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d", header.BaseFee, expectedBaseFee, parent.BaseFee, parent.GasUsed) @@ -56,7 +56,8 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade } // CalcBaseFee calculates the basefee of the header. -func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { +// The time belongs to the new block to check if Canyon is activted or not +func CalcBaseFee(config *params.ChainConfig, parent *types.Header, time uint64) *big.Int { // If the current block is the first EIP-1559 block, return the InitialBaseFee. if !config.IsLondon(parent.Number) { return new(big.Int).SetUint64(params.InitialBaseFee) @@ -79,7 +80,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { num.SetUint64(parent.GasUsed - parentGasTarget) num.Mul(num, parent.BaseFee) num.Div(num, denom.SetUint64(parentGasTarget)) - num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) + num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator(time))) baseFeeDelta := math.BigMax(num, common.Big1) return num.Add(parent.BaseFee, baseFeeDelta) @@ -89,7 +90,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { num.SetUint64(parentGasTarget - parent.GasUsed) num.Mul(num, parent.BaseFee) num.Div(num, denom.SetUint64(parentGasTarget)) - num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) + num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator(time))) baseFee := num.Sub(parent.BaseFee, num) return math.BigMax(baseFee, common.Big0) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index b5afdf0fe5..a5d5cf253e 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -55,6 +55,19 @@ func config() *params.ChainConfig { return config } +func opConfig() *params.ChainConfig { + config := copyConfig(params.TestChainConfig) + config.LondonBlock = big.NewInt(5) + ct := uint64(10) + config.CanyonTime = &ct + config.Optimism = ¶ms.OptimismConfig{ + EIP1559Elasticity: 6, + EIP1559Denominator: 50, + EIP1559DenominatorPostCanyon: 250, + } + return config +} + // TestBlockGasLimits tests the gasLimit checks for blocks both across // the EIP-1559 boundary and post-1559 blocks func TestBlockGasLimits(t *testing.T) { @@ -124,7 +137,40 @@ func TestCalcBaseFee(t *testing.T) { GasUsed: test.parentGasUsed, BaseFee: big.NewInt(test.parentBaseFee), } - if have, want := CalcBaseFee(config(), parent), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 { + if have, want := CalcBaseFee(config(), parent, 0), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 { + t.Errorf("test %d: have %d want %d, ", i, have, want) + } + } +} + +// TestCalcBaseFeeOptimism assumes all blocks are 1559-blocks but tests the Canyon activation +func TestCalcBaseFeeOptimism(t *testing.T) { + tests := []struct { + parentBaseFee int64 + parentGasLimit uint64 + parentGasUsed uint64 + expectedBaseFee int64 + postCanyon bool + }{ + {params.InitialBaseFee, 30_000_000, 5_000_000, params.InitialBaseFee, false}, // usage == target + {params.InitialBaseFee, 30_000_000, 4_000_000, 996000000, false}, // usage below target + {params.InitialBaseFee, 30_000_000, 10_000_000, 1020000000, false}, // usage above target + {params.InitialBaseFee, 30_000_000, 5_000_000, params.InitialBaseFee, true}, // usage == target + {params.InitialBaseFee, 30_000_000, 4_000_000, 999200000, true}, // usage below target + {params.InitialBaseFee, 30_000_000, 10_000_000, 1004000000, true}, // usage above target + } + for i, test := range tests { + parent := &types.Header{ + Number: common.Big32, + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: big.NewInt(test.parentBaseFee), + Time: 6, + } + if test.postCanyon { + parent.Time = 8 + } + if have, want := CalcBaseFee(opConfig(), parent, parent.Time+2), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 { t.Errorf("test %d: have %d want %d, ", i, have, want) } } diff --git a/core/chain_makers.go b/core/chain_makers.go index 3608329a13..ccffbbdddc 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -207,7 +207,7 @@ func (b *BlockGen) AddUncle(h *types.Header) { // The gas limit and price should be derived from the parent h.GasLimit = parent.GasLimit if b.config.IsLondon(h.Number) { - h.BaseFee = eip1559.CalcBaseFee(b.config, parent) + h.BaseFee = eip1559.CalcBaseFee(b.config, parent, h.Time) if !b.config.IsLondon(parent.Number) { parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier() h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) @@ -391,7 +391,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S Time: time, } if chain.Config().IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header()) + header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header(), header.Time) if !chain.Config().IsLondon(parent.Number()) { parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier() header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index aade2f6d73..1e70a166d5 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -377,7 +377,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr UncleHash: types.EmptyUncleHash, } if config.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(config, parent.Header()) + header.BaseFee = eip1559.CalcBaseFee(config, parent.Header(), header.Time) } if config.IsShanghai(header.Number, header.Time) { header.WithdrawalsHash = &types.EmptyWithdrawalsHash diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 32c6c0e8fe..3b6292d642 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -399,7 +399,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr p.recheck(addr, nil) } var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head)) + basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, p.head.Time+1)) blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice)) ) if p.head.ExcessBlobGas != nil { @@ -782,7 +782,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) { } // Reset the price heap for the new set of basefee/blobfee pairs var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead)) + basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead, newHead.Time+1)) blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice)) ) if newHead.ExcessBlobGas != nil { diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 8914301e14..6011f33bfa 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -114,7 +114,7 @@ func (bc *testBlockChain) CurrentBlock() *types.Header { GasLimit: gasLimit, GasUsed: 0, BaseFee: mid, - }).Cmp(bc.basefee.ToBig()) > 0 { + }, blockTime).Cmp(bc.basefee.ToBig()) > 0 { hi = mid } else { lo = mid diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 652043ec11..caff323191 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -1317,7 +1317,7 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, pool.demoteUnexecutables() if reset.newHead != nil { if pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { - pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead) + pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead, reset.newHead.Time+1) pool.priced.SetBaseFee(pendingBaseFee) } else { pool.priced.Reheap() diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go index 226991b24b..13f36499d4 100644 --- a/eth/gasprice/feehistory.go +++ b/eth/gasprice/feehistory.go @@ -83,7 +83,7 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) { bf.results.baseFee = new(big.Int) } if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) { - bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header) + bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header, bf.header.Time+1) } else { bf.results.nextBaseFee = new(big.Int) } diff --git a/graphql/graphql.go b/graphql/graphql.go index 8304a64cf4..51e1c1797d 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -772,7 +772,7 @@ func (b *Block) NextBaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { return nil, nil } } - nextBaseFee := eip1559.CalcBaseFee(chaincfg, header) + nextBaseFee := eip1559.CalcBaseFee(chaincfg, header, header.Time+1) return (*hexutil.Big)(nextBaseFee), nil } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 14734ee67a..046da5c499 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1696,7 +1696,7 @@ func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, conf blockTime = uint64(0) ) if current != nil { - baseFee = eip1559.CalcBaseFee(config, current) + baseFee = eip1559.CalcBaseFee(config, current, current.Time+1) blockNumber = current.Number.Uint64() blockTime = current.Time } diff --git a/miner/worker.go b/miner/worker.go index fbe9d1c53e..d932091283 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -983,7 +983,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { } // Set baseFee and GasLimit if we are on an EIP-1559 chain if w.chainConfig.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent) + header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent, header.Time) if !w.chainConfig.IsLondon(parent.Number) { parentGasLimit := parent.GasLimit * w.chainConfig.ElasticityMultiplier() header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) diff --git a/params/config.go b/params/config.go index 415700dfbb..a3e425fd3a 100644 --- a/params/config.go +++ b/params/config.go @@ -392,8 +392,9 @@ func (c *CliqueConfig) String() string { // OptimismConfig is the optimism config. type OptimismConfig struct { - EIP1559Elasticity uint64 `json:"eip1559Elasticity"` - EIP1559Denominator uint64 `json:"eip1559Denominator"` + EIP1559Elasticity uint64 `json:"eip1559Elasticity"` + EIP1559Denominator uint64 `json:"eip1559Denominator"` + EIP1559DenominatorPostCanyon uint64 `json:"eip1559DenominatorPostCanyon"` } // String implements the stringer interface, returning the optimism fee config details. @@ -798,8 +799,12 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, } // BaseFeeChangeDenominator bounds the amount the base fee can change between blocks. -func (c *ChainConfig) BaseFeeChangeDenominator() uint64 { +// The time parameters is the timestamp of the block to determine if Canyon is active or not +func (c *ChainConfig) BaseFeeChangeDenominator(time uint64) uint64 { if c.Optimism != nil { + if c.IsCanyon(time) { + return c.Optimism.EIP1559DenominatorPostCanyon + } return c.Optimism.EIP1559Denominator } return DefaultBaseFeeChangeDenominator diff --git a/params/superchain.go b/params/superchain.go index 00eb424731..c58a0de312 100644 --- a/params/superchain.go +++ b/params/superchain.go @@ -75,8 +75,9 @@ func LoadOPStackChainConfig(chainID uint64) (*ChainConfig, error) { Ethash: nil, Clique: nil, Optimism: &OptimismConfig{ - EIP1559Elasticity: 6, - EIP1559Denominator: 50, + EIP1559Elasticity: 6, + EIP1559Denominator: 50, + EIP1559DenominatorPostCanyon: 250, }, }