evm/standard/
config.rs

1use evm_interpreter::runtime::RuntimeConfig;
2
3/// Runtime configuration.
4#[derive(Clone, Debug)]
5#[non_exhaustive]
6pub struct Config {
7	/// Runtime config.
8	pub runtime: RuntimeConfig,
9	/// Disallow empty contract creation.
10	pub eip2_no_empty_contract: bool,
11	/// Increase contract creation transaction cost.
12	pub eip2_create_transaction_increase: bool,
13	/// EIP-1884: trie repricing.
14	pub eip1884_trie_repricing: bool,
15	/// EIP-1283.
16	pub eip2200_sstore_gas_metering: bool,
17	/// EIP-1706.
18	pub eip2200_sstore_revert_under_stipend: bool,
19	/// EIP-2929
20	pub eip2929_increase_state_access_gas: bool,
21	/// EIP-3529
22	pub eip3529_decrease_clears_refund: bool,
23	/// EIP-3541
24	pub eip3541_disallow_executable_format: bool,
25	/// Gas increases of EIP150.
26	pub eip150_gas_increase: bool,
27	/// Whether to throw out of gas error when
28	/// CALL/CALLCODE/DELEGATECALL requires more than maximum amount
29	/// of gas.
30	pub eip150_no_err_on_call_with_more_gas: bool,
31	/// Take l64 for callcreate after gas.
32	pub eip150_call_l64_after_gas: bool,
33	/// Whether create transactions and create opcode increases nonce by one.
34	pub eip161_create_increase_nonce: bool,
35	/// EIP170.
36	pub eip170_create_contract_limit: bool,
37	/// EIP-3860, maximum size limit of init_code.
38	pub eip3860_max_initcode_size: bool,
39	/// Has delegate call.
40	pub eip7_delegate_call: bool,
41	/// Has create2.
42	pub eip1014_create2: bool,
43	/// Has revert.
44	pub eip140_revert: bool,
45	/// EIP160.
46	pub eip160_exp_increase: bool,
47	/// Has return data.
48	pub eip211_return_data: bool,
49	/// Static call.
50	pub eip214_static_call: bool,
51	/// Has bitwise shifting.
52	pub eip145_bitwise_shifting: bool,
53	/// Has chain ID.
54	pub eip1344_chain_id: bool,
55	/// Has self balance.
56	pub eip1884_self_balance: bool,
57	/// Has ext code hash.
58	pub eip1052_ext_code_hash: bool,
59	/// Has ext block fee. See [EIP-3198](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3198.md)
60	pub eip3198_base_fee: bool,
61	/// Has PUSH0 opcode. See [EIP-3855](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3855.md)
62	pub eip3855_push0: bool,
63	/// Enables transient storage. See [EIP-1153](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1153.md)
64	pub eip1153_transient_storage: bool,
65	/// Enables MCOPY instruction. See [EIP-5656](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-5656.md)
66	pub eip5656_mcopy: bool,
67	/// Uses EIP-1559 (Base fee is burned when this flag is enabled) [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)
68	pub eip1559_fee_market: bool,
69	/// Call data gas cost reduction.
70	pub eip2028_transaction_calldata_decrease: bool,
71	/// EIP-198: Modexp precompile.
72	pub eip198_modexp_precompile: bool,
73	/// EIP-196: EC ADD/MUL precompile.
74	pub eip196_ec_add_mul_precompile: bool,
75	/// EIP-197: EC Pairing precompile.
76	pub eip197_ec_pairing_precompile: bool,
77	/// EIP-152: Blake2F precompile.
78	pub eip152_blake_2f_precompile: bool,
79	/// EIP-1108: Reduce EC ADD/MUL/Pairing costs.
80	pub eip1108_ec_add_mul_pairing_decrease: bool,
81	/// EIP-2565.
82	pub eip2565_lower_modexp: bool,
83	/// EIP-2930: Optional access list.
84	pub eip2930_access_list: bool,
85	/// EIP-4844: Shard blob.
86	pub eip4844_shard_blob: bool,
87	/// EIP-7516: Blob base fee per gas.
88	pub eip7516_blob_base_fee: bool,
89	/// EIP-7623: Increase calldata cost with floor.
90	pub eip7623_calldata_floor: bool,
91}
92
93impl Config {
94	/// Frontier hard fork configuration.
95	pub const fn frontier() -> Config {
96		Config {
97			runtime: RuntimeConfig::frontier(),
98			eip2_no_empty_contract: false,
99			eip2_create_transaction_increase: false,
100			eip2200_sstore_gas_metering: false,
101			eip2200_sstore_revert_under_stipend: false,
102			eip2929_increase_state_access_gas: false,
103			eip3529_decrease_clears_refund: false,
104			eip3541_disallow_executable_format: false,
105			eip150_no_err_on_call_with_more_gas: false,
106			eip161_create_increase_nonce: false,
107			eip150_call_l64_after_gas: false,
108			eip170_create_contract_limit: false,
109			eip3860_max_initcode_size: false,
110			eip7_delegate_call: false,
111			eip1014_create2: false,
112			eip140_revert: false,
113			eip211_return_data: false,
114			eip145_bitwise_shifting: false,
115			eip1344_chain_id: false,
116			eip1884_self_balance: false,
117			eip1052_ext_code_hash: false,
118			eip3198_base_fee: false,
119			eip3855_push0: false,
120			eip1153_transient_storage: false,
121			eip5656_mcopy: false,
122			eip1559_fee_market: false,
123			eip198_modexp_precompile: false,
124			eip196_ec_add_mul_precompile: false,
125			eip197_ec_pairing_precompile: false,
126			eip152_blake_2f_precompile: false,
127			eip150_gas_increase: false,
128			eip160_exp_increase: false,
129			eip1884_trie_repricing: false,
130			eip214_static_call: false,
131			eip1108_ec_add_mul_pairing_decrease: false,
132			eip2028_transaction_calldata_decrease: false,
133			eip2565_lower_modexp: false,
134			eip2930_access_list: false,
135			eip4844_shard_blob: false,
136			eip7516_blob_base_fee: false,
137			eip7623_calldata_floor: false,
138		}
139	}
140
141	/// Homestead
142	pub const fn homestead() -> Config {
143		let mut config = Self::frontier();
144		config.eip2_no_empty_contract = true;
145		config.eip2_create_transaction_increase = true;
146		config.eip7_delegate_call = true;
147		config
148	}
149
150	/// Tangerine whistle
151	pub const fn tangerine_whistle() -> Config {
152		let mut config = Self::homestead();
153		config.eip150_gas_increase = true;
154		config.eip150_no_err_on_call_with_more_gas = true;
155		config.eip150_call_l64_after_gas = true;
156		config
157	}
158
159	/// Spurious dragon
160	pub const fn spurious_dragon() -> Config {
161		let mut config = Self::tangerine_whistle();
162		config.runtime.eip161_empty_check = true;
163		config.eip161_create_increase_nonce = true;
164		config.eip160_exp_increase = true;
165		config.eip170_create_contract_limit = true;
166		config
167	}
168
169	/// Byzantium
170	pub const fn byzantium() -> Config {
171		let mut config = Self::spurious_dragon();
172		config.eip140_revert = true;
173		config.eip196_ec_add_mul_precompile = true;
174		config.eip197_ec_pairing_precompile = true;
175		config.eip198_modexp_precompile = true;
176		config.eip211_return_data = true;
177		config.eip214_static_call = true;
178		config
179	}
180
181	/// Petersburg
182	pub const fn petersburg() -> Config {
183		let mut config = Self::byzantium();
184		config.eip145_bitwise_shifting = true;
185		config.eip1014_create2 = true;
186		config.eip1052_ext_code_hash = true;
187		config
188	}
189
190	/// Istanbul hard fork configuration.
191	pub const fn istanbul() -> Config {
192		let mut config = Self::petersburg();
193		config.eip152_blake_2f_precompile = true;
194		config.eip1108_ec_add_mul_pairing_decrease = true;
195		config.eip1344_chain_id = true;
196		config.eip1884_trie_repricing = true;
197		config.eip1884_self_balance = true;
198		config.eip2028_transaction_calldata_decrease = true;
199		config.eip2200_sstore_gas_metering = true;
200		config.eip2200_sstore_revert_under_stipend = true;
201		config
202	}
203
204	/// Berlin
205	pub const fn berlin() -> Config {
206		let mut config = Self::istanbul();
207		config.eip2565_lower_modexp = true;
208		config.eip2929_increase_state_access_gas = true;
209		config.eip2930_access_list = true;
210		config
211	}
212
213	/// London
214	pub const fn london() -> Config {
215		let mut config = Self::berlin();
216		config.eip1559_fee_market = true;
217		config.eip3198_base_fee = true;
218		config.eip3529_decrease_clears_refund = true;
219		config.eip3541_disallow_executable_format = true;
220		config
221	}
222
223	/// Shanghai
224	pub const fn shanghai() -> Config {
225		let mut config = Self::london();
226		config.runtime.eip3651_warm_coinbase_address = true;
227		config.eip3855_push0 = true;
228		config.eip3860_max_initcode_size = true;
229		config
230	}
231
232	/// Cancun
233	pub const fn cancun() -> Config {
234		let mut config = Self::shanghai();
235		config.eip1153_transient_storage = true;
236		config.eip5656_mcopy = true;
237		config.runtime.eip6780_suicide_only_in_same_tx = true;
238		config.eip4844_shard_blob = true;
239		config.eip7516_blob_base_fee = true;
240		config
241	}
242
243	/// Prague
244	pub const fn prague() -> Config {
245		let mut config = Self::cancun();
246		config.eip7623_calldata_floor = true;
247		config
248	}
249
250	/// Gas paid for extcode.
251	pub fn gas_ext_code(&self) -> u64 {
252		if self.eip150_gas_increase { 700 } else { 20 }
253	}
254
255	/// Gas paid for extcodehash.
256	pub fn gas_ext_code_hash(&self) -> u64 {
257		if self.eip1884_trie_repricing {
258			700
259		} else {
260			400
261		}
262	}
263
264	/// Gas paid for sstore set.
265	pub fn gas_sstore_set(&self) -> u64 {
266		20000
267	}
268
269	/// Gas paid for sstore reset.
270	pub fn gas_sstore_reset(&self) -> u64 {
271		if self.eip2929_increase_state_access_gas {
272			2900
273		} else {
274			5000
275		}
276	}
277
278	/// Gas paid for sstore refund.
279	pub fn refund_sstore_clears(&self) -> i64 {
280		if self.eip3529_decrease_clears_refund {
281			4800
282		} else {
283			15000
284		}
285	}
286
287	/// EIP-3529
288	pub fn max_refund_quotient(&self) -> u64 {
289		if self.eip3529_decrease_clears_refund {
290			5
291		} else {
292			2
293		}
294	}
295
296	/// Gas paid for BALANCE opcode.
297	pub fn gas_balance(&self) -> u64 {
298		if self.eip1884_trie_repricing {
299			700
300		} else if self.eip150_gas_increase {
301			400
302		} else {
303			20
304		}
305	}
306
307	/// Gas paid for SLOAD opcode.
308	pub fn gas_sload(&self) -> u64 {
309		if self.eip2929_increase_state_access_gas {
310			100
311		} else if self.eip2200_sstore_gas_metering {
312			800
313		} else if self.eip150_gas_increase {
314			200
315		} else {
316			50
317		}
318	}
319
320	/// Gas paid for cold SLOAD opcode.
321	pub fn gas_sload_cold(&self) -> u64 {
322		if self.eip2929_increase_state_access_gas {
323			2100
324		} else {
325			0
326		}
327	}
328
329	/// Gas paid for SUICIDE opcode.
330	pub fn gas_suicide(&self) -> u64 {
331		if self.eip150_gas_increase { 5000 } else { 0 }
332	}
333
334	/// Gas paid for SUICIDE opcode when it hits a new account.
335	pub fn gas_suicide_new_account(&self) -> u64 {
336		if self.eip150_gas_increase { 25000 } else { 0 }
337	}
338
339	/// Gas paid for CALL opcode.
340	pub fn gas_call(&self) -> u64 {
341		if self.eip150_gas_increase { 700 } else { 40 }
342	}
343
344	/// Gas paid for EXP opcode for every byte.
345	pub fn gas_expbyte(&self) -> u64 {
346		if self.eip160_exp_increase { 50 } else { 10 }
347	}
348
349	/// Gas paid for a contract creation transaction.
350	pub fn gas_transaction_create(&self) -> u64 {
351		if self.eip2_create_transaction_increase {
352			53000
353		} else {
354			21000
355		}
356	}
357
358	/// Gas paid for a message call transaction.
359	pub fn gas_transaction_call(&self) -> u64 {
360		21000
361	}
362
363	/// Gas paid for zero data in a transaction.
364	pub fn gas_transaction_zero_data(&self) -> u64 {
365		4
366	}
367
368	/// Gas paid for non-zero data in a transaction.
369	pub fn gas_transaction_non_zero_data(&self) -> u64 {
370		if self.eip2028_transaction_calldata_decrease {
371			16
372		} else {
373			68
374		}
375	}
376
377	/// Floor gas paid for zero data in a transaction.
378	pub fn gas_floor_transaction_zero_data(&self) -> u64 {
379		if self.eip7623_calldata_floor { 10 } else { 0 }
380	}
381
382	/// Floor gas paid for non-zero data in a transaction.
383	pub fn gas_floor_transaction_non_zero_data(&self) -> u64 {
384		if self.eip7623_calldata_floor { 40 } else { 0 }
385	}
386
387	/// Gas paid per address in transaction access list (see EIP-2930).
388	pub fn gas_access_list_address(&self) -> u64 {
389		if self.eip2930_access_list { 2400 } else { 0 }
390	}
391
392	/// Gas paid per storage key in transaction access list (see EIP-2930).
393	pub fn gas_access_list_storage_key(&self) -> u64 {
394		if self.eip2930_access_list { 1900 } else { 0 }
395	}
396
397	/// Gas paid for accessing cold account.
398	pub fn gas_account_access_cold(&self) -> u64 {
399		if self.eip2929_increase_state_access_gas {
400			2600
401		} else {
402			0
403		}
404	}
405
406	/// Gas paid for accessing ready storage.
407	pub fn gas_storage_read_warm(&self) -> u64 {
408		if self.eip2929_increase_state_access_gas {
409			100
410		} else {
411			0
412		}
413	}
414
415	/// Stack limit.
416	pub fn stack_limit(&self) -> usize {
417		1024
418	}
419
420	/// Memory limit.
421	pub fn memory_limit(&self) -> usize {
422		usize::MAX
423	}
424
425	/// Call stack limit.
426	pub fn call_stack_limit(&self) -> usize {
427		1024
428	}
429
430	/// Call stipend.
431	pub fn call_stipend(&self) -> u64 {
432		2300
433	}
434
435	/// Maximum size limit of init code.
436	pub fn max_initcode_size(&self) -> Option<usize> {
437		if self.eip3860_max_initcode_size {
438			Some(0xc000)
439		} else {
440			None
441		}
442	}
443
444	/// Create contract limit.
445	pub fn create_contract_limit(&self) -> Option<usize> {
446		if self.eip170_create_contract_limit {
447			Some(0x6000)
448		} else {
449			None
450		}
451	}
452}