1pub use context_interface::Cfg;
2
3use primitives::{eip170::MAX_CODE_SIZE, hardfork::SpecId};
4use std::{vec, vec::Vec};
5
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[derive(Clone, Debug, Eq, PartialEq)]
9#[non_exhaustive]
10pub struct CfgEnv<SPEC = SpecId> {
11 pub chain_id: u64,
17 pub spec: SPEC,
19 pub limit_contract_code_size: Option<usize>,
25 pub disable_nonce_check: bool,
27 pub blob_target_and_max_count: Vec<(SpecId, u64, u64)>,
31 #[cfg(feature = "memory_limit")]
39 pub memory_limit: u64,
40 #[cfg(feature = "optional_balance_check")]
46 pub disable_balance_check: bool,
47 #[cfg(feature = "optional_block_gas_limit")]
53 pub disable_block_gas_limit: bool,
54 #[cfg(feature = "optional_eip3607")]
60 pub disable_eip3607: bool,
61 #[cfg(feature = "optional_no_base_fee")]
67 pub disable_base_fee: bool,
68}
69
70impl CfgEnv {
71 pub fn new() -> Self {
73 Self::default()
74 }
75}
76
77impl<SPEC> CfgEnv<SPEC> {
78 pub fn new_with_spec(spec: SPEC) -> Self {
79 Self {
80 chain_id: 1,
81 limit_contract_code_size: None,
82 spec,
83 disable_nonce_check: false,
84 blob_target_and_max_count: vec![(SpecId::CANCUN, 3, 6), (SpecId::PRAGUE, 6, 9)],
85 #[cfg(feature = "memory_limit")]
86 memory_limit: (1 << 32) - 1,
87 #[cfg(feature = "optional_balance_check")]
88 disable_balance_check: false,
89 #[cfg(feature = "optional_block_gas_limit")]
90 disable_block_gas_limit: false,
91 #[cfg(feature = "optional_eip3607")]
92 disable_eip3607: false,
93 #[cfg(feature = "optional_no_base_fee")]
94 disable_base_fee: false,
95 }
96 }
97
98 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
99 self.chain_id = chain_id;
100 self
101 }
102
103 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
104 CfgEnv {
105 chain_id: self.chain_id,
106 limit_contract_code_size: self.limit_contract_code_size,
107 spec,
108 disable_nonce_check: self.disable_nonce_check,
109 blob_target_and_max_count: self.blob_target_and_max_count,
110 #[cfg(feature = "memory_limit")]
111 memory_limit: self.memory_limit,
112 #[cfg(feature = "optional_balance_check")]
113 disable_balance_check: self.disable_balance_check,
114 #[cfg(feature = "optional_block_gas_limit")]
115 disable_block_gas_limit: self.disable_block_gas_limit,
116 #[cfg(feature = "optional_eip3607")]
117 disable_eip3607: self.disable_eip3607,
118 #[cfg(feature = "optional_no_base_fee")]
119 disable_base_fee: self.disable_base_fee,
120 }
121 }
122
123 pub fn with_blob_max_and_target_count(mut self, blob_params: Vec<(SpecId, u64, u64)>) -> Self {
125 self.set_blob_max_and_target_count(blob_params);
126 self
127 }
128
129 pub fn set_blob_max_and_target_count(&mut self, mut blob_params: Vec<(SpecId, u64, u64)>) {
131 blob_params.sort_by_key(|(id, _, _)| *id);
132 self.blob_target_and_max_count = blob_params;
133 }
134}
135
136impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
137 type Spec = SPEC;
138
139 fn chain_id(&self) -> u64 {
140 self.chain_id
141 }
142
143 fn spec(&self) -> Self::Spec {
144 self.spec
145 }
146
147 #[inline]
148 fn blob_max_count(&self, spec_id: SpecId) -> u64 {
149 self.blob_target_and_max_count
150 .iter()
151 .rev()
152 .find_map(|(id, _, max)| {
153 if spec_id as u8 >= *id as u8 {
154 return Some(*max);
155 }
156 None
157 })
158 .unwrap_or(6)
159 }
160
161 fn max_code_size(&self) -> usize {
162 self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE)
163 }
164
165 fn is_eip3607_disabled(&self) -> bool {
166 cfg_if::cfg_if! {
167 if #[cfg(feature = "optional_eip3607")] {
168 self.disable_eip3607
169 } else {
170 false
171 }
172 }
173 }
174
175 fn is_balance_check_disabled(&self) -> bool {
176 cfg_if::cfg_if! {
177 if #[cfg(feature = "optional_balance_check")] {
178 self.disable_balance_check
179 } else {
180 false
181 }
182 }
183 }
184
185 fn is_block_gas_limit_disabled(&self) -> bool {
187 cfg_if::cfg_if! {
188 if #[cfg(feature = "optional_block_gas_limit")] {
189 self.disable_block_gas_limit
190 } else {
191 false
192 }
193 }
194 }
195
196 fn is_nonce_check_disabled(&self) -> bool {
197 self.disable_nonce_check
198 }
199
200 fn is_base_fee_check_disabled(&self) -> bool {
201 cfg_if::cfg_if! {
202 if #[cfg(feature = "optional_no_base_fee")] {
203 self.disable_base_fee
204 } else {
205 false
206 }
207 }
208 }
209}
210
211impl<SPEC: Default> Default for CfgEnv<SPEC> {
212 fn default() -> Self {
213 Self::new_with_spec(SPEC::default())
214 }
215}
216
217#[cfg(test)]
218mod test {
219 use super::*;
220
221 #[test]
222 fn blob_max_and_target_count() {
223 let cfg: CfgEnv = Default::default();
224 assert_eq!(cfg.blob_max_count(SpecId::BERLIN), (6));
225 assert_eq!(cfg.blob_max_count(SpecId::CANCUN), (6));
226 assert_eq!(cfg.blob_max_count(SpecId::PRAGUE), (9));
227 assert_eq!(cfg.blob_max_count(SpecId::OSAKA), (9));
228 }
229}