feat(params,core,consensus,eth,cmd): add gas2500x fork switch - #2516
feat(params,core,consensus,eth,cmd): add gas2500x fork switch#2516gzliudan wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds the optional Gas2500x gas tier and makes base-fee, TRC21, RPC, and transaction-pool pricing fork-height aware.
Changes:
- Centralizes gas-tier resolution and adds Gas2500x configuration.
- Uses scheduled base fees throughout consensus, RPC, simulation, and txpool paths.
- Updates localnet configuration, compatibility metadata, and tests.
Reviewed changes
Copilot reviewed 40 out of 41 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tests/state_test_util.go |
Replaces removed base-fee constant. |
params/gas.go |
Implements centralized gas-tier pricing. |
params/gas_test.go |
Tests tier pricing and value isolation. |
params/forks/forks.go |
Registers the Gas2500x fork. |
params/forks/forks_test.go |
Tests fork labels and ordering. |
params/config.go |
Adds configuration and fork validation. |
params/config_test.go |
Tests Gas2500x configuration constraints. |
params/config_networks.go |
Enables Gas2500x on localnet. |
params/config_networks_test.go |
Verifies network scheduling defaults. |
params/config_forks.go |
Adds the activation predicate. |
params/config_compat_test.go |
Updates compatibility-order expectations. |
params/config_backfill.go |
Integrates compatibility and backfill metadata. |
params/config_backfill_test.go |
Tests backfill field coverage. |
params/config_backfill_generated.go |
Adds generated field metadata. |
params/config_backfill_fields.json |
Declares the new generated field. |
internal/ethapi/transaction_args_test.go |
Updates mock fork configuration. |
internal/ethapi/simulate.go |
Corrects simulated base-fee activation. |
internal/ethapi/api.go |
Prices pending RPC results for the next block. |
internal/ethapi/api_test.go |
Updates gas-price expectations. |
eth/gasprice/gasprice.go |
Applies the next-block gas floor. |
eth/gasprice/feehistory.go |
Calculates scheduled next-block base fees. |
core/vm/interpreter.go |
Corrects NoBaseFee documentation. |
core/vm/instructions_test.go |
Tests BASEFEE opcode behavior. |
core/vm/evm.go |
Corrects EVM context documentation. |
core/vm/eips.go |
Reads BASEFEE from block context. |
core/txpool/validation.go |
Validates against the next-block schedule. |
core/txpool/validation_mingasprice_test.go |
Tests schedule-boundary admission. |
core/txpool/validation_denylist_test.go |
Uses the immutable gas baseline. |
core/txpool/legacypool/legacypool.go |
Updates promotion, demotion, and reorg pricing. |
core/txpool/legacypool/legacypool_test.go |
Tests next-block affordability behavior. |
core/state_processor_test.go |
Updates test block base-fee construction. |
core/genesis.go |
Derives genesis base fee from the schedule. |
core/genesis_test.go |
Tests scheduled genesis pricing. |
core/chainconfig_equal.go |
Bumps the config digest version. |
core/chainconfig_equal_test.go |
Updates digest coverage and vectors. |
consensus/tests/engine_v2_tests/helper.go |
Updates engine-v2 test base fees. |
consensus/tests/engine_v1_tests/helper.go |
Updates engine-v1 test base fees. |
consensus/misc/eip1559/eip1559.go |
Makes base-fee calculation block-aware. |
consensus/misc/eip1559/eip1559_test.go |
Tests scheduled consensus base fees. |
common/constants.go |
Removes mutable legacy gas constants. |
cmd/XDC/config.go |
Removes the ineffective pool-floor override. |
Files not reviewed (1)
- params/config_backfill_generated.go: Generated file
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
340a670 to
5eabbea
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 40 out of 41 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- params/config_backfill_generated.go: Generated file
Suppressed comments (4)
internal/ethapi/api_test.go:4285
- This test does not verify the next-block fork behavior: the mock has no Gas2500x activation, and the expected value is computed with the same helper as production, so using the current height would also pass. Exercise a fork at block 1101 and assert the explicit 2500x value.
wantGasPrice := new(big.Int).Add(big.NewInt(42), params.BaseFeeForBlock(backend.ChainConfig(), big.NewInt(1101)))
internal/ethapi/simulate.go:165
- The observable simulation change is untested: existing simulate tests contain no base-fee assertions, so a regression could again synthesize a fee in the London-to-EIP1559 window or fail to return zero for non-validation blocks. Add cases for both modes at the EIP-1559 boundary and execute BASEFEE in the simulated call.
if sim.chainConfig.IsEIP1559(header.Number) {
// In non-validation mode base fee is set to 0 if it is not overridden.
// This is because it creates an edge case in EVM where gasPrice < baseFee.
// Base fee could have been overridden.
if header.BaseFee == nil {
if sim.validate {
header.BaseFee = eip1559.CalcBaseFee(sim.chainConfig, header)
params/config_networks.go:515
- Enabling this fork at genesis changes the localnet genesis hash and makes existing localnet data directories unusable. Add the operator-facing release or migration note requiring a localnet reset; the PR description identifies the impact, but the repository currently has no corresponding documentation change.
eth/gasprice/feehistory.go:89 - Fee history has comprehensive tests, but they only check the base-fee array length and do not cover this next-block tier transition. Add a case where
Gas2500xBlock == bf.blockNumber+1and assert that the finalbaseFeePerGasentry is the 2500x price; otherwise an off-by-one regression here remains undetected.
nextNumber := new(big.Int).SetUint64(bf.blockNumber + 1)
if chainconfig.IsEIP1559(nextNumber) {
bf.results.nextBaseFee = eip1559.CalcBaseFeeForBlockNumber(chainconfig, nextNumber)
5eabbea to
c53816c
Compare
Introduce an optional Gas2500xBlock fork that raises the XDC gas schedule from the Gas50x tier to the Gas2500x tier, moving the chain default gas price and the EIP-1559 base fee from 12.5 gwei to 625 gwei. Gas tier resolution is refactored into a single ordered table in params/gas.go, so a future tier only needs one more row. TRC21 gas price, gas fee and chain default gas price queries resolve the active tier instead of testing Gas50xBlock directly. Every tier, including the transaction pool floor returned by GetMinGasPrice, is scaled from the immutable common.DefaultMinGasPrice, so the cached params.SetMinGasPrice50x and the mutable common.MinGasPrice it was derived from are both removed. Tier prices are computed once at init and shared, so accessors copy before handing one out. On paper that removes the ability to raise the pool minimum gas price through --miner.gasprice, but the path was not dead: MinerGasPriceFlag is a *flags.BigFlag, and ctx.Int in urfave/cli v2 parses the flag value's decimal string (lookupInt calls strconv.ParseInt on f.Value.String()), so for any value that fits in int64 and exceeds common.DefaultMinGasPrice the guarded assignment fired and common.MinGasPrice was overridden, raising the Gas50x pool floor to miner.gasprice times 50. Removing it is therefore an operator-facing behaviour change: the floor becomes a pure function of the chain config gas schedule, no node-level knob can move it any more, and raising it now requires scheduling a tier fork. The flag still feeds the miner and the gas price oracle exactly as before. The EIP-1559 base fee becomes block-number aware: CalcBaseFee is expressed in terms of the new CalcBaseFeeForBlockNumber and the common.BaseFee constant is replaced by params.BaseFeeForBlock. Callers that price a not yet mined transaction - txpool promotion, demotion and reorg, ValidateTransactionWithState, the gas price oracle, fee history and the pending transaction RPC - now resolve the schedule at the next block height instead of at the current head. Promotion and demotion also read that head from pool.currentHead instead of pool.chain.CurrentHeader(), matching the gas limit source they already used and avoiding a race with the canonical head during reorgs. Unlike upstream, CalcBaseFee takes the block being built or verified rather than its parent, which every caller already did but which only now changes the result at a tier activation, so the doc comment spells the contract out. Two pre-existing inconsistencies are fixed along the way. The BASEFEE opcode returned a hard-coded constant regardless of the block being executed and now reports the header base fee. Where the header carries none - the London-to-EIP1559 window - it falls back to params.BaseFeeForOpcode, kept separate from BaseFeeForBlock so the opcode baseline stays pinned to InitialBaseFee rather than following the chain default gas price, and held as a precomputed uint256 because that window spans over twenty million mainnet blocks. That pinning is only safe while the window stays on the Gas50x tier, whose price is InitialBaseFee, so CheckConfigForkOrder now rejects a configuration that would let Gas2500x take effect inside it. The check is window aware rather than a plain EIP1559Block/Gas2500xBlock ordering rule: a sparse localnet genesis legitimately backfills Gas2500xBlock to 0 while London and EIP-1559 both activate later, which leaves the window empty and the schedule sound. eth_simulateV1 gated base fee synthesis on IsLondon, which made simulated blocks in that same window report a zero base fee while real blocks omit the field; it now gates on IsEIP1559. Reading the block context has one visible consequence beyond that window. eth_simulateV1 deliberately runs non-validation blocks with a zero base fee, so BASEFEE now reports 0 there instead of the old constant, matching upstream. eth_call, eth_estimateGas and the tracers are unaffected: they carry the real header base fee, and vm.Config.NoBaseFee only skips the fee check and payment in the state transition. The comments on BlockContext.BaseFee, TxContext.GasPrice and Config.NoBaseFee claiming the flag zeroes the base fee describe behaviour that no longer exists in either this fork or upstream, and are corrected. One operational consequence is left unaddressed on purpose. Admission resolves the pool floor at the next block height, so underpriced transactions are rejected from the block before a tier fires onwards, but transactions already sitting in the pending queue when it fires are not swept. They stop being mineable, since the miner filters on effective tip, yet nothing evicts them: truncatePending caps by account size rather than price and pending entries have no lifetime eviction, so they are reclaimed only once the pool fills and priced.Discard makes room for newer transactions, or on restart. Senders recover by resubmitting at the new price, and the affected set is small because admission already rejects underpriced transactions one block early, so a dedicated sweep is not worth the extra churn in the reorg path. Chain config metadata, fork ordering, backfill definitions and network configs are updated, and the chain config digest version is bumped to 2. The fork is left unscheduled on mainnet, testnet and devnet, so no existing network changes behaviour: at the Gas50x tier the derived base fee is identical to the constant it replaces. It is enabled at block 0 on localnet, which changes the localnet genesis hash and requires existing local data directories to be reset. Release notes should carry three operator facing items: - Localnet data directories must be reset, since the genesis hash changes. - BASEFEE returns 0 in eth_simulateV1 non-validation blocks instead of 12.5 gwei. - Transactions left pending across a future tier activation must be resubmitted at the new price.
c53816c to
47e1d42
Compare
Proposed changes
Summary
Introduce an optional
Gas2500xBlockfork that raises the XDC gas schedule from the Gas50x tier (12.5 gwei) to the Gas2500x tier (625 gwei), scaling the chain default gas price and the EIP-1559 base fee together.Motivation & design
params/gas.go, so a future tier only needs one more row.Gas50xBlockdirectly.GetMinGasPrice, is scaled from the immutablecommon.DefaultMinGasPrice; the cachedparams.SetMinGasPrice50xand the mutablecommon.MinGasPriceit was derived from are removed.CalcBaseFeeis expressed in terms ofCalcBaseFeeForBlockNumber, andcommon.BaseFeeis replaced byparams.BaseFeeForBlock.ValidateTransactionWithState, gas price oracle, fee history, pending tx RPC) now resolve the schedule at the next block height instead of the current head.params.BaseFeeForOpcode.CheckConfigForkOrderrejects configurations that would let Gas2500x take effect inside that window.Behavior changes (operator-facing)
--miner.gaspriceno longer raises the tx pool minimum gas price: the floor is now a pure function of the chain config gas schedule, and raising it requires scheduling a tier fork. The flag still feeds the miner and the gas price oracle as before.eth_simulateV1non-validation blocks now report BASEFEE = 0 (matching upstream) instead of the old hard-coded 12.5 gwei.Compatibility
Testing
params/...,core/txpool/...,core/vm,consensus/misc/eip1559,eth/gasprice,core,internal/ethapiall pass;cmd/XDCbuilds.Release notes
eth_simulateV1non-validation blocks instead of 12.5 gwei.Types of changes
What types of changes does your code introduce to XDC network?
Put an
✅in the boxes that applyImpacted Components
Which parts of the codebase does this PR touch?
Put an
✅in the boxes that applyChecklist
Put an
✅in the boxes once you have confirmed below actions (or provide reasons on not doing so) that