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 enable_amsterdam_eip8037: bool,
142 pub enable_amsterdam_eip8024: bool,
147 pub enable_amsterdam_eip2780: bool,
156 pub amsterdam_eip7708_disabled: bool,
160 pub amsterdam_eip8246_delayed_clear_disabled: bool,
173}
174
175impl CfgEnv {
176 pub fn new() -> Self {
178 Self::default()
179 }
180}
181
182impl<SPEC> CfgEnv<SPEC> {
183 #[inline]
185 pub const fn spec(&self) -> &SPEC {
186 &self.spec
187 }
188
189 pub const fn with_chain_id(mut self, chain_id: u64) -> Self {
191 self.chain_id = chain_id;
192 self
193 }
194
195 #[inline]
197 pub fn with_gas_params(mut self, gas_params: GasParams) -> Self {
198 self.set_gas_params(gas_params);
199 self
200 }
201
202 #[inline]
204 #[deprecated(note = "Use [`CfgEnv::set_spec_and_mainnet_gas_params`] instead")]
205 pub fn set_spec(&mut self, spec: SPEC) {
206 self.spec = spec;
207 }
208
209 #[inline]
211 pub fn set_gas_params(&mut self, gas_params: GasParams) {
212 self.gas_params = gas_params;
213 }
214
215 pub const fn enable_tx_chain_id_check(mut self) -> Self {
217 self.tx_chain_id_check = true;
218 self
219 }
220
221 pub const fn disable_tx_chain_id_check(mut self) -> Self {
223 self.tx_chain_id_check = false;
224 self
225 }
226
227 #[inline]
229 #[deprecated(note = "Use [`CfgEnv::with_spec_and_mainnet_gas_params`] instead")]
230 pub fn with_spec(mut self, spec: SPEC) -> Self {
231 self.spec = spec;
232 self
233 }
234
235 pub fn with_spec_and_mainnet_gas_params<OSPEC: Into<SpecId> + Clone>(
239 self,
240 spec: OSPEC,
241 ) -> CfgEnv<OSPEC> {
242 let is_amsterdam = spec.clone().into().is_enabled_in(SpecId::AMSTERDAM);
243 let enable_amsterdam_eip8037 = self.enable_amsterdam_eip8037 || is_amsterdam;
244 let enable_amsterdam_eip2780 = self.enable_amsterdam_eip2780 || is_amsterdam;
245 let enable_amsterdam_eip8024 = self.enable_amsterdam_eip8024 || is_amsterdam;
246 let mut cfg = self.with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()));
247 cfg.enable_amsterdam_eip8037 = enable_amsterdam_eip8037;
248 cfg.enable_amsterdam_eip2780 = enable_amsterdam_eip2780;
249 cfg.enable_amsterdam_eip8024 = enable_amsterdam_eip8024;
250 cfg
251 }
252
253 pub fn with_spec_and_gas_params<OSPEC: Into<SpecId> + Clone>(
257 self,
258 spec: OSPEC,
259 gas_params: GasParams,
260 ) -> CfgEnv<OSPEC> {
261 CfgEnv {
262 chain_id: self.chain_id,
263 tx_chain_id_check: self.tx_chain_id_check,
264 limit_contract_code_size: self.limit_contract_code_size,
265 limit_contract_initcode_size: self.limit_contract_initcode_size,
266 spec,
267 disable_nonce_check: self.disable_nonce_check,
268 tx_gas_limit_cap: self.tx_gas_limit_cap,
269 max_blobs_per_tx: self.max_blobs_per_tx,
270 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
271 gas_params,
272 #[cfg(feature = "memory_limit")]
273 memory_limit: self.memory_limit,
274 #[cfg(feature = "optional_balance_check")]
275 disable_balance_check: self.disable_balance_check,
276 #[cfg(feature = "optional_block_gas_limit")]
277 disable_block_gas_limit: self.disable_block_gas_limit,
278 #[cfg(feature = "optional_eip3541")]
279 disable_eip3541: self.disable_eip3541,
280 #[cfg(feature = "optional_eip3607")]
281 disable_eip3607: self.disable_eip3607,
282 #[cfg(feature = "optional_eip7623")]
283 disable_eip7623: self.disable_eip7623,
284 #[cfg(feature = "optional_no_base_fee")]
285 disable_base_fee: self.disable_base_fee,
286 #[cfg(feature = "optional_priority_fee_check")]
287 disable_priority_fee_check: self.disable_priority_fee_check,
288 #[cfg(feature = "optional_fee_charge")]
289 disable_fee_charge: self.disable_fee_charge,
290 enable_amsterdam_eip8037: self.enable_amsterdam_eip8037,
291 enable_amsterdam_eip2780: self.enable_amsterdam_eip2780,
292 enable_amsterdam_eip8024: self.enable_amsterdam_eip8024,
293 amsterdam_eip7708_disabled: self.amsterdam_eip7708_disabled,
294 amsterdam_eip8246_delayed_clear_disabled: self.amsterdam_eip8246_delayed_clear_disabled,
295 }
296 }
297
298 pub const fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
300 self.set_max_blobs_per_tx(max_blobs_per_tx);
301 self
302 }
303
304 pub const fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
306 self.max_blobs_per_tx = Some(max_blobs_per_tx);
307 }
308
309 pub const fn clear_max_blobs_per_tx(&mut self) {
311 self.max_blobs_per_tx = None;
312 }
313
314 #[cfg(feature = "optional_priority_fee_check")]
316 pub const fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
317 self.disable_priority_fee_check = disable;
318 self
319 }
320
321 #[cfg(feature = "optional_fee_charge")]
323 pub const fn with_disable_fee_charge(mut self, disable: bool) -> Self {
324 self.disable_fee_charge = disable;
325 self
326 }
327
328 #[cfg(feature = "optional_eip7623")]
330 pub const fn with_disable_eip7623(mut self, disable: bool) -> Self {
331 self.disable_eip7623 = disable;
332 self
333 }
334
335 pub const fn with_enable_amsterdam_eip8037(mut self, enable: bool) -> Self {
337 self.enable_amsterdam_eip8037 = enable;
338 self
339 }
340
341 pub const fn with_enable_amsterdam_eip8024(mut self, enable: bool) -> Self {
343 self.enable_amsterdam_eip8024 = enable;
344 self
345 }
346
347 pub const fn with_enable_amsterdam_eip2780(mut self, enable: bool) -> Self {
350 self.enable_amsterdam_eip2780 = enable;
351 self
352 }
353}
354
355impl<SPEC: Into<SpecId> + Clone> CfgEnv<SPEC> {
356 pub fn new_with_spec_and_gas_params(spec: SPEC, gas_params: GasParams) -> Self {
358 let is_amsterdam = spec.clone().into().is_enabled_in(SpecId::AMSTERDAM);
359 Self {
360 chain_id: 1,
361 tx_chain_id_check: true,
362 limit_contract_code_size: None,
363 limit_contract_initcode_size: None,
364 spec,
365 disable_nonce_check: false,
366 max_blobs_per_tx: None,
367 tx_gas_limit_cap: None,
368 blob_base_fee_update_fraction: None,
369 gas_params,
370 #[cfg(feature = "memory_limit")]
371 memory_limit: (1 << 32) - 1,
372 #[cfg(feature = "optional_balance_check")]
373 disable_balance_check: false,
374 #[cfg(feature = "optional_block_gas_limit")]
375 disable_block_gas_limit: false,
376 #[cfg(feature = "optional_eip3541")]
377 disable_eip3541: false,
378 #[cfg(feature = "optional_eip3607")]
379 disable_eip3607: false,
380 #[cfg(feature = "optional_eip7623")]
381 disable_eip7623: false,
382 #[cfg(feature = "optional_no_base_fee")]
383 disable_base_fee: false,
384 #[cfg(feature = "optional_priority_fee_check")]
385 disable_priority_fee_check: false,
386 #[cfg(feature = "optional_fee_charge")]
387 disable_fee_charge: false,
388 enable_amsterdam_eip8037: is_amsterdam,
389 enable_amsterdam_eip2780: is_amsterdam,
390 enable_amsterdam_eip8024: is_amsterdam,
391 amsterdam_eip7708_disabled: false,
392 amsterdam_eip8246_delayed_clear_disabled: false,
393 }
394 }
395
396 pub fn blob_base_fee_update_fraction(&self) -> u64 {
403 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
404 let spec: SpecId = self.spec.clone().into();
405 if spec.is_enabled_in(SpecId::PRAGUE) {
406 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
407 } else {
408 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
409 }
410 })
411 }
412
413 pub fn new_with_spec(spec: SPEC) -> Self {
418 Self::new_with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
419 }
420
421 pub fn with_mainnet_gas_params(mut self) -> Self {
425 self.set_gas_params(GasParams::new_spec(self.spec.clone().into()));
426 self
427 }
428
429 #[inline]
433 pub fn set_spec_and_mainnet_gas_params(&mut self, spec: SPEC) {
434 self.spec = spec.clone();
435 self.set_gas_params(GasParams::new_spec(spec.clone().into()));
436 if spec.into().is_enabled_in(SpecId::AMSTERDAM) {
438 self.enable_amsterdam_eip8037 = true;
439 self.enable_amsterdam_eip2780 = true;
440 self.enable_amsterdam_eip8024 = true;
441 }
442 }
443}
444
445impl<SPEC: Into<SpecId> + Clone> Cfg for CfgEnv<SPEC> {
446 type Spec = SPEC;
447
448 #[inline]
449 fn chain_id(&self) -> u64 {
450 self.chain_id
451 }
452
453 #[inline]
454 fn spec(&self) -> Self::Spec {
455 self.spec.clone()
456 }
457
458 #[inline]
459 fn tx_chain_id_check(&self) -> bool {
460 self.tx_chain_id_check
461 }
462
463 #[inline]
464 fn tx_gas_limit_cap(&self) -> u64 {
465 self.tx_gas_limit_cap
466 .unwrap_or(if self.spec.clone().into().is_enabled_in(SpecId::OSAKA) {
467 eip7825::TX_GAS_LIMIT_CAP
468 } else {
469 u64::MAX
470 })
471 }
472
473 #[inline]
474 fn max_blobs_per_tx(&self) -> Option<u64> {
475 self.max_blobs_per_tx
476 }
477
478 fn max_code_size(&self) -> usize {
479 self.limit_contract_code_size.unwrap_or(
480 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
481 eip7954::MAX_CODE_SIZE
482 } else {
483 eip170::MAX_CODE_SIZE
484 },
485 )
486 }
487
488 fn max_initcode_size(&self) -> usize {
489 self.limit_contract_initcode_size
490 .or_else(|| {
491 self.limit_contract_code_size
492 .map(|size| size.saturating_mul(2))
493 })
494 .unwrap_or(
495 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
496 eip7954::MAX_INITCODE_SIZE
497 } else {
498 eip3860::MAX_INITCODE_SIZE
499 },
500 )
501 }
502
503 fn is_eip3541_disabled(&self) -> bool {
504 cfg_if::cfg_if! {
505 if #[cfg(feature = "optional_eip3541")] {
506 self.disable_eip3541
507 } else {
508 false
509 }
510 }
511 }
512
513 fn is_eip3607_disabled(&self) -> bool {
514 cfg_if::cfg_if! {
515 if #[cfg(feature = "optional_eip3607")] {
516 self.disable_eip3607
517 } else {
518 false
519 }
520 }
521 }
522
523 fn is_eip7623_disabled(&self) -> bool {
524 cfg_if::cfg_if! {
525 if #[cfg(feature = "optional_eip7623")] {
526 self.disable_eip7623
527 } else {
528 false
529 }
530 }
531 }
532
533 fn is_balance_check_disabled(&self) -> bool {
534 cfg_if::cfg_if! {
535 if #[cfg(feature = "optional_balance_check")] {
536 self.disable_balance_check
537 } else {
538 false
539 }
540 }
541 }
542
543 fn is_block_gas_limit_disabled(&self) -> bool {
545 cfg_if::cfg_if! {
546 if #[cfg(feature = "optional_block_gas_limit")] {
547 self.disable_block_gas_limit
548 } else {
549 false
550 }
551 }
552 }
553
554 fn is_nonce_check_disabled(&self) -> bool {
555 self.disable_nonce_check
556 }
557
558 fn is_base_fee_check_disabled(&self) -> bool {
559 cfg_if::cfg_if! {
560 if #[cfg(feature = "optional_no_base_fee")] {
561 self.disable_base_fee
562 } else {
563 false
564 }
565 }
566 }
567
568 fn is_priority_fee_check_disabled(&self) -> bool {
569 cfg_if::cfg_if! {
570 if #[cfg(feature = "optional_priority_fee_check")] {
571 self.disable_priority_fee_check
572 } else {
573 false
574 }
575 }
576 }
577
578 fn is_fee_charge_disabled(&self) -> bool {
579 cfg_if::cfg_if! {
580 if #[cfg(feature = "optional_fee_charge")] {
581 self.disable_fee_charge
582 } else {
583 false
584 }
585 }
586 }
587
588 fn is_eip7708_disabled(&self) -> bool {
589 self.amsterdam_eip7708_disabled
590 }
591
592 fn is_eip8246_delayed_clear_disabled(&self) -> bool {
593 self.amsterdam_eip8246_delayed_clear_disabled
594 }
595
596 fn memory_limit(&self) -> u64 {
597 cfg_if::cfg_if! {
598 if #[cfg(feature = "memory_limit")] {
599 self.memory_limit
600 } else {
601 u64::MAX
602 }
603 }
604 }
605
606 #[inline]
607 fn gas_params(&self) -> &GasParams {
608 &self.gas_params
609 }
610
611 fn is_amsterdam_eip8037_enabled(&self) -> bool {
612 self.enable_amsterdam_eip8037
613 }
614
615 fn is_amsterdam_eip2780_enabled(&self) -> bool {
616 self.enable_amsterdam_eip2780
617 }
618
619 fn is_amsterdam_eip8024_enabled(&self) -> bool {
620 self.enable_amsterdam_eip8024
621 }
622}
623
624impl<SPEC: Default + Into<SpecId> + Clone> Default for CfgEnv<SPEC> {
625 fn default() -> Self {
626 Self::new_with_spec_and_gas_params(
627 SPEC::default(),
628 GasParams::new_spec(SPEC::default().into()),
629 )
630 }
631}
632
633#[cfg(test)]
634mod test {
635 use super::*;
636
637 #[test]
638 fn eip8024_defaults_and_overrides() {
639 let osaka = CfgEnv::new_with_spec(SpecId::OSAKA);
640 assert!(!osaka.is_amsterdam_eip8024_enabled());
641 let enabled = osaka.clone().with_enable_amsterdam_eip8024(true);
642 assert!(enabled.is_amsterdam_eip8024_enabled());
643 assert_eq!(enabled.gas_params, osaka.gas_params);
644 assert!(!enabled.is_amsterdam_eip8037_enabled());
645 assert!(!enabled.is_amsterdam_eip2780_enabled());
646
647 let amsterdam = CfgEnv::new_with_spec(SpecId::AMSTERDAM);
648 assert!(amsterdam.is_amsterdam_eip8024_enabled());
649 assert!(!amsterdam
650 .with_enable_amsterdam_eip8024(false)
651 .is_amsterdam_eip8024_enabled());
652 }
653
654 #[test]
655 fn eip8024_survives_config_conversion() {
656 let cfg = CfgEnv::new_with_spec(SpecId::OSAKA).with_enable_amsterdam_eip8024(true);
657 let cfg = cfg.with_spec_and_gas_params(SpecId::PRAGUE, GasParams::new_spec(SpecId::PRAGUE));
658 assert!(cfg.is_amsterdam_eip8024_enabled());
659 let cfg = cfg.with_spec_and_mainnet_gas_params(SpecId::OSAKA);
660 assert!(cfg.is_amsterdam_eip8024_enabled());
661
662 let cfg = CfgEnv::new_with_spec(SpecId::AMSTERDAM)
663 .with_enable_amsterdam_eip8024(false)
664 .with_spec_and_gas_params(SpecId::AMSTERDAM, GasParams::new_spec(SpecId::AMSTERDAM));
665 assert!(!cfg.is_amsterdam_eip8024_enabled());
666 }
667
668 #[test]
669 fn eip8024_enabled_by_mainnet_spec_setters() {
670 let mut cfg = CfgEnv::new_with_spec(SpecId::OSAKA);
671 cfg.set_spec_and_mainnet_gas_params(SpecId::AMSTERDAM);
672 assert!(cfg.is_amsterdam_eip8024_enabled());
673 let cfg = CfgEnv::new_with_spec(SpecId::OSAKA)
674 .with_spec_and_mainnet_gas_params(SpecId::AMSTERDAM);
675 assert!(cfg.is_amsterdam_eip8024_enabled());
676 }
677
678 #[test]
679 fn blob_max_and_target_count() {
680 let cfg: CfgEnv = Default::default();
681 assert_eq!(cfg.max_blobs_per_tx(), None);
682 }
683}