kona_genesis/system/
log.rs

1//! Contains the [`SystemConfigLog`].
2
3use alloy_primitives::Log;
4
5use crate::{
6    BatcherUpdate, CONFIG_UPDATE_EVENT_VERSION_0, CONFIG_UPDATE_TOPIC, Eip1559Update,
7    GasConfigUpdate, GasLimitUpdate, LogProcessingError, OperatorFeeUpdate, SystemConfigUpdate,
8    SystemConfigUpdateError, SystemConfigUpdateKind,
9};
10
11/// The system config log is an EVM log entry emitted
12/// by the system contract to update the system config.
13///
14/// The log data is formatted as follows:
15/// ```text
16/// event ConfigUpdate(
17///    uint256 indexed version,
18///    UpdateType indexed updateType,
19///    bytes data
20/// );
21/// ```
22#[derive(Debug, Clone, Hash, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct SystemConfigLog {
25    /// The log.
26    pub log: Log,
27    /// Whether ecotone is active.
28    pub ecotone_active: bool,
29}
30
31impl SystemConfigLog {
32    /// Constructs a new system config update.
33    pub const fn new(log: Log, ecotone_active: bool) -> Self {
34        Self { log, ecotone_active }
35    }
36
37    /// Validate the log topic.
38    pub fn validate_topic(&self) -> Result<(), LogProcessingError> {
39        if self.log.topics().len() < 3 {
40            return Err(LogProcessingError::InvalidTopicLen(self.log.topics().len()));
41        }
42        if self.log.topics()[0] != CONFIG_UPDATE_TOPIC {
43            return Err(LogProcessingError::InvalidTopic);
44        }
45        Ok(())
46    }
47
48    /// Validate the config update version.
49    pub fn validate_version(&self) -> Result<(), LogProcessingError> {
50        let version = self.log.topics()[1];
51        if version != CONFIG_UPDATE_EVENT_VERSION_0 {
52            return Err(LogProcessingError::UnsupportedVersion(version));
53        }
54        Ok(())
55    }
56
57    /// Extracts the update type from the log.
58    pub fn update_type(&self) -> Result<SystemConfigUpdateKind, SystemConfigUpdateError> {
59        if self.log.topics().len() < 3 {
60            return Err(LogProcessingError::InvalidTopicLen(self.log.topics().len()).into());
61        }
62        let topic = self.log.topics()[2];
63        let topic_bytes = <&[u8; 8]>::try_from(&topic.as_slice()[24..])
64            .map_err(|_| LogProcessingError::UpdateTypeDecodingError)?;
65        let ty = u64::from_be_bytes(*topic_bytes);
66        ty.try_into()
67    }
68
69    /// Builds the [`SystemConfigUpdate`] from the log.
70    pub fn build(&self) -> Result<SystemConfigUpdate, SystemConfigUpdateError> {
71        self.validate_topic()?;
72        self.validate_version()?;
73        match self.update_type()? {
74            SystemConfigUpdateKind::Batcher => {
75                let update = BatcherUpdate::try_from(self)?;
76                Ok(SystemConfigUpdate::Batcher(update))
77            }
78            SystemConfigUpdateKind::GasConfig => {
79                let update = GasConfigUpdate::try_from(self)?;
80                Ok(SystemConfigUpdate::GasConfig(update))
81            }
82            SystemConfigUpdateKind::GasLimit => {
83                let update = GasLimitUpdate::try_from(self)?;
84                Ok(SystemConfigUpdate::GasLimit(update))
85            }
86            SystemConfigUpdateKind::Eip1559 => {
87                let update = Eip1559Update::try_from(self)?;
88                Ok(SystemConfigUpdate::Eip1559(update))
89            }
90            SystemConfigUpdateKind::OperatorFee => {
91                let update = OperatorFeeUpdate::try_from(self)?;
92                Ok(SystemConfigUpdate::OperatorFee(update))
93            }
94            SystemConfigUpdateKind::UnsafeBlockSigner => Ok(SystemConfigUpdate::UnsafeBlockSigner),
95        }
96    }
97}