1pub use context_interface::Cfg;
3
4use context_interface::cfg::GasParams;
5use primitives::{eip170, eip3860, eip7825, 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}
134
135impl CfgEnv {
136 pub fn new() -> Self {
138 Self::default()
139 }
140}
141
142impl<SPEC> CfgEnv<SPEC> {
143 pub fn new_with_spec_and_gas_params(spec: SPEC, gas_params: GasParams) -> Self {
145 Self {
146 chain_id: 1,
147 tx_chain_id_check: true,
148 limit_contract_code_size: None,
149 limit_contract_initcode_size: None,
150 spec,
151 disable_nonce_check: false,
152 max_blobs_per_tx: None,
153 tx_gas_limit_cap: None,
154 blob_base_fee_update_fraction: None,
155 gas_params,
156 #[cfg(feature = "memory_limit")]
157 memory_limit: (1 << 32) - 1,
158 #[cfg(feature = "optional_balance_check")]
159 disable_balance_check: false,
160 #[cfg(feature = "optional_block_gas_limit")]
161 disable_block_gas_limit: false,
162 #[cfg(feature = "optional_eip3541")]
163 disable_eip3541: false,
164 #[cfg(feature = "optional_eip3607")]
165 disable_eip3607: false,
166 #[cfg(feature = "optional_eip7623")]
167 disable_eip7623: false,
168 #[cfg(feature = "optional_no_base_fee")]
169 disable_base_fee: false,
170 #[cfg(feature = "optional_priority_fee_check")]
171 disable_priority_fee_check: false,
172 #[cfg(feature = "optional_fee_charge")]
173 disable_fee_charge: false,
174 }
175 }
176
177 #[inline]
179 pub fn spec(&self) -> &SPEC {
180 &self.spec
181 }
182
183 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
185 self.chain_id = chain_id;
186 self
187 }
188
189 #[inline]
191 pub fn with_gas_params(mut self, gas_params: GasParams) -> Self {
192 self.set_gas_params(gas_params);
193 self
194 }
195
196 #[inline]
198 pub fn set_spec(&mut self, spec: SPEC) {
199 self.spec = spec;
200 }
201
202 #[inline]
204 pub fn set_gas_params(&mut self, gas_params: GasParams) {
205 self.gas_params = gas_params;
206 }
207
208 pub fn enable_tx_chain_id_check(mut self) -> Self {
210 self.tx_chain_id_check = true;
211 self
212 }
213
214 pub fn disable_tx_chain_id_check(mut self) -> Self {
216 self.tx_chain_id_check = false;
217 self
218 }
219
220 #[inline]
222 #[deprecated(
223 since = "0.1.0",
224 note = "Use [`CfgEnv::with_spec_and_mainnet_gas_params`] instead"
225 )]
226 pub fn with_spec(mut self, spec: SPEC) -> Self {
227 self.spec = spec;
228 self
229 }
230
231 pub fn with_spec_and_mainnet_gas_params<OSPEC: Into<SpecId> + Clone>(
233 self,
234 spec: OSPEC,
235 ) -> CfgEnv<OSPEC> {
236 self.with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
237 }
238
239 pub fn with_spec_and_gas_params<OSPEC: Into<SpecId> + Clone>(
243 self,
244 spec: OSPEC,
245 gas_params: GasParams,
246 ) -> CfgEnv<OSPEC> {
247 CfgEnv {
248 chain_id: self.chain_id,
249 tx_chain_id_check: self.tx_chain_id_check,
250 limit_contract_code_size: self.limit_contract_code_size,
251 limit_contract_initcode_size: self.limit_contract_initcode_size,
252 spec,
253 disable_nonce_check: self.disable_nonce_check,
254 tx_gas_limit_cap: self.tx_gas_limit_cap,
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 }
277 }
278
279 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
281 self.set_max_blobs_per_tx(max_blobs_per_tx);
282 self
283 }
284
285 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
287 self.max_blobs_per_tx = Some(max_blobs_per_tx);
288 }
289
290 pub fn clear_max_blobs_per_tx(&mut self) {
292 self.max_blobs_per_tx = None;
293 }
294
295 #[cfg(feature = "optional_priority_fee_check")]
297 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
298 self.disable_priority_fee_check = disable;
299 self
300 }
301
302 #[cfg(feature = "optional_fee_charge")]
304 pub fn with_disable_fee_charge(mut self, disable: bool) -> Self {
305 self.disable_fee_charge = disable;
306 self
307 }
308
309 #[cfg(feature = "optional_eip7623")]
311 pub fn with_disable_eip7623(mut self, disable: bool) -> Self {
312 self.disable_eip7623 = disable;
313 self
314 }
315}
316
317impl<SPEC: Into<SpecId> + Clone> CfgEnv<SPEC> {
318 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
325 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
326 let spec: SpecId = self.spec.clone().into();
327 if spec.is_enabled_in(SpecId::PRAGUE) {
328 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
329 } else {
330 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
331 }
332 })
333 }
334
335 pub fn new_with_spec(spec: SPEC) -> Self {
340 Self::new_with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into()))
341 }
342
343 pub fn with_mainnet_gas_params(mut self) -> Self {
347 self.set_gas_params(GasParams::new_spec(self.spec.clone().into()));
348 self
349 }
350
351 #[inline]
353 pub fn set_spec_and_mainnet_gas_params(&mut self, spec: SPEC) {
354 self.set_spec(spec.clone());
355 self.set_gas_params(GasParams::new_spec(spec.into()));
356 }
357}
358
359impl<SPEC: Into<SpecId> + Clone> Cfg for CfgEnv<SPEC> {
360 type Spec = SPEC;
361
362 #[inline]
363 fn chain_id(&self) -> u64 {
364 self.chain_id
365 }
366
367 #[inline]
368 fn spec(&self) -> Self::Spec {
369 self.spec.clone()
370 }
371
372 #[inline]
373 fn tx_chain_id_check(&self) -> bool {
374 self.tx_chain_id_check
375 }
376
377 #[inline]
378 fn tx_gas_limit_cap(&self) -> u64 {
379 self.tx_gas_limit_cap
380 .unwrap_or(if self.spec.clone().into().is_enabled_in(SpecId::OSAKA) {
381 eip7825::TX_GAS_LIMIT_CAP
382 } else {
383 u64::MAX
384 })
385 }
386
387 #[inline]
388 fn max_blobs_per_tx(&self) -> Option<u64> {
389 self.max_blobs_per_tx
390 }
391
392 fn max_code_size(&self) -> usize {
393 self.limit_contract_code_size
394 .unwrap_or(eip170::MAX_CODE_SIZE)
395 }
396
397 fn max_initcode_size(&self) -> usize {
398 self.limit_contract_initcode_size
399 .or_else(|| {
400 self.limit_contract_code_size
401 .map(|size| size.saturating_mul(2))
402 })
403 .unwrap_or(eip3860::MAX_INITCODE_SIZE)
404 }
405
406 fn is_eip3541_disabled(&self) -> bool {
407 cfg_if::cfg_if! {
408 if #[cfg(feature = "optional_eip3541")] {
409 self.disable_eip3541
410 } else {
411 false
412 }
413 }
414 }
415
416 fn is_eip3607_disabled(&self) -> bool {
417 cfg_if::cfg_if! {
418 if #[cfg(feature = "optional_eip3607")] {
419 self.disable_eip3607
420 } else {
421 false
422 }
423 }
424 }
425
426 fn is_eip7623_disabled(&self) -> bool {
427 cfg_if::cfg_if! {
428 if #[cfg(feature = "optional_eip7623")] {
429 self.disable_eip7623
430 } else {
431 false
432 }
433 }
434 }
435
436 fn is_balance_check_disabled(&self) -> bool {
437 cfg_if::cfg_if! {
438 if #[cfg(feature = "optional_balance_check")] {
439 self.disable_balance_check
440 } else {
441 false
442 }
443 }
444 }
445
446 fn is_block_gas_limit_disabled(&self) -> bool {
448 cfg_if::cfg_if! {
449 if #[cfg(feature = "optional_block_gas_limit")] {
450 self.disable_block_gas_limit
451 } else {
452 false
453 }
454 }
455 }
456
457 fn is_nonce_check_disabled(&self) -> bool {
458 self.disable_nonce_check
459 }
460
461 fn is_base_fee_check_disabled(&self) -> bool {
462 cfg_if::cfg_if! {
463 if #[cfg(feature = "optional_no_base_fee")] {
464 self.disable_base_fee
465 } else {
466 false
467 }
468 }
469 }
470
471 fn is_priority_fee_check_disabled(&self) -> bool {
472 cfg_if::cfg_if! {
473 if #[cfg(feature = "optional_priority_fee_check")] {
474 self.disable_priority_fee_check
475 } else {
476 false
477 }
478 }
479 }
480
481 fn is_fee_charge_disabled(&self) -> bool {
482 cfg_if::cfg_if! {
483 if #[cfg(feature = "optional_fee_charge")] {
484 self.disable_fee_charge
485 } else {
486 false
487 }
488 }
489 }
490
491 fn memory_limit(&self) -> u64 {
492 cfg_if::cfg_if! {
493 if #[cfg(feature = "memory_limit")] {
494 self.memory_limit
495 } else {
496 u64::MAX
497 }
498 }
499 }
500
501 #[inline]
502 fn gas_params(&self) -> &GasParams {
503 &self.gas_params
504 }
505}
506
507impl<SPEC: Default + Into<SpecId>> Default for CfgEnv<SPEC> {
508 fn default() -> Self {
509 Self::new_with_spec_and_gas_params(
510 SPEC::default(),
511 GasParams::new_spec(SPEC::default().into()),
512 )
513 }
514}
515
516#[cfg(test)]
517mod test {
518 use super::*;
519
520 #[test]
521 fn blob_max_and_target_count() {
522 let cfg: CfgEnv = Default::default();
523 assert_eq!(cfg.max_blobs_per_tx(), None);
524 }
525}