1pub use context_interface::Cfg;
2
3use interpreter::MAX_CODE_SIZE;
4use specification::hardfork::SpecId;
5use std::{vec, vec::Vec};
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 chain_id: u64,
18 pub spec: SPEC,
20 pub limit_contract_code_size: Option<usize>,
26 pub disable_nonce_check: bool,
28 pub blob_target_and_max_count: Vec<(SpecId, u8, u8)>,
32 #[cfg(feature = "memory_limit")]
40 pub memory_limit: u64,
41 #[cfg(feature = "optional_balance_check")]
47 pub disable_balance_check: bool,
48 #[cfg(feature = "optional_block_gas_limit")]
54 pub disable_block_gas_limit: bool,
55 #[cfg(feature = "optional_eip3607")]
61 pub disable_eip3607: bool,
62 #[cfg(feature = "optional_gas_refund")]
70 pub disable_gas_refund: bool,
71 #[cfg(feature = "optional_no_base_fee")]
77 pub disable_base_fee: bool,
78}
79
80impl CfgEnv {
81 pub fn new() -> Self {
83 Self::default()
84 }
85}
86
87impl<SPEC> CfgEnv<SPEC> {
88 pub fn with_chain_id(mut self, chain_id: u64) -> Self {
89 self.chain_id = chain_id;
90 self
91 }
92
93 pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
94 CfgEnv {
95 chain_id: self.chain_id,
96 limit_contract_code_size: self.limit_contract_code_size,
97 spec,
98 disable_nonce_check: self.disable_nonce_check,
99 blob_target_and_max_count: self.blob_target_and_max_count,
100 #[cfg(feature = "memory_limit")]
101 memory_limit: self.memory_limit,
102 #[cfg(feature = "optional_balance_check")]
103 disable_balance_check: self.disable_balance_check,
104 #[cfg(feature = "optional_block_gas_limit")]
105 disable_block_gas_limit: self.disable_block_gas_limit,
106 #[cfg(feature = "optional_eip3607")]
107 disable_eip3607: self.disable_eip3607,
108 #[cfg(feature = "optional_gas_refund")]
109 disable_gas_refund: self.disable_gas_refund,
110 #[cfg(feature = "optional_no_base_fee")]
111 disable_base_fee: self.disable_base_fee,
112 }
113 }
114
115 pub fn set_blob_max_and_target_count(&mut self, mut vec: Vec<(SpecId, u8, u8)>) {
117 vec.sort_by_key(|(id, _, _)| *id);
118 self.blob_target_and_max_count = vec;
119 }
120}
121
122impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
123 type Spec = SPEC;
124
125 fn chain_id(&self) -> u64 {
126 self.chain_id
127 }
128
129 fn spec(&self) -> Self::Spec {
130 self.spec
131 }
132
133 #[inline]
134 fn blob_max_count(&self, spec_id: SpecId) -> u8 {
135 self.blob_target_and_max_count
136 .iter()
137 .rev()
138 .find_map(|(id, _, max)| {
139 if spec_id as u8 >= *id as u8 {
140 return Some(*max);
141 }
142 None
143 })
144 .unwrap_or(6)
145 }
146
147 fn max_code_size(&self) -> usize {
148 self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE)
149 }
150
151 fn is_eip3607_disabled(&self) -> bool {
152 cfg_if::cfg_if! {
153 if #[cfg(feature = "optional_eip3607")] {
154 self.disable_eip3607
155 } else {
156 false
157 }
158 }
159 }
160
161 fn is_balance_check_disabled(&self) -> bool {
162 cfg_if::cfg_if! {
163 if #[cfg(feature = "optional_balance_check")] {
164 self.disable_balance_check
165 } else {
166 false
167 }
168 }
169 }
170
171 fn is_gas_refund_disabled(&self) -> bool {
172 cfg_if::cfg_if! {
173 if #[cfg(feature = "optional_gas_refund")] {
174 self.disable_gas_refund
175 } else {
176 false
177 }
178 }
179 }
180
181 fn is_block_gas_limit_disabled(&self) -> bool {
182 cfg_if::cfg_if! {
183 if #[cfg(feature = "optional_block_gas_limit")] {
184 self.disable_block_gas_limit
185 } else {
186 false
187 }
188 }
189 }
190
191 fn is_nonce_check_disabled(&self) -> bool {
192 self.disable_nonce_check
193 }
194
195 fn is_base_fee_check_disabled(&self) -> bool {
196 cfg_if::cfg_if! {
197 if #[cfg(feature = "optional_no_base_fee")] {
198 self.disable_base_fee
199 } else {
200 false
201 }
202 }
203 }
204}
205
206impl<SPEC: Default> Default for CfgEnv<SPEC> {
207 fn default() -> Self {
208 Self {
209 chain_id: 1,
210 limit_contract_code_size: None,
211 spec: Default::default(),
212 disable_nonce_check: false,
213 blob_target_and_max_count: vec![(SpecId::CANCUN, 3, 6), (SpecId::PRAGUE, 6, 9)],
214 #[cfg(feature = "memory_limit")]
215 memory_limit: (1 << 32) - 1,
216 #[cfg(feature = "optional_balance_check")]
217 disable_balance_check: false,
218 #[cfg(feature = "optional_block_gas_limit")]
219 disable_block_gas_limit: false,
220 #[cfg(feature = "optional_eip3607")]
221 disable_eip3607: false,
222 #[cfg(feature = "optional_gas_refund")]
223 disable_gas_refund: false,
224 #[cfg(feature = "optional_no_base_fee")]
225 disable_base_fee: false,
226 }
227 }
228}
229
230#[cfg(test)]
231mod test {
232 use super::*;
233
234 #[test]
235 fn blob_max_and_target_count() {
236 let cfg: CfgEnv = Default::default();
237 assert_eq!(cfg.blob_max_count(SpecId::BERLIN), (6));
238 assert_eq!(cfg.blob_max_count(SpecId::CANCUN), (6));
239 assert_eq!(cfg.blob_max_count(SpecId::PRAGUE), (9));
240 assert_eq!(cfg.blob_max_count(SpecId::OSAKA), (9));
241 }
242}