@@ -122,6 +122,11 @@ func calcBaseFeeFeynman(config *params.ChainConfig, parent *types.Header, overhe
122122 baseFee := new (big.Int ).Set (baseFeeEIP1559 )
123123 baseFee .Add (baseFee , overhead )
124124
125+ // Apply maximum base fee bound to the final result (including overhead)
126+ if baseFee .Cmp (big .NewInt (MaximumL2BaseFee )) > 0 {
127+ baseFee = big .NewInt (MaximumL2BaseFee )
128+ }
129+
125130 return baseFee
126131}
127132
@@ -159,9 +164,6 @@ func calcBaseFeeEIP1559(config *params.ChainConfig, parent *types.Header) *big.I
159164 return num .Add (parentBaseFeeEIP1559 , common .Big1 )
160165 }
161166 baseFee := num .Add (parentBaseFeeEIP1559 , num )
162- if baseFee .Cmp (big .NewInt (MaximumL2BaseFee )) > 0 {
163- baseFee = big .NewInt (MaximumL2BaseFee )
164- }
165167 return baseFee
166168 } else {
167169 // Otherwise if the parent block used less gas than its target, the baseFee should decrease.
@@ -179,10 +181,21 @@ func calcBaseFeeEIP1559(config *params.ChainConfig, parent *types.Header) *big.I
179181 }
180182}
181183
182- func extractBaseFeeEIP1559 (config * params.ChainConfig , baseFee * big.Int ) * big.Int {
184+ func extractBaseFeeEIP1559 (_ * params.ChainConfig , baseFee * big.Int ) * big.Int {
183185 _ , overhead := ReadL2BaseFeeCoefficients ()
186+
184187 // In Feynman base fee calculation, we reuse the contract's baseFeeOverhead slot as the proving base fee.
185- return new (big.Int ).Sub (baseFee , overhead )
188+ result := new (big.Int ).Sub (baseFee , overhead )
189+
190+ // Add underflow protection: return max(0, baseFee - overhead)
191+ //
192+ // Potential underflow scenarios:
193+ // - Contract overhead updates: when overhead is updated via contract,
194+ // it might become larger than current base fee
195+ if result .Sign () < 0 {
196+ return big .NewInt (0 )
197+ }
198+ return result
186199}
187200
188201// MinBaseFee calculates the minimum L2 base fee based on the current coefficients.
0 commit comments