1use std::collections::HashMap;
19use ethereum_types::U256;
20
21#[derive(Debug)]
23pub enum VersionedSchedule {
24	PWasm,
25}
26
27#[derive(Debug)]
29pub struct Schedule {
30	pub exceptional_failed_code_deposit: bool,
32	pub have_delegate_call: bool,
34	pub have_create2: bool,
36	pub have_revert: bool,
38	pub have_extcodehash: bool,
40	pub stack_limit: usize,
42	pub max_depth: usize,
44	pub tier_step_gas: [usize; 8],
46	pub exp_gas: usize,
48	pub exp_byte_gas: usize,
50	pub sha3_gas: usize,
52	pub sha3_word_gas: usize,
54	pub sload_gas: usize,
56	pub sstore_dirty_gas: Option<usize>,
58	pub sstore_set_gas: usize,
60	pub sstore_reset_gas: usize,
62	pub sstore_refund_gas: usize,
64	pub jumpdest_gas: usize,
66	pub log_gas: usize,
68	pub log_data_gas: usize,
70	pub log_topic_gas: usize,
72	pub create_gas: usize,
74	pub call_gas: usize,
76	pub call_stipend: usize,
78	pub call_value_transfer_gas: usize,
80	pub call_new_account_gas: usize,
82	pub suicide_refund_gas: usize,
84	pub memory_gas: usize,
86	pub quad_coeff_div: usize,
88	pub create_data_gas: usize,
90	pub create_data_limit: usize,
92	pub tx_gas: usize,
94	pub tx_create_gas: usize,
96	pub tx_data_zero_gas: usize,
98	pub tx_data_non_zero_gas: usize,
100	pub copy_gas: usize,
102	pub extcodesize_gas: usize,
104	pub extcodecopy_base_gas: usize,
106	pub balance_gas: usize,
108	pub extcodehash_gas: usize,
110	pub suicide_gas: usize,
112	pub suicide_to_new_account_cost: usize,
114	pub sub_gas_cap_divisor: Option<usize>,
117	pub no_empty: bool,
119	pub kill_empty: bool,
121	pub blockhash_gas: usize,
123	pub have_static_call: bool,
125	pub have_return_data: bool,
127	pub have_bitwise_shifting: bool,
129	pub have_chain_id: bool,
131	pub have_selfbalance: bool,
133	pub kill_dust: CleanDustMode,
135	pub eip1283: bool,
137	pub eip1706: bool,
139	pub keep_unsigned_nonce: bool,
141	pub latest_version: U256,
143	pub versions: HashMap<U256, VersionedSchedule>,
145	pub wasm: Option<WasmCosts>,
147}
148
149#[derive(Debug)]
151pub struct WasmCosts {
152	pub regular: u32,
154	pub div: u32,
156	pub mul: u32,
158	pub mem: u32,
160	pub static_u256: u32,
162	pub static_address: u32,
164	pub initial_mem: u32,
166	pub grow_mem: u32,
168	pub memcpy: u32,
170	pub max_stack_height: u32,
172	pub opcodes_mul: u32,
174	pub opcodes_div: u32,
176	pub have_create2: bool,
178	pub have_gasleft: bool,
180}
181
182impl Default for WasmCosts {
183	fn default() -> Self {
184		WasmCosts {
185			regular: 1,
186			div: 16,
187			mul: 4,
188			mem: 2,
189			static_u256: 64,
190			static_address: 40,
191			initial_mem: 4096,
192			grow_mem: 8192,
193			memcpy: 1,
194			max_stack_height: 64*1024,
195			opcodes_mul: 3,
196			opcodes_div: 8,
197			have_create2: false,
198			have_gasleft: false,
199		}
200	}
201}
202
203#[derive(Debug, PartialEq, Eq)]
205pub enum CleanDustMode {
206	Off,
208	BasicOnly,
210	WithCodeAndStorage,
212}
213
214impl Schedule {
215	pub fn new_frontier() -> Schedule {
217		Self::new(false, false, 21000)
218	}
219
220	pub fn new_homestead() -> Schedule {
222		Self::new(true, true, 53000)
223	}
224
225	pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule {
227		Schedule {
228			exceptional_failed_code_deposit: true,
229			have_delegate_call: true,
230			have_create2: false,
231			have_revert: false,
232			have_return_data: false,
233			have_bitwise_shifting: false,
234			have_chain_id: false,
235			have_selfbalance: false,
236			have_extcodehash: false,
237			stack_limit: 1024,
238			max_depth: 1024,
239			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
240			exp_gas: 10,
241			exp_byte_gas: if fix_exp {50} else {10},
242			sha3_gas: 30,
243			sha3_word_gas: 6,
244			sload_gas: 200,
245			sstore_dirty_gas: None,
246			sstore_set_gas: 20000,
247			sstore_reset_gas: 5000,
248			sstore_refund_gas: 15000,
249			jumpdest_gas: 1,
250			log_gas: 375,
251			log_data_gas: 8,
252			log_topic_gas: 375,
253			create_gas: 32000,
254			call_gas: 700,
255			call_stipend: 2300,
256			call_value_transfer_gas: 9000,
257			call_new_account_gas: 25000,
258			suicide_refund_gas: 24000,
259			memory_gas: 3,
260			quad_coeff_div: 512,
261			create_data_gas: 200,
262			create_data_limit: max_code_size,
263			tx_gas: 21000,
264			tx_create_gas: 53000,
265			tx_data_zero_gas: 4,
266			tx_data_non_zero_gas: 68,
267			copy_gas: 3,
268			extcodesize_gas: 700,
269			extcodecopy_base_gas: 700,
270			extcodehash_gas: 400,
271			balance_gas: 400,
272			suicide_gas: 5000,
273			suicide_to_new_account_cost: 25000,
274			sub_gas_cap_divisor: Some(64),
275			no_empty: no_empty,
276			kill_empty: kill_empty,
277			blockhash_gas: 20,
278			have_static_call: false,
279			kill_dust: CleanDustMode::Off,
280			eip1283: false,
281			eip1706: false,
282			keep_unsigned_nonce: false,
283			latest_version: U256::zero(),
284			versions: HashMap::new(),
285			wasm: None,
286		}
287	}
288
289	pub fn new_byzantium() -> Schedule {
291		let mut schedule = Self::new_post_eip150(24576, true, true, true);
292		schedule.have_create2 = true;
293		schedule.have_revert = true;
294		schedule.have_static_call = true;
295		schedule.have_return_data = true;
296		schedule
297	}
298
299	pub fn new_constantinople() -> Schedule {
301		let mut schedule = Self::new_byzantium();
302		schedule.have_bitwise_shifting = true;
303		schedule
304	}
305
306	pub fn new_istanbul() -> Schedule {
308		let mut schedule = Self::new_constantinople();
309		schedule.have_chain_id = true; schedule.tx_data_non_zero_gas = 16; schedule.sload_gas = 800; schedule.balance_gas = 700; schedule.extcodehash_gas = 700; schedule.have_selfbalance = true; schedule
316	}
317
318	fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
319		Schedule {
320			exceptional_failed_code_deposit: efcd,
321			have_delegate_call: hdc,
322			have_create2: false,
323			have_revert: false,
324			have_return_data: false,
325			have_bitwise_shifting: false,
326			have_chain_id: false,
327			have_selfbalance: false,
328			have_extcodehash: false,
329			stack_limit: 1024,
330			max_depth: 1024,
331			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
332			exp_gas: 10,
333			exp_byte_gas: 10,
334			sha3_gas: 30,
335			sha3_word_gas: 6,
336			sload_gas: 50,
337			sstore_dirty_gas: None,
338			sstore_set_gas: 20000,
339			sstore_reset_gas: 5000,
340			sstore_refund_gas: 15000,
341			jumpdest_gas: 1,
342			log_gas: 375,
343			log_data_gas: 8,
344			log_topic_gas: 375,
345			create_gas: 32000,
346			call_gas: 40,
347			call_stipend: 2300,
348			call_value_transfer_gas: 9000,
349			call_new_account_gas: 25000,
350			suicide_refund_gas: 24000,
351			memory_gas: 3,
352			quad_coeff_div: 512,
353			create_data_gas: 200,
354			create_data_limit: usize::max_value(),
355			tx_gas: 21000,
356			tx_create_gas: tcg,
357			tx_data_zero_gas: 4,
358			tx_data_non_zero_gas: 68,
359			copy_gas: 3,
360			extcodesize_gas: 20,
361			extcodecopy_base_gas: 20,
362			extcodehash_gas: 400,
363			balance_gas: 20,
364			suicide_gas: 0,
365			suicide_to_new_account_cost: 0,
366			sub_gas_cap_divisor: None,
367			no_empty: false,
368			kill_empty: false,
369			blockhash_gas: 20,
370			have_static_call: false,
371			kill_dust: CleanDustMode::Off,
372			eip1283: false,
373			eip1706: false,
374			keep_unsigned_nonce: false,
375			latest_version: U256::zero(),
376			versions: HashMap::new(),
377			wasm: None,
378		}
379	}
380
381	pub fn wasm(&self) -> &WasmCosts {
385		self.wasm.as_ref().expect("Wasm schedule expected to exist while checking wasm contract. Misconfigured client?")
387	}
388}
389
390impl Default for Schedule {
391	fn default() -> Self {
392		Schedule::new_frontier()
393	}
394}
395
396#[test]
397#[cfg(test)]
398fn schedule_evm_assumptions() {
399	let s1 = Schedule::new_frontier();
400	let s2 = Schedule::new_homestead();
401
402	assert_eq!(s1.quad_coeff_div, 512);
404	assert_eq!(s2.quad_coeff_div, 512);
405}