espresso_types/v0/impls/
chain_config.rs

1use alloy::primitives::U256;
2use sequencer_utils::{
3    impl_serde_from_string_or_integer, impl_to_fixed_bytes, ser::FromStringOrInteger,
4};
5
6use super::parse_size;
7use crate::{BlockSize, ChainId};
8
9impl_serde_from_string_or_integer!(ChainId);
10impl_to_fixed_bytes!(ChainId, U256);
11
12impl FromStringOrInteger for ChainId {
13    type Binary = ethers_core::types::U256;
14    type Integer = u64;
15
16    fn from_binary(b: Self::Binary) -> anyhow::Result<Self> {
17        Ok(Self(U256::from_limbs(b.0)))
18    }
19
20    fn from_integer(i: Self::Integer) -> anyhow::Result<Self> {
21        Ok(i.into())
22    }
23
24    fn from_string(s: String) -> anyhow::Result<Self> {
25        if let Some(stripped) = s.strip_prefix("0x") {
26            Ok(Self(U256::from_str_radix(stripped, 16)?))
27        } else {
28            Ok(Self(U256::from_str_radix(&s, 10)?))
29        }
30    }
31
32    fn to_binary(&self) -> anyhow::Result<Self::Binary> {
33        Ok(ethers_core::types::U256(self.0.into_limbs()))
34    }
35
36    fn to_string(&self) -> anyhow::Result<String> {
37        Ok(format!("{self}"))
38    }
39}
40
41impl From<u64> for ChainId {
42    fn from(id: u64) -> Self {
43        Self(U256::from(id))
44    }
45}
46
47impl_serde_from_string_or_integer!(BlockSize);
48
49impl FromStringOrInteger for BlockSize {
50    type Binary = u64;
51    type Integer = u64;
52
53    fn from_binary(b: Self::Binary) -> anyhow::Result<Self> {
54        Ok(Self(b))
55    }
56
57    fn from_integer(i: Self::Integer) -> anyhow::Result<Self> {
58        Ok(Self(i))
59    }
60
61    fn from_string(s: String) -> anyhow::Result<Self> {
62        Ok(parse_size(&s)?.into())
63    }
64
65    fn to_binary(&self) -> anyhow::Result<Self::Binary> {
66        Ok(self.0)
67    }
68
69    fn to_string(&self) -> anyhow::Result<String> {
70        Ok(format!("{self}"))
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::v0_99::{ChainConfig, ResolvableChainConfig};
78
79    #[test]
80    fn test_chainid_serde_json_as_decimal() {
81        let id = ChainId::from(123);
82        let serialized = serde_json::to_string(&id).unwrap();
83
84        // The value is serialized as a decimal string.
85        assert_eq!(serialized, "\"123\"");
86
87        // Deserialization produces the original value
88        let deserialized: ChainId = serde_json::from_str(&serialized).unwrap();
89        assert_eq!(deserialized, id);
90    }
91
92    #[test]
93    fn test_chainid_serde_json_from_hex() {
94        // For backwards compatibility, chain ID can also be deserialized from a 0x-prefixed hex
95        // string.
96        let id: ChainId = serde_json::from_str("\"0x123\"").unwrap();
97        assert_eq!(id, ChainId::from(0x123));
98    }
99
100    #[test]
101    fn test_chainid_serde_json_from_number() {
102        // For convenience, chain ID can also be deserialized from a decimal number.
103        let id: ChainId = serde_json::from_str("123").unwrap();
104        assert_eq!(id, ChainId::from(123));
105    }
106
107    #[test]
108    fn test_chainid_serde_bincode_unchanged() {
109        // For non-human-readable formats, ChainId just serializes as the underlying U256.
110        // note: for backward compat, it has to be the same as ethers' U256 instead of alloy's
111        let n = ethers_core::types::U256::from(123);
112        let id = ChainId(U256::from(123));
113        assert_eq!(
114            bincode::serialize(&n).unwrap(),
115            bincode::serialize(&id).unwrap(),
116        );
117    }
118
119    #[test]
120    fn test_block_size_serde_json_as_decimal() {
121        let size = BlockSize::from(123);
122        let serialized = serde_json::to_string(&size).unwrap();
123
124        // The value is serialized as a decimal string.
125        assert_eq!(serialized, "\"123\"");
126
127        // Deserialization produces the original value
128        let deserialized: BlockSize = serde_json::from_str(&serialized).unwrap();
129        assert_eq!(deserialized, size);
130    }
131
132    #[test]
133    fn test_block_size_serde_json_from_number() {
134        // For backwards compatibility, block size can also be deserialized from a decimal number.
135        let size: BlockSize = serde_json::from_str("123").unwrap();
136        assert_eq!(size, BlockSize::from(123));
137    }
138
139    #[test]
140    fn test_block_size_serde_bincode_unchanged() {
141        // For non-human-readable formats, BlockSize just serializes as the underlying u64.
142        let n = 123u64;
143        let size = BlockSize(n);
144        assert_eq!(
145            bincode::serialize(&n).unwrap(),
146            bincode::serialize(&size).unwrap(),
147        );
148    }
149
150    #[test]
151    fn test_chain_config_equality() {
152        let chain_config = ChainConfig::default();
153        assert_eq!(chain_config, chain_config.clone());
154        let ChainConfig {
155            chain_id,
156            max_block_size,
157            ..
158        } = chain_config;
159        let other_config = ChainConfig {
160            chain_id,
161            max_block_size,
162            base_fee: 1.into(),
163            ..Default::default()
164        };
165        assert!(chain_config != other_config);
166    }
167
168    #[test]
169    fn test_resolve_chain_config() {
170        let chain_config = ChainConfig::default();
171        let resolvable: ResolvableChainConfig = chain_config.into();
172        assert_eq!(chain_config, resolvable.resolve().unwrap());
173    }
174}