kona_genesis/updates/
batcher.rs1use alloy_primitives::{Address, LogData};
4use alloy_sol_types::{SolType, sol};
5
6use crate::{BatcherUpdateError, SystemConfig, SystemConfigLog};
7
8#[derive(Debug, Clone, Hash, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct BatcherUpdate {
12 pub batcher_address: Address,
14}
15
16impl BatcherUpdate {
17 pub const fn apply(&self, config: &mut SystemConfig) {
19 config.batcher_address = self.batcher_address;
20 }
21}
22
23impl TryFrom<&SystemConfigLog> for BatcherUpdate {
24 type Error = BatcherUpdateError;
25
26 fn try_from(log: &SystemConfigLog) -> Result<Self, Self::Error> {
27 let LogData { data, .. } = &log.log.data;
28 if data.len() != 96 {
29 return Err(BatcherUpdateError::InvalidDataLen(data.len()));
30 }
31
32 let Ok(pointer) = <sol!(uint64)>::abi_decode_validate(&data[0..32]) else {
33 return Err(BatcherUpdateError::PointerDecodingError);
34 };
35 if pointer != 32 {
36 return Err(BatcherUpdateError::InvalidDataPointer(pointer));
37 }
38
39 let Ok(length) = <sol!(uint64)>::abi_decode_validate(&data[32..64]) else {
40 return Err(BatcherUpdateError::LengthDecodingError);
41 };
42 if length != 32 {
43 return Err(BatcherUpdateError::InvalidDataLength(length));
44 }
45
46 let Ok(batcher_address) = <sol!(address)>::abi_decode_validate(&data[64..96]) else {
47 return Err(BatcherUpdateError::BatcherAddressDecodingError);
48 };
49
50 Ok(Self { batcher_address })
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::{CONFIG_UPDATE_EVENT_VERSION_0, CONFIG_UPDATE_TOPIC};
58 use alloc::vec;
59 use alloy_primitives::{B256, Bytes, Log, LogData, address, hex};
60
61 #[test]
62 fn test_batcher_update_try_from() {
63 let update_type = B256::ZERO;
64
65 let log = Log {
66 address: Address::ZERO,
67 data: LogData::new_unchecked(
68 vec![
69 CONFIG_UPDATE_TOPIC,
70 CONFIG_UPDATE_EVENT_VERSION_0,
71 update_type,
72 ],
73 hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000beef").into()
74 )
75 };
76
77 let system_log = SystemConfigLog::new(log, false);
78 let update = BatcherUpdate::try_from(&system_log).unwrap();
79 assert_eq!(update.batcher_address, address!("000000000000000000000000000000000000bEEF"),);
80 }
81
82 #[test]
83 fn test_batcher_update_invalid_data_len() {
84 let log =
85 Log { address: Address::ZERO, data: LogData::new_unchecked(vec![], Bytes::default()) };
86 let system_log = SystemConfigLog::new(log, false);
87 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
88 assert_eq!(err, BatcherUpdateError::InvalidDataLen(0));
89 }
90
91 #[test]
92 fn test_batcher_update_pointer_decoding_error() {
93 let log = Log {
94 address: Address::ZERO,
95 data: LogData::new_unchecked(
96 vec![
97 CONFIG_UPDATE_TOPIC,
98 CONFIG_UPDATE_EVENT_VERSION_0,
99 B256::ZERO,
100 ],
101 hex!("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000babe0000beef").into()
102 )
103 };
104
105 let system_log = SystemConfigLog::new(log, false);
106 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
107 assert_eq!(err, BatcherUpdateError::PointerDecodingError);
108 }
109
110 #[test]
111 fn test_batcher_update_invalid_pointer_length() {
112 let log = Log {
113 address: Address::ZERO,
114 data: LogData::new_unchecked(
115 vec![
116 CONFIG_UPDATE_TOPIC,
117 CONFIG_UPDATE_EVENT_VERSION_0,
118 B256::ZERO,
119 ],
120 hex!("000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000babe0000beef").into()
121 )
122 };
123
124 let system_log = SystemConfigLog::new(log, false);
125 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
126 assert_eq!(err, BatcherUpdateError::InvalidDataPointer(33));
127 }
128
129 #[test]
130 fn test_batcher_update_length_decoding_error() {
131 let log = Log {
132 address: Address::ZERO,
133 data: LogData::new_unchecked(
134 vec![
135 CONFIG_UPDATE_TOPIC,
136 CONFIG_UPDATE_EVENT_VERSION_0,
137 B256::ZERO,
138 ],
139 hex!("0000000000000000000000000000000000000000000000000000000000000020FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000babe0000beef").into()
140 )
141 };
142
143 let system_log = SystemConfigLog::new(log, false);
144 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
145 assert_eq!(err, BatcherUpdateError::LengthDecodingError);
146 }
147
148 #[test]
149 fn test_batcher_update_invalid_data_length() {
150 let log = Log {
151 address: Address::ZERO,
152 data: LogData::new_unchecked(
153 vec![
154 CONFIG_UPDATE_TOPIC,
155 CONFIG_UPDATE_EVENT_VERSION_0,
156 B256::ZERO,
157 ],
158 hex!("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000babe0000beef").into()
159 )
160 };
161
162 let system_log = SystemConfigLog::new(log, false);
163 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
164 assert_eq!(err, BatcherUpdateError::InvalidDataLength(33));
165 }
166
167 #[test]
168 fn test_batcher_update_batcher_decoding_error() {
169 let log = Log {
170 address: Address::ZERO,
171 data: LogData::new_unchecked(
172 vec![
173 CONFIG_UPDATE_TOPIC,
174 CONFIG_UPDATE_EVENT_VERSION_0,
175 B256::ZERO,
176 ],
177 hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").into()
178 )
179 };
180
181 let system_log = SystemConfigLog::new(log, false);
182 let err = BatcherUpdate::try_from(&system_log).unwrap_err();
183 assert_eq!(err, BatcherUpdateError::BatcherAddressDecodingError);
184 }
185}