-
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, | ||
|
||
| } | ||
| } | ||
|
|
||
| /// 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) | ||
|
||
| } | ||
|
|
||
| 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) { | ||
|
||
| self.substate.sstore_clears_refund = self.substate.sstore_clears_refund + value; | ||
|
||
| } | ||
|
|
||
| fn dec_sstore_refund(&mut self, value: U256) { | ||
| self.substate.sstore_clears_refund = self.substate.sstore_clears_refund - value; | ||
|
||
| } | ||
|
|
||
| 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
originside theschedule.eip1283branch, I'd move it there.