use std::collections::HashMap;
use ethereum_types::U256;
#[derive(Debug)]
pub enum VersionedSchedule {
PWasm,
}
#[derive(Debug)]
pub struct Schedule {
pub exceptional_failed_code_deposit: bool,
pub have_delegate_call: bool,
pub have_create2: bool,
pub have_revert: bool,
pub have_extcodehash: bool,
pub stack_limit: usize,
pub max_depth: usize,
pub tier_step_gas: [usize; 8],
pub exp_gas: usize,
pub exp_byte_gas: usize,
pub sha3_gas: usize,
pub sha3_word_gas: usize,
pub sload_gas: usize,
pub sstore_dirty_gas: Option<usize>,
pub sstore_set_gas: usize,
pub sstore_reset_gas: usize,
pub sstore_refund_gas: usize,
pub jumpdest_gas: usize,
pub log_gas: usize,
pub log_data_gas: usize,
pub log_topic_gas: usize,
pub create_gas: usize,
pub call_gas: usize,
pub call_stipend: usize,
pub call_value_transfer_gas: usize,
pub call_new_account_gas: usize,
pub suicide_refund_gas: usize,
pub memory_gas: usize,
pub quad_coeff_div: usize,
pub create_data_gas: usize,
pub create_data_limit: usize,
pub tx_gas: usize,
pub tx_create_gas: usize,
pub tx_data_zero_gas: usize,
pub tx_data_non_zero_gas: usize,
pub copy_gas: usize,
pub extcodesize_gas: usize,
pub extcodecopy_base_gas: usize,
pub balance_gas: usize,
pub extcodehash_gas: usize,
pub suicide_gas: usize,
pub suicide_to_new_account_cost: usize,
pub sub_gas_cap_divisor: Option<usize>,
pub no_empty: bool,
pub kill_empty: bool,
pub blockhash_gas: usize,
pub have_static_call: bool,
pub have_return_data: bool,
pub have_bitwise_shifting: bool,
pub have_chain_id: bool,
pub have_selfbalance: bool,
pub kill_dust: CleanDustMode,
pub eip1283: bool,
pub eip1706: bool,
pub keep_unsigned_nonce: bool,
pub latest_version: U256,
pub versions: HashMap<U256, VersionedSchedule>,
pub wasm: Option<WasmCosts>,
}
#[derive(Debug)]
pub struct WasmCosts {
pub regular: u32,
pub div: u32,
pub mul: u32,
pub mem: u32,
pub static_u256: u32,
pub static_address: u32,
pub initial_mem: u32,
pub grow_mem: u32,
pub memcpy: u32,
pub max_stack_height: u32,
pub opcodes_mul: u32,
pub opcodes_div: u32,
pub have_create2: bool,
pub have_gasleft: bool,
}
impl Default for WasmCosts {
fn default() -> Self {
WasmCosts {
regular: 1,
div: 16,
mul: 4,
mem: 2,
static_u256: 64,
static_address: 40,
initial_mem: 4096,
grow_mem: 8192,
memcpy: 1,
max_stack_height: 64*1024,
opcodes_mul: 3,
opcodes_div: 8,
have_create2: false,
have_gasleft: false,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum CleanDustMode {
Off,
BasicOnly,
WithCodeAndStorage,
}
impl Schedule {
pub fn new_frontier() -> Schedule {
Self::new(false, false, 21000)
}
pub fn new_homestead() -> Schedule {
Self::new(true, true, 53000)
}
pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule {
Schedule {
exceptional_failed_code_deposit: true,
have_delegate_call: true,
have_create2: false,
have_revert: false,
have_return_data: false,
have_bitwise_shifting: false,
have_chain_id: false,
have_selfbalance: false,
have_extcodehash: false,
stack_limit: 1024,
max_depth: 1024,
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
exp_gas: 10,
exp_byte_gas: if fix_exp {50} else {10},
sha3_gas: 30,
sha3_word_gas: 6,
sload_gas: 200,
sstore_dirty_gas: None,
sstore_set_gas: 20000,
sstore_reset_gas: 5000,
sstore_refund_gas: 15000,
jumpdest_gas: 1,
log_gas: 375,
log_data_gas: 8,
log_topic_gas: 375,
create_gas: 32000,
call_gas: 700,
call_stipend: 2300,
call_value_transfer_gas: 9000,
call_new_account_gas: 25000,
suicide_refund_gas: 24000,
memory_gas: 3,
quad_coeff_div: 512,
create_data_gas: 200,
create_data_limit: max_code_size,
tx_gas: 21000,
tx_create_gas: 53000,
tx_data_zero_gas: 4,
tx_data_non_zero_gas: 68,
copy_gas: 3,
extcodesize_gas: 700,
extcodecopy_base_gas: 700,
extcodehash_gas: 400,
balance_gas: 400,
suicide_gas: 5000,
suicide_to_new_account_cost: 25000,
sub_gas_cap_divisor: Some(64),
no_empty: no_empty,
kill_empty: kill_empty,
blockhash_gas: 20,
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip1283: false,
eip1706: false,
keep_unsigned_nonce: false,
latest_version: U256::zero(),
versions: HashMap::new(),
wasm: None,
}
}
pub fn new_byzantium() -> Schedule {
let mut schedule = Self::new_post_eip150(24576, true, true, true);
schedule.have_create2 = true;
schedule.have_revert = true;
schedule.have_static_call = true;
schedule.have_return_data = true;
schedule
}
pub fn new_constantinople() -> Schedule {
let mut schedule = Self::new_byzantium();
schedule.have_bitwise_shifting = true;
schedule
}
pub fn new_istanbul() -> Schedule {
let mut schedule = Self::new_constantinople();
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
}
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
Schedule {
exceptional_failed_code_deposit: efcd,
have_delegate_call: hdc,
have_create2: false,
have_revert: false,
have_return_data: false,
have_bitwise_shifting: false,
have_chain_id: false,
have_selfbalance: false,
have_extcodehash: false,
stack_limit: 1024,
max_depth: 1024,
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
exp_gas: 10,
exp_byte_gas: 10,
sha3_gas: 30,
sha3_word_gas: 6,
sload_gas: 50,
sstore_dirty_gas: None,
sstore_set_gas: 20000,
sstore_reset_gas: 5000,
sstore_refund_gas: 15000,
jumpdest_gas: 1,
log_gas: 375,
log_data_gas: 8,
log_topic_gas: 375,
create_gas: 32000,
call_gas: 40,
call_stipend: 2300,
call_value_transfer_gas: 9000,
call_new_account_gas: 25000,
suicide_refund_gas: 24000,
memory_gas: 3,
quad_coeff_div: 512,
create_data_gas: 200,
create_data_limit: usize::max_value(),
tx_gas: 21000,
tx_create_gas: tcg,
tx_data_zero_gas: 4,
tx_data_non_zero_gas: 68,
copy_gas: 3,
extcodesize_gas: 20,
extcodecopy_base_gas: 20,
extcodehash_gas: 400,
balance_gas: 20,
suicide_gas: 0,
suicide_to_new_account_cost: 0,
sub_gas_cap_divisor: None,
no_empty: false,
kill_empty: false,
blockhash_gas: 20,
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip1283: false,
eip1706: false,
keep_unsigned_nonce: false,
latest_version: U256::zero(),
versions: HashMap::new(),
wasm: None,
}
}
pub fn wasm(&self) -> &WasmCosts {
self.wasm.as_ref().expect("Wasm schedule expected to exist while checking wasm contract. Misconfigured client?")
}
}
impl Default for Schedule {
fn default() -> Self {
Schedule::new_frontier()
}
}
#[test]
#[cfg(test)]
fn schedule_evm_assumptions() {
let s1 = Schedule::new_frontier();
let s2 = Schedule::new_homestead();
assert_eq!(s1.quad_coeff_div, 512);
assert_eq!(s2.quad_coeff_div, 512);
}