use crate::{
base_fee_params, AddressList, ChainGenesis, OpBaseFeeParams, RollupConfig,
GRANITE_CHANNEL_TIMEOUT,
};
use alloc::string::String;
use alloy_primitives::Address;
#[derive(Debug, Copy, Clone, Default, Hash, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr))]
#[repr(u8)]
pub enum SuperchainLevel {
Frontier = 0,
#[default]
Standard = 1,
}
#[derive(Debug, Copy, Clone, Default, Hash, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AltDAConfig {
pub da_challenge_address: Option<Address>,
pub da_challenge_window: Option<u64>,
pub da_resolve_window: Option<u64>,
}
#[derive(Debug, Copy, Clone, Default, Hash, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HardForkConfiguration {
pub canyon_time: Option<u64>,
pub delta_time: Option<u64>,
pub ecotone_time: Option<u64>,
pub fjord_time: Option<u64>,
pub granite_time: Option<u64>,
pub holocene_time: Option<u64>,
}
#[derive(Debug, Clone, Default, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ChainConfig {
#[cfg_attr(feature = "serde", serde(rename = "Name", alias = "name"))]
pub name: String,
#[cfg_attr(feature = "serde", serde(rename = "l2_chain_id", alias = "chain_id"))]
pub chain_id: u64,
#[cfg_attr(feature = "serde", serde(skip))]
pub l1_chain_id: u64,
#[cfg_attr(feature = "serde", serde(rename = "PublicRPC", alias = "public_rpc"))]
pub public_rpc: String,
#[cfg_attr(feature = "serde", serde(rename = "SequencerRPC", alias = "sequencer_rpc"))]
pub sequencer_rpc: String,
#[cfg_attr(feature = "serde", serde(rename = "Explorer", alias = "explorer"))]
pub explorer: String,
#[cfg_attr(feature = "serde", serde(rename = "SuperchainLevel", alias = "superchain_level"))]
pub superchain_level: SuperchainLevel,
#[cfg_attr(
feature = "serde",
serde(rename = "StandardChainCandidate", alias = "standard_chain_candidate")
)]
pub standard_chain_candidate: bool,
#[cfg_attr(feature = "serde", serde(rename = "SuperchainTime", alias = "superchain_time"))]
pub superchain_time: Option<u64>,
#[cfg_attr(feature = "serde", serde(rename = "batch_inbox_address"))]
pub batch_inbox_addr: Address,
#[cfg_attr(feature = "serde", serde(rename = "Superchain"))]
pub superchain: String,
#[cfg_attr(feature = "serde", serde(skip))]
pub chain: String,
#[cfg_attr(feature = "serde", serde(flatten))]
pub hardfork_configuration: HardForkConfiguration,
#[cfg_attr(feature = "serde", serde(rename = "block_time"))]
pub block_time: u64,
#[cfg_attr(feature = "serde", serde(rename = "seq_window_size"))]
pub seq_window_size: u64,
#[cfg_attr(feature = "serde", serde(rename = "max_sequencer_drift"))]
pub max_sequencer_drift: u64,
#[cfg_attr(
feature = "serde",
serde(rename = "DataAvailabilityType", alias = "data_availability_type")
)]
pub data_availability_type: String,
#[cfg_attr(feature = "serde", serde(rename = "optimism"))]
pub optimism: Option<OpBaseFeeParams>,
#[cfg_attr(feature = "serde", serde(rename = "alt_da"))]
pub alt_da: Option<AltDAConfig>,
pub genesis: ChainGenesis,
#[cfg_attr(feature = "serde", serde(rename = "Addresses", alias = "addresses"))]
pub addresses: Option<AddressList>,
#[cfg_attr(feature = "serde", serde(rename = "GasPayingToken", alias = "gas_paying_token"))]
pub gas_paying_token: Option<Address>,
}
impl ChainConfig {
pub fn set_missing_fork_configs(&mut self, defaults: &HardForkConfiguration) {
let Some(super_time) = self.superchain_time else {
return;
};
let cfg = &mut self.hardfork_configuration;
if cfg.canyon_time.is_none() && defaults.canyon_time.is_some_and(|t| t > super_time) {
cfg.canyon_time = defaults.canyon_time;
}
if cfg.delta_time.is_none() && defaults.delta_time.is_some_and(|t| t > super_time) {
cfg.delta_time = defaults.delta_time;
}
if cfg.ecotone_time.is_none() && defaults.ecotone_time.is_some_and(|t| t > super_time) {
cfg.ecotone_time = defaults.ecotone_time;
}
if cfg.fjord_time.is_none() && defaults.fjord_time.is_some_and(|t| t > super_time) {
cfg.fjord_time = defaults.fjord_time;
}
if cfg.granite_time.is_none() && defaults.granite_time.is_some_and(|t| t > super_time) {
cfg.granite_time = defaults.granite_time;
}
if cfg.holocene_time.is_none() && defaults.holocene_time.is_some_and(|t| t > super_time) {
cfg.holocene_time = defaults.holocene_time;
}
}
pub fn load_op_stack_rollup_config(&self) -> RollupConfig {
let config = base_fee_params(self.chain_id);
RollupConfig {
genesis: self.genesis,
l1_chain_id: self.l1_chain_id,
l2_chain_id: self.chain_id,
base_fee_params: config.as_base_fee_params(),
block_time: self.block_time,
seq_window_size: self.seq_window_size,
max_sequencer_drift: self.max_sequencer_drift,
canyon_base_fee_params: config.as_canyon_base_fee_params(),
regolith_time: Some(0),
canyon_time: self.hardfork_configuration.canyon_time,
delta_time: self.hardfork_configuration.delta_time,
ecotone_time: self.hardfork_configuration.ecotone_time,
fjord_time: self.hardfork_configuration.fjord_time,
granite_time: self.hardfork_configuration.granite_time,
holocene_time: self.hardfork_configuration.holocene_time,
batch_inbox_address: self.batch_inbox_addr,
deposit_contract_address: self
.addresses
.as_ref()
.map(|a| a.optimism_portal_proxy)
.unwrap_or_default(),
l1_system_config_address: self
.addresses
.as_ref()
.map(|a| a.system_config_proxy)
.unwrap_or_default(),
protocol_versions_address: self
.addresses
.as_ref()
.map(|a| a.address_manager)
.unwrap_or_default(),
superchain_config_address: None,
blobs_enabled_l1_timestamp: None,
da_challenge_address: self
.alt_da
.as_ref()
.and_then(|alt_da| alt_da.da_challenge_address),
channel_timeout: 300,
granite_channel_timeout: GRANITE_CHANNEL_TIMEOUT,
}
}
}