Skip to content

Add logic to generate simulation report#4537

Open
MartinquaXD wants to merge 2 commits into
mainfrom
generate-simulation-report
Open

Add logic to generate simulation report#4537
MartinquaXD wants to merge 2 commits into
mainfrom
generate-simulation-report

Conversation

@MartinquaXD

Copy link
Copy Markdown
Contributor

Description

The new simulation approach for the order verification has a few limitations and we'd like to know whether an order doesn't pass the simulation because the order is just broken or because of an edge case in our simulation.

Changes

This PR introduces new logic to basically turn a CallFrame trace into a simple easy to digest simulation report. The report only concerns itself with specific checkpoints we need to hit throughout the settlement as those should be enough to give the caller a tip where to start debugging their order (hooks, signature, wrapper setup, etc.).
We are relying on a callframe tracer instead of the more detailed structopt tracer because it is significantly faster, requires less memory and still gives us enough information to infer everything we need to know in our report.

How to test

Since this code will only run in shadow mode (in a follow up PR) I only sanity checked the report for a few specific transactions.

@MartinquaXD MartinquaXD requested a review from a team as a code owner June 19, 2026 13:11
@claude

claude Bot commented Jun 19, 2026

Copy link
Copy Markdown

Claude finished @MartinquaXD's task in 3m 23s —— View job


PR Review: Add logic to generate simulation report

  • Read changed files (report.rs, lib.rs)
  • Understand CallFrame trace structure and contract bindings
  • Review correctness, edge cases, and code style
  • Post inline comments and summary

Nice, focused addition — the checkpoint-based approach over the call tracer reads clearly and the doc comments explaining the design choices (sig-check-via-vault-relayer, high-level-only traversal) are helpful.

I found one correctness issue which I left as an inline comment:

  • Flashloan router never detected (report.rs:85): the branch decodes against FlashLoanRouter::settlementContractCall, but settlementContract() is a view getter, not the router entry point. The actual entry is flashLoanAndSettle(...) (analogous to wrappedSettle). Different selector ⇒ the abi_decode never matches, so flashloan settlements emit no WrapperEntered/WrapperExited. Suggested fix + a request for a flashloan test case in the comment.

Everything else looks good. The process_settle_frame limitations (only direct-child transfers, transfers through the Balancer vault not surfaced) are acknowledged by the "high-level report" design and the PR notes shadow-mode-only usage, so I'm not flagging those.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new report module to generate high-level simulation reports from Geth call traces, along with corresponding tests. The review feedback highlights a potential issue where Event::SignatureCheck could be pushed multiple times during multi-order settlements because the vault relayer is called once per trade, and suggests guarding the push to ensure it is only added once.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/simulator/src/report.rs
Comment thread crates/simulator/src/report.rs Outdated
}
}

fn process_frame(frame: &CallFrame, ctx: &Context, events: &mut Vec<Event>) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc pls

|| FlashLoanRouter::flashLoanAndSettleCall::abi_decode(&frame.input).is_ok()
{
events.push(Event::WrapperEntered { wrapper: to });
for sub in &frame.calls {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is sub: subcalls?
a more explicit name would be better

revert: frame.revert_reason.clone(),
});
} else {
for sub in &frame.calls {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

});
} else {
for sub in &frame.calls {
process_frame(sub, ctx, events);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know there's a limit to how large a frame can be, but the technically unbounded recursion here is a risk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants