Skip to content

feat(params,core,consensus,eth,cmd): add gas2500x fork switch - #2516

Open
gzliudan wants to merge 1 commit into
XinFinOrg:dev-upgradefrom
gzliudan:new-gas-price
Open

feat(params,core,consensus,eth,cmd): add gas2500x fork switch#2516
gzliudan wants to merge 1 commit into
XinFinOrg:dev-upgradefrom
gzliudan:new-gas-price

Conversation

@gzliudan

@gzliudan gzliudan commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Proposed changes

Summary

Introduce an optional Gas2500xBlock fork 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

  • 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 pool floor returned by GetMinGasPrice, is scaled from the immutable common.DefaultMinGasPrice; the cached params.SetMinGasPrice50x and the mutable common.MinGasPrice it was derived from are removed.
  • The EIP-1559 base fee becomes block-number aware: CalcBaseFee is expressed in terms of CalcBaseFeeForBlockNumber, and common.BaseFee is replaced by params.BaseFeeForBlock.
  • Callers that price a not-yet-mined transaction (txpool promotion/demotion/reorg, ValidateTransactionWithState, gas price oracle, fee history, pending tx RPC) now resolve the schedule at the next block height instead of the current head.
  • The BASEFEE opcode now reports the header base fee; where the header carries none (the London-to-EIP1559 window) it falls back to the pinned params.BaseFeeForOpcode. CheckConfigForkOrder rejects configurations that would let Gas2500x take effect inside that window.

Behavior changes (operator-facing)

  • --miner.gasprice no 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_simulateV1 non-validation blocks now report BASEFEE = 0 (matching upstream) instead of the old hard-coded 12.5 gwei.
  • Localnet enables the fork at block 0, which changes the localnet genesis hash — existing local data directories must be reset.
  • Transactions already pending when a tier activates are not swept; they stop being mineable and senders must resubmit at the new price. Admission rejects underpriced transactions one block before the tier fires, keeping the affected set small.

Compatibility

  • The fork is unscheduled on mainnet, testnet and devnet: no existing network changes behavior. At the Gas50x tier the derived base fee is identical to the constant it replaces.
  • Chain config digest version is bumped to 2; fork ordering rules, backfill definitions and network configs are updated accordingly.

Testing

  • New unit tests cover the tier table invariants, fork ordering (including the BASEFEE window rule), txpool admission/promotion/demotion pricing at tier boundaries, the BASEFEE opcode fallback, and the chain config digest golden vectors.
  • Verified: params/..., core/txpool/..., core/vm, consensus/misc/eip1559, eth/gasprice, core, internal/ethapi all pass; cmd/XDC builds.

Release notes

  • 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.

Types of changes

What types of changes does your code introduce to XDC network?
Put an in the boxes that apply

  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Changes that don't change source code or tests
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • revert: Revert something
  • style: Changes that do not affect the meaning of the code
  • test: Adding missing tests or correcting existing tests

Impacted Components

Which parts of the codebase does this PR touch?
Put an in the boxes that apply

  • Consensus
  • Account
  • Network
  • Geth
  • Smart Contract
  • External components
  • Not sure (Please specify below)

Checklist

Put an in the boxes once you have confirmed below actions (or provide reasons on not doing so) that

  • This PR has sufficient test coverage (unit/integration test) OR I have provided reason in the PR description for not having test coverage
  • Tested on a private network from the genesis block and monitored the chain operating correctly for multiple epochs.
  • Provide an end-to-end test plan in the PR description on how to manually test it on the devnet/testnet.
  • Tested the backwards compatibility.
  • Tested with XDC nodes running this version co-exist with those running the previous version.
  • Relevant documentation has been updated as part of this PR
  • N/A

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 87456e9d-dd75-4bb1-ada0-1528e8a83c09

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread consensus/tests/engine_v1_tests/helper.go Outdated
Comment thread core/state_processor_test.go Outdated
Comment thread consensus/tests/engine_v2_tests/helper.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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+1 and assert that the final baseFeePerGas entry 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)

Comment thread internal/ethapi/simulate.go
Comment thread params/forks/forks.go
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants