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}