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, u8, u8)>,
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 set_blob_max_and_target_count(&mut self, mut vec: Vec<(SpecId, u8, u8)>) {
125 vec.sort_by_key(|(id, _, _)| *id);
126 self.blob_target_and_max_count = vec;
127 }
128}
129
130impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
131 type Spec = SPEC;
132
133 fn chain_id(&self) -> u64 {
134 self.chain_id
135 }
136
137 fn spec(&self) -> Self::Spec {
138 self.spec
139 }
140
141 #[inline]
142 fn blob_max_count(&self, spec_id: SpecId) -> u8 {
143 self.blob_target_and_max_count
144 .iter()
145 .rev()
146 .find_map(|(id, _, max)| {
147 if spec_id as u8 >= *id as u8 {
148 return Some(*max);
149 }
150 None
151 })
152 .unwrap_or(6)
153 }
154
155 fn max_code_size(&self) -> usize {
156 self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE)
157 }
158
159 fn is_eip3607_disabled(&self) -> bool {
160 cfg_if::cfg_if! {
161 if #[cfg(feature = "optional_eip3607")] {
162 self.disable_eip3607
163 } else {
164 false
165 }
166 }
167 }
168
169 fn is_balance_check_disabled(&self) -> bool {
170 cfg_if::cfg_if! {
171 if #[cfg(feature = "optional_balance_check")] {
172 self.disable_balance_check
173 } else {
174 false
175 }
176 }
177 }
178
179 fn is_block_gas_limit_disabled(&self) -> bool {
181 cfg_if::cfg_if! {
182 if #[cfg(feature = "optional_block_gas_limit")] {
183 self.disable_block_gas_limit
184 } else {
185 false
186 }
187 }
188 }
189
190 fn is_nonce_check_disabled(&self) -> bool {
191 self.disable_nonce_check
192 }
193
194 fn is_base_fee_check_disabled(&self) -> bool {
195 cfg_if::cfg_if! {
196 if #[cfg(feature = "optional_no_base_fee")] {
197 self.disable_base_fee
198 } else {
199 false
200 }
201 }
202 }
203}
204
205impl<SPEC: Default> Default for CfgEnv<SPEC> {
206 fn default() -> Self {
207 Self::new_with_spec(SPEC::default())
208 }
209}
210
211#[cfg(test)]
212mod test {
213 use super::*;
214
215 #[test]
216 fn blob_max_and_target_count() {
217 let cfg: CfgEnv = Default::default();
218 assert_eq!(cfg.blob_max_count(SpecId::BERLIN), (6));
219 assert_eq!(cfg.blob_max_count(SpecId::CANCUN), (6));
220 assert_eq!(cfg.blob_max_count(SpecId::PRAGUE), (9));
221 assert_eq!(cfg.blob_max_count(SpecId::OSAKA), (9));
222 }
223}