1pub use context_interface::Cfg;
3
4use context_interface::cfg::GasParams;
5use primitives::{eip170, eip3860, eip7825, eip7954, eip8037, 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 pub cpsb_override: Option<u64>,
76 #[cfg(feature = "memory_limit")]
84 pub memory_limit: u64,
85 #[cfg(feature = "optional_balance_check")]
91 pub disable_balance_check: bool,
92 #[cfg(feature = "optional_block_gas_limit")]
98 pub disable_block_gas_limit: bool,
99 #[cfg(feature = "optional_eip3541")]
105 pub disable_eip3541: bool,
106 #[cfg(feature = "optional_eip3607")]
112 pub disable_eip3607: bool,
113 #[cfg(feature = "optional_eip7623")]
120 pub disable_eip7623: bool,
121 #[cfg(feature = "optional_no_base_fee")]
127 pub disable_base_fee: bool,
128 #[cfg(feature = "optional_priority_fee_check")]
132 pub disable_priority_fee_check: bool,
133 #[cfg(feature = "optional_fee_charge")]
138 pub disable_fee_charge: bool,
139 pub enable_amsterdam_eip8037: bool,
148 pub amsterdam_eip7708_disabled: bool,
152 pub amsterdam_eip7708_delayed_burn_disabled: bool,
162}
163
164impl CfgEnv {
165 pub fn new() -> Self {
167 Self::default()
168 }
169}
170
171impl<SPEC> CfgEnv<SPEC> {
172 #[inline]
174 pub const fn spec(&self) -> &SPEC {
175 &self.spec
176 }
177
178 pub const fn with_chain_id(mut self, chain_id: u64) -> Self {
180 self.chain_id = chain_id;
181 self
182 }
183
184 #[inline]
186 pub fn with_gas_params(mut self, gas_params: GasParams) -> Self {
187 self.set_gas_params(gas_params);
188 self
189 }
190
191 #[inline]
193 #[deprecated(note = "Use [`CfgEnv::set_spec_and_mainnet_gas_params`] instead")]
194 pub fn set_spec(&mut self, spec: SPEC) {
195 self.spec = spec;
196 }
197
198 #[inline]
200 pub fn set_gas_params(&mut self, gas_params: GasParams) {
201 self.gas_params = gas_params;
202 }
203
204 pub const fn enable_tx_chain_id_check(mut self) -> Self {
206 self.tx_chain_id_check = true;
207 self
208 }
209
210 pub const fn disable_tx_chain_id_check(mut self) -> Self {
212 self.tx_chain_id_check = false;
213 self
214 }
215
216 #[inline]
218 #[deprecated(note = "Use [`CfgEnv::with_spec_and_mainnet_gas_params`] instead")]
219 pub fn with_spec(mut self, spec: SPEC) -> Self {
220 self.spec = spec;
221 self
222 }
223
224 pub fn with_spec_and_mainnet_gas_params<OSPEC: Into<SpecId> + Clone>(
228 self,
229 spec: OSPEC,
230 ) -> CfgEnv<OSPEC> {
231 let is_amsterdam = spec.clone().into().is_enabled_in(SpecId::AMSTERDAM);
232 let enable_amsterdam_eip8037 = self.enable_amsterdam_eip8037 || is_amsterdam;
233 let mut cfg = self.with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()));
234 cfg.enable_amsterdam_eip8037 = enable_amsterdam_eip8037;
235 cfg
236 }
237
238 pub fn with_spec_and_gas_params<OSPEC: Into<SpecId> + Clone>(
242 self,
243 spec: OSPEC,
244 gas_params: GasParams,
245 ) -> CfgEnv<OSPEC> {
246 CfgEnv {
247 chain_id: self.chain_id,
248 tx_chain_id_check: self.tx_chain_id_check,
249 limit_contract_code_size: self.limit_contract_code_size,
250 limit_contract_initcode_size: self.limit_contract_initcode_size,
251 spec,
252 disable_nonce_check: self.disable_nonce_check,
253 tx_gas_limit_cap: self.tx_gas_limit_cap,
254 cpsb_override: self.cpsb_override,
255 max_blobs_per_tx: self.max_blobs_per_tx,
256 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
257 gas_params,
258 #[cfg(feature = "memory_limit")]
259 memory_limit: self.memory_limit,
260 #[cfg(feature = "optional_balance_check")]
261 disable_balance_check: self.disable_balance_check,
262 #[cfg(feature = "optional_block_gas_limit")]
263 disable_block_gas_limit: self.disable_block_gas_limit,
264 #[cfg(feature = "optional_eip3541")]
265 disable_eip3541: self.disable_eip3541,
266 #[cfg(feature = "optional_eip3607")]
267 disable_eip3607: self.disable_eip3607,
268 #[cfg(feature = "optional_eip7623")]
269 disable_eip7623: self.disable_eip7623,
270 #[cfg(feature = "optional_no_base_fee")]
271 disable_base_fee: self.disable_base_fee,
272 #[cfg(feature = "optional_priority_fee_check")]
273 disable_priority_fee_check: self.disable_priority_fee_check,
274 #[cfg(feature = "optional_fee_charge")]
275 disable_fee_charge: self.disable_fee_charge,
276 enable_amsterdam_eip8037: self.enable_amsterdam_eip8037,
277 amsterdam_eip7708_disabled: self.amsterdam_eip7708_disabled,
278 amsterdam_eip7708_delayed_burn_disabled: self.amsterdam_eip7708_delayed_burn_disabled,
279 }
280 }
281
282 pub const fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
284 self.set_max_blobs_per_tx(max_blobs_per_tx);
285 self
286 }
287
288 pub const fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
290 self.max_blobs_per_tx = Some(max_blobs_per_tx);
291 }
292
293 pub const fn clear_max_blobs_per_tx(&mut self) {
295 self.max_blobs_per_tx = None;
296 }
297
298 #[cfg(feature = "optional_priority_fee_check")]
300 pub const fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
301 self.disable_priority_fee_check = disable;
302 self
303 }
304
305 #[cfg(feature = "optional_fee_charge")]
307 pub const fn with_disable_fee_charge(mut self, disable: bool) -> Self {
308 self.disable_fee_charge = disable;
309 self
310 }
311
312 #[cfg(feature = "optional_eip7623")]
314 pub const fn with_disable_eip7623(mut self, disable: bool) -> Self {
315 self.disable_eip7623 = disable;
316 self
317 }
318
319 pub const fn with_enable_amsterdam_eip8037(mut self, enable: bool) -> Self {
321 self.enable_amsterdam_eip8037 = enable;
322 self
323 }
324}
325
326impl<SPEC: Into<SpecId> + Clone> CfgEnv<SPEC> {
327 pub fn new_with_spec_and_gas_params(spec: SPEC, gas_params: GasParams) -> Self {
329 let is_amsterdam = spec.clone().into().is_enabled_in(SpecId::AMSTERDAM);
330 Self {
331 chain_id: 1,
332 tx_chain_id_check: true,
333 limit_contract_code_size: None,
334 limit_contract_initcode_size: None,
335 spec,
336 disable_nonce_check: false,
337 max_blobs_per_tx: None,
338 tx_gas_limit_cap: None,
339 cpsb_override: None,
340 blob_base_fee_update_fraction: None,
341 gas_params,
342 #[cfg(feature = "memory_limit")]
343 memory_limit: (1 << 32) - 1,
344 #[cfg(feature = "optional_balance_check")]
345 disable_balance_check: false,
346 #[cfg(feature = "optional_block_gas_limit")]
347 disable_block_gas_limit: false,
348 #[cfg(feature = "optional_eip3541")]
349 disable_eip3541: false,
350 #[cfg(feature = "optional_eip3607")]
351 disable_eip3607: false,
352 #[cfg(feature = "optional_eip7623")]
353 disable_eip7623: false,
354 #[cfg(feature = "optional_no_base_fee")]
355 disable_base_fee: false,
356 #[cfg(feature = "optional_priority_fee_check")]
357 disable_priority_fee_check: false,
358 #[cfg(feature = "optional_fee_charge")]
359 disable_fee_charge: false,
360 enable_amsterdam_eip8037: is_amsterdam,
361 amsterdam_eip7708_disabled: false,
362 amsterdam_eip7708_delayed_burn_disabled: false,
363 }
364 }
365
366 pub fn blob_base_fee_update_fraction(&self) -> u64 {
373 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
374 let spec: SpecId = self.spec.clone().into();
375 if spec.is_enabled_in(SpecId::PRAGUE) {
376 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
377 } else {
378 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
379 }
380 })
381 }
382
383 pub fn new_with_spec(spec: SPEC) -> Self {
388 Self::new_with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
389 }
390
391 pub fn with_mainnet_gas_params(mut self) -> Self {
395 self.set_gas_params(GasParams::new_spec(self.spec.clone().into()));
396 self
397 }
398
399 #[inline]
403 pub fn set_spec_and_mainnet_gas_params(&mut self, spec: SPEC) {
404 self.spec = spec.clone();
405 self.set_gas_params(GasParams::new_spec(spec.clone().into()));
406 if spec.into().is_enabled_in(SpecId::AMSTERDAM) {
408 self.enable_amsterdam_eip8037 = true;
409 }
410 }
411}
412
413impl<SPEC: Into<SpecId> + Clone> Cfg for CfgEnv<SPEC> {
414 type Spec = SPEC;
415
416 #[inline]
417 fn chain_id(&self) -> u64 {
418 self.chain_id
419 }
420
421 #[inline]
422 fn spec(&self) -> Self::Spec {
423 self.spec.clone()
424 }
425
426 #[inline]
427 fn tx_chain_id_check(&self) -> bool {
428 self.tx_chain_id_check
429 }
430
431 #[inline]
432 fn tx_gas_limit_cap(&self) -> u64 {
433 self.tx_gas_limit_cap
434 .unwrap_or(if self.spec.clone().into().is_enabled_in(SpecId::OSAKA) {
435 eip7825::TX_GAS_LIMIT_CAP
436 } else {
437 u64::MAX
438 })
439 }
440
441 #[inline]
442 fn max_blobs_per_tx(&self) -> Option<u64> {
443 self.max_blobs_per_tx
444 }
445
446 fn max_code_size(&self) -> usize {
447 self.limit_contract_code_size.unwrap_or(
448 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
449 eip7954::MAX_CODE_SIZE
450 } else {
451 eip170::MAX_CODE_SIZE
452 },
453 )
454 }
455
456 fn max_initcode_size(&self) -> usize {
457 self.limit_contract_initcode_size
458 .or_else(|| {
459 self.limit_contract_code_size
460 .map(|size| size.saturating_mul(2))
461 })
462 .unwrap_or(
463 if self.spec.clone().into().is_enabled_in(SpecId::AMSTERDAM) {
464 eip7954::MAX_INITCODE_SIZE
465 } else {
466 eip3860::MAX_INITCODE_SIZE
467 },
468 )
469 }
470
471 fn is_eip3541_disabled(&self) -> bool {
472 cfg_if::cfg_if! {
473 if #[cfg(feature = "optional_eip3541")] {
474 self.disable_eip3541
475 } else {
476 false
477 }
478 }
479 }
480
481 fn is_eip3607_disabled(&self) -> bool {
482 cfg_if::cfg_if! {
483 if #[cfg(feature = "optional_eip3607")] {
484 self.disable_eip3607
485 } else {
486 false
487 }
488 }
489 }
490
491 fn is_eip7623_disabled(&self) -> bool {
492 cfg_if::cfg_if! {
493 if #[cfg(feature = "optional_eip7623")] {
494 self.disable_eip7623
495 } else {
496 false
497 }
498 }
499 }
500
501 fn is_balance_check_disabled(&self) -> bool {
502 cfg_if::cfg_if! {
503 if #[cfg(feature = "optional_balance_check")] {
504 self.disable_balance_check
505 } else {
506 false
507 }
508 }
509 }
510
511 fn is_block_gas_limit_disabled(&self) -> bool {
513 cfg_if::cfg_if! {
514 if #[cfg(feature = "optional_block_gas_limit")] {
515 self.disable_block_gas_limit
516 } else {
517 false
518 }
519 }
520 }
521
522 fn is_nonce_check_disabled(&self) -> bool {
523 self.disable_nonce_check
524 }
525
526 fn is_base_fee_check_disabled(&self) -> bool {
527 cfg_if::cfg_if! {
528 if #[cfg(feature = "optional_no_base_fee")] {
529 self.disable_base_fee
530 } else {
531 false
532 }
533 }
534 }
535
536 fn is_priority_fee_check_disabled(&self) -> bool {
537 cfg_if::cfg_if! {
538 if #[cfg(feature = "optional_priority_fee_check")] {
539 self.disable_priority_fee_check
540 } else {
541 false
542 }
543 }
544 }
545
546 fn is_fee_charge_disabled(&self) -> bool {
547 cfg_if::cfg_if! {
548 if #[cfg(feature = "optional_fee_charge")] {
549 self.disable_fee_charge
550 } else {
551 false
552 }
553 }
554 }
555
556 fn is_eip7708_disabled(&self) -> bool {
557 self.amsterdam_eip7708_disabled
558 }
559
560 fn is_eip7708_delayed_burn_disabled(&self) -> bool {
561 self.amsterdam_eip7708_delayed_burn_disabled
562 }
563
564 fn memory_limit(&self) -> u64 {
565 cfg_if::cfg_if! {
566 if #[cfg(feature = "memory_limit")] {
567 self.memory_limit
568 } else {
569 u64::MAX
570 }
571 }
572 }
573
574 #[inline]
575 fn gas_params(&self) -> &GasParams {
576 &self.gas_params
577 }
578
579 fn is_amsterdam_eip8037_enabled(&self) -> bool {
580 self.enable_amsterdam_eip8037
581 }
582
583 #[inline]
584 fn cpsb(&self) -> u64 {
585 if !self.enable_amsterdam_eip8037 {
586 return 0;
587 }
588 self.cpsb_override.unwrap_or(eip8037::CPSB_GLAMSTERDAM)
589 }
590}
591
592impl<SPEC: Default + Into<SpecId> + Clone> Default for CfgEnv<SPEC> {
593 fn default() -> Self {
594 Self::new_with_spec_and_gas_params(
595 SPEC::default(),
596 GasParams::new_spec(SPEC::default().into()),
597 )
598 }
599}
600
601#[cfg(test)]
602mod test {
603 use super::*;
604
605 #[test]
606 fn blob_max_and_target_count() {
607 let cfg: CfgEnv = Default::default();
608 assert_eq!(cfg.max_blobs_per_tx(), None);
609 }
610}