Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 42f0ae1

Browse files
committed
More STATICALL fixes
1 parent 22269b6 commit 42f0ae1

File tree

6 files changed

+35
-3
lines changed

6 files changed

+35
-3
lines changed

ethcore/evm/src/interpreter/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ impl<Cost: CostType> Interpreter<Cost> {
380380
// Get sender & receive addresses, check if we have balance
381381
let (sender_address, receive_address, has_balance, call_type) = match instruction {
382382
instructions::CALL => {
383+
if ext.is_static() && value.map_or(false, |v| !v.is_zero()) {
384+
return Err(vm::Error::MutableCallInStaticContext);
385+
}
383386
let has_balance = ext.balance(&params.address)? >= value.expect("value set for all but delegate call and staticcall; qed");
384387
(&params.address, &code_address, has_balance, CallType::Call)
385388
},
@@ -388,11 +391,11 @@ impl<Cost: CostType> Interpreter<Cost> {
388391
(&params.address, &params.address, has_balance, CallType::CallCode)
389392
},
390393
instructions::DELEGATECALL => (&params.sender, &params.address, true, CallType::DelegateCall),
391-
instructions::STATICCALL => (&params.sender, &code_address, true, CallType::StaticCall),
394+
instructions::STATICCALL => (&params.address, &code_address, true, CallType::StaticCall),
392395
_ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction))
393396
};
394397

395-
// clear return data buffer before crearing new call frame.
398+
// clear return data buffer before creating new call frame.
396399
self.return_data = ReturnData::empty();
397400

398401
let can_call = has_balance && ext.depth() < ext.schedule().max_depth;
@@ -415,6 +418,11 @@ impl<Cost: CostType> Interpreter<Cost> {
415418
self.return_data = data;
416419
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater then current one")))
417420
},
421+
MessageCallResult::Reverted(gas_left, data) => {
422+
stack.push(U256::zero());
423+
self.return_data = data;
424+
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater then current one")))
425+
},
418426
MessageCallResult::Failed => {
419427
stack.push(U256::zero());
420428
Ok(InstructionResult::Ok)

ethcore/src/externalities.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
125125
}
126126
}
127127

128+
fn is_static(&self) -> bool {
129+
return self.static_flag
130+
}
131+
128132
fn exists(&self, address: &Address) -> vm::Result<bool> {
129133
self.state.exists(address).map_err(Into::into)
130134
}
@@ -276,7 +280,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
276280
let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag);
277281

278282
match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) {
279-
Ok(FinalizationResult{ gas_left, return_data, .. }) => MessageCallResult::Success(gas_left, return_data),
283+
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
284+
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
280285
_ => MessageCallResult::Failed
281286
}
282287
}

ethcore/src/json_tests/executive.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E>
180180
0
181181
}
182182

183+
fn is_static(&self) -> bool {
184+
false
185+
}
186+
183187
fn inc_sstore_clears(&mut self) {
184188
self.ext.inc_sstore_clears()
185189
}

ethcore/vm/src/ext.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ pub enum MessageCallResult {
4545
/// Returned when message call failed.
4646
/// VM doesn't have to know the reason.
4747
Failed,
48+
/// Returned when message call was reverted.
49+
/// Contains gas left and output data.
50+
Reverted(U256, ReturnData),
4851
}
4952

5053
/// Specifies how an address is calculated for a new contract.
@@ -143,4 +146,7 @@ pub trait Ext {
143146

144147
/// Trace the finalised execution of a single instruction.
145148
fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {}
149+
150+
/// Check if running in static context.
151+
fn is_static(&self) -> bool;
146152
}

ethcore/vm/src/tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ impl Ext for FakeExt {
182182
self.depth
183183
}
184184

185+
fn is_static(&self) -> bool {
186+
false
187+
}
188+
185189
fn inc_sstore_clears(&mut self) {
186190
self.sstore_clears += 1;
187191
}

ethcore/wasm/src/runtime.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@ impl<'a, 'b> Runtime<'a, 'b> {
290290
self.memory.set(result_ptr, &result)?;
291291
Ok(Some(0i32.into()))
292292
},
293+
vm::MessageCallResult::Reverted(gas_left, _) => {
294+
self.gas_counter = self.gas_limit - gas_left.low_u64();
295+
self.memory.set(result_ptr, &result)?;
296+
Ok(Some((-1i32).into()))
297+
},
293298
vm::MessageCallResult::Failed => {
294299
Ok(Some((-1i32).into()))
295300
}

0 commit comments

Comments
 (0)