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