Skip to content

Commit a896eae

Browse files
committed
Include the program counter in contract-reverted messages
This makes it possible to tell on which instruction the contract reverted where as previously the message wasn't all that useful. The runtime cost should be negligible.
1 parent 8ad9e28 commit a896eae

File tree

5 files changed

+14
-6
lines changed

5 files changed

+14
-6
lines changed

actors/evm/src/interpreter/instructions/control.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,44 @@ pub fn invalid(
3131
pub fn ret(
3232
state: &mut ExecutionState,
3333
_system: &System<impl Runtime>,
34+
pc: usize,
3435
offset: U256,
3536
size: U256,
3637
) -> Result<Output, ActorError> {
37-
exit(&mut state.memory, offset, size, Outcome::Return)
38+
exit(&mut state.memory, pc, offset, size, Outcome::Return)
3839
}
3940

4041
#[inline]
4142
pub fn revert(
4243
state: &mut ExecutionState,
4344
_system: &System<impl Runtime>,
45+
pc: usize,
4446
offset: U256,
4547
size: U256,
4648
) -> Result<Output, ActorError> {
47-
exit(&mut state.memory, offset, size, Outcome::Revert)
49+
exit(&mut state.memory, pc, offset, size, Outcome::Revert)
4850
}
4951

5052
#[inline]
5153
pub fn stop(
5254
_state: &mut ExecutionState,
5355
_system: &System<impl Runtime>,
56+
pc: usize,
5457
) -> Result<Output, ActorError> {
55-
Ok(Output { return_data: Vec::new(), outcome: Outcome::Return })
58+
Ok(Output { return_data: Vec::new(), outcome: Outcome::Return, pc: pc })
5659
}
5760

5861
#[inline]
5962
fn exit(
6063
memory: &mut Memory,
64+
pc: usize,
6165
offset: U256,
6266
size: U256,
6367
status: Outcome,
6468
) -> Result<Output, ActorError> {
6569
Ok(Output {
6670
outcome: status,
71+
pc: pc,
6772
return_data: super::memory::get_memory_region(memory, offset, size)?
6873
.map(|region| memory[region.offset..region.offset + region.size.get()].to_vec())
6974
.unwrap_or_default(),

actors/evm/src/interpreter/instructions/lifecycle.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ fn create_common(
150150
pub fn selfdestruct(
151151
_state: &mut ExecutionState,
152152
system: &mut System<impl Runtime>,
153+
pc: usize,
153154
beneficiary: U256,
154155
) -> Result<Output, ActorError> {
155156
use crate::interpreter::output::Outcome;
@@ -185,7 +186,7 @@ pub fn selfdestruct(
185186
//
186187
// 1. In the constructor, this will set our code to "empty". This is correct.
187188
// 2. Otherwise, we'll successfully return nothing to the caller.
188-
Ok(Output { outcome: Outcome::Return, return_data: Vec::new() })
189+
Ok(Output { outcome: Outcome::Return, return_data: Vec::new(), pc: pc })
189190
}
190191

191192
#[cfg(test)]

actors/evm/src/interpreter/instructions/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ macro_rules! def_exit {
187187
($op:ident ($($arg:ident),*) => $impl:path) => {
188188
def_op!{ $op (m) => {
189189
let &rev![$($arg),*] = m.state.stack.pop_many()?;
190-
m.output = $impl(&mut m.state, &mut m.system, $($arg),*)?;
190+
m.output = $impl(&mut m.state, &mut m.system, m.pc, $($arg),*)?;
191191
m.pc = m.bytecode.len(); // stop execution
192192
Ok(())
193193
}}

actors/evm/src/interpreter/output.rs

+2
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ pub struct Output {
1414
pub outcome: Outcome,
1515
/// The return data.
1616
pub return_data: Vec<u8>,
17+
/// The final program counter (for debugging).
18+
pub pc: usize,
1719
}

actors/evm/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ where
181181
}
182182
Outcome::Revert => Err(ActorError::unchecked_with_data(
183183
EVM_CONTRACT_REVERTED,
184-
"contract reverted".to_string(),
184+
format!("contract reverted at {0}", output.pc),
185185
IpldBlock::serialize_cbor(&BytesSer(&output.return_data)).unwrap(),
186186
)),
187187
}

0 commit comments

Comments
 (0)