Zero TargetBlockUtilization disables fee market
Description
The UpdateBaseGasPrice computes the following:
baseGasPrice = someValue / (MaxGas \* TargetBlockUtilization)Currently, at the time of writing, ValidateBasic allows TargetBlockUtilization = 0. A governance-param change to zero triggers a divide-by-zero panic every block.
The panic is caught by
defer func() {
if rec := recover(); rec != nil {
logger.Error("Panic recovered in state.UpdateBaseGasPrice", "err", rec)
s.BaseGasPrice = params.MinBaseGasPrice
gasPrice = s.BaseGasPrice
}
}()so the chain stays alive, but BaseGasPrice is reset to the floor each block, and an error is logged every block.
Impact
This has the following impacts.
The fee-market mechanism is effectively disabled; the gas price sticks at
MinBaseGasPrice.Continuous error logs pollute node output and can degrade performance over time.
A griefing vector is created: one malicious param vote breaks dynamic pricing until another vote passes.
Recommendations
We recommend tightening param validation — enforce 0 < TargetBlockUtilization ≤ 1 and BaseFeeChangeDenom > 0.
Also, add unit tests covering edge values (0, 1, negative, >1).
Remediation
This issue has been acknowledged by AtomOne, and a fix was implemented in PR #166↗.