-
Notifications
You must be signed in to change notification settings - Fork 1.7k
EIP 1283: Net gas metering for SSTORE without dirty maps #9319
Changes from 12 commits
b7a9402
a082907
3ba5467
87a93c0
5f2e25c
9c56484
4861e35
11490b5
399abe8
f57853c
8909d6e
e4a6668
e2b5899
00ae258
fb99c74
3149c7f
c07d12f
971e82c
b1b7c57
b01c566
c2b9e97
7f672c3
6269c33
0e4ba15
196f831
14b89c2
f9af2c3
a718e90
f6aa738
ad8dc94
4d5555b
8b31417
72693d3
ab83e36
ef6a01c
aa6006e
aabc367
8a573a1
c31cc59
522f2e9
14283f8
ae73ed4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,13 +124,18 @@ impl<Gas: evm::CostType> Gasometer<Gas> { | |
let address = H256::from(stack.peek(0)); | ||
let newval = stack.peek(1); | ||
let val = U256::from(&*ext.storage_at(&address)?); | ||
let orig = U256::from(&*ext.reverted_storage_at(&address)?); | ||
|
||
let gas = if val.is_zero() && !newval.is_zero() { | ||
schedule.sstore_set_gas | ||
let gas = if schedule.eip1283 { | ||
calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could orig be initiated in this conditional branch ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You address it in your last commit (my comment was unclear) |
||
} else { | ||
// Refund for below case is added when actually executing sstore | ||
// !is_zero(&val) && is_zero(newval) | ||
schedule.sstore_reset_gas | ||
if val.is_zero() && !newval.is_zero() { | ||
schedule.sstore_set_gas | ||
} else { | ||
// Refund for below case is added when actually executing sstore | ||
// !is_zero(&val) && is_zero(newval) | ||
schedule.sstore_reset_gas | ||
} | ||
}; | ||
Request::Gas(Gas::from(gas)) | ||
}, | ||
|
@@ -342,6 +347,60 @@ fn add_gas_usize<Gas: evm::CostType>(value: Gas, num: usize) -> (Gas, bool) { | |
value.overflow_add(Gas::from(num)) | ||
} | ||
|
||
#[inline] | ||
fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas { | ||
Gas::from( | ||
if current == new { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe early-return pattern would look a bit better here instead of this nested ifs? match (current, new, original) {
(current, new, _) if current == new => schedule.sload_gas,
(current, _, original) if current != original => schedule.sload_gas,
(_, _, original) if original.is_zero() => schedule.sstore_set_gas,
_ => schedule.sstore_reset_gas,
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TBH I think for this, using if branches may be better. In that way we can directly follow the spec of each cause. Using match is indeed shorter, but I think it may actually be more confusing. |
||
schedule.sload_gas | ||
} else { | ||
if original == current { | ||
if original.is_zero() { | ||
schedule.sstore_set_gas | ||
} else { | ||
schedule.sstore_reset_gas | ||
} | ||
} else { | ||
schedule.sload_gas | ||
} | ||
} | ||
) | ||
} | ||
|
||
pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there may be issues doing this -- sometimes we need to issue two refunds at once, and the value itself can be either positive or negative. So returning a value instead of directly modifying ext would mean that we need extra codes to handle signed addition/subtraction. |
||
let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); | ||
|
||
if current == new { | ||
// No refund | ||
} else { | ||
if original == current { | ||
if original.is_zero() { | ||
// No refund | ||
} else { | ||
if new.is_zero() { | ||
ext.inc_sstore_refund(sstore_clears_schedule); | ||
} | ||
} | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code looks is similar to your eip description (great eip by the way), but it is not that easy to ensure that all state transition are covered just by reading it. So I find it useful to write a few additional comments for checking the algorithm: pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) {
let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas);
if current == new {
// No refund
} else {
if original == current {
if original.is_zero() {
// No refund
} else {
if new.is_zero() {
ext.inc_sstore_refund(sstore_clears_schedule);
}
}
} else {
// put in a `dirty_refund` function??
if !original.is_zero() {
// refund case
if current.is_zero() {
// a refund happened, revert refund
ext.dec_sstore_refund(sstore_clears_schedule);
} else if new.is_zero() {
// refund
ext.inc_sstore_refund(sstore_clears_schedule);
}
}
if original == new {
// reverting to init state
if original.is_zero() {
// revert sstore full cost (minus sload amount)
let refund = U256::from(ext.schedule().sstore_set_gas - ext.schedule().sload_gas);
ext.inc_sstore_refund(refund);
} else {
// revert sstore change cost (revert of refund done in previous conditions)
let refund = U256::from(ext.schedule().sstore_reset_gas - ext.schedule().sload_gas);
ext.inc_sstore_refund(refund);
}
}
}
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps pattern matching here as well? Not sure if it would be more readable though. |
||
if !original.is_zero() { | ||
if current.is_zero() { | ||
ext.dec_sstore_refund(sstore_clears_schedule); | ||
} else if new.is_zero() { | ||
ext.inc_sstore_refund(sstore_clears_schedule); | ||
} | ||
} | ||
if original == new { | ||
if original.is_zero() { | ||
let refund = U256::from(ext.schedule().sstore_set_gas - ext.schedule().sload_gas); | ||
ext.inc_sstore_refund(refund); | ||
} else { | ||
let refund = U256::from(ext.schedule().sstore_reset_gas - ext.schedule().sload_gas); | ||
ext.inc_sstore_refund(refund); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_mem_gas_cost() { | ||
// given | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -628,9 +628,15 @@ impl<Cost: CostType> Interpreter<Cost> { | |
let val = self.stack.pop_back(); | ||
|
||
let current_val = U256::from(&*ext.storage_at(&address)?); | ||
let original_val = U256::from(&*ext.reverted_storage_at(&address)?); | ||
// Increase refund for clear | ||
if !current_val.is_zero() && val.is_zero() { | ||
ext.inc_sstore_clears(); | ||
if ext.schedule().eip1283 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as earlier - we only need |
||
gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val); | ||
} else { | ||
if !current_val.is_zero() && val.is_zero() { | ||
let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); | ||
ext.inc_sstore_refund(sstore_clears_schedule); | ||
} | ||
} | ||
ext.set_storage(address, H256::from(&val))?; | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -172,6 +172,7 @@ pub struct Executive<'a, B: 'a> { | |
schedule: &'a Schedule, | ||
depth: usize, | ||
static_flag: bool, | ||
transaction_checkpoint_index: Option<usize>, | ||
} | ||
|
||
impl<'a, B: 'a + StateBackend> Executive<'a, B> { | ||
|
@@ -184,18 +185,20 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
schedule: schedule, | ||
depth: 0, | ||
static_flag: false, | ||
transaction_checkpoint_index: None, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a bit of comment I think. From what I understand it is to manage reentrant call by addressing the first checkpoint initial values; if it is the case renaming to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This value actually just means to be |
||
} | ||
} | ||
|
||
/// Populates executive from parent properties. Increments executive depth. | ||
pub fn from_parent(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine, schedule: &'a Schedule, parent_depth: usize, static_flag: bool) -> Self { | ||
pub fn from_parent(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine, schedule: &'a Schedule, parent_depth: usize, static_flag: bool, transaction_checkpoint_index: usize) -> Self { | ||
Executive { | ||
state: state, | ||
info: info, | ||
machine: machine, | ||
schedule: schedule, | ||
depth: parent_depth + 1, | ||
static_flag: static_flag, | ||
transaction_checkpoint_index: Some(transaction_checkpoint_index), | ||
} | ||
} | ||
|
||
|
@@ -208,9 +211,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
tracer: &'any mut T, | ||
vm_tracer: &'any mut V, | ||
static_call: bool, | ||
current_checkpoint_index: usize, | ||
) -> Externalities<'any, T, V, B> where T: Tracer, V: VMTracer { | ||
let is_static = self.static_flag || static_call; | ||
Externalities::new(self.state, self.info, self.machine, self.schedule, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static) | ||
let transaction_checkpoint_index = self.transaction_checkpoint_index.unwrap_or(current_checkpoint_index); | ||
Externalities::new(self.state, self.info, self.machine, self.schedule, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static, transaction_checkpoint_index) | ||
} | ||
|
||
/// This function should be used to execute transaction. | ||
|
@@ -352,6 +357,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
params: ActionParams, | ||
unconfirmed_substate: &mut Substate, | ||
output_policy: OutputPolicy, | ||
current_checkpoint_index: usize, | ||
tracer: &mut T, | ||
vm_tracer: &mut V | ||
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer { | ||
|
@@ -365,7 +371,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
let origin_info = OriginInfo::from(¶ms); | ||
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", self.schedule.have_delegate_call); | ||
let mut vm = vm_factory.create(params, self.schedule, self.depth); | ||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); | ||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call, current_checkpoint_index); | ||
return vm.exec(&mut ext).finalize(ext); | ||
} | ||
|
||
|
@@ -376,7 +382,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
|
||
scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || { | ||
let mut vm = vm_factory.create(params, self.schedule, self.depth); | ||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); | ||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call, current_checkpoint_index); | ||
vm.exec(&mut ext).finalize(ext) | ||
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed") | ||
}).join() | ||
|
@@ -403,7 +409,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
} | ||
|
||
// backup used in case of running out of gas | ||
self.state.checkpoint(); | ||
let current_checkpoint_index = self.state.checkpoint(); | ||
|
||
let schedule = self.schedule; | ||
|
||
|
@@ -491,7 +497,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed")); | ||
|
||
let res = { | ||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return, &mut subtracer, &mut subvmtracer) | ||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return, current_checkpoint_index, &mut subtracer, &mut subvmtracer) | ||
}; | ||
|
||
vm_tracer.done_subtrace(subvmtracer); | ||
|
@@ -560,7 +566,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
} | ||
|
||
// backup used in case of running out of gas | ||
self.state.checkpoint(); | ||
let current_checkpoint_index = self.state.checkpoint(); | ||
|
||
// part of substate that may be reverted | ||
let mut unconfirmed_substate = Substate::new(); | ||
|
@@ -588,6 +594,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
params, | ||
&mut unconfirmed_substate, | ||
OutputPolicy::InitContract, | ||
current_checkpoint_index, | ||
&mut subtracer, | ||
&mut subvmtracer | ||
); | ||
|
@@ -626,7 +633,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |
let schedule = self.schedule; | ||
|
||
// refunds from SSTORE nonzero -> zero | ||
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count; | ||
let sstore_refunds = substate.sstore_clears_refund; | ||
// refunds from contract suicides | ||
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len()); | ||
let refunds_bound = sstore_refunds + suicide_refunds; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,6 +75,7 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> { | |
tracer: &'a mut T, | ||
vm_tracer: &'a mut V, | ||
static_flag: bool, | ||
transaction_checkpoint_index: usize, | ||
} | ||
|
||
impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> | ||
|
@@ -93,6 +94,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> | |
tracer: &'a mut T, | ||
vm_tracer: &'a mut V, | ||
static_flag: bool, | ||
transaction_checkpoint_index: usize, | ||
) -> Self { | ||
Externalities { | ||
state: state, | ||
|
@@ -106,13 +108,18 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> | |
tracer: tracer, | ||
vm_tracer: vm_tracer, | ||
static_flag: static_flag, | ||
transaction_checkpoint_index: transaction_checkpoint_index, | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | ||
where T: Tracer, V: VMTracer, B: StateBackend | ||
{ | ||
fn reverted_storage_at(&self, key: &H256) -> vm::Result<H256> { | ||
self.state.checkpoint_storage_at(self.transaction_checkpoint_index, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Am I correct if I say that in the current state of the code, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're right! I don't think we had this assumption, but right now it's indeed the case -- checkpoints are only created via |
||
} | ||
|
||
fn storage_at(&self, key: &H256) -> vm::Result<H256> { | ||
self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) | ||
} | ||
|
@@ -237,7 +244,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |
} | ||
} | ||
} | ||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag); | ||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag, self.transaction_checkpoint_index); | ||
|
||
// TODO: handle internal error separately | ||
match ex.create(params, self.substate, self.tracer, self.vm_tracer) { | ||
|
@@ -291,7 +298,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |
params.value = ActionValue::Transfer(value); | ||
} | ||
|
||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag); | ||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag, self.transaction_checkpoint_index); | ||
|
||
match ex.call(params, self.substate, self.tracer, self.vm_tracer) { | ||
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data), | ||
|
@@ -390,8 +397,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |
self.depth | ||
} | ||
|
||
fn inc_sstore_clears(&mut self) { | ||
self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); | ||
fn inc_sstore_refund(&mut self, value: U256) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it's possible to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That won't save memory, IMO. The issue is that we would need a enum/union for that, but it always takes more compared what U256 takes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't mean memory, but rather a performance improvement since we are not using our custom U256 arithmetic. But as mentioned, it's fine for me to see a separate PR with that if anyone is interested on working on this, it's probably not super hot code anyway, so it would be marginal. |
||
self.substate.sstore_clears_refund = self.substate.sstore_clears_refund + value; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure it won't overflow? Can we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're sure it won't overflow -- Refund will never go above gas provided, and gas provided has upper limit of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be a consensus bug only if it's implemented differently in other clients. Always panicking doesn't seem to me like a good idea (would actually prefer the network to split than to kill large part of it, or even the entire network if it's a private Parity-only chain). Happy with whatever behavior that doesn't cause a panic (i.e. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tomusdrw What I meant is that theoretically that cannot happen. Refund can never go over There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realized that I was wrong here. Theoretically it's indeed possible for this value to go over |
||
} | ||
|
||
fn dec_sstore_refund(&mut self, value: U256) { | ||
self.substate.sstore_clears_refund = self.substate.sstore_clears_refund - value; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as above -- we're mostly sure it won't overflow, otherwise it's a consensus bug. |
||
} | ||
|
||
fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { | ||
|
@@ -473,7 +484,7 @@ mod tests { | |
let mut tracer = NoopTracer; | ||
let mut vm_tracer = NoopVMTracer; | ||
|
||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
|
||
assert_eq!(ext.env_info().number, 100); | ||
} | ||
|
@@ -485,7 +496,7 @@ mod tests { | |
let mut tracer = NoopTracer; | ||
let mut vm_tracer = NoopVMTracer; | ||
|
||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
|
||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap()); | ||
|
||
|
@@ -509,7 +520,7 @@ mod tests { | |
let mut tracer = NoopTracer; | ||
let mut vm_tracer = NoopVMTracer; | ||
|
||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
|
||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap()); | ||
|
||
|
@@ -524,7 +535,7 @@ mod tests { | |
let mut tracer = NoopTracer; | ||
let mut vm_tracer = NoopVMTracer; | ||
|
||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
|
||
// this should panic because we have no balance on any account | ||
ext.call( | ||
|
@@ -549,7 +560,7 @@ mod tests { | |
let mut vm_tracer = NoopVMTracer; | ||
|
||
{ | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
ext.log(log_topics, &log_data).unwrap(); | ||
} | ||
|
||
|
@@ -566,7 +577,7 @@ mod tests { | |
let mut vm_tracer = NoopVMTracer; | ||
|
||
{ | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
ext.suicide(refund_account).unwrap(); | ||
} | ||
|
||
|
@@ -583,7 +594,7 @@ mod tests { | |
let mut vm_tracer = NoopVMTracer; | ||
|
||
let address = { | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) { | ||
ContractCreateResult::Created(address, _) => address, | ||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."), | ||
|
@@ -603,7 +614,7 @@ mod tests { | |
let mut vm_tracer = NoopVMTracer; | ||
|
||
let address = { | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false); | ||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false, 0); | ||
|
||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) { | ||
ContractCreateResult::Created(address, _) => address, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only need
orig
inside theschedule.eip1283
branch, I'd move it there.