XGR Chain — Technical Whitepaper
XGR.Network GmbH
Version: 1.0 (Draft)
Last updated: 2026-02-07
Network: xgrchain (chain ID 1643)
Abstract
XGR Chain is an EVM-compatible blockchain network built on Polygon Edge and configured as a bootstrap chain (not a fork). It provides:
- IBFT (Istanbul BFT) Proof-of-Authority consensus with immediate finality
- BLS-based validators with aggregated commit seals
- A predictable fee policy: a modified EIP-1559 model with a governance-controlled minimum base fee
- Standard Ethereum developer experience: common JSON-RPC endpoints, transaction types, logs and receipts
This paper describes the chain protocol and implementation architecture at a technical level, based on the canonical network parameters in genesis.json and the public chain client codebase.
Reading guide
- Validators / operators: Sections 4, 6, 10, 11 + Appendices
- Infrastructure / RPC / indexers: Sections 5, 7, 9
- Auditors / protocol reviewers: Sections 4–8 + 10 + Appendices
Table of contents
- Introduction
- Design goals
- Node architecture (client components)
- Network identity & genesis
- Execution model (EVM, state, blocks)
- Consensus protocol (IBFT PoA with BLS)
- Fees and gas model (modified EIP-1559 + fee distribution)
- On-chain governance parameters (EngineRegistry)
- Networking, synchronization, and JSON-RPC
- Security considerations
- Operations and deployment patterns
- Appendices
1. Introduction
1.1 Bootstrap chain, not a fork
XGR Chain starts from a custom genesis block and begins at height 0. It is not a fork of Ethereum mainnet (or any other chain). Concretely:
- There is no inherited state (balances/contracts) from any external chain.
- The genesis file defines the initial state and consensus validator set.
- The network has its own
chainIDfor transaction signing and replay protection.
1.2 Open chain code vs. closed Engine
The XGR stack is layered:
- The chain client (consensus + execution + networking) is intended to be public.
- The Engine component is closed source and documented separately.
Where governance influences consensus-critical behavior (e.g., the minimum base fee floor), the chain reads the relevant values from on-chain state (EngineRegistry) so the rules remain auditable and verifiable by any node.
1.3 Scope
This paper covers:
- consensus and finality,
- execution and state transition,
- network parameters and genesis,
- fee policy and its on-chain governance hooks,
- operational and security considerations for node deployments.
This paper intentionally does not document closed-source Engine internals.
2. Design goals
2.1 EVM compatibility
XGR Chain targets compatibility with existing Ethereum tooling:
- standard transaction types (legacy and EIP-1559),
- standard JSON-RPC endpoints,
- standard receipt and log semantics.
2.2 Fast, deterministic finality
The network uses IBFT in PoA mode to deliver:
- immediate finality,
- stable block production in controlled validator environments.
2.3 Predictable fees
Instead of continuously fluctuating base fees, XGR Chain:
- clamps the base fee to a governance-defined floor under normal load,
- only activates emergency pricing above high utilization.
2.4 Governance without hard forks (where safe)
Economic / operational parameters can be governed through on-chain state (EngineRegistry). This enables parameter updates without requiring protocol forks, while keeping the rules publicly verifiable.
3. Node architecture (client components)
XGR Chain nodes use Polygon Edge’s modular architecture. At a high level:
flowchart LR
subgraph Node["XGR Chain Node (Polygon Edge based)"]
RPC["JSON-RPC API\n(jsonrpc/*)"]
TXP["TxPool / Mempool\n(txpool/*)"]
CONS["Consensus: IBFT\n(consensus/ibft/*)"]
EXEC["State Transition + EVM\n(state/*, state/runtime/*)"]
CHAIN["Blockchain / Headers / Storage\n(blockchain/*)"]
P2P["P2P Networking (libp2p)\n(network/*)"]
DB["State DB + Trie\n(state/immutable-trie/*)"]
end
RPC --> TXP
TXP --> CONS
CONS --> CHAIN
CONS --> P2P
P2P --> CONS
CHAIN --> EXEC
EXEC --> DB
DB --> EXEC
CHAIN --> DB
3.1 Key components
- P2P networking (
network/*)- peer discovery (bootnodes) and connection management
- block and transaction propagation
- Blockchain storage (
blockchain/*)- canonical chain tracking, header / block persistence
- base fee calculation for EIP-1559 semantics (with XGR policy)
- Consensus (
consensus/ibft/*)- proposer selection
- IBFT message handling (prepare/commit phases, view changes)
- finality and block insertion rules
- State transition (
state/*,state/runtime/*)- EVM execution
- gas accounting
- fee distribution
- TxPool (
txpool/*)- transaction validation
- fee-based ordering
- per-account nonce management
- JSON-RPC (
jsonrpc/*)- external API for wallets, dApps, explorers
- fee estimation endpoints (gas price, fee history)
3.2 Where “protocol” lives
From a protocol / interoperability perspective, the critical behaviors are:
- Block validity rules (consensus headers, seals, difficulty rules)
- State transition rules (gas costs, EVM semantics, fee distribution)
- Fee / base fee policy
- Validator set definition and changes
- On-chain governance parameters that modify any of the above
4. Network identity & genesis
4.1 Identity parameters
| Parameter | Value |
|---|---|
| Network name | xgrchain |
| Chain ID | 1643 |
Chain ID is used for EIP-155 signing and replay protection.
4.2 Genesis headline parameters
| Parameter | Value |
|---|---|
| Block gas limit (genesis) | 60,000,000 |
| Block time | ~2.0 seconds |
| Epoch size | 500 blocks |
| Consensus | IBFT PoA (BLS) |
4.3 Bootnodes
Bootnodes are libp2p multiaddrs used for initial discovery:
| # | Bootnode multiaddr | |---|---| | 1 | /ip4/217.154.225.157/tcp/1478/p2p/16Uiu2HAmGYfGAKCNzuzZPPauKk7FpqMk192hEmiQsqYTXvrga4Ck |
4.4 Initial allocations (genesis state)
Balances are defined in wei (10^-18 of the native token).
| Address | Balance (wei) | Balance (native units, 18 decimals) | |---|---|---| | 0x0000000000000000000000000000000000000000 | 0 | 0 | | 0x00000000000000000000000000000000000000e1 | 1 | 1.00000000000000007e-18 | | 0x2A021a1B25DA25e14C4046e5BAc9375Ec3bebf8c | 2103833846420000000000000000 | 2,103,833,846.42000008 | | 0x4675EdCa3c4637E68Ed1C1776a11EB5c9828F056 | 3141592653580000000000000000 | 3,141,592,653.57999992 | | 0x7818A59b2D279Fe3444B75dcE1A443C1b124c161 | 1380649000000000000000000000 | 1,380,649,000 |
4.5 Initial validator set and genesis extraData
The genesis block extraData encodes the initial validator set:
| # | Validator address (ECDSA) | BLS public key (48 bytes) | |---|---|---| | 1 | 0x7913fdae82c678f42b98ca8076fe7d13b3edff15 | 0xb56b72d028aa6d063d36917f9f18a3ee4b216e22694a701814af4fd55e6cbbe99209fc1359012e4733987ebdd0123e88 | | 2 | 0x7e8f8fd2a198f77df298041b48d79b0df4c8b1fa | 0xa32a09397128b801da5b88319bcca6cc33d4400e12ef7e1a94141b2360abd70306aaeb5599dd0d0984bb02f88fe20b71 | | 3 | 0x82f0b6f1efbb3fc9bcde0ee5a08e01e76cc29e13 | 0x8b94120a8ae2a89a0f7deb09f266d90bf5d5152a6ee559977d7f3361a0ce1cc65b012f3a820c7f1c18a01cef9ba8ae90 | | 4 | 0xc5cc7b4ee5b0f6524ecac177ed37b2b567180707 | 0x91bf571d3f5563976e560c5f7d9898f75a0829804ce5e212370834303c23953388f01e06d0a9da2615c5e7f1aaf10da7 | | 5 | 0x98f8bc086454b8386788244eee9a43d5d0b4e63e | 0xa65579c3b300f0d8e94e77b3915ac09f309c0a109a3aa3bb66d8beb538d733026624bf9d096e2a3d52deff78a36513d1 |
This list is not merely informational: for IBFT PoA it defines the initial consensus authority set.
4.6 Parameter rationale (informative)
The genesis parameters encode explicit trade-offs:
- Block time (~2.0s): targets low-latency finality while keeping IBFT message overhead manageable.
- Gas limit (60,000,000): allows high throughput for complex contract workloads. At a theoretical maximum, this corresponds to:
- ~30,000,000 gas/second (assuming full blocks every 2.0s),
- ~2,857 simple ETH transfers per block (upper bound, ignoring overhead).
- Epoch size (500): defines a periodic checkpoint cadence of ~16.7 minutes, balancing:
- snapshot / validator-set bookkeeping overhead,
- ease of syncing validator set state for new joiners.
The 80% utilization threshold in the fee policy (Section 7) creates a reserved headroom of 12,000,000 gas per block for “emergency” congestion response.
5. Execution model (EVM, state, blocks)
5.1 Account-based state
XGR Chain follows the standard Ethereum account model:
- Externally Owned Accounts (EOAs) identified by 20-byte addresses
- hold balances and nonces
- controlled by private keys
- Contract accounts
- hold bytecode
- have persistent storage (key/value)
- are executed by EVM message calls / contract creations
5.2 State root and determinism
After each block, the state is committed to a Merkle-style trie root (stateRoot).
This provides:
- cryptographic commitment to full state
- deterministic replay and verification
5.3 Blocks and headers
Each block includes:
- a header (hash-linked to its parent),
- a list of transactions,
- receipts/logs (derivable from execution),
- and consensus metadata.
For EIP-1559-style semantics, the header includes a baseFee.
For IBFT, the header includes consensus metadata in extraData and uses a consensus identifier digest in mixHash.
5.4 Fork configuration and EVM semantics
XGR Chain activates modern EVM fork behavior from block 0, including London.
Forks active from genesis:
london(block 0)EIP150(block 0)EIP155(block 0)EIP158(block 0)byzantium(block 0)constantinople(block 0)homestead(block 0)istanbul(block 0)londonfix(block 0)petersburg(block 0)quorumcalcalignment(block 0)txHashWithType(block 0)
5.5 Transaction formats and signing
XGR Chain follows Ethereum’s transaction signing model:
- Every transaction is signed with the sender’s private key.
- The signature includes EIP-155 replay protection, binding the signature to
chainID = 1643.
Supported transaction types:
- Type 0 (legacy): uses a single
gasPricefield. - Type 2 (EIP-1559): uses fee caps:
maxFeePerGasmaxPriorityFeePerGas
Effective gas price for a type-2 tx is:
effectiveGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
A tx is valid only if it can pay at least the current baseFee (plus any tip and intrinsic gas).
5.6 Transaction lifecycle (from RPC to finality)
A high-level lifecycle for a submitted transaction is:
flowchart TD
A["User signs tx (chainID)"] --> B["Send via JSON-RPC\neth_sendRawTransaction"]
B --> C["TxPool validates: signature, nonce, fee fields"]
C --> D["TxPool queues tx by sender + fee priority"]
D --> E["Proposer selects txs for next block"]
E --> F["EVM execution updates state"]
F --> G["Receipt + logs created"]
G --> H["Fees distributed\n(burn + donation + validator)"]
H --> I["Block finalized by IBFT commits"]
Key points:
- The txpool performs stateless checks (format, signature) and stateful checks (nonce, balance, fee constraints).
- The proposer selects transactions based on fee priority and validity.
- Execution produces deterministic state changes, logs, and receipts.
- Fees are distributed and the block is finalized by IBFT commit quorum.
5.7 Gas accounting and block limits
XGR Chain uses standard EVM gas accounting semantics:
- Each transaction specifies a gas limit (
tx.gas). - During execution, gas is consumed deterministically by:
- intrinsic costs (e.g., transaction base cost),
- opcode execution costs,
- memory expansion,
- storage reads/writes (SLOAD/SSTORE),
- contract calls/creates, etc.
If a transaction runs out of gas, it reverts state changes (except that gas is still paid).
Block gas limit
The genesis specifies G = 60,000,000 gas per block. Validators must ensure that the sum of gas used by included transactions does not exceed G.
80% congestion threshold
Fee emergency pricing is triggered only in the top 20% band:
T = 0.8 * G = 48,000,000
So the network can operate with high throughput while keeping a predictable fee regime under typical load.
5.8 Receipts, logs, and indexing
For each executed transaction, the chain produces a receipt containing:
- execution status (success/revert),
gasUsed,- logs/events emitted by smart contracts.
Logs are the primary indexing mechanism for:
- explorers,
- analytics pipelines,
- off-chain services that react to on-chain events.
Because XGR Chain is EVM-compatible, standard indexing approaches apply (filtering by address and topics, scanning receipts, etc.).
6. Consensus protocol (IBFT PoA with BLS)
6.1 IBFT overview
IBFT is a PBFT-family protocol with rounds (“views”). For each height:
- a proposer proposes a block,
- validators exchange prepare messages,
- validators exchange commit messages,
- once commit quorum is reached (≥ 2f+1), the block is finalized.
6.2 Fault tolerance
Let n be validator count and f = floor((n-1)/3). The protocol tolerates up to f Byzantine validators, assuming eventual synchrony.
At genesis:
n = 5f = 1- finalization quorum is
2f+1 = 3
6.3 Message phases (conceptual)
sequenceDiagram
autonumber
participant P as Proposer
participant V1 as Validator 1
participant V2 as Validator 2
participant V3 as Validator 3
participant Vn as Validator n
Note over P,Vn: Round r at height h
P->>V1: PRE-PREPARE (proposal block)
P->>V2: PRE-PREPARE (proposal block)
P->>V3: PRE-PREPARE (proposal block)
P->>Vn: PRE-PREPARE (proposal block)
V1->>P: PREPARE (vote)
V2->>P: PREPARE (vote)
V3->>P: PREPARE (vote)
Vn->>P: PREPARE (vote)
Note over P: Collect ≥ 2f+1 PREPARE
P->>V1: COMMIT (aggregate / commit proof)
P->>V2: COMMIT (aggregate / commit proof)
P->>V3: COMMIT (aggregate / commit proof)
P->>Vn: COMMIT (aggregate / commit proof)
Note over V1,Vn: Collect ≥ 2f+1 COMMIT
V1-->>V1: Finalize block h (immediate finality)
V2-->>V2: Finalize block h
V3-->>V3: Finalize block h
Vn-->>Vn: Finalize block h
6.4 Consensus-specific header validity rules
XGR Chain’s IBFT implementation enforces several header rules. Abridged excerpt:
// consensus/ibft/ibft.go (abridged)
if header.MixHash != signer.IstanbulDigest {
return ErrInvalidMixHash
}
if header.Sha3Uncles != types.EmptyUncleHash {
return ErrInvalidSha3Uncles
}
// IBFT rule: difficulty equals block number
if header.Difficulty != header.Number {
return ErrWrongDifficulty
}
Interpretation:
mixHashis used as a consensus identifier and must equalIstanbulDigest.sha3Unclesmust be empty (uncles are not used).difficultyis not a PoW difficulty. In this IBFT mode it is used as a deterministic check:- difficulty must equal the block number.
Genesis blocks are special-cased in most clients; operationally, these rules apply to “normal” IBFT blocks after genesis.
6.5 IBFT wire protocol identity
The IBFT networking protocol ID is defined as:
// consensus/ibft/ibft.go (abridged)
const (
ibftProto = "/ibft/0.2"
DefaultEpochSize = 100000
)
This is relevant for interoperable clients and debugging P2P streams.
6.6 BLS commit seals
In BLS mode:
- Each validator has an ECDSA address identity, and a BLS key.
- Commit votes are aggregated into a single signature and a participant bitmap.
Abridged structures (for intuition):
// consensus/ibft/signer/bls.go (abridged)
type AggregatedSeal struct {
Bitmap *big.Int // which validators participated
Signature []byte // aggregated BLS signature
}
// consensus/ibft/signer/extra.go (abridged)
type IstanbulExtra struct {
Validators validators.Validators
ProposerSeal []byte
CommittedSeals Seals
ParentCommittedSeals Seals
RoundNumber *uint64
}
6.7 Validator ordering and bitmaps
Important detail: for aggregated seals, the bitmap maps to the validator set order.
Therefore, the order of validators in IstanbulExtra.Validators is consensus-relevant.
Genesis defines this order explicitly (see validator table in Section 4.5).
6.8 Epochs and snapshots
Epoch size is configured to 500 blocks (~16.7 minutes). Epoch mechanisms are typically used to:
- checkpoint validator set snapshots,
- reset vote tallies / simplify syncing validator set state.
6.9 Validator set management (PoA operations)
Because XGR Chain runs in PoA mode, validator set updates are operational / governance events.
The codebase provides IBFT operator subcommands under command/ibft/:
| Subcommand | Purpose (high level) | |---|---| | candidates | List current candidate validators | | helper | Shared utilities | | propose | Propose adding/removing a validator | | quorum | Inspect quorum configuration / state | | snapshot | Inspect validator snapshot at a given height | | status | Inspect IBFT status / health | | switch | Consensus switching helper (deployment-specific) |
The exact governance workflow (who is allowed to propose, voting rules, operational checks) is deployment-specific, but the IBFT mechanics are implemented in the chain client.
6.10 Rounds, timeouts, and view changes (conceptual)
IBFT is round-based. When the proposer for the current round fails to produce a valid block within a timeout, the validator set advances to the next round (view change).
Symptoms of network stress:
- frequent round increments (multiple rounds for the same height),
- increased block time variance,
- failure to reach commit quorum.
Operational mitigations typically include:
- improving validator connectivity / peering,
- investigating outlier validators (latency, CPU saturation, disk I/O),
- ensuring clock sync and stable network routing.
7. Fees and gas model (modified EIP-1559 + fee distribution)
XGR Chain uses EIP-1559 transaction compatibility, but with a fee policy optimized for stable costs and explicit fee distribution.
7.1 Base fee policy (stable floor + emergency ramp)
Key properties:
minBaseFeeis a governance-controlled floor (via EngineRegistry).- Below 80% utilization, base fee is clamped to
minBaseFee. - Above 80%, base fee ramps up, with an upper slope of ~+25% per block at full blocks.
Given the genesis gas limit G = 60,000,000:
- threshold
T = 0.8 * G = 48,000,000 - headroom
H = G - T = 12,000,000
So only the last 12,000,000 gas of each block (the 80–100% band) triggers emergency pricing.
Example ramp intuition (with denom=4):
- at 100% utilization:
Δ ≈ baseFee/4(+25%) - at 90% utilization:
Δ ≈ baseFee/8(+12.5%)
Code reference and abridged implementation:
// chain/params.go (abridged)
const (
// Fallback floor, used if no dynamic minBaseFee is available via EngineRegistry
MinBaseFee uint64 = 100_000_000_000 // 100 gwei
// "Kink" point: below this utilization, baseFee is clamped to minBaseFee
CriticalGasThresholdPct uint64 = 80
// Max ramp at 100% load: +baseFee/denom per block → denom=4 => +25% per block
EmergencyBaseFeeChangeDenom uint64 = 4
)
// blockchain/blockchain.go (abridged)
func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 {
minBaseFee := b.resolveMinBaseFee(parent)
// First post-genesis London block: start from GenesisBaseFee then clamp to minBaseFee
if parent.BaseFee == 0 {
baseFee := chain.GenesisBaseFee // 1 gwei default
if baseFee < minBaseFee {
return minBaseFee
}
return baseFee
}
gasLimit := parent.GasLimit
threshold := (gasLimit * chain.CriticalGasThresholdPct) / 100
if parent.GasUsed <= threshold {
return minBaseFee
}
// emergency pricing: ramp up within the 80–100% utilization headroom
headroom := gasLimit - threshold
excess := parent.GasUsed - threshold
parentBF := parent.BaseFee
if parentBF < minBaseFee {
parentBF = minBaseFee
}
delta := parentBF * excess / headroom / chain.EmergencyBaseFeeChangeDenom
if delta < 1 {
delta = 1
}
return parentBF + delta
}
7.2 Priority fee estimation (client behavior)
Because base fee is intentionally stable under normal load, wallet UX often relies on eth_maxPriorityFeePerGas or eth_feeHistory to recommend a tip.
The client includes a gas helper configuration:
// gasprice/gasprice.go (abridged)
var DefaultGasHelperConfig = &Config{
NumOfBlocksToCheck: 20,
PricePercentile: 60,
SampleNumber: 3,
MaxPrice: ethgo.Gwei(500),
LastPrice: ethgo.Gwei(1),
IgnorePrice: big.NewInt(2), // 2 wei
}
Interpretation (conceptual):
- sample the last 20 blocks,
- use a 60th percentile tip estimate,
- cap at 500 gwei, with a 1 gwei last-known default,
- ignore near-zero prices (<2 wei).
7.3 Fee distribution (burn + donation + validator)
In addition to base fee behavior, the chain defines how paid fees are distributed during execution.
At transaction finalization time, the chain computes a total fee and splits it across:
- a fixed “burn” component (sent to a burn sink address),
- an optional donation component (configurable %),
- the validator/proposer reward (coinbase).
Conceptually:
totalFeeRaw = gasUsed * effectiveGasPrice
burnedApplied = min(totalFeeRaw, fixedBurn)
totalFee = totalFeeRaw - burnedApplied
donation = totalFee * donationPercent / 100
validator = totalFee - donation
credit(burnedAddr, burnedApplied)
credit(donationAddr, donation)
credit(coinbase, validator)
Implementation excerpt:
// state/executor.go (abridged)
// totalFeeRaw = gasUsed * gasPrice
// fixed burn amount: 1000 gwei (1000000000000 wei)
burned := big.NewInt(0).Mul(big.NewInt(1000), big.NewInt(1_000_000_000))
burnedApplied := min(totalFeeRaw, burned)
totalFee := totalFeeRaw - burnedApplied
// donationPercent defaults to 15% and can be overridden via EngineRegistry
donation := totalFee * donationPercent / 100
validator := totalFee - donation
state.AddBalance(donationAddr, donation)
state.AddBalance(coinbase, validator)
state.AddBalance(burnedAddr, burnedApplied)
Default values (when EngineRegistry does not override donation settings):
- fixed burn: 1000 gwei per transaction (clamped so total fees never go negative)
- burn sink address:
0x0000000000000000000000000000000000000666 - donation percent:
15%(can be overridden) - donation address: defaults to burn sink unless configured
Developer impact: these mechanics do not change how transactions are constructed; they affect the destination of paid fees.
7.4 Developer-facing gas behavior spec
A dedicated spec document defines expected behavior for eth_feeHistory and fee fields:
XRC-GAS_Gas_Price_Behavior.md
7.5 Worked examples
Example A — base fee behavior at normal load
Assume:
G = 60,000,000- threshold
T = 48,000,000 minBaseFee = 100 gwei(fallback default)
If the parent block uses U = 30,000,000 gas (< T), then:
baseFee(next) = minBaseFee
So fee volatility is eliminated under normal load.
Example B — emergency ramp at high load
Assume the parent block uses U = 60,000,000 gas (~100% of G):
- excess =
U - T = 12,000,000 - headroom =
12,000,000
So excess/headroom ≈ 1, and:
baseFee(next) ≈ baseFee(parent) + baseFee(parent)/4(+25%)
At 90% utilization (U = 54,000,000):
- excess = 6,000,000
- excess/headroom = 0.5
Δ ≈ baseFee(parent)/8(+12.5%)
Example C — fee distribution
Suppose a transaction uses:
gasUsed = 50,000effectiveGasPrice = 100 gwei
Then:
totalFeeRaw = 50,000 * 100 gwei = 5,000,000 gwei
Fixed burn:
burnedApplied = min(totalFeeRaw, 1000 gwei) = 1000 gwei
Remaining fee:
totalFee = 4,999,000 gwei
If donationPercent = 15%:
- donation = 749,850 gwei
- validator = 4,249,150 gwei
The burn amount is sent to 0x0000000000000000000000000000000000000666, donation to the configured donation address, and the validator portion to block coinbase.
7.6 EIP-1559 validity constraints under a stable base fee
Even though base fee is “stable” most of the time, EIP-1559 validity rules still apply:
- For a type-2 transaction to be includable at block
h, it must satisfy:maxFeePerGas >= baseFee(h)
- Otherwise, the transaction is underpriced and will be rejected by proposers / validators.
In practice, wallet defaults should set:
maxFeePerGas = baseFee + tip + safetyMargin
Because base fee is usually clamped to minBaseFee, users can set predictable caps and avoid overpaying, while still being protected during short congestion bursts (emergency ramp).
8. On-chain governance parameters (EngineRegistry)
8.1 Purpose
EngineRegistry is an on-chain contract address known to the chain via genesis:
engineRegistryAddress = 0x72cbbb5c95662510da052b98add933ff99ec820f
It is used as a verifiable store for governance-controlled parameters such as:
minBaseFee- donation address and donation percent
- (optionally) other operational flags
8.2 Storage layout (slots)
The chain client reads specific storage slots. Abridged slot constants:
// chain/engine_registry.go (abridged)
const (
engineRegistrySlotAuthorizedEngines uint64 = 2
engineRegistrySlotMinBaseFee uint64 = 5
engineRegistrySlotPaused uint64 = 6
engineRegistrySlotDonationAddress uint64 = 8
engineRegistrySlotDonationPercent uint64 = 9
)
8.3 Reading minBaseFee safely
At runtime, the client:
- checks if code is deployed at
engineRegistryAddress(otherwise treat as absent), - reads the configured storage slot for
minBaseFee, - validates the decoded value (non-negative, fits in uint64),
- falls back to a safe default if any step fails.
Slot key helper:
// chain/engine_registry.go (abridged)
const (
// Storage slot containing minBaseFee (uint256)
engineRegistrySlotMinBaseFee uint64 = 5
)
func EngineRegistrySlotKeyMinBaseFee() types.Hash {
return u256Slot(engineRegistrySlotMinBaseFee)
}
8.4 Donation configuration
Donation settings are read analogously from:
- slot 8 (
donationAddress) - slot 9 (
donationPercent)
Safety behavior:
- if
donationAddressresolves to the zero address, donation is disabled.
8.5 Registry absence and bootstrap behavior
The chain is designed to remain functional even if EngineRegistry is not deployed or temporarily unavailable:
- If
engineRegistryAddressis the zero address, or code size at that address is 0:minBaseFeefalls back to a constant floor (default: 100 gwei)- donation settings fall back to defaults (15% donation, default donation address)
This “bootstrap” behavior is important for:
- early network bring-up,
- genesis-to-registry deployment sequencing,
- fault tolerance (avoid bricking the chain due to registry read failures).
8.6 Governance workflow (informative)
EngineRegistry-based governance is intentionally simple:
- To update
minBaseFee(or donation settings), governance submits a transaction that updates the registry contract storage. - All nodes observe the updated value when they execute blocks (because the value is read from state at the configured address).
- The rule is therefore:
- transparent (auditable on-chain),
- deterministic (nodes read the same state),
- and does not require a fork for parameter changes.
This design shifts governance disputes away from “client code changes” and into explicit on-chain state changes that can be monitored and reviewed.
9. Networking, synchronization, and JSON-RPC
9.1 Discovery and connectivity
Nodes discover peers via bootnodes and maintain a peer set through libp2p connection management.
Operationally:
- validator nodes should be directly peered where possible (to minimize latency),
- bootnodes should be stable, well-connected, and DDoS-protected.
9.2 Synchronization
A joining node must:
- obtain the genesis configuration (to identify the chain),
- discover peers,
- sync blocks and state from the network.
9.3 JSON-RPC surface
RPC nodes expose the EVM-standard API. Typical calls:
eth_chainId→1643eth_blockNumber,eth_getBlockByNumbereth_sendRawTransactioneth_call,eth_estimateGaseth_getTransactionReceipt,eth_getLogs- fee helpers:
eth_gasPrice,eth_maxPriorityFeePerGas,eth_feeHistory
Production guidance:
- isolate RPC nodes from validator nodes,
- rate-limit public RPC,
- monitor and autoscale based on load.
9.4 RPC hardening guidelines (production)
Recommended baseline controls for public RPC:
- Rate limiting on
eth_call,eth_estimateGas,eth_getLogs(these can be expensive). - Request size limits for batched calls.
- Timeouts and circuit breakers for long-running queries.
- Separate endpoints for:
- public read-only traffic,
- authenticated write traffic,
- internal validator monitoring.
For validators, strongly prefer private RPC access and do not expose validator node RPC publicly.
10. Security considerations
10.1 Consensus security
IBFT provides strong safety guarantees but relies on:
- ≤
fByzantine validators, - eventual network synchrony,
- correct proposer rotation and view-change logic.
10.2 PoA trust model
PoA means validator governance is a core trust anchor:
- validator onboarding/offboarding is a security-critical process,
- key compromise of a validator is a major incident.
10.3 Fee policy security
The stable-floor fee policy reduces fee volatility but introduces considerations:
- validators could attempt to manipulate gas usage near the threshold to trigger emergency pricing,
- governance-controlled
minBaseFeemust be managed transparently and securely.
Because the chain reads minBaseFee from on-chain state, any changes are publicly observable.
10.4 Operational threats
- DDoS against validators or bootnodes
- network partitions reducing quorum
- misconfiguration (wrong genesis, wrong chain ID, mismatched validator sets)
10.5 Threat overview (non-exhaustive)
| Threat | Impact | Typical mitigations | |---|---|---| | Validator key compromise | Safety / governance failure | HSMs, key rotation, incident response | | Validator collusion | Censorship / governance capture | decentralize validator operators, transparent governance | | Network partition | Liveness loss | redundant connectivity, direct peering, monitoring | | DDoS on bootnodes | Slow join / degraded discovery | multiple bootnodes, Anycast / DDoS protection | | Spam tx floods | Mempool bloat / liveness | base fee floor, emergency ramp, RPC rate limits | | Misconfiguration (wrong genesis) | Chain split | config management, checksums, CI validation |
11. Operations and deployment patterns
11.1 Recommended topology
A common production topology is:
Nvalidator nodes (BLS + ECDSA keys, private networking)- a set of public RPC nodes behind load balancers
- optionally, archive/indexer nodes for analytics
11.2 Monitoring
Key signals:
- block production rate vs expected block time
- IBFT round/view changes (excessive rounds indicate liveness issues)
- peer count and connectivity metrics
- RPC latency and error rates
- fee regime state (normal vs emergency pricing)
- on-chain
minBaseFeechanges (EngineRegistry)
11.3 Safe upgrades
Upgrades should be:
- rolled out gradually across validators,
- compatible across a window (avoid consensus splits),
- pinned to explicit versions and release hashes.
Genesis changes are never “small”: any change to genesis typically defines a new chain.
11.4 Validator key management (ECDSA + BLS)
Because BLS mode requires dual key material, validator operators should treat key management as a first-class security domain.
Recommended baseline practices:
- Store private keys in an HSM or hardware-backed keystore whenever possible.
- Enforce multi-person control for any key export or rotation.
- Maintain an incident playbook:
- what to do on suspected compromise,
- how to coordinate validator removal and replacement.
Suggested separation of duties:
- One operational key set for node deployment and maintenance.
- Separate protected signing keys for consensus participation.
Where supported, perform regular key rotation drills to reduce recovery time during real incidents.
12. Appendices
Appendix A — Parameter snapshot (from genesis)
| Category | Key | Value |
|---|---|---|
| Identity | name | xgrchain |
| Identity | chainID | 1643 |
| Consensus | engine | ibft |
| Consensus | ibft.type | PoA |
| Consensus | ibft.validator_type | bls |
| Consensus | ibft.blockTime | 2000000000 ns |
| Consensus | ibft.epochSize | 500 |
| Gas | genesis.gasLimit | 0x3938700 |
| Registry | engineRegistryAddress | 0x72cbbb5c95662510da052b98add933ff99ec820f |
Appendix B — Initial validator set
| # | Validator address (ECDSA) | BLS public key (48 bytes) | |---|---|---| | 1 | 0x7913fdae82c678f42b98ca8076fe7d13b3edff15 | 0xb56b72d028aa6d063d36917f9f18a3ee4b216e22694a701814af4fd55e6cbbe99209fc1359012e4733987ebdd0123e88 | | 2 | 0x7e8f8fd2a198f77df298041b48d79b0df4c8b1fa | 0xa32a09397128b801da5b88319bcca6cc33d4400e12ef7e1a94141b2360abd70306aaeb5599dd0d0984bb02f88fe20b71 | | 3 | 0x82f0b6f1efbb3fc9bcde0ee5a08e01e76cc29e13 | 0x8b94120a8ae2a89a0f7deb09f266d90bf5d5152a6ee559977d7f3361a0ce1cc65b012f3a820c7f1c18a01cef9ba8ae90 | | 4 | 0xc5cc7b4ee5b0f6524ecac177ed37b2b567180707 | 0x91bf571d3f5563976e560c5f7d9898f75a0829804ce5e212370834303c23953388f01e06d0a9da2615c5e7f1aaf10da7 | | 5 | 0x98f8bc086454b8386788244eee9a43d5d0b4e63e | 0xa65579c3b300f0d8e94e77b3915ac09f309c0a109a3aa3bb66d8beb538d733026624bf9d096e2a3d52deff78a36513d1 |
Appendix C — Genesis allocations
| Address | Balance (wei) | Balance (native units, 18 decimals) | |---|---|---| | 0x0000000000000000000000000000000000000000 | 0 | 0 | | 0x00000000000000000000000000000000000000e1 | 1 | 1.00000000000000007e-18 | | 0x2A021a1B25DA25e14C4046e5BAc9375Ec3bebf8c | 2103833846420000000000000000 | 2,103,833,846.42000008 | | 0x4675EdCa3c4637E68Ed1C1776a11EB5c9828F056 | 3141592653580000000000000000 | 3,141,592,653.57999992 | | 0x7818A59b2D279Fe3444B75dcE1A443C1b124c161 | 1380649000000000000000000000 | 1,380,649,000 |
Appendix D — ExtraData decoding notes
Genesis extraData uses:
- 32-byte vanity prefix
RLP(IstanbulExtra)whereIstanbulExtra[0]is the validator set
Conceptually:
# Conceptual: decoding the validator list from genesis.extraData
# extraData = 32 bytes vanity + RLP(IstanbulExtra)
# IstanbulExtra[0] == Validators list
validators = [
# each entry: [validator_address (20 bytes), bls_public_key (48 bytes)]
]
Appendix E — Genesis extraData layout (IBFT / IstanbulExtra)
At genesis, extraData is:
- 32 bytes vanity (all zeros in the current genesis)
- followed by an RLP list representing
IstanbulExtra
Conceptually:
extraData =
vanity[32] ||
RLP([
Validators: [
[address_1, blsPubKey_1],
[address_2, blsPubKey_2],
...
],
ProposerSeal: <65 bytes or null>,
CommittedSeals: [bitmap, signature] (BLS aggregated seal),
ParentCommittedSeals: [bitmap, signature] or empty,
RoundNumber: uint64 or null
])
Example (first validator entry):
- address:
0x7913fdae82c678f42b98ca8076fe7d13b3edff15 - BLS pubkey:
0xb56b72d028aa6d063d36917f9f18a3ee4b216e22694a701814af4fd55e6cbbe99209fc1359012e4733987ebdd0123e88
Appendix F — Priority fee estimation (GasHelper)
The client’s gas helper (used for endpoints such as eth_maxPriorityFeePerGas and parts of eth_feeHistory) samples recent blocks and derives a recommended priority fee.
High-level behavior:
- Look back over a fixed number of recent blocks.
- Sample a percentile of transaction tips.
- Return a bounded estimate (with caps and a last-known fallback).
This is designed to:
- work well when base fee is stable (normal regime),
- adapt when congestion pushes the network into emergency pricing.
The exact sampling constants are documented in Section 7.2 and in gasprice/gasprice.go.
Appendix G — Fee distribution constants (default behavior)
When EngineRegistry does not override donation settings, the execution layer uses:
- Fixed burn per transaction:
1000 gwei(1000000000000wei) - Burn sink address:
0x0000000000000000000000000000000000000666 - Donation percent:
15% - Donation address default:
0x0000000000000000000000000000000000000666(unless configured)
These values are part of the deterministic state transition and therefore consensus-relevant.
References
- Fee behavior (developer spec):
XRC-GAS_Gas_Price_Behavior.md - Relevant source tree paths:
blockchain/*(base fee policy, chain storage)consensus/ibft/*(IBFT protocol)state/*(execution, fee distribution)network/*(P2P)jsonrpc/*(RPC)