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