1pub use context_interface::Cfg;
3
4use primitives::{eip170, eip3860, eip7825, hardfork::SpecId};
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[derive(Clone, Debug, Eq, PartialEq)]
8#[non_exhaustive]
9pub struct CfgEnv<SPEC = SpecId> {
10 pub chain_id: u64,
14
15 pub tx_chain_id_check: bool,
19
20 pub spec: SPEC,
22 pub limit_contract_code_size: Option<usize>,
29 pub limit_contract_initcode_size: Option<usize>,
37 pub disable_nonce_check: bool,
39 pub max_blobs_per_tx: Option<u64>,
43 pub blob_base_fee_update_fraction: Option<u64>,
51 pub tx_gas_limit_cap: Option<u64>,
58 #[cfg(feature = "memory_limit")]
66 pub memory_limit: u64,
67 #[cfg(feature = "optional_balance_check")]
73 pub disable_balance_check: bool,
74 #[cfg(feature = "optional_block_gas_limit")]
80 pub disable_block_gas_limit: bool,
81 #[cfg(feature = "optional_eip3541")]
87 pub disable_eip3541: bool,
88 #[cfg(feature = "optional_eip3607")]
94 pub disable_eip3607: bool,
95 #[cfg(feature = "optional_eip7623")]
102 pub disable_eip7623: bool,
103 #[cfg(feature = "optional_no_base_fee")]
109 pub disable_base_fee: bool,
110 #[cfg(feature = "optional_priority_fee_check")]
114 pub disable_priority_fee_check: bool,
115 #[cfg(feature = "optional_fee_charge")]
120 pub disable_fee_charge: bool,
121}
122
123impl CfgEnv {
124 pub fn new() -> Self {
126 Self::default()
127 }
128}
129
130impl<SPEC: Into<SpecId> + Copy> CfgEnv<SPEC> {
131 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
138 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
139 let spec: SpecId = self.spec.into();
140 if spec.is_enabled_in(SpecId::PRAGUE) {
141 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
142 } else {
143 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
144 }
145 })
146 }
147}
148
149impl<SPEC> CfgEnv<SPEC> {
150 pub fn new_with_spec(spec: SPEC) -> Self {
152 Self {
153 chain_id: 1,
154 tx_chain_id_check: true,
155 limit_contract_code_size: None,
156 limit_contract_initcode_size: None,
157 spec,
158 disable_nonce_check: false,
159 max_blobs_per_tx: None,
160 tx_gas_limit_cap: None,
161 blob_base_fee_update_fraction: None,
162 #[cfg(feature = "memory_limit")]
163 memory_limit: (1 << 32) - 1,
164 #[cfg(feature = "optional_balance_check")]
165 disable_balance_check: false,
166 #[cfg(feature = "optional_block_gas_limit")]
167 disable_block_gas_limit: false,
168 #[cfg(feature = "optional_eip3541")]
169 disable_eip3541: false,
170 #[cfg(feature = "optional_eip3607")]
171 disable_eip3607: false,
172 #[cfg(feature = "optional_eip7623")]
173 disable_eip7623: false,
174 #[cfg(feature = "optional_no_base_fee")]
175 disable_base_fee: false,
176 #[cfg(feature = "optional_priority_fee_check")]
177 disable_priority_fee_check: false,
178 #[cfg(feature = "optional_fee_charge")]
179 disable_fee_charge: false,
180 }
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 pub fn enable_tx_chain_id_check(mut self) -> Self {
191 self.tx_chain_id_check = true;
192 self
193 }
194
195 pub fn disable_tx_chain_id_check(mut self) -> Self {
197 self.tx_chain_id_check = false;
198 self
199 }
200
201 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
203 CfgEnv {
204 chain_id: self.chain_id,
205 tx_chain_id_check: self.tx_chain_id_check,
206 limit_contract_code_size: self.limit_contract_code_size,
207 limit_contract_initcode_size: self.limit_contract_initcode_size,
208 spec,
209 disable_nonce_check: self.disable_nonce_check,
210 tx_gas_limit_cap: self.tx_gas_limit_cap,
211 max_blobs_per_tx: self.max_blobs_per_tx,
212 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
213 #[cfg(feature = "memory_limit")]
214 memory_limit: self.memory_limit,
215 #[cfg(feature = "optional_balance_check")]
216 disable_balance_check: self.disable_balance_check,
217 #[cfg(feature = "optional_block_gas_limit")]
218 disable_block_gas_limit: self.disable_block_gas_limit,
219 #[cfg(feature = "optional_eip3541")]
220 disable_eip3541: self.disable_eip3541,
221 #[cfg(feature = "optional_eip3607")]
222 disable_eip3607: self.disable_eip3607,
223 #[cfg(feature = "optional_eip7623")]
224 disable_eip7623: self.disable_eip7623,
225 #[cfg(feature = "optional_no_base_fee")]
226 disable_base_fee: self.disable_base_fee,
227 #[cfg(feature = "optional_priority_fee_check")]
228 disable_priority_fee_check: self.disable_priority_fee_check,
229 #[cfg(feature = "optional_fee_charge")]
230 disable_fee_charge: self.disable_fee_charge,
231 }
232 }
233
234 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
236 self.set_max_blobs_per_tx(max_blobs_per_tx);
237 self
238 }
239
240 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
242 self.max_blobs_per_tx = Some(max_blobs_per_tx);
243 }
244
245 pub fn clear_max_blobs_per_tx(&mut self) {
247 self.max_blobs_per_tx = None;
248 }
249
250 #[cfg(feature = "optional_priority_fee_check")]
252 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
253 self.disable_priority_fee_check = disable;
254 self
255 }
256
257 #[cfg(feature = "optional_fee_charge")]
259 pub fn with_disable_fee_charge(mut self, disable: bool) -> Self {
260 self.disable_fee_charge = disable;
261 self
262 }
263
264 #[cfg(feature = "optional_eip7623")]
266 pub fn with_disable_eip7623(mut self, disable: bool) -> Self {
267 self.disable_eip7623 = disable;
268 self
269 }
270}
271
272impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
273 type Spec = SPEC;
274
275 #[inline]
276 fn chain_id(&self) -> u64 {
277 self.chain_id
278 }
279
280 #[inline]
281 fn spec(&self) -> Self::Spec {
282 self.spec
283 }
284
285 #[inline]
286 fn tx_chain_id_check(&self) -> bool {
287 self.tx_chain_id_check
288 }
289
290 #[inline]
291 fn tx_gas_limit_cap(&self) -> u64 {
292 self.tx_gas_limit_cap
293 .unwrap_or(if self.spec.into().is_enabled_in(SpecId::OSAKA) {
294 eip7825::TX_GAS_LIMIT_CAP
295 } else {
296 u64::MAX
297 })
298 }
299
300 #[inline]
301 fn max_blobs_per_tx(&self) -> Option<u64> {
302 self.max_blobs_per_tx
303 }
304
305 fn max_code_size(&self) -> usize {
306 self.limit_contract_code_size
307 .unwrap_or(eip170::MAX_CODE_SIZE)
308 }
309
310 fn max_initcode_size(&self) -> usize {
311 self.limit_contract_initcode_size
312 .or_else(|| {
313 self.limit_contract_code_size
314 .map(|size| size.saturating_mul(2))
315 })
316 .unwrap_or(eip3860::MAX_INITCODE_SIZE)
317 }
318
319 fn is_eip3541_disabled(&self) -> bool {
320 cfg_if::cfg_if! {
321 if #[cfg(feature = "optional_eip3541")] {
322 self.disable_eip3541
323 } else {
324 false
325 }
326 }
327 }
328
329 fn is_eip3607_disabled(&self) -> bool {
330 cfg_if::cfg_if! {
331 if #[cfg(feature = "optional_eip3607")] {
332 self.disable_eip3607
333 } else {
334 false
335 }
336 }
337 }
338
339 fn is_eip7623_disabled(&self) -> bool {
340 cfg_if::cfg_if! {
341 if #[cfg(feature = "optional_eip7623")] {
342 self.disable_eip7623
343 } else {
344 false
345 }
346 }
347 }
348
349 fn is_balance_check_disabled(&self) -> bool {
350 cfg_if::cfg_if! {
351 if #[cfg(feature = "optional_balance_check")] {
352 self.disable_balance_check
353 } else {
354 false
355 }
356 }
357 }
358
359 fn is_block_gas_limit_disabled(&self) -> bool {
361 cfg_if::cfg_if! {
362 if #[cfg(feature = "optional_block_gas_limit")] {
363 self.disable_block_gas_limit
364 } else {
365 false
366 }
367 }
368 }
369
370 fn is_nonce_check_disabled(&self) -> bool {
371 self.disable_nonce_check
372 }
373
374 fn is_base_fee_check_disabled(&self) -> bool {
375 cfg_if::cfg_if! {
376 if #[cfg(feature = "optional_no_base_fee")] {
377 self.disable_base_fee
378 } else {
379 false
380 }
381 }
382 }
383
384 fn is_priority_fee_check_disabled(&self) -> bool {
385 cfg_if::cfg_if! {
386 if #[cfg(feature = "optional_priority_fee_check")] {
387 self.disable_priority_fee_check
388 } else {
389 false
390 }
391 }
392 }
393
394 fn is_fee_charge_disabled(&self) -> bool {
395 cfg_if::cfg_if! {
396 if #[cfg(feature = "optional_fee_charge")] {
397 self.disable_fee_charge
398 } else {
399 false
400 }
401 }
402 }
403}
404
405impl<SPEC: Default> Default for CfgEnv<SPEC> {
406 fn default() -> Self {
407 Self::new_with_spec(SPEC::default())
408 }
409}
410
411#[cfg(test)]
412mod test {
413 use super::*;
414
415 #[test]
416 fn blob_max_and_target_count() {
417 let cfg: CfgEnv = Default::default();
418 assert_eq!(cfg.max_blobs_per_tx(), None);
419 }
420}