Skip to content

Commit

Permalink
(feat) add conditional breakpoints (#4801)
Browse files Browse the repository at this point in the history
* add conditional breakpoints

* help desk

* char return

* chore: small cheatcode improvements (#4799)

* fmt: abigens

* Pass by reference when patching Hardhat selector

rebase master

* help desk

* fmt

* help desk

rebase

* chore(clippy): make clippy happy

---------

Co-authored-by: DaniPopes <[email protected]>
Co-authored-by: Matthias Seitz <[email protected]>
  • Loading branch information
3 people authored Apr 26, 2023
1 parent e9bc782 commit f05fdd8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
1 change: 1 addition & 0 deletions evm/src/executor/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ abigen!(
ffi(string[])(bytes)
breakpoint(string)
breakpoint(string,bool)
roll(uint256)
warp(uint256)
Expand Down
16 changes: 13 additions & 3 deletions evm/src/executor/inspector/cheatcodes/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,12 @@ fn get_recorded_logs(state: &mut Cheatcodes) -> Bytes {
}

/// Entry point of the breakpoint cheatcode. Adds the called breakpoint to the state.
fn add_breakpoint(state: &mut Cheatcodes, caller: Address, inner: &str) -> Result<Bytes, Bytes> {
fn add_breakpoint(
state: &mut Cheatcodes,
caller: Address,
inner: &str,
add: bool,
) -> Result<Bytes, Bytes> {
let mut chars = inner.chars();
let point = chars.next();

Expand All @@ -209,7 +214,11 @@ fn add_breakpoint(state: &mut Cheatcodes, caller: Address, inner: &str) -> Resul
}

// add a breakpoint from the interpreter
state.breakpoints.insert(point, (caller, state.pc));
if add {
state.breakpoints.insert(point, (caller, state.pc));
} else {
state.breakpoints.remove(&point);
}

Ok(Bytes::new())
}
Expand Down Expand Up @@ -264,7 +273,8 @@ pub fn apply<DB: DatabaseExt>(
.map_err(|err| err.encode_string())?;
val.encode().into()
}
HEVMCalls::Breakpoint(inner) => add_breakpoint(state, caller, &inner.0)?,
HEVMCalls::Breakpoint0(inner) => add_breakpoint(state, caller, &inner.0, true)?,
HEVMCalls::Breakpoint1(inner) => add_breakpoint(state, caller, &inner.0, inner.1)?,
HEVMCalls::Etch(inner) => {
let code = inner.1.clone();
trace!(address=?inner.0, code=?hex::encode(&code.0), "etch cheatcode");
Expand Down
55 changes: 48 additions & 7 deletions ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ impl Tui {
draw_memory: &mut DrawMemory,
stack_labels: bool,
mem_utf: bool,
help: bool,
) {
let total_size = f.size();
if total_size.width < 225 {
Expand All @@ -163,6 +164,7 @@ impl Tui {
draw_memory,
stack_labels,
mem_utf,
help,
);
} else {
Tui::square_layout(
Expand All @@ -179,6 +181,7 @@ impl Tui {
draw_memory,
stack_labels,
mem_utf,
help,
);
}
}
Expand All @@ -198,11 +201,16 @@ impl Tui {
draw_memory: &mut DrawMemory,
stack_labels: bool,
mem_utf: bool,
help: bool,
) {
let total_size = f.size();
let h_height = if help { 4 } else { 0 };

if let [app, footer] = Layout::default()
.constraints(
[Constraint::Ratio(100 - h_height, 100), Constraint::Ratio(h_height, 100)].as_ref(),
)
.direction(Direction::Vertical)
.constraints([Constraint::Ratio(98, 100), Constraint::Ratio(2, 100)].as_ref())
.split(total_size)[..]
{
if let [op_pane, stack_pane, memory_pane, src_pane] = Layout::default()
Expand All @@ -218,7 +226,9 @@ impl Tui {
)
.split(app)[..]
{
Tui::draw_footer(f, footer);
if help {
Tui::draw_footer(f, footer);
}
Tui::draw_src(
f,
address,
Expand Down Expand Up @@ -253,7 +263,7 @@ impl Tui {
}
} else {
panic!("unable to create footer / app")
}
};
}

#[allow(clippy::too_many_arguments)]
Expand All @@ -271,14 +281,18 @@ impl Tui {
draw_memory: &mut DrawMemory,
stack_labels: bool,
mem_utf: bool,
help: bool,
) {
let total_size = f.size();
let h_height = if help { 4 } else { 0 };

// split in 2 vertically

if let [app, footer] = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Ratio(98, 100), Constraint::Ratio(2, 100)].as_ref())
.constraints(
[Constraint::Ratio(100 - h_height, 100), Constraint::Ratio(h_height, 100)].as_ref(),
)
.split(total_size)[..]
{
if let [left_pane, right_pane] = Layout::default()
Expand All @@ -297,7 +311,9 @@ impl Tui {
.constraints([Constraint::Ratio(1, 4), Constraint::Ratio(3, 4)].as_ref())
.split(right_pane)[..]
{
Tui::draw_footer(f, footer);
if help {
Tui::draw_footer(f, footer)
};
Tui::draw_src(
f,
address,
Expand Down Expand Up @@ -348,15 +364,34 @@ impl Tui {

fn draw_footer<B: Backend>(f: &mut Frame<B>, area: Rect) {
let block_controls = Block::default();
let dim = Style::default().add_modifier(Modifier::DIM);

let _text_output = vec![
Spans::from(
Span::styled(
"[q]: quit | [k/j]: prev/next op | [a/s]: prev/next jump | [c/C]: prev/next call | [g/G]: start/end",
dim,
),
),
Spans::from(
Span::styled(
"[t]: stack labels | [m]: memory decoding | [shift + j/k]: scroll stack | [ctrl + j/k]: scroll memory | ['<char>]: goto breakpoint | [h] close help",
dim,
)
)
];

let text_output = Text::from(Span::styled(
"[q]: quit | [k/j]: prev/next op | [a/s]: prev/next jump | [c/C]: prev/next call | [g/G]: start/end | [t]: toggle stack labels | [m]: toggle memory decoding | [shift + j/k]: scroll stack | [ctrl + j/k]: scroll memory",
Style::default().add_modifier(Modifier::DIM)
"[q]: quit | [k/j]: prev/next op | [a/s]: prev/next jump | [c/C]: prev/next call | [g/G]: start/end\n
[t]: stack labels | [m]: memory decoding | [shift + j/k]: scroll stack | [ctrl + j/k]: scroll memory | ['<char>]: goto breakpoint",
Style::default().add_modifier(Modifier::DIM),
));

let paragraph = Paragraph::new(text_output)
.block(block_controls)
.alignment(Alignment::Center)
.wrap(Wrap { trim: false });

f.render_widget(paragraph, area);
}

Expand Down Expand Up @@ -1017,6 +1052,7 @@ impl Ui for Tui {

let mut stack_labels = false;
let mut mem_utf = false;
let mut help = false;
// UI thread that manages drawing
loop {
if last_index != draw_memory.inner_call_index {
Expand Down Expand Up @@ -1211,6 +1247,10 @@ impl Ui for Tui {
KeyCode::Char('m') => {
mem_utf = !mem_utf;
}
// toggle help notice
KeyCode::Char('h') => {
help = !help;
}
KeyCode::Char(other) => match other {
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '\'' => {
self.key_buffer.push(other);
Expand Down Expand Up @@ -1273,6 +1313,7 @@ impl Ui for Tui {
&mut draw_memory,
stack_labels,
mem_utf,
help,
)
})?;
}
Expand Down

0 comments on commit f05fdd8

Please sign in to comment.