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_eip3607")]
87 pub disable_eip3607: bool,
88 #[cfg(feature = "optional_no_base_fee")]
94 pub disable_base_fee: bool,
95 #[cfg(feature = "optional_priority_fee_check")]
99 pub disable_priority_fee_check: bool,
100}
101
102impl CfgEnv {
103 pub fn new() -> Self {
105 Self::default()
106 }
107}
108
109impl<SPEC: Into<SpecId> + Copy> CfgEnv<SPEC> {
110 pub fn blob_base_fee_update_fraction(&mut self) -> u64 {
117 self.blob_base_fee_update_fraction.unwrap_or_else(|| {
118 let spec: SpecId = self.spec.into();
119 if spec.is_enabled_in(SpecId::PRAGUE) {
120 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
121 } else {
122 primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
123 }
124 })
125 }
126}
127
128impl<SPEC> CfgEnv<SPEC> {
129 pub fn new_with_spec(spec: SPEC) -> Self {
131 Self {
132 chain_id: 1,
133 tx_chain_id_check: false,
134 limit_contract_code_size: None,
135 limit_contract_initcode_size: None,
136 spec,
137 disable_nonce_check: false,
138 max_blobs_per_tx: None,
139 tx_gas_limit_cap: None,
140 blob_base_fee_update_fraction: None,
141 #[cfg(feature = "memory_limit")]
142 memory_limit: (1 << 32) - 1,
143 #[cfg(feature = "optional_balance_check")]
144 disable_balance_check: false,
145 #[cfg(feature = "optional_block_gas_limit")]
146 disable_block_gas_limit: false,
147 #[cfg(feature = "optional_eip3607")]
148 disable_eip3607: false,
149 #[cfg(feature = "optional_no_base_fee")]
150 disable_base_fee: false,
151 #[cfg(feature = "optional_priority_fee_check")]
152 disable_priority_fee_check: false,
153 }
154 }
155
156 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
158 self.chain_id = chain_id;
159 self
160 }
161
162 pub fn enable_tx_chain_id_check(mut self) -> Self {
164 self.tx_chain_id_check = true;
165 self
166 }
167
168 pub fn disable_tx_chain_id_check(mut self) -> Self {
170 self.tx_chain_id_check = false;
171 self
172 }
173
174 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
176 CfgEnv {
177 chain_id: self.chain_id,
178 tx_chain_id_check: self.tx_chain_id_check,
179 limit_contract_code_size: self.limit_contract_code_size,
180 limit_contract_initcode_size: self.limit_contract_initcode_size,
181 spec,
182 disable_nonce_check: self.disable_nonce_check,
183 tx_gas_limit_cap: self.tx_gas_limit_cap,
184 max_blobs_per_tx: self.max_blobs_per_tx,
185 blob_base_fee_update_fraction: self.blob_base_fee_update_fraction,
186 #[cfg(feature = "memory_limit")]
187 memory_limit: self.memory_limit,
188 #[cfg(feature = "optional_balance_check")]
189 disable_balance_check: self.disable_balance_check,
190 #[cfg(feature = "optional_block_gas_limit")]
191 disable_block_gas_limit: self.disable_block_gas_limit,
192 #[cfg(feature = "optional_eip3607")]
193 disable_eip3607: self.disable_eip3607,
194 #[cfg(feature = "optional_no_base_fee")]
195 disable_base_fee: self.disable_base_fee,
196 #[cfg(feature = "optional_priority_fee_check")]
197 disable_priority_fee_check: self.disable_priority_fee_check,
198 }
199 }
200
201 pub fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
203 self.set_max_blobs_per_tx(max_blobs_per_tx);
204 self
205 }
206
207 pub fn set_max_blobs_per_tx(&mut self, max_blobs_per_tx: u64) {
209 self.max_blobs_per_tx = Some(max_blobs_per_tx);
210 }
211
212 pub fn clear_max_blobs_per_tx(&mut self) {
214 self.max_blobs_per_tx = None;
215 }
216
217 #[cfg(feature = "optional_priority_fee_check")]
219 pub fn with_disable_priority_fee_check(mut self, disable: bool) -> Self {
220 self.disable_priority_fee_check = disable;
221 self
222 }
223}
224
225impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
226 type Spec = SPEC;
227
228 #[inline]
229 fn chain_id(&self) -> u64 {
230 self.chain_id
231 }
232
233 #[inline]
234 fn spec(&self) -> Self::Spec {
235 self.spec
236 }
237
238 #[inline]
239 fn tx_chain_id_check(&self) -> bool {
240 self.tx_chain_id_check
241 }
242
243 #[inline]
244 fn tx_gas_limit_cap(&self) -> u64 {
245 self.tx_gas_limit_cap
246 .unwrap_or(if self.spec.into().is_enabled_in(SpecId::OSAKA) {
247 eip7825::TX_GAS_LIMIT_CAP
248 } else {
249 u64::MAX
250 })
251 }
252
253 #[inline]
254 fn max_blobs_per_tx(&self) -> Option<u64> {
255 self.max_blobs_per_tx
256 }
257
258 fn max_code_size(&self) -> usize {
259 self.limit_contract_code_size
260 .unwrap_or(eip170::MAX_CODE_SIZE)
261 }
262
263 fn max_initcode_size(&self) -> usize {
264 self.limit_contract_initcode_size
265 .or_else(|| {
266 self.limit_contract_code_size
267 .map(|size| size.saturating_mul(2))
268 })
269 .unwrap_or(eip3860::MAX_INITCODE_SIZE)
270 }
271
272 fn is_eip3607_disabled(&self) -> bool {
273 cfg_if::cfg_if! {
274 if #[cfg(feature = "optional_eip3607")] {
275 self.disable_eip3607
276 } else {
277 false
278 }
279 }
280 }
281
282 fn is_balance_check_disabled(&self) -> bool {
283 cfg_if::cfg_if! {
284 if #[cfg(feature = "optional_balance_check")] {
285 self.disable_balance_check
286 } else {
287 false
288 }
289 }
290 }
291
292 fn is_block_gas_limit_disabled(&self) -> bool {
294 cfg_if::cfg_if! {
295 if #[cfg(feature = "optional_block_gas_limit")] {
296 self.disable_block_gas_limit
297 } else {
298 false
299 }
300 }
301 }
302
303 fn is_nonce_check_disabled(&self) -> bool {
304 self.disable_nonce_check
305 }
306
307 fn is_base_fee_check_disabled(&self) -> bool {
308 cfg_if::cfg_if! {
309 if #[cfg(feature = "optional_no_base_fee")] {
310 self.disable_base_fee
311 } else {
312 false
313 }
314 }
315 }
316
317 fn is_priority_fee_check_disabled(&self) -> bool {
318 cfg_if::cfg_if! {
319 if #[cfg(feature = "optional_priority_fee_check")] {
320 self.disable_priority_fee_check
321 } else {
322 false
323 }
324 }
325 }
326}
327
328impl<SPEC: Default> Default for CfgEnv<SPEC> {
329 fn default() -> Self {
330 Self::new_with_spec(SPEC::default())
331 }
332}
333
334#[cfg(test)]
335mod test {
336 use super::*;
337
338 #[test]
339 fn blob_max_and_target_count() {
340 let cfg: CfgEnv = Default::default();
341 assert_eq!(cfg.max_blobs_per_tx(), None);
342 }
343}