Skip to content

Commit 4a7f84b

Browse files
authored
fix: refactor step and step_end for clarity (#10590)
* fix: refactor `step` and `step_end` for clarity * fix: mark fns as cold
1 parent 5a4b19e commit 4a7f84b

File tree

1 file changed

+80
-59
lines changed

1 file changed

+80
-59
lines changed

crates/evm/evm/src/inspectors/revert_diagnostic.rs

Lines changed: 80 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use foundry_evm_core::{
55
constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS},
66
};
77
use revm::{
8-
bytecode::opcode::{EXTCODESIZE, REVERT},
8+
bytecode::opcode,
99
context::{ContextTr, JournalTr},
1010
inspector::JournalExt,
1111
interpreter::{
@@ -101,7 +101,7 @@ impl RevertDiagnostic {
101101
}
102102

103103
/// Injects the revert diagnostic into the debug traces. Should only be called after a revert.
104-
fn handle_revert_diagnostic(&self, interp: &mut Interpreter) {
104+
fn broadcast_diagnostic(&self, interp: &mut Interpreter) {
105105
if let Some(reason) = self.reason() {
106106
interp.control.instruction_result = InstructionResult::Revert;
107107
interp.control.next_action = InterpreterAction::Return {
@@ -113,6 +113,79 @@ impl RevertDiagnostic {
113113
};
114114
}
115115
}
116+
117+
/// When a `REVERT` opcode with zero data size occurs:
118+
/// - if `non_contract_call` was set at the current depth, `broadcast_diagnostic` is called.
119+
/// Otherwise, it is cleared.
120+
/// - if `non_contract_size_check` was set at the current depth, `broadcast_diagnostic` is
121+
/// called. Otherwise, it is cleared.
122+
#[cold]
123+
fn handle_revert<CTX, D>(&mut self, interp: &mut Interpreter, ctx: &mut CTX)
124+
where
125+
D: Database<Error = DatabaseError>,
126+
CTX: ContextTr<Db = D>,
127+
CTX::Journal: JournalExt,
128+
{
129+
// REVERT (offset, size)
130+
if let Ok(size) = interp.stack.peek(1) {
131+
if size.is_zero() {
132+
// Check empty revert with same depth as a non-contract call
133+
if let Some((_, _, depth)) = self.non_contract_call {
134+
if ctx.journal_ref().depth() == depth {
135+
self.broadcast_diagnostic(interp);
136+
} else {
137+
self.non_contract_call = None;
138+
}
139+
return;
140+
}
141+
142+
// Check empty revert with same depth as a non-contract size check
143+
if let Some((_, depth)) = self.non_contract_size_check {
144+
if depth == ctx.journal_ref().depth() {
145+
self.broadcast_diagnostic(interp);
146+
} else {
147+
self.non_contract_size_check = None;
148+
}
149+
}
150+
}
151+
}
152+
}
153+
154+
/// When an `EXTCODESIZE` opcode occurs:
155+
/// - Optimistically caches the target address and current depth in `non_contract_size_check`,
156+
/// pending later validation.
157+
#[cold]
158+
fn handle_extcodesize<CTX, D>(&mut self, interp: &mut Interpreter, ctx: &mut CTX)
159+
where
160+
D: Database<Error = DatabaseError>,
161+
CTX: ContextTr<Db = D>,
162+
CTX::Journal: JournalExt,
163+
{
164+
// EXTCODESIZE (address)
165+
if let Ok(word) = interp.stack.peek(0) {
166+
let addr = Address::from_word(word.into());
167+
if IGNORE.contains(&addr) || ctx.journal_ref().precompile_addresses().contains(&addr) {
168+
return;
169+
}
170+
171+
// Optimistically cache --> validated and cleared (if necessary) at `fn
172+
// step_end()`
173+
self.non_contract_size_check = Some((addr, ctx.journal_ref().depth()));
174+
self.is_extcodesize_step = true;
175+
}
176+
}
177+
178+
/// Tracks `EXTCODESIZE` output. If the bytecode size is NOT 0, clears the cache.
179+
#[cold]
180+
fn handle_extcodesize_output(&mut self, interp: &mut Interpreter) {
181+
if let Ok(size) = interp.stack.peek(0) {
182+
if size != U256::ZERO {
183+
self.non_contract_size_check = None;
184+
}
185+
}
186+
187+
self.is_extcodesize_step = false;
188+
}
116189
}
117190

118191
impl<CTX, D> Inspector<CTX, EthInterpreter> for RevertDiagnostic
@@ -139,69 +212,17 @@ where
139212
}
140213

141214
/// Handles `REVERT` and `EXTCODESIZE` opcodes for diagnostics.
142-
///
143-
/// When a `REVERT` opcode with zero data size occurs:
144-
/// - if `non_contract_call` was set at the current depth, `handle_revert_diagnostic` is
145-
/// called. Otherwise, it is cleared.
146-
/// - if `non_contract_call` was set at the current depth, `handle_revert_diagnostic` is
147-
/// called. Otherwise, it is cleared.
148-
///
149-
/// When an `EXTCODESIZE` opcode occurs:
150-
/// - Optimistically caches the target address and current depth in `non_contract_size_check`,
151-
/// pending later validation.
152215
fn step(&mut self, interp: &mut Interpreter, ctx: &mut CTX) {
153-
// REVERT (offset, size)
154-
if REVERT == interp.bytecode.opcode() {
155-
if let Ok(size) = interp.stack.peek(1) {
156-
if size.is_zero() {
157-
// Check empty revert with same depth as a non-contract call
158-
if let Some((_, _, depth)) = self.non_contract_call {
159-
if ctx.journal_ref().depth() == depth {
160-
self.handle_revert_diagnostic(interp);
161-
} else {
162-
self.non_contract_call = None;
163-
}
164-
return;
165-
}
166-
167-
// Check empty revert with same depth as a non-contract size check
168-
if let Some((_, depth)) = self.non_contract_size_check {
169-
if depth == ctx.journal_ref().depth() {
170-
self.handle_revert_diagnostic(interp);
171-
} else {
172-
self.non_contract_size_check = None;
173-
}
174-
}
175-
}
176-
}
177-
}
178-
// EXTCODESIZE (address)
179-
else if EXTCODESIZE == interp.bytecode.opcode() {
180-
if let Ok(word) = interp.stack.peek(0) {
181-
let addr = Address::from_word(word.into());
182-
if IGNORE.contains(&addr) ||
183-
ctx.journal_ref().precompile_addresses().contains(&addr)
184-
{
185-
return;
186-
}
187-
188-
// Optimistically cache --> validated and cleared (if necessary) at `fn step_end()`
189-
self.non_contract_size_check = Some((addr, ctx.journal_ref().depth()));
190-
self.is_extcodesize_step = true;
191-
}
216+
match interp.bytecode.opcode() {
217+
opcode::REVERT => self.handle_revert(interp, ctx),
218+
opcode::EXTCODESIZE => self.handle_extcodesize(interp, ctx),
219+
_ => {}
192220
}
193221
}
194222

195-
/// Tracks `EXTCODESIZE` output. If the bytecode size is 0, clears the cache.
196223
fn step_end(&mut self, interp: &mut Interpreter, _ctx: &mut CTX) {
197224
if self.is_extcodesize_step {
198-
if let Ok(size) = interp.stack.peek(0) {
199-
if size != U256::ZERO {
200-
self.non_contract_size_check = None;
201-
}
202-
}
203-
204-
self.is_extcodesize_step = false;
225+
self.handle_extcodesize_output(interp);
205226
}
206227
}
207228
}

0 commit comments

Comments
 (0)