Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ tests/merged.genesis.json
tests/merged.genesis.json.tar.gz
tests/genesis-testnet-reth.json

crates/chainspec/res/genesis/xlayer-devnet-genesis-hash.txt
crates/chainspec/res/genesis/xlayer-devnet-state-root.txt

# Local development: cargo config for debugging with local reth
.cargo
53 changes: 53 additions & 0 deletions crates/chainspec/res/genesis/xlayer-devnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"config": {
"chainId": 195,
"homesteadBlock": 0,
"daoForkSupport": false,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"mergeNetsplitBlock": 0,
"shanghaiTime": 0,
"cancunTime": 0,
"pragueTime": 0,
"terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": false,
"bedrockBlock": 0,
"canyonTime": 0,
"ecotoneTime": 0,
"fjordTime": 0,
"graniteTime": 0,
"holoceneTime": 0,
"isthmusTime": 0,
"jovianTime": 0,
"legacyXLayerBlock": 18696116,
"optimism": {
"eip1559Denominator": 100000000,
"eip1559DenominatorCanyon": 100000000,
"eip1559Elasticity": 1
},
"regolithTime": 0,
"depositContractAddress": "0x0000000000000000000000000000000000000000"
},
"nonce": "0x0",
"timestamp": "0x699d723d",
"extraData": "0x01000000fa000000060000000000000000",
"gasLimit": "0xbebc200",
"difficulty": "0x0",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x4200000000000000000000000000000000000011",
"baseFeePerGas": "0x5fc01c5",
"excessBlobGas": "0x0",
"blobGasUsed": "0x0",
"number": "0x11d47b4",
"parentHash": "0xa3a639b09fea244d577c7e7ed7bcc4eb1adb0c5b54441cd29d9949e417dfa355"
}
47 changes: 47 additions & 0 deletions crates/chainspec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
//! This crate provides chain specifications for XLayer mainnet and testnet networks.

mod parser;
mod xlayer_devnet;
mod xlayer_mainnet;
mod xlayer_testnet;

pub use parser::XLayerChainSpecParser;
pub use xlayer_devnet::XLAYER_DEVNET;
pub use xlayer_mainnet::XLAYER_MAINNET;
pub use xlayer_testnet::XLAYER_TESTNET;

Expand All @@ -27,6 +29,10 @@ pub const XLAYER_MAINNET_JOVIAN_TIMESTAMP: u64 = 1764691201;
/// 2025-11-28 11:00:00 UTC
pub const XLAYER_TESTNET_JOVIAN_TIMESTAMP: u64 = 1764327600;

/// XLayer devnet Jovian hardfork activation timestamp
/// 2025-11-28 11:00:00 UTC
pub const XLAYER_DEVNET_JOVIAN_TIMESTAMP: u64 = 1764327600;

/// X Layer mainnet list of hardforks.
///
/// All time-based hardforks are activated at genesis (timestamp 0).
Expand Down Expand Up @@ -108,3 +114,44 @@ pub static XLAYER_TESTNET_HARDFORKS: Lazy<ChainHardforks> = Lazy::new(|| {
(OpHardfork::Jovian.boxed(), ForkCondition::Timestamp(XLAYER_TESTNET_JOVIAN_TIMESTAMP)),
])
});

/// X Layer devnet list of hardforks.
///
/// All time-based hardforks are activated at genesis (timestamp 0).
pub static XLAYER_DEVNET_HARDFORKS: Lazy<ChainHardforks> = Lazy::new(|| {
ChainHardforks::new(vec![
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::ArrowGlacier.boxed(), ForkCondition::Block(0)),
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
activation_block_number: 0,
fork_block: Some(0),
total_difficulty: U256::ZERO,
},
),
(OpHardfork::Bedrock.boxed(), ForkCondition::Block(0)),
(OpHardfork::Regolith.boxed(), ForkCondition::Timestamp(0)),
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Canyon.boxed(), ForkCondition::Timestamp(0)),
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Ecotone.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Fjord.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Granite.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Holocene.boxed(), ForkCondition::Timestamp(0)),
(EthereumHardfork::Prague.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Isthmus.boxed(), ForkCondition::Timestamp(0)),
(OpHardfork::Jovian.boxed(), ForkCondition::Timestamp(XLAYER_DEVNET_JOVIAN_TIMESTAMP)),
])
});
17 changes: 16 additions & 1 deletion crates/chainspec/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! XLayer chain specification parser

use crate::{XLAYER_MAINNET, XLAYER_TESTNET};
use crate::{XLAYER_DEVNET, XLAYER_MAINNET, XLAYER_TESTNET};
use alloy_genesis::Genesis;
use reth_cli::chainspec::ChainSpecParser;
use reth_optimism_chainspec::{generated_chain_value_parser, OpChainSpec};
Expand All @@ -12,6 +12,7 @@ use tracing::debug;
/// This parser extends the default OpChainSpecParser to support XLayer chains:
/// - xlayer-mainnet (chain id 196)
/// - xlayer-testnet (chain id 1952)
/// - xlayer-devnet (chain id 195)
///
/// It also supports all standard Optimism chains through delegation to the
/// upstream OpChainSpecParser.
Expand All @@ -34,6 +35,7 @@ impl ChainSpecParser for XLayerChainSpecParser {
// XLayer chains
"xlayer-mainnet",
"xlayer-testnet",
"xlayer-devnet",
];

fn parse(s: &str) -> eyre::Result<Arc<Self::ChainSpec>> {
Expand Down Expand Up @@ -81,6 +83,13 @@ fn xlayer_chain_value_parser(s: &str) -> eyre::Result<Arc<OpChainSpec>> {
}
Ok(XLAYER_TESTNET.clone())
}
"xlayer-devnet" => {
// Support environment variable override for genesis path
if let Ok(genesis_path) = std::env::var("XLAYER_DEVNET_GENESIS") {
return Ok(Arc::new(parse_genesis(&genesis_path)?.into()));
}
Ok(XLAYER_DEVNET.clone())
}
// For other inputs, try known OP chains first, then parse as genesis
_ => {
// Try to match known OP chains (optimism, base, etc.)
Expand Down Expand Up @@ -110,6 +119,12 @@ mod tests {
assert_eq!(spec.chain().id(), 1952);
}

#[test]
fn test_parse_xlayer_devnet() {
let spec = XLayerChainSpecParser::parse("xlayer-devnet").unwrap();
assert_eq!(spec.chain().id(), 195);
}

#[test]
fn test_parse_optimism() {
let spec = XLayerChainSpecParser::parse("optimism").unwrap();
Expand Down
Loading