From cf7301639e9a79ca4a1c583804479383685d7fe9 Mon Sep 17 00:00:00 2001 From: Lucca Martins Date: Mon, 5 Jan 2026 15:56:46 -0300 Subject: [PATCH 01/18] remove baseFee validation after hf --- consensus/misc/eip1559/eip1559.go | 32 ++++++++++++++++++++++++++----- params/config.go | 7 +++++++ params/protocol_params.go | 6 +++++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index fb18096330..5a6ac7936e 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) @@ -44,10 +45,15 @@ 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) - 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) + + if !config.Bor.IsFee(parent.Number) { + expectedBaseFee := CalcBaseFee(config, parent) + 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) + } + } else { + log.Info("[debuglocal] Fee block, skipping check") } return nil @@ -60,7 +66,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { return new(big.Int).SetUint64(params.InitialBaseFee) } - parentGasTarget := parent.GasLimit / config.ElasticityMultiplier() + parentGasTarget := CalcParentGasTarget(config, parent) // If the parent gasUsed is the same as the target, the baseFee remains unchanged. if parent.GasUsed == parentGasTarget { return new(big.Int).Set(parent.BaseFee) @@ -98,3 +104,19 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { return baseFee } } + +func CalcParentGasTarget( + config *params.ChainConfig, + parent *types.Header, +) uint64 { + if !config.Bor.IsFee(parent.Number) || config.Bor.TargetGasPercentage == 0 { + return parent.GasLimit / config.ElasticityMultiplier() + } + + pct := uint64(config.Bor.TargetGasPercentage) + if pct > 100 { + panic("invalid Bor TargetGasPercentage") + } + log.Info("[debuglocal] Fee block, calculating gas target", "parentGasLimit", parent.GasLimit, "targetGasPercentage", pct, "result", parent.GasLimit*pct/100) + return parent.GasLimit * pct / 100 +} diff --git a/params/config.go b/params/config.go index 62347fe2d1..a9ca6387ef 100644 --- a/params/config.go +++ b/params/config.go @@ -879,6 +879,8 @@ type BorConfig struct { BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork Coinbase map[string]string `json:"coinbase"` // coinbase address SkipValidatorByteCheck []uint64 `json:"skipValidatorByteCheck"` // skip validator byte check + TargetGasPercentage uint64 `json:"targetGasPercentage"` // Target gas percentage for gas limit calculation (sets the percentage of Gas Limit to be the Gas Target) + BaseFeeChangeDenominator uint64 `json:"baseFeeChangeDenominator"` // Base fee change denominator for EIP-1559 JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) @@ -888,6 +890,7 @@ type BorConfig struct { RioBlock *big.Int `json:"rioBlock"` // Rio switch block (nil = no fork, 0 = already on rio) MadhugiriBlock *big.Int `json:"madhugiriBlock"` // Madhugiri switch block (nil = no fork, 0 = already on madhugiri) MadhugiriProBlock *big.Int `json:"madhugiriProBlock"` // MadhugiriPro switch block (nil = no fork, 0 = already on madhugiriPro) + FeeBlock *big.Int `json:"feeBlock"` // Fee switch block (nil = no fork, 0 = already on fee) } // String implements the stringer interface, returning the consensus engine details. @@ -947,6 +950,10 @@ func (c *BorConfig) IsMadhugiriPro(number *big.Int) bool { return isBlockForked(c.MadhugiriProBlock, number) } +func (c *BorConfig) IsFee(number *big.Int) bool { + return isBlockForked(c.FeeBlock, number) +} + // // TODO: modify this function once the block number is finalized // func (c *BorConfig) IsNapoli(number *big.Int) bool { // if c.NapoliBlock != nil { diff --git a/params/protocol_params.go b/params/protocol_params.go index 2ab3126619..45962cd51a 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -20,6 +20,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" ) const ( @@ -244,7 +245,10 @@ func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 { if borConfig == nil { return DefaultBaseFeeChangeDenominator } - if borConfig.IsBhilai(number) { + if borConfig.IsFee(number) { + log.Info("[debuglocal] Fee block, BaseFeeChangeDenominator from borConfig", "denominator", borConfig.BaseFeeChangeDenominator) + return borConfig.BaseFeeChangeDenominator + } else if borConfig.IsBhilai(number) { return BaseFeeChangeDenominatorPostBhilai } else if borConfig.IsDelhi(number) { return BaseFeeChangeDenominatorPostDelhi From df3fb8999ca387e3216bd2a7eacafb559425778d Mon Sep 17 00:00:00 2001 From: Lucca Martins Date: Mon, 5 Jan 2026 16:06:49 -0300 Subject: [PATCH 02/18] remove logs --- consensus/misc/eip1559/eip1559.go | 4 ---- params/protocol_params.go | 2 -- 2 files changed, 6 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 5a6ac7936e..b99005d27d 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) @@ -52,8 +51,6 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d", header.BaseFee, expectedBaseFee, parent.BaseFee, parent.GasUsed) } - } else { - log.Info("[debuglocal] Fee block, skipping check") } return nil @@ -117,6 +114,5 @@ func CalcParentGasTarget( if pct > 100 { panic("invalid Bor TargetGasPercentage") } - log.Info("[debuglocal] Fee block, calculating gas target", "parentGasLimit", parent.GasLimit, "targetGasPercentage", pct, "result", parent.GasLimit*pct/100) return parent.GasLimit * pct / 100 } diff --git a/params/protocol_params.go b/params/protocol_params.go index 45962cd51a..3afd854c95 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -20,7 +20,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" ) const ( @@ -246,7 +245,6 @@ func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 { return DefaultBaseFeeChangeDenominator } if borConfig.IsFee(number) { - log.Info("[debuglocal] Fee block, BaseFeeChangeDenominator from borConfig", "denominator", borConfig.BaseFeeChangeDenominator) return borConfig.BaseFeeChangeDenominator } else if borConfig.IsBhilai(number) { return BaseFeeChangeDenominatorPostBhilai From 6845adf2b6ba5060546b09b52ffddd53b4f335c1 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 16:29:55 +0530 Subject: [PATCH 03/18] params, consensus: use target gas percentage for base fee calculations --- consensus/misc/eip1559/eip1559.go | 25 ++++++++----------------- params/config.go | 18 +++++++++++++++--- params/protocol_params.go | 7 ++++--- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index b99005d27d..2d6cd74ba3 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -45,12 +45,10 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade } // Verify the baseFee is correct based on the parent header. - if !config.Bor.IsFee(parent.Number) { - expectedBaseFee := CalcBaseFee(config, parent) - 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) - } + expectedBaseFee := CalcBaseFee(config, parent) + 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) } return nil @@ -63,7 +61,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { return new(big.Int).SetUint64(params.InitialBaseFee) } - parentGasTarget := CalcParentGasTarget(config, parent) + parentGasTarget := calcParentGasTarget(config, parent) // If the parent gasUsed is the same as the target, the baseFee remains unchanged. if parent.GasUsed == parentGasTarget { return new(big.Int).Set(parent.BaseFee) @@ -102,17 +100,10 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { } } -func CalcParentGasTarget( - config *params.ChainConfig, - parent *types.Header, -) uint64 { - if !config.Bor.IsFee(parent.Number) || config.Bor.TargetGasPercentage == 0 { +func calcParentGasTarget(config *params.ChainConfig, parent *types.Header) uint64 { + if config.Bor == nil || !config.Bor.IsUntitled(parent.Number) { return parent.GasLimit / config.ElasticityMultiplier() } - pct := uint64(config.Bor.TargetGasPercentage) - if pct > 100 { - panic("invalid Bor TargetGasPercentage") - } - return parent.GasLimit * pct / 100 + return parent.GasLimit * config.TargetGasPercentage(parent.Number) / 100 } diff --git a/params/config.go b/params/config.go index a9ca6387ef..0d70b2cd69 100644 --- a/params/config.go +++ b/params/config.go @@ -890,7 +890,7 @@ type BorConfig struct { RioBlock *big.Int `json:"rioBlock"` // Rio switch block (nil = no fork, 0 = already on rio) MadhugiriBlock *big.Int `json:"madhugiriBlock"` // Madhugiri switch block (nil = no fork, 0 = already on madhugiri) MadhugiriProBlock *big.Int `json:"madhugiriProBlock"` // MadhugiriPro switch block (nil = no fork, 0 = already on madhugiriPro) - FeeBlock *big.Int `json:"feeBlock"` // Fee switch block (nil = no fork, 0 = already on fee) + UntitledBlock *big.Int `json:"untitledBlock"` // Untitled switch block (nil = no fork, 0 = already on untitled) } // String implements the stringer interface, returning the consensus engine details. @@ -950,8 +950,8 @@ func (c *BorConfig) IsMadhugiriPro(number *big.Int) bool { return isBlockForked(c.MadhugiriProBlock, number) } -func (c *BorConfig) IsFee(number *big.Int) bool { - return isBlockForked(c.FeeBlock, number) +func (c *BorConfig) IsUntitled(number *big.Int) bool { + return isBlockForked(c.UntitledBlock, number) } // // TODO: modify this function once the block number is finalized @@ -1491,6 +1491,18 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 { return DefaultElasticityMultiplier } +func (c *ChainConfig) TargetGasPercentage(number *big.Int) uint64 { + if c.Bor == nil { + return DefaultTargetGasPercentage + } + + if c.Bor.IsUntitled(number) { + return TargetGasPercentagePostUntitled + } + + return DefaultTargetGasPercentage +} + // LatestFork returns the latest time-based fork that would be active for the given time. func (c *ChainConfig) LatestFork(time uint64) forks.Fork { // Assume last non-time-based fork has passed. diff --git a/params/protocol_params.go b/params/protocol_params.go index 3afd854c95..66456d2f7d 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -140,6 +140,9 @@ const ( DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks. DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. + DefaultTargetGasPercentage = 50 + TargetGasPercentagePostUntitled = 60 + MaxCodeSize = 24576 // Maximum bytecode to permit for a contract MaxCodeSizePostAhmedabad = 32768 // Maximum bytecode to permit for a contract post Ahmedabad hard fork (bor / polygon pos) (32KB) MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions @@ -244,9 +247,7 @@ func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 { if borConfig == nil { return DefaultBaseFeeChangeDenominator } - if borConfig.IsFee(number) { - return borConfig.BaseFeeChangeDenominator - } else if borConfig.IsBhilai(number) { + if borConfig.IsBhilai(number) { return BaseFeeChangeDenominatorPostBhilai } else if borConfig.IsDelhi(number) { return BaseFeeChangeDenominatorPostDelhi From b4330d0cb89b94169dd29549b995e62b1cc08d2d Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 16:31:17 +0530 Subject: [PATCH 04/18] cleanup --- consensus/misc/eip1559/eip1559.go | 1 - params/config.go | 2 -- 2 files changed, 3 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 2d6cd74ba3..7f7a1ee276 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -44,7 +44,6 @@ 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) if header.BaseFee.Cmp(expectedBaseFee) != 0 { return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d", diff --git a/params/config.go b/params/config.go index 0d70b2cd69..1e0bdb91e7 100644 --- a/params/config.go +++ b/params/config.go @@ -879,8 +879,6 @@ type BorConfig struct { BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork Coinbase map[string]string `json:"coinbase"` // coinbase address SkipValidatorByteCheck []uint64 `json:"skipValidatorByteCheck"` // skip validator byte check - TargetGasPercentage uint64 `json:"targetGasPercentage"` // Target gas percentage for gas limit calculation (sets the percentage of Gas Limit to be the Gas Target) - BaseFeeChangeDenominator uint64 `json:"baseFeeChangeDenominator"` // Base fee change denominator for EIP-1559 JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) From 78a3c067a931d03a689300e97fe28290276313df Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 16:43:54 +0530 Subject: [PATCH 05/18] add comments --- consensus/misc/eip1559/eip1559.go | 3 +++ params/config.go | 1 + params/protocol_params.go | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 7f7a1ee276..6a92f631ca 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -99,6 +99,9 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { } } +// calcParentGasTarget calculates the target gas based on parent block gas limit. Earlier +// it was derived by `ElasticityMultiplier` as it had an integer multiplier value. Post +// untitled HF, a percentage value will be used to calculate the gas target. func calcParentGasTarget(config *params.ChainConfig, parent *types.Header) uint64 { if config.Bor == nil || !config.Bor.IsUntitled(parent.Number) { return parent.GasLimit / config.ElasticityMultiplier() diff --git a/params/config.go b/params/config.go index 1e0bdb91e7..5e0569cb8b 100644 --- a/params/config.go +++ b/params/config.go @@ -1489,6 +1489,7 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 { return DefaultElasticityMultiplier } +// TargetGasPercentage is the target block gas as percentage of block gas limit for EIP-1559 func (c *ChainConfig) TargetGasPercentage(number *big.Int) uint64 { if c.Bor == nil { return DefaultTargetGasPercentage diff --git a/params/protocol_params.go b/params/protocol_params.go index 66456d2f7d..03810979cb 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -140,8 +140,8 @@ const ( DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks. DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. - DefaultTargetGasPercentage = 50 - TargetGasPercentagePostUntitled = 60 + DefaultTargetGasPercentage = 50 // Specifies target block gas as percentage of block gas limit for EIP-1559 + TargetGasPercentagePostUntitled = 60 // Specifies target block gas as percentage of block gas limit for EIP-1559 after Untitled hard fork MaxCodeSize = 24576 // Maximum bytecode to permit for a contract MaxCodeSizePostAhmedabad = 32768 // Maximum bytecode to permit for a contract post Ahmedabad hard fork (bor / polygon pos) (32KB) From fe4576a17e97cdb1c269769b5dfd747984a21660 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 18:31:02 +0530 Subject: [PATCH 06/18] consensus/misc/eip1559: add tests for untitled HF --- consensus/misc/eip1559/eip1559_test.go | 191 +++++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index b4e1444e33..918b52a01b 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -17,11 +17,13 @@ package eip1559 import ( + "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" ) // copyConfig does a _shallow_ copy of a given config. Safe to set new values, but @@ -171,3 +173,192 @@ func TestCalcBaseFeeDelhi(t *testing.T) { } } } + +func TestCalcParentGasTarget(t *testing.T) { + t.Parallel() + + testConfig := copyConfig(config()) + testConfig.Bor.UntitledBlock = big.NewInt(20) + + defaultGasLimit := uint64(60_000_000) + + t.Run("gas target calculation pre untitled HF", func(t *testing.T) { + block := &types.Header{ + Number: big.NewInt(9), + GasLimit: defaultGasLimit, + GasUsed: defaultGasLimit / 2, + BaseFee: big.NewInt(params.InitialBaseFee), + } + gasTarget := calcParentGasTarget(testConfig, block) + expected := block.GasLimit / 2 // because elasticity multiplier is set to 2 by default + require.Equal(t, expected, gasTarget, "expected gas target = gaslimit/2") + }) + + t.Run("gas target calculation post untitled HF", func(t *testing.T) { + block := &types.Header{ + Number: big.NewInt(20), + GasLimit: defaultGasLimit, + GasUsed: defaultGasLimit / 2, + BaseFee: big.NewInt(params.InitialBaseFee), + } + gasTarget := calcParentGasTarget(testConfig, block) + expected := block.GasLimit * 6 / 10 // because gas target is 60% of total block gas limit + require.Equal(t, expected, gasTarget, "case #1: expected gas target = 60 percent of gas limit") + + block = &types.Header{ + Number: big.NewInt(21), + GasLimit: defaultGasLimit, + GasUsed: defaultGasLimit / 2, + BaseFee: big.NewInt(params.InitialBaseFee), + } + gasTarget = calcParentGasTarget(testConfig, block) + expected = block.GasLimit * 6 / 10 // because gas target is 60% of total block gas limit + require.Equal(t, expected, gasTarget, "case #2: expected gas target = 60 percent of gas limit") + }) + + t.Run("nil bor config", func(t *testing.T) { + testConfig.Bor = nil + block := &types.Header{ + Number: big.NewInt(21), + GasLimit: defaultGasLimit, + GasUsed: defaultGasLimit / 2, + BaseFee: big.NewInt(params.InitialBaseFee), + } + gasTarget := calcParentGasTarget(testConfig, block) + expected := block.GasLimit / 2 // because elasticity multiplier is set to 2 by default + require.Equal(t, expected, gasTarget, "expected gas target = gaslimit/2 when bor config is nil") + }) +} + +// simpleBaseFeeCalculator contains an overly simplified logic of base fee calculations useful for generating +// expected values in test cases. It assumes all blocks are pre-bhilai HF. +func simpleBaseFeeCalculator(initialBaseFee int64, gasLimit, gasUsed uint64, targetGasPercentage uint64) uint64 { + initial := big.NewInt(initialBaseFee) + val := big.NewInt(1) + val.Mul(val, initial) + + // Assuming tests are running post bhilai + bfd := int64(params.BaseFeeChangeDenominatorPostBhilai) + + // Define a target gas based on given percentage + target := gasLimit * targetGasPercentage / 100 + if gasUsed == target { + return initial.Uint64() + } + + // follow the simple formula to get the new base fee: + // base fee = initialBaseFee +/- (initialBaseFee * gasUsedDelta / gasTarget / baseFeeChangeDenominator) + + var delta int64 + if gasUsed > target { + delta = int64(gasUsed - target) + } else { + delta = int64(target - gasUsed) + } + + val.Mul(val, big.NewInt(delta)) + val.Div(val, big.NewInt(int64(bfd))) + val.Div(val, big.NewInt(int64(target))) + + if gasUsed > target { + return initial.Add(initial, val).Uint64() + } else { + return initial.Sub(initial, val).Uint64() + } +} + +func TestCalcBaseFeeUntitled(t *testing.T) { + t.Parallel() + + testConfig := copyConfig(config()) + testConfig.Bor.BhilaiBlock = big.NewInt(8) + testConfig.Bor.UntitledBlock = big.NewInt(20) + + // Case 1: Create pre-untitled cases where HF is defined in future. Validate + // base fee calculations before HF kicks in. Base fee should be calculated + // based on default elasticity multiplier. + tests := []struct { + name string + parentBaseFee int64 + parentGasLimit uint64 + parentGasUsed uint64 + expectedBaseFee int64 + }{ + {"usage == target", params.InitialBaseFee, 60_000_000, 30_000_000, params.InitialBaseFee}, + {"usage below target #1", params.InitialBaseFee, 60_000_000, 20_000_000, 994791667}, + {"usage below target #2", params.InitialBaseFee, 60_000_000, 10_000_000, 989583334}, + {"usage above target #1", params.InitialBaseFee, 60_000_000, 40_000_000, 1005208333}, + {"usage above target #2", params.InitialBaseFee, 60_000_000, 50_000_000, 1010416666}, + {"usage full", params.InitialBaseFee, 60_000_000, 60_000_000, 1015625000}, + {"usage 0", params.InitialBaseFee, 60_000_000, 0, 984375000}, + } + for _, test := range tests { + block := &types.Header{ + Number: big.NewInt(8), + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: big.NewInt(test.parentBaseFee), + } + baseFee := CalcBaseFee(testConfig, block).Uint64() + expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 50) + require.Equal( + t, + expectedBaseFee, + baseFee, + fmt.Sprintf("invalid base fee pre-untitled, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + } + + // Case 2: Create post-untitled cases where HF has kicked in. Validate base fee changes + // based on the newly introduced protocol param: TargetGasPrecentage. Target gas limit + // should be calculated based on this percentage value out of total gas limit. Base + // fee should be changed accordingly. + tests = []struct { + name string + parentBaseFee int64 + parentGasLimit uint64 + parentGasUsed uint64 + expectedBaseFee int64 + }{ + {"usage == target (60%)", params.InitialBaseFee, 60_000_000, 36_000_000, params.InitialBaseFee}, + {"usage below target #1", params.InitialBaseFee, 60_000_000, 30_000_000, 997395834}, + {"usage below target #2", params.InitialBaseFee, 60_000_000, 10_000_000, 988715278}, + {"usage above target #1", params.InitialBaseFee, 60_000_000, 40_000_000, 1001736111}, + {"usage above target #2", params.InitialBaseFee, 60_000_000, 50_000_000, 1006076388}, + {"usage full", params.InitialBaseFee, 60_000_000, 60_000_000, 1010416666}, + {"usage 0", params.InitialBaseFee, 60_000_000, 0, 984375000}, + } + for _, test := range tests { + // Post-untitled block #1 + block := &types.Header{ + Number: big.NewInt(20), + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: big.NewInt(test.parentBaseFee), + } + baseFee := CalcBaseFee(testConfig, block).Uint64() + expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 60) + require.Equal( + t, + expectedBaseFee, + baseFee, + fmt.Sprintf("invalid base fee post-untitled #1, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + + // Post-untitled block #2 + block = &types.Header{ + Number: big.NewInt(21), + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: big.NewInt(test.parentBaseFee), + } + baseFee = CalcBaseFee(testConfig, block).Uint64() + expectedBaseFee = simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 60) + require.Equal( + t, + expectedBaseFee, + baseFee, + fmt.Sprintf("invalid base fee post-untitled #2, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + } +} From 7b8b86b327ea724c0d6e19feb5e71f15d04b181f Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 18:31:49 +0530 Subject: [PATCH 07/18] typo --- consensus/misc/eip1559/eip1559_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index 918b52a01b..c41a3f8732 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -231,7 +231,7 @@ func TestCalcParentGasTarget(t *testing.T) { } // simpleBaseFeeCalculator contains an overly simplified logic of base fee calculations useful for generating -// expected values in test cases. It assumes all blocks are pre-bhilai HF. +// expected values in test cases. It assumes all blocks are post-bhilai HF. func simpleBaseFeeCalculator(initialBaseFee int64, gasLimit, gasUsed uint64, targetGasPercentage uint64) uint64 { initial := big.NewInt(initialBaseFee) val := big.NewInt(1) From 3a31904ff5884f7587cbf889b033f8a36dd35d2b Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 18:38:36 +0530 Subject: [PATCH 08/18] test fixes --- consensus/misc/eip1559/eip1559_test.go | 31 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index c41a3f8732..1ba6ae6e0c 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -282,7 +282,7 @@ func TestCalcBaseFeeUntitled(t *testing.T) { parentBaseFee int64 parentGasLimit uint64 parentGasUsed uint64 - expectedBaseFee int64 + expectedBaseFee uint64 }{ {"usage == target", params.InitialBaseFee, 60_000_000, 30_000_000, params.InitialBaseFee}, {"usage below target #1", params.InitialBaseFee, 60_000_000, 20_000_000, 994791667}, @@ -305,7 +305,14 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("invalid base fee pre-untitled, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("pre-untitled base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + // Also check with manually calculated base fee + require.Equal( + t, + test.expectedBaseFee, + baseFee, + fmt.Sprintf("pre-untitled base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) } @@ -318,7 +325,7 @@ func TestCalcBaseFeeUntitled(t *testing.T) { parentBaseFee int64 parentGasLimit uint64 parentGasUsed uint64 - expectedBaseFee int64 + expectedBaseFee uint64 }{ {"usage == target (60%)", params.InitialBaseFee, 60_000_000, 36_000_000, params.InitialBaseFee}, {"usage below target #1", params.InitialBaseFee, 60_000_000, 30_000_000, 997395834}, @@ -342,7 +349,14 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("invalid base fee post-untitled #1, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-untitled #1: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + // Also check with manually calculated base fee + require.Equal( + t, + test.expectedBaseFee, + baseFee, + fmt.Sprintf("post-untitled #1: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) // Post-untitled block #2 @@ -358,7 +372,14 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("invalid base fee post-untitled #2, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-untitled #2: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + ) + // Also check with manually calculated base fee + require.Equal( + t, + test.expectedBaseFee, + baseFee, + fmt.Sprintf("post-untitled #2: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) } } From 44c4132b774ff81319033020acc0c805bf19ea41 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 19:44:59 +0530 Subject: [PATCH 09/18] update HF name to dandeli --- consensus/misc/eip1559/eip1559.go | 4 ++-- consensus/misc/eip1559/eip1559_test.go | 30 +++++++++++++------------- params/config.go | 10 ++++----- params/protocol_params.go | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 6a92f631ca..246fd3a4e6 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -101,9 +101,9 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { // calcParentGasTarget calculates the target gas based on parent block gas limit. Earlier // it was derived by `ElasticityMultiplier` as it had an integer multiplier value. Post -// untitled HF, a percentage value will be used to calculate the gas target. +// dandeli HF, a percentage value will be used to calculate the gas target. func calcParentGasTarget(config *params.ChainConfig, parent *types.Header) uint64 { - if config.Bor == nil || !config.Bor.IsUntitled(parent.Number) { + if config.Bor == nil || !config.Bor.IsDandeli(parent.Number) { return parent.GasLimit / config.ElasticityMultiplier() } diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index 1ba6ae6e0c..34dd34da94 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -178,11 +178,11 @@ func TestCalcParentGasTarget(t *testing.T) { t.Parallel() testConfig := copyConfig(config()) - testConfig.Bor.UntitledBlock = big.NewInt(20) + testConfig.Bor.DandeliBlock = big.NewInt(20) defaultGasLimit := uint64(60_000_000) - t.Run("gas target calculation pre untitled HF", func(t *testing.T) { + t.Run("gas target calculation pre dandeli HF", func(t *testing.T) { block := &types.Header{ Number: big.NewInt(9), GasLimit: defaultGasLimit, @@ -194,7 +194,7 @@ func TestCalcParentGasTarget(t *testing.T) { require.Equal(t, expected, gasTarget, "expected gas target = gaslimit/2") }) - t.Run("gas target calculation post untitled HF", func(t *testing.T) { + t.Run("gas target calculation post dandeli HF", func(t *testing.T) { block := &types.Header{ Number: big.NewInt(20), GasLimit: defaultGasLimit, @@ -267,14 +267,14 @@ func simpleBaseFeeCalculator(initialBaseFee int64, gasLimit, gasUsed uint64, tar } } -func TestCalcBaseFeeUntitled(t *testing.T) { +func TestCalcBaseFeeDandeli(t *testing.T) { t.Parallel() testConfig := copyConfig(config()) testConfig.Bor.BhilaiBlock = big.NewInt(8) - testConfig.Bor.UntitledBlock = big.NewInt(20) + testConfig.Bor.DandeliBlock = big.NewInt(20) - // Case 1: Create pre-untitled cases where HF is defined in future. Validate + // Case 1: Create pre-dandeli cases where HF is defined in future. Validate // base fee calculations before HF kicks in. Base fee should be calculated // based on default elasticity multiplier. tests := []struct { @@ -305,18 +305,18 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("pre-untitled base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("pre-dandeli base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) // Also check with manually calculated base fee require.Equal( t, test.expectedBaseFee, baseFee, - fmt.Sprintf("pre-untitled base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("pre-dandeli base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) } - // Case 2: Create post-untitled cases where HF has kicked in. Validate base fee changes + // Case 2: Create post-dandeli cases where HF has kicked in. Validate base fee changes // based on the newly introduced protocol param: TargetGasPrecentage. Target gas limit // should be calculated based on this percentage value out of total gas limit. Base // fee should be changed accordingly. @@ -336,7 +336,7 @@ func TestCalcBaseFeeUntitled(t *testing.T) { {"usage 0", params.InitialBaseFee, 60_000_000, 0, 984375000}, } for _, test := range tests { - // Post-untitled block #1 + // Post-dandeli block #1 block := &types.Header{ Number: big.NewInt(20), GasLimit: test.parentGasLimit, @@ -349,17 +349,17 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("post-untitled #1: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-dandeli #1: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) // Also check with manually calculated base fee require.Equal( t, test.expectedBaseFee, baseFee, - fmt.Sprintf("post-untitled #1: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-dandeli #1: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) - // Post-untitled block #2 + // Post-dandeli block #2 block = &types.Header{ Number: big.NewInt(21), GasLimit: test.parentGasLimit, @@ -372,14 +372,14 @@ func TestCalcBaseFeeUntitled(t *testing.T) { t, expectedBaseFee, baseFee, - fmt.Sprintf("post-untitled #2: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-dandeli #2: base fee mismatch with expected value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) // Also check with manually calculated base fee require.Equal( t, test.expectedBaseFee, baseFee, - fmt.Sprintf("post-untitled #2: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), + fmt.Sprintf("post-dandeli #2: base fee mismatch with manually calculated value, test: %s, got: %d, want: %d", test.name, baseFee, expectedBaseFee), ) } } diff --git a/params/config.go b/params/config.go index 5e0569cb8b..809fea46fb 100644 --- a/params/config.go +++ b/params/config.go @@ -888,7 +888,7 @@ type BorConfig struct { RioBlock *big.Int `json:"rioBlock"` // Rio switch block (nil = no fork, 0 = already on rio) MadhugiriBlock *big.Int `json:"madhugiriBlock"` // Madhugiri switch block (nil = no fork, 0 = already on madhugiri) MadhugiriProBlock *big.Int `json:"madhugiriProBlock"` // MadhugiriPro switch block (nil = no fork, 0 = already on madhugiriPro) - UntitledBlock *big.Int `json:"untitledBlock"` // Untitled switch block (nil = no fork, 0 = already on untitled) + DandeliBlock *big.Int `json:"dandeliBlock"` // Dandeli switch block (nil = no fork, 0 = already on dandeli) } // String implements the stringer interface, returning the consensus engine details. @@ -948,8 +948,8 @@ func (c *BorConfig) IsMadhugiriPro(number *big.Int) bool { return isBlockForked(c.MadhugiriProBlock, number) } -func (c *BorConfig) IsUntitled(number *big.Int) bool { - return isBlockForked(c.UntitledBlock, number) +func (c *BorConfig) IsDandeli(number *big.Int) bool { + return isBlockForked(c.DandeliBlock, number) } // // TODO: modify this function once the block number is finalized @@ -1495,8 +1495,8 @@ func (c *ChainConfig) TargetGasPercentage(number *big.Int) uint64 { return DefaultTargetGasPercentage } - if c.Bor.IsUntitled(number) { - return TargetGasPercentagePostUntitled + if c.Bor.IsDandeli(number) { + return TargetGasPercentagePostDandeli } return DefaultTargetGasPercentage diff --git a/params/protocol_params.go b/params/protocol_params.go index 03810979cb..0e3d075f64 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -140,8 +140,8 @@ const ( DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks. DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. - DefaultTargetGasPercentage = 50 // Specifies target block gas as percentage of block gas limit for EIP-1559 - TargetGasPercentagePostUntitled = 60 // Specifies target block gas as percentage of block gas limit for EIP-1559 after Untitled hard fork + DefaultTargetGasPercentage = 50 // Specifies target block gas as percentage of block gas limit for EIP-1559 + TargetGasPercentagePostDandeli = 60 // Specifies target block gas as percentage of block gas limit for EIP-1559 after Dandeli hard fork MaxCodeSize = 24576 // Maximum bytecode to permit for a contract MaxCodeSizePostAhmedabad = 32768 // Maximum bytecode to permit for a contract post Ahmedabad hard fork (bor / polygon pos) (32KB) From 4fdf1eecd1506c7d11dd7bd4778e9123b9fd6760 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 20:01:54 +0530 Subject: [PATCH 10/18] simplify --- consensus/misc/eip1559/eip1559.go | 7 +++---- params/config.go | 13 ------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 246fd3a4e6..e44e1ae3c9 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -103,9 +103,8 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { // it was derived by `ElasticityMultiplier` as it had an integer multiplier value. Post // dandeli HF, a percentage value will be used to calculate the gas target. func calcParentGasTarget(config *params.ChainConfig, parent *types.Header) uint64 { - if config.Bor == nil || !config.Bor.IsDandeli(parent.Number) { - return parent.GasLimit / config.ElasticityMultiplier() + if config.Bor != nil && config.Bor.IsDandeli(parent.Number) { + return parent.GasLimit * params.TargetGasPercentagePostDandeli / 100 } - - return parent.GasLimit * config.TargetGasPercentage(parent.Number) / 100 + return parent.GasLimit / config.ElasticityMultiplier() } diff --git a/params/config.go b/params/config.go index 809fea46fb..93bc6492f6 100644 --- a/params/config.go +++ b/params/config.go @@ -1489,19 +1489,6 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 { return DefaultElasticityMultiplier } -// TargetGasPercentage is the target block gas as percentage of block gas limit for EIP-1559 -func (c *ChainConfig) TargetGasPercentage(number *big.Int) uint64 { - if c.Bor == nil { - return DefaultTargetGasPercentage - } - - if c.Bor.IsDandeli(number) { - return TargetGasPercentagePostDandeli - } - - return DefaultTargetGasPercentage -} - // LatestFork returns the latest time-based fork that would be active for the given time. func (c *ChainConfig) LatestFork(time uint64) forks.Fork { // Assume last non-time-based fork has passed. From 455074e27fd1a84e5b172ff3e7433836f0902a6f Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 20:43:11 +0530 Subject: [PATCH 11/18] update gas target to 65%, fix tests --- consensus/misc/eip1559/eip1559_test.go | 18 +++++++++--------- params/protocol_params.go | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index 34dd34da94..c8168c07bc 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -300,7 +300,7 @@ func TestCalcBaseFeeDandeli(t *testing.T) { BaseFee: big.NewInt(test.parentBaseFee), } baseFee := CalcBaseFee(testConfig, block).Uint64() - expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 50) + expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, params.DefaultTargetGasPercentage) require.Equal( t, expectedBaseFee, @@ -327,12 +327,12 @@ func TestCalcBaseFeeDandeli(t *testing.T) { parentGasUsed uint64 expectedBaseFee uint64 }{ - {"usage == target (60%)", params.InitialBaseFee, 60_000_000, 36_000_000, params.InitialBaseFee}, - {"usage below target #1", params.InitialBaseFee, 60_000_000, 30_000_000, 997395834}, - {"usage below target #2", params.InitialBaseFee, 60_000_000, 10_000_000, 988715278}, - {"usage above target #1", params.InitialBaseFee, 60_000_000, 40_000_000, 1001736111}, - {"usage above target #2", params.InitialBaseFee, 60_000_000, 50_000_000, 1006076388}, - {"usage full", params.InitialBaseFee, 60_000_000, 60_000_000, 1010416666}, + {"usage == target (65%)", params.InitialBaseFee, 60_000_000, 39_000_000, params.InitialBaseFee}, + {"usage below target #1", params.InitialBaseFee, 60_000_000, 30_000_000, 996394231}, + {"usage below target #2", params.InitialBaseFee, 60_000_000, 10_000_000, 988381411}, + {"usage above target #1", params.InitialBaseFee, 60_000_000, 40_000_000, 1000400641}, + {"usage above target #2", params.InitialBaseFee, 60_000_000, 50_000_000, 1004407051}, + {"usage full", params.InitialBaseFee, 60_000_000, 60_000_000, 1008413461}, {"usage 0", params.InitialBaseFee, 60_000_000, 0, 984375000}, } for _, test := range tests { @@ -344,7 +344,7 @@ func TestCalcBaseFeeDandeli(t *testing.T) { BaseFee: big.NewInt(test.parentBaseFee), } baseFee := CalcBaseFee(testConfig, block).Uint64() - expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 60) + expectedBaseFee := simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, params.TargetGasPercentagePostDandeli) require.Equal( t, expectedBaseFee, @@ -367,7 +367,7 @@ func TestCalcBaseFeeDandeli(t *testing.T) { BaseFee: big.NewInt(test.parentBaseFee), } baseFee = CalcBaseFee(testConfig, block).Uint64() - expectedBaseFee = simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, 60) + expectedBaseFee = simpleBaseFeeCalculator(block.BaseFee.Int64(), block.GasLimit, block.GasUsed, params.TargetGasPercentagePostDandeli) require.Equal( t, expectedBaseFee, diff --git a/params/protocol_params.go b/params/protocol_params.go index 0e3d075f64..f2d4091ae1 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -141,7 +141,7 @@ const ( DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. DefaultTargetGasPercentage = 50 // Specifies target block gas as percentage of block gas limit for EIP-1559 - TargetGasPercentagePostDandeli = 60 // Specifies target block gas as percentage of block gas limit for EIP-1559 after Dandeli hard fork + TargetGasPercentagePostDandeli = 65 // Specifies target block gas as percentage of block gas limit for EIP-1559 after Dandeli hard fork MaxCodeSize = 24576 // Maximum bytecode to permit for a contract MaxCodeSizePostAhmedabad = 32768 // Maximum bytecode to permit for a contract post Ahmedabad hard fork (bor / polygon pos) (32KB) From 8106468beb4e10304605b289863495ea9675fbac Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 20:59:06 +0530 Subject: [PATCH 12/18] update comment --- consensus/misc/eip1559/eip1559.go | 1 + 1 file changed, 1 insertion(+) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index e44e1ae3c9..f94b0a2ad2 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -60,6 +60,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { return new(big.Int).SetUint64(params.InitialBaseFee) } + // Modified for bor to derive gas target by percentage instead of using elasticity multiplier post dandeli HF parentGasTarget := calcParentGasTarget(config, parent) // If the parent gasUsed is the same as the target, the baseFee remains unchanged. if parent.GasUsed == parentGasTarget { From 8594c5488d6e7cb8b985643076bf662f34e3d15e Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 21:47:28 +0530 Subject: [PATCH 13/18] fix tests --- consensus/misc/eip1559/eip1559_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index c8168c07bc..7777e2767b 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -202,7 +202,8 @@ func TestCalcParentGasTarget(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), } gasTarget := calcParentGasTarget(testConfig, block) - expected := block.GasLimit * 6 / 10 // because gas target is 60% of total block gas limit + expected := block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is 60% of total block gas limit + fmt.Println("gas target", gasTarget, "expected", expected) require.Equal(t, expected, gasTarget, "case #1: expected gas target = 60 percent of gas limit") block = &types.Header{ @@ -212,7 +213,7 @@ func TestCalcParentGasTarget(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), } gasTarget = calcParentGasTarget(testConfig, block) - expected = block.GasLimit * 6 / 10 // because gas target is 60% of total block gas limit + expected = block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is 60% of total block gas limit require.Equal(t, expected, gasTarget, "case #2: expected gas target = 60 percent of gas limit") }) From df4f5b6b1184c4f77b03212627c055482e2053c7 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 21:48:47 +0530 Subject: [PATCH 14/18] fix tests --- consensus/misc/eip1559/eip1559_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index 7777e2767b..e3e2a7ee5d 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -202,7 +202,7 @@ func TestCalcParentGasTarget(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), } gasTarget := calcParentGasTarget(testConfig, block) - expected := block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is 60% of total block gas limit + expected := block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is derived by this protocol parameter fmt.Println("gas target", gasTarget, "expected", expected) require.Equal(t, expected, gasTarget, "case #1: expected gas target = 60 percent of gas limit") @@ -213,7 +213,7 @@ func TestCalcParentGasTarget(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), } gasTarget = calcParentGasTarget(testConfig, block) - expected = block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is 60% of total block gas limit + expected = block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is derived by this protocol parameter require.Equal(t, expected, gasTarget, "case #2: expected gas target = 60 percent of gas limit") }) From 13ec77af412604f62e388d1b73747b457f0db5d2 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 21:49:03 +0530 Subject: [PATCH 15/18] fix tests --- consensus/misc/eip1559/eip1559_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index e3e2a7ee5d..6d5af332d6 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -203,7 +203,6 @@ func TestCalcParentGasTarget(t *testing.T) { } gasTarget := calcParentGasTarget(testConfig, block) expected := block.GasLimit * params.TargetGasPercentagePostDandeli / 100 // because gas target is derived by this protocol parameter - fmt.Println("gas target", gasTarget, "expected", expected) require.Equal(t, expected, gasTarget, "case #1: expected gas target = 60 percent of gas limit") block = &types.Header{ From 335c838a62cf24d43b3c7f6e407594faa215713b Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 22:49:16 +0530 Subject: [PATCH 16/18] schedule dandeli HF for amoy at block 31890000 --- builder/files/genesis-amoy.json | 1 + internal/cli/server/chains/amoy.go | 1 + params/config.go | 1 + 3 files changed, 3 insertions(+) diff --git a/builder/files/genesis-amoy.json b/builder/files/genesis-amoy.json index 5935e8e9a1..78100d1df0 100644 --- a/builder/files/genesis-amoy.json +++ b/builder/files/genesis-amoy.json @@ -24,6 +24,7 @@ "bhilaiBlock": 22765056, "rioBlock": 26272256, "madhugiriBlock": 28899616, + "dandeliBlock": 31890000, "skipValidatorByteCheck": [26160367, 26161087, 26171567, 26173743, 26175647], "stateSyncConfirmationDelay": { "0": 128 diff --git a/internal/cli/server/chains/amoy.go b/internal/cli/server/chains/amoy.go index cacec69f15..714b0e282a 100644 --- a/internal/cli/server/chains/amoy.go +++ b/internal/cli/server/chains/amoy.go @@ -38,6 +38,7 @@ var amoyTestnet = &Chain{ RioBlock: big.NewInt(26272256), MadhugiriBlock: big.NewInt(28899616), MadhugiriProBlock: big.NewInt(29287400), + DandeliBlock: big.NewInt(31890000), StateSyncConfirmationDelay: map[string]uint64{ "0": 128, }, diff --git a/params/config.go b/params/config.go index 93bc6492f6..b02022ac9e 100644 --- a/params/config.go +++ b/params/config.go @@ -340,6 +340,7 @@ var ( RioBlock: big.NewInt(26272256), MadhugiriBlock: big.NewInt(28899616), MadhugiriProBlock: big.NewInt(29287400), + DandeliBlock: big.NewInt(31890000), StateSyncConfirmationDelay: map[string]uint64{ "0": 128, }, From dc90771b7861544155545be41528f8ed0d4c3a5c Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 22:50:25 +0530 Subject: [PATCH 17/18] fix lint --- consensus/misc/eip1559/eip1559_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index 6d5af332d6..ca9fe8e4e2 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -257,7 +257,7 @@ func simpleBaseFeeCalculator(initialBaseFee int64, gasLimit, gasUsed uint64, tar } val.Mul(val, big.NewInt(delta)) - val.Div(val, big.NewInt(int64(bfd))) + val.Div(val, big.NewInt(bfd)) val.Div(val, big.NewInt(int64(target))) if gasUsed > target { From a7686abc56816b8f48f5d8bc85783693b6de2861 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 6 Jan 2026 22:53:37 +0530 Subject: [PATCH 18/18] add missing madhugiripro HF in amoy genesis --- builder/files/genesis-amoy.json | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/files/genesis-amoy.json b/builder/files/genesis-amoy.json index 78100d1df0..ceada67a8e 100644 --- a/builder/files/genesis-amoy.json +++ b/builder/files/genesis-amoy.json @@ -24,6 +24,7 @@ "bhilaiBlock": 22765056, "rioBlock": 26272256, "madhugiriBlock": 28899616, + "madhugiriProBlock": 29287400, "dandeliBlock": 31890000, "skipValidatorByteCheck": [26160367, 26161087, 26171567, 26173743, 26175647], "stateSyncConfirmationDelay": {