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_no_base_fee")]
101 pub disable_base_fee: bool,
102 #[cfg(feature = "optional_priority_fee_check")]
106 pub disable_priority_fee_check: bool,
107 #[cfg(feature = "optional_fee_charge")]
112 pub disable_fee_charge: bool,
113}
114
115impl CfgEnv {
116 pub fn new() -> Self {
118 Self::default()
119 }
120}
121
122impl<SPEC: Into<SpecId> + Copy> CfgEnv<SPEC> {
123 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
130 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
131 let spec: SpecId = self.spec.into();
132 if spec.is_enabled_in(SpecId::PRAGUE) {
133 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
134 } else {
135 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
136 }
137 })
138 }
139}
140
141impl<SPEC> CfgEnv<SPEC> {
142 pub fn new_with_spec(spec: SPEC) -> Self {
144 Self {
145 chain_id: 1,
146 tx_chain_id_check: false,
147 limit_contract_code_size: None,
148 limit_contract_initcode_size: None,
149 spec,
150 disable_nonce_check: false,
151 max_blobs_per_tx: None,
152 tx_gas_limit_cap: None,
153 blob_base_fee_update_fraction: None,
154 #[cfg(feature = "memory_limit")]
155 memory_limit: (1 << 32) - 1,
156 #[cfg(feature = "optional_balance_check")]
157 disable_balance_check: false,
158 #[cfg(feature = "optional_block_gas_limit")]
159 disable_block_gas_limit: false,
160 #[cfg(feature = "optional_eip3541")]
161 disable_eip3541: false,
162 #[cfg(feature = "optional_eip3607")]
163 disable_eip3607: false,
164 #[cfg(feature = "optional_no_base_fee")]
165 disable_base_fee: false,
166 #[cfg(feature = "optional_priority_fee_check")]
167 disable_priority_fee_check: false,
168 #[cfg(feature = "optional_fee_charge")]
169 disable_fee_charge: false,
170 }
171 }
172
173 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
175 self.chain_id = chain_id;
176 self
177 }
178
179 pub fn enable_tx_chain_id_check(mut self) -> Self {
181 self.tx_chain_id_check = true;
182 self
183 }
184
185 pub fn disable_tx_chain_id_check(mut self) -> Self {
187 self.tx_chain_id_check = false;
188 self
189 }
190
191 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
193 CfgEnv {
194 chain_id: self.chain_id,
195 tx_chain_id_check: self.tx_chain_id_check,
196 limit_contract_code_size: self.limit_contract_code_size,
197 limit_contract_initcode_size: self.limit_contract_initcode_size,
198 spec,
199 disable_nonce_check: self.disable_nonce_check,
200 tx_gas_limit_cap: self.tx_gas_limit_cap,
201 max_blobs_per_tx: self.max_blobs_per_tx,
202 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
203 #[cfg(feature = "memory_limit")]
204 memory_limit: self.memory_limit,
205 #[cfg(feature = "optional_balance_check")]
206 disable_balance_check: self.disable_balance_check,
207 #[cfg(feature = "optional_block_gas_limit")]
208 disable_block_gas_limit: self.disable_block_gas_limit,
209 #[cfg(feature = "optional_eip3541")]
210 disable_eip3541: self.disable_eip3541,
211 #[cfg(feature = "optional_eip3607")]
212 disable_eip3607: self.disable_eip3607,
213 #[cfg(feature = "optional_no_base_fee")]
214 disable_base_fee: self.disable_base_fee,
215 #[cfg(feature = "optional_priority_fee_check")]
216 disable_priority_fee_check: self.disable_priority_fee_check,
217 #[cfg(feature = "optional_fee_charge")]
218 disable_fee_charge: self.disable_fee_charge,
219 }
220 }
221
222 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
224 self.set_max_blobs_per_tx(max_blobs_per_tx);
225 self
226 }
227
228 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
230 self.max_blobs_per_tx = Some(max_blobs_per_tx);
231 }
232
233 pub fn clear_max_blobs_per_tx(&mut self) {
235 self.max_blobs_per_tx = None;
236 }
237
238 #[cfg(feature = "optional_priority_fee_check")]
240 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
241 self.disable_priority_fee_check = disable;
242 self
243 }
244
245 #[cfg(feature = "optional_fee_charge")]
247 pub fn with_disable_fee_charge(mut self, disable: bool) -> Self {
248 self.disable_fee_charge = disable;
249 self
250 }
251}
252
253impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
254 type Spec = SPEC;
255
256 #[inline]
257 fn chain_id(&self) -> u64 {
258 self.chain_id
259 }
260
261 #[inline]
262 fn spec(&self) -> Self::Spec {
263 self.spec
264 }
265
266 #[inline]
267 fn tx_chain_id_check(&self) -> bool {
268 self.tx_chain_id_check
269 }
270
271 #[inline]
272 fn tx_gas_limit_cap(&self) -> u64 {
273 self.tx_gas_limit_cap
274 .unwrap_or(if self.spec.into().is_enabled_in(SpecId::OSAKA) {
275 eip7825::TX_GAS_LIMIT_CAP
276 } else {
277 u64::MAX
278 })
279 }
280
281 #[inline]
282 fn max_blobs_per_tx(&self) -> Option<u64> {
283 self.max_blobs_per_tx
284 }
285
286 fn max_code_size(&self) -> usize {
287 self.limit_contract_code_size
288 .unwrap_or(eip170::MAX_CODE_SIZE)
289 }
290
291 fn max_initcode_size(&self) -> usize {
292 self.limit_contract_initcode_size
293 .or_else(|| {
294 self.limit_contract_code_size
295 .map(|size| size.saturating_mul(2))
296 })
297 .unwrap_or(eip3860::MAX_INITCODE_SIZE)
298 }
299
300 fn is_eip3541_disabled(&self) -> bool {
301 cfg_if::cfg_if! {
302 if #[cfg(feature = "optional_eip3541")] {
303 self.disable_eip3541
304 } else {
305 false
306 }
307 }
308 }
309
310 fn is_eip3607_disabled(&self) -> bool {
311 cfg_if::cfg_if! {
312 if #[cfg(feature = "optional_eip3607")] {
313 self.disable_eip3607
314 } else {
315 false
316 }
317 }
318 }
319
320 fn is_balance_check_disabled(&self) -> bool {
321 cfg_if::cfg_if! {
322 if #[cfg(feature = "optional_balance_check")] {
323 self.disable_balance_check
324 } else {
325 false
326 }
327 }
328 }
329
330 fn is_block_gas_limit_disabled(&self) -> bool {
332 cfg_if::cfg_if! {
333 if #[cfg(feature = "optional_block_gas_limit")] {
334 self.disable_block_gas_limit
335 } else {
336 false
337 }
338 }
339 }
340
341 fn is_nonce_check_disabled(&self) -> bool {
342 self.disable_nonce_check
343 }
344
345 fn is_base_fee_check_disabled(&self) -> bool {
346 cfg_if::cfg_if! {
347 if #[cfg(feature = "optional_no_base_fee")] {
348 self.disable_base_fee
349 } else {
350 false
351 }
352 }
353 }
354
355 fn is_priority_fee_check_disabled(&self) -> bool {
356 cfg_if::cfg_if! {
357 if #[cfg(feature = "optional_priority_fee_check")] {
358 self.disable_priority_fee_check
359 } else {
360 false
361 }
362 }
363 }
364
365 fn is_fee_charge_disabled(&self) -> bool {
366 cfg_if::cfg_if! {
367 if #[cfg(feature = "optional_fee_charge")] {
368 self.disable_fee_charge
369 } else {
370 false
371 }
372 }
373 }
374}
375
376impl<SPEC: Default> Default for CfgEnv<SPEC> {
377 fn default() -> Self {
378 Self::new_with_spec(SPEC::default())
379 }
380}
381
382#[cfg(test)]
383mod test {
384 use super::*;
385
386 #[test]
387 fn blob_max_and_target_count() {
388 let cfg: CfgEnv = Default::default();
389 assert_eq!(cfg.max_blobs_per_tx(), None);
390 }
391}