1pub use context_interface::Cfg;
3
4use context_interface::cfg::GasParams;
5use primitives::{eip170, eip3860, eip7825, eip7954, hardfork::SpecId};
6
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Clone, Debug, Eq, PartialEq)]
10#[non_exhaustive]
11pub struct CfgEnv<SPEC = SpecId> {
12 pub spec: SPEC,
19
20 pub gas_params: GasParams,
23
24 pub chain_id: u64,
28
29 pub tx_chain_id_check: bool,
33
34 pub limit_contract_code_size: Option<usize>,
41 pub limit_contract_initcode_size: Option<usize>,
49 pub disable_nonce_check: bool,
51 pub max_blobs_per_tx: Option<u64>,
55 pub blob_base_fee_update_fraction: Option<u64>,
63 pub tx_gas_limit_cap: Option<u64>,
70 #[cfg(feature = "memory_limit")]
78 pub memory_limit: u64,
79 #[cfg(feature = "optional_balance_check")]
85 pub disable_balance_check: bool,
86 #[cfg(feature = "optional_block_gas_limit")]
92 pub disable_block_gas_limit: bool,
93 #[cfg(feature = "optional_eip3541")]
99 pub disable_eip3541: bool,
100 #[cfg(feature = "optional_eip3607")]
106 pub disable_eip3607: bool,
107 #[cfg(feature = "optional_eip7623")]
114 pub disable_eip7623: bool,
115 #[cfg(feature = "optional_no_base_fee")]
121 pub disable_base_fee: bool,
122 #[cfg(feature = "optional_priority_fee_check")]
126 pub disable_priority_fee_check: bool,
127 #[cfg(feature = "optional_fee_charge")]
132 pub disable_fee_charge: bool,
133 pub amsterdam_eip7708_disabled: bool,
137 pub amsterdam_eip7708_delayed_burn_disabled: bool,
147}
148
149impl CfgEnv {
150 pub fn new() -> Self {
152 Self::default()
153 }
154}
155
156impl<SPEC> CfgEnv<SPEC> {
157 pub fn new_with_spec_and_gas_params(spec: SPEC, gas_params: GasParams) -> Self {
159 Self {
160 chain_id: 1,
161 tx_chain_id_check: true,
162 limit_contract_code_size: None,
163 limit_contract_initcode_size: None,
164 spec,
165 disable_nonce_check: false,
166 max_blobs_per_tx: None,
167 tx_gas_limit_cap: None,
168 blob_base_fee_update_fraction: None,
169 gas_params,
170 #[cfg(feature = "memory_limit")]
171 memory_limit: (1 << 32) - 1,
172 #[cfg(feature = "optional_balance_check")]
173 disable_balance_check: false,
174 #[cfg(feature = "optional_block_gas_limit")]
175 disable_block_gas_limit: false,
176 #[cfg(feature = "optional_eip3541")]
177 disable_eip3541: false,
178 #[cfg(feature = "optional_eip3607")]
179 disable_eip3607: false,
180 #[cfg(feature = "optional_eip7623")]
181 disable_eip7623: false,
182 #[cfg(feature = "optional_no_base_fee")]
183 disable_base_fee: false,
184 #[cfg(feature = "optional_priority_fee_check")]
185 disable_priority_fee_check: false,
186 #[cfg(feature = "optional_fee_charge")]
187 disable_fee_charge: false,
188 amsterdam_eip7708_disabled: false,
189 amsterdam_eip7708_delayed_burn_disabled: false,
190 }
191 }
192
193 #[inline]
195 pub fn spec(&self) -> &SPEC {
196 &self.spec
197 }
198
199 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
201 self.chain_id = chain_id;
202 self
203 }
204
205 #[inline]
207 pub fn with_gas_params(mut self, gas_params: GasParams) -> Self {
208 self.set_gas_params(gas_params);
209 self
210 }
211
212 #[inline]
214 pub fn set_spec(&mut self, spec: SPEC) {
215 self.spec = spec;
216 }
217
218 #[inline]
220 pub fn set_gas_params(&mut self, gas_params: GasParams) {
221 self.gas_params = gas_params;
222 }
223
224 pub fn enable_tx_chain_id_check(mut self) -> Self {
226 self.tx_chain_id_check = true;
227 self
228 }
229
230 pub fn disable_tx_chain_id_check(mut self) -> Self {
232 self.tx_chain_id_check = false;
233 self
234 }
235
236 #[inline]
238 #[deprecated(
239 since = "0.1.0",
240 note = "Use [`CfgEnv::with_spec_and_mainnet_gas_params`] instead"
241 )]
242 pub fn with_spec(mut self, spec: SPEC) -> Self {
243 self.spec = spec;
244 self
245 }
246
247 pub fn with_spec_and_mainnet_gas_params<OSPEC: Into<SpecId> + Clone>(
249 self,
250 spec: OSPEC,
251 ) -> CfgEnv<OSPEC> {
252 self.with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
253 }
254
255 pub fn with_spec_and_gas_params<OSPEC: Into<SpecId> + Clone>(
259 self,
260 spec: OSPEC,
261 gas_params: GasParams,
262 ) -> CfgEnv<OSPEC> {
263 CfgEnv {
264 chain_id: self.chain_id,
265 tx_chain_id_check: self.tx_chain_id_check,
266 limit_contract_code_size: self.limit_contract_code_size,
267 limit_contract_initcode_size: self.limit_contract_initcode_size,
268 spec,
269 disable_nonce_check: self.disable_nonce_check,
270 tx_gas_limit_cap: self.tx_gas_limit_cap,
271 max_blobs_per_tx: self.max_blobs_per_tx,
272 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
273 gas_params,
274 #[cfg(feature = "memory_limit")]
275 memory_limit: self.memory_limit,
276 #[cfg(feature = "optional_balance_check")]
277 disable_balance_check: self.disable_balance_check,
278 #[cfg(feature = "optional_block_gas_limit")]
279 disable_block_gas_limit: self.disable_block_gas_limit,
280 #[cfg(feature = "optional_eip3541")]
281 disable_eip3541: self.disable_eip3541,
282 #[cfg(feature = "optional_eip3607")]
283 disable_eip3607: self.disable_eip3607,
284 #[cfg(feature = "optional_eip7623")]
285 disable_eip7623: self.disable_eip7623,
286 #[cfg(feature = "optional_no_base_fee")]
287 disable_base_fee: self.disable_base_fee,
288 #[cfg(feature = "optional_priority_fee_check")]
289 disable_priority_fee_check: self.disable_priority_fee_check,
290 #[cfg(feature = "optional_fee_charge")]
291 disable_fee_charge: self.disable_fee_charge,
292 amsterdam_eip7708_disabled: self.amsterdam_eip7708_disabled,
293 amsterdam_eip7708_delayed_burn_disabled: self.amsterdam_eip7708_delayed_burn_disabled,
294 }
295 }
296
297 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
299 self.set_max_blobs_per_tx(max_blobs_per_tx);
300 self
301 }
302
303 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
305 self.max_blobs_per_tx = Some(max_blobs_per_tx);
306 }
307
308 pub fn clear_max_blobs_per_tx(&mut self) {
310 self.max_blobs_per_tx = None;
311 }
312
313 #[cfg(feature = "optional_priority_fee_check")]
315 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
316 self.disable_priority_fee_check = disable;
317 self
318 }
319
320 #[cfg(feature = "optional_fee_charge")]
322 pub fn with_disable_fee_charge(mut self, disable: bool) -> Self {
323 self.disable_fee_charge = disable;
324 self
325 }
326
327 #[cfg(feature = "optional_eip7623")]
329 pub fn with_disable_eip7623(mut self, disable: bool) -> Self {
330 self.disable_eip7623 = disable;
331 self
332 }
333}
334
335impl<SPEC: Into<SpecId> + Clone> CfgEnv<SPEC> {
336 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
343 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
344 let spec: SpecId = self.spec.clone().into();
345 if spec.is_enabled_in(SpecId::PRAGUE) {
346 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
347 } else {
348 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
349 }
350 })
351 }
352
353 pub fn new_with_spec(spec: SPEC) -> Self {
358 Self::new_with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
359 }
360
361 pub fn with_mainnet_gas_params(mut self) -> Self {
365 self.set_gas_params(GasParams::new_spec(self.spec.clone().into()));
366 self
367 }
368
369 #[inline]
371 pub fn set_spec_and_mainnet_gas_params(&mut self, spec: SPEC) {
372 self.set_spec(spec.clone());
373 self.set_gas_params(GasParams::new_spec(spec.into()));
374 }
375}
376
377impl<SPEC: Into<SpecId> + Clone> Cfg for CfgEnv<SPEC> {
378 type Spec = SPEC;
379
380 #[inline]
381 fn chain_id(&self) -> u64 {
382 self.chain_id
383 }
384
385 #[inline]
386 fn spec(&self) -> Self::Spec {
387 self.spec.clone()
388 }
389
390 #[inline]
391 fn tx_chain_id_check(&self) -> bool {
392 self.tx_chain_id_check
393 }
394
395 #[inline]
396 fn tx_gas_limit_cap(&self) -> u64 {
397 self.tx_gas_limit_cap
398 .unwrap_or(if self.spec.clone().into().is_enabled_in(SpecId::OSAKA) {
399 eip7825::TX_GAS_LIMIT_CAP
400 } else {
401 u64::MAX
402 })
403 }
404
405 #[inline]
406 fn max_blobs_per_tx(&self) -> Option<u64> {
407 self.max_blobs_per_tx
408 }
409
410 fn max_code_size(&self) -> usize {
411 self.limit_contract_code_size.unwrap_or(
412 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
413 eip7954::MAX_CODE_SIZE
414 } else {
415 eip170::MAX_CODE_SIZE
416 },
417 )
418 }
419
420 fn max_initcode_size(&self) -> usize {
421 self.limit_contract_initcode_size
422 .or_else(|| {
423 self.limit_contract_code_size
424 .map(|size| size.saturating_mul(2))
425 })
426 .unwrap_or(
427 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
428 eip7954::MAX_INITCODE_SIZE
429 } else {
430 eip3860::MAX_INITCODE_SIZE
431 },
432 )
433 }
434
435 fn is_eip3541_disabled(&self) -> bool {
436 cfg_if::cfg_if! {
437 if #[cfg(feature = "optional_eip3541")] {
438 self.disable_eip3541
439 } else {
440 false
441 }
442 }
443 }
444
445 fn is_eip3607_disabled(&self) -> bool {
446 cfg_if::cfg_if! {
447 if #[cfg(feature = "optional_eip3607")] {
448 self.disable_eip3607
449 } else {
450 false
451 }
452 }
453 }
454
455 fn is_eip7623_disabled(&self) -> bool {
456 cfg_if::cfg_if! {
457 if #[cfg(feature = "optional_eip7623")] {
458 self.disable_eip7623
459 } else {
460 false
461 }
462 }
463 }
464
465 fn is_balance_check_disabled(&self) -> bool {
466 cfg_if::cfg_if! {
467 if #[cfg(feature = "optional_balance_check")] {
468 self.disable_balance_check
469 } else {
470 false
471 }
472 }
473 }
474
475 fn is_block_gas_limit_disabled(&self) -> bool {
477 cfg_if::cfg_if! {
478 if #[cfg(feature = "optional_block_gas_limit")] {
479 self.disable_block_gas_limit
480 } else {
481 false
482 }
483 }
484 }
485
486 fn is_nonce_check_disabled(&self) -> bool {
487 self.disable_nonce_check
488 }
489
490 fn is_base_fee_check_disabled(&self) -> bool {
491 cfg_if::cfg_if! {
492 if #[cfg(feature = "optional_no_base_fee")] {
493 self.disable_base_fee
494 } else {
495 false
496 }
497 }
498 }
499
500 fn is_priority_fee_check_disabled(&self) -> bool {
501 cfg_if::cfg_if! {
502 if #[cfg(feature = "optional_priority_fee_check")] {
503 self.disable_priority_fee_check
504 } else {
505 false
506 }
507 }
508 }
509
510 fn is_fee_charge_disabled(&self) -> bool {
511 cfg_if::cfg_if! {
512 if #[cfg(feature = "optional_fee_charge")] {
513 self.disable_fee_charge
514 } else {
515 false
516 }
517 }
518 }
519
520 fn is_eip7708_disabled(&self) -> bool {
521 self.amsterdam_eip7708_disabled
522 }
523
524 fn is_eip7708_delayed_burn_disabled(&self) -> bool {
525 self.amsterdam_eip7708_delayed_burn_disabled
526 }
527
528 fn memory_limit(&self) -> u64 {
529 cfg_if::cfg_if! {
530 if #[cfg(feature = "memory_limit")] {
531 self.memory_limit
532 } else {
533 u64::MAX
534 }
535 }
536 }
537
538 #[inline]
539 fn gas_params(&self) -> &GasParams {
540 &self.gas_params
541 }
542}
543
544impl<SPEC: Default + Into<SpecId>> Default for CfgEnv<SPEC> {
545 fn default() -> Self {
546 Self::new_with_spec_and_gas_params(
547 SPEC::default(),
548 GasParams::new_spec(SPEC::default().into()),
549 )
550 }
551}
552
553#[cfg(test)]
554mod test {
555 use super::*;
556
557 #[test]
558 fn blob_max_and_target_count() {
559 let cfg: CfgEnv = Default::default();
560 assert_eq!(cfg.max_blobs_per_tx(), None);
561 }
562}