1pub use context_interface::Cfg;
3
4use primitives::{eip170, eip3860, eip7825, hardfork::SpecId};
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[derive(Clone, Debug, Eq, PartialEq)]
8#[non_exhaustive]
9pub struct CfgEnv<SPEC = SpecId> {
10 pub chain_id: u64,
14
15 pub tx_chain_id_check: bool,
19
20 pub spec: SPEC,
22 pub limit_contract_code_size: Option<usize>,
29 pub limit_contract_initcode_size: Option<usize>,
37 pub disable_nonce_check: bool,
39 pub max_blobs_per_tx: Option<u64>,
43 pub blob_base_fee_update_fraction: Option<u64>,
51 pub tx_gas_limit_cap: Option<u64>,
58 #[cfg(feature = "memory_limit")]
66 pub memory_limit: u64,
67 #[cfg(feature = "optional_balance_check")]
73 pub disable_balance_check: bool,
74 #[cfg(feature = "optional_block_gas_limit")]
80 pub disable_block_gas_limit: bool,
81 #[cfg(feature = "optional_eip3541")]
87 pub disable_eip3541: bool,
88 #[cfg(feature = "optional_eip3607")]
94 pub disable_eip3607: bool,
95 #[cfg(feature = "optional_no_base_fee")]
101 pub disable_base_fee: bool,
102 #[cfg(feature = "optional_priority_fee_check")]
106 pub disable_priority_fee_check: bool,
107}
108
109impl CfgEnv {
110 pub fn new() -> Self {
112 Self::default()
113 }
114}
115
116impl<SPEC: Into<SpecId> + Copy> CfgEnv<SPEC> {
117 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
124 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
125 let spec: SpecId = self.spec.into();
126 if spec.is_enabled_in(SpecId::PRAGUE) {
127 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
128 } else {
129 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
130 }
131 })
132 }
133}
134
135impl<SPEC> CfgEnv<SPEC> {
136 pub fn new_with_spec(spec: SPEC) -> Self {
138 Self {
139 chain_id: 1,
140 tx_chain_id_check: false,
141 limit_contract_code_size: None,
142 limit_contract_initcode_size: None,
143 spec,
144 disable_nonce_check: false,
145 max_blobs_per_tx: None,
146 tx_gas_limit_cap: None,
147 blob_base_fee_update_fraction: None,
148 #[cfg(feature = "memory_limit")]
149 memory_limit: (1 << 32) - 1,
150 #[cfg(feature = "optional_balance_check")]
151 disable_balance_check: false,
152 #[cfg(feature = "optional_block_gas_limit")]
153 disable_block_gas_limit: false,
154 #[cfg(feature = "optional_eip3541")]
155 disable_eip3541: false,
156 #[cfg(feature = "optional_eip3607")]
157 disable_eip3607: false,
158 #[cfg(feature = "optional_no_base_fee")]
159 disable_base_fee: false,
160 #[cfg(feature = "optional_priority_fee_check")]
161 disable_priority_fee_check: false,
162 }
163 }
164
165 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
167 self.chain_id = chain_id;
168 self
169 }
170
171 pub fn enable_tx_chain_id_check(mut self) -> Self {
173 self.tx_chain_id_check = true;
174 self
175 }
176
177 pub fn disable_tx_chain_id_check(mut self) -> Self {
179 self.tx_chain_id_check = false;
180 self
181 }
182
183 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
185 CfgEnv {
186 chain_id: self.chain_id,
187 tx_chain_id_check: self.tx_chain_id_check,
188 limit_contract_code_size: self.limit_contract_code_size,
189 limit_contract_initcode_size: self.limit_contract_initcode_size,
190 spec,
191 disable_nonce_check: self.disable_nonce_check,
192 tx_gas_limit_cap: self.tx_gas_limit_cap,
193 max_blobs_per_tx: self.max_blobs_per_tx,
194 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
195 #[cfg(feature = "memory_limit")]
196 memory_limit: self.memory_limit,
197 #[cfg(feature = "optional_balance_check")]
198 disable_balance_check: self.disable_balance_check,
199 #[cfg(feature = "optional_block_gas_limit")]
200 disable_block_gas_limit: self.disable_block_gas_limit,
201 #[cfg(feature = "optional_eip3541")]
202 disable_eip3541: self.disable_eip3541,
203 #[cfg(feature = "optional_eip3607")]
204 disable_eip3607: self.disable_eip3607,
205 #[cfg(feature = "optional_no_base_fee")]
206 disable_base_fee: self.disable_base_fee,
207 #[cfg(feature = "optional_priority_fee_check")]
208 disable_priority_fee_check: self.disable_priority_fee_check,
209 }
210 }
211
212 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
214 self.set_max_blobs_per_tx(max_blobs_per_tx);
215 self
216 }
217
218 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
220 self.max_blobs_per_tx = Some(max_blobs_per_tx);
221 }
222
223 pub fn clear_max_blobs_per_tx(&mut self) {
225 self.max_blobs_per_tx = None;
226 }
227
228 #[cfg(feature = "optional_priority_fee_check")]
230 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
231 self.disable_priority_fee_check = disable;
232 self
233 }
234}
235
236impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
237 type Spec = SPEC;
238
239 #[inline]
240 fn chain_id(&self) -> u64 {
241 self.chain_id
242 }
243
244 #[inline]
245 fn spec(&self) -> Self::Spec {
246 self.spec
247 }
248
249 #[inline]
250 fn tx_chain_id_check(&self) -> bool {
251 self.tx_chain_id_check
252 }
253
254 #[inline]
255 fn tx_gas_limit_cap(&self) -> u64 {
256 self.tx_gas_limit_cap
257 .unwrap_or(if self.spec.into().is_enabled_in(SpecId::OSAKA) {
258 eip7825::TX_GAS_LIMIT_CAP
259 } else {
260 u64::MAX
261 })
262 }
263
264 #[inline]
265 fn max_blobs_per_tx(&self) -> Option<u64> {
266 self.max_blobs_per_tx
267 }
268
269 fn max_code_size(&self) -> usize {
270 self.limit_contract_code_size
271 .unwrap_or(eip170::MAX_CODE_SIZE)
272 }
273
274 fn max_initcode_size(&self) -> usize {
275 self.limit_contract_initcode_size
276 .or_else(|| {
277 self.limit_contract_code_size
278 .map(|size| size.saturating_mul(2))
279 })
280 .unwrap_or(eip3860::MAX_INITCODE_SIZE)
281 }
282
283 fn is_eip3541_disabled(&self) -> bool {
284 cfg_if::cfg_if! {
285 if #[cfg(feature = "optional_eip3541")] {
286 self.disable_eip3541
287 } else {
288 false
289 }
290 }
291 }
292
293 fn is_eip3607_disabled(&self) -> bool {
294 cfg_if::cfg_if! {
295 if #[cfg(feature = "optional_eip3607")] {
296 self.disable_eip3607
297 } else {
298 false
299 }
300 }
301 }
302
303 fn is_balance_check_disabled(&self) -> bool {
304 cfg_if::cfg_if! {
305 if #[cfg(feature = "optional_balance_check")] {
306 self.disable_balance_check
307 } else {
308 false
309 }
310 }
311 }
312
313 fn is_block_gas_limit_disabled(&self) -> bool {
315 cfg_if::cfg_if! {
316 if #[cfg(feature = "optional_block_gas_limit")] {
317 self.disable_block_gas_limit
318 } else {
319 false
320 }
321 }
322 }
323
324 fn is_nonce_check_disabled(&self) -> bool {
325 self.disable_nonce_check
326 }
327
328 fn is_base_fee_check_disabled(&self) -> bool {
329 cfg_if::cfg_if! {
330 if #[cfg(feature = "optional_no_base_fee")] {
331 self.disable_base_fee
332 } else {
333 false
334 }
335 }
336 }
337
338 fn is_priority_fee_check_disabled(&self) -> bool {
339 cfg_if::cfg_if! {
340 if #[cfg(feature = "optional_priority_fee_check")] {
341 self.disable_priority_fee_check
342 } else {
343 false
344 }
345 }
346 }
347}
348
349impl<SPEC: Default> Default for CfgEnv<SPEC> {
350 fn default() -> Self {
351 Self::new_with_spec(SPEC::default())
352 }
353}
354
355#[cfg(test)]
356mod test {
357 use super::*;
358
359 #[test]
360 fn blob_max_and_target_count() {
361 let cfg: CfgEnv = Default::default();
362 assert_eq!(cfg.max_blobs_per_tx(), None);
363 }
364}