Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces enhanced logging for request deserialization and makes access list estimation best-effort for certain settlements. Specifically, it adds custom Axum extractors for JSON and Query types that log warnings on failure. It also updates the settlement simulation logic to treat access list fetch failures as non-fatal warnings when no ETH-to-contract transfers are involved, preventing unnecessary transaction aborts. I have no feedback to provide.
MartinquaXD
left a comment
There was a problem hiding this comment.
Sorry, forgot to submit the review yesterday. :(
| // the on-chain tx would succeed without it. | ||
| let access_list = match simulator.access_list(&tx).await { | ||
| Ok(list) => list, | ||
| Err(err) if !access_list_required => { |
There was a problem hiding this comment.
I think here we need to do stricter error handling. If the error indicates a revert we should still abort. Only if we can't reason about the outcome of the simulation we should assume things are okay (e.g. deserialization error like in the post-mortem, transport error, something else? 🤷♂️).
There was a problem hiding this comment.
The error handling should be split into a separate PR IMO.
A revert from simulator.access_list signals a real problem with the settlement even when no trade strictly requires the access-list workaround, so it must still propagate. The empty-partial-list fallback now fires only for simulator::Error::Other (transport, deserialization, etc.) where we cannot reason about the simulation outcome.
Revert the LoggingJson / LoggingQuery extractors and the /solve body parse warning. They land in a follow-up PR so this branch only covers the access-list-fetch optionality change.
| // settlement. | ||
| let access_list = match simulator.access_list(&tx).await { | ||
| Ok(list) => list, | ||
| Err(simulator::Error::Other(err)) if partial_access_list.is_empty() => { |
There was a problem hiding this comment.
Can you please double check that matching on Error::Other is sufficient / correct here?
What I'm worried about is that the Other variant still contains a bunch of revert related errors internally.
There was a problem hiding this comment.
Based on this
services/crates/simulator/src/lib.rs
Lines 152 to 169 in 3dd0844
, the
Error::Other is used only for http and Tenderly's "other" errors. Everything else is mapped to Error::Revert.
| /// smart-contract receiver. Returns an empty access list when the trade does | ||
| /// not trigger the gas-limit workaround (non-ETH buy or EOA receiver). |
There was a problem hiding this comment.
I wonder if a new type makes sense here: RequiredAccessList.
This function would then return Result<Option<RequiredAccessList>> to indicate on a type level whether we can continue after non-revert errors.
Encodes "trade needs the ETH->contract gas-limit workaround" at the type level. partial_access_list_for returns Option<RequiredAccessList> (None = not required), the aggregation reduces only the required entries, and the simulate() fallback keys off is_none() instead of is_empty() — unambiguous regardless of whether a required entry set happens to be empty.
jmg-duarte
left a comment
There was a problem hiding this comment.
Codewise LGTM but there's space to make the docs clearer
| /// Access list entries covering a trade that strictly requires the | ||
| /// ETH→contract gas-limit workaround. Distinct from a bare `eth::AccessList` | ||
| /// so the settlement-level fallback can tell "no trade required one" (`None`) | ||
| /// apart from "trade required one but the list turned out empty" (`Some`). | ||
| #[derive(Debug, Clone)] | ||
| struct RequiredAccessList(eth::AccessList); | ||
|
|
||
| /// Return the partial access list for a single trade. `None` means the trade | ||
| /// does not trigger the gas-limit workaround (non-ETH buy or EOA receiver), | ||
| /// so its absence must not be treated as "required but empty". | ||
| async fn partial_access_list_for( |
There was a problem hiding this comment.
"gas-limit workaround" is a bit abstract here, could you cover what it exactly is?
My understanding it that without the access list the TX would not pass below the gas limit?
| "access list estimation failed; continuing without it (no ETH->contract \ | ||
| trades)" |
There was a problem hiding this comment.
Like the other comment, I also don't understand what "ETH->contract" is supposed to mean, is it a transfer?
Description
The driver currently aborts the whole settlement whenever
simulator.access_listfails. The access list is only functionally required for trades that send ETH to a smart-contract receiver (the EVM hard gas limit bypass described atsettlement.rsline 140). For every other settlement it is just a gas optimization, so a failed RPC should not cost the solver the auction.Changes
How to test
Existing tests.