Skip to content

Settle fast-path quote solutions via the existing /settle - #4710

Merged
AryanGodara merged 15 commits into
mainfrom
aryan/be-58-settle-fastpath-quote
Aug 13, 2026
Merged

Settle fast-path quote solutions via the existing /settle#4710
AryanGodara merged 15 commits into
mainfrom
aryan/be-58-settle-fastpath-quote

Conversation

@AryanGodara

Copy link
Copy Markdown
Member

Description

Completes the driver half of BE-58. A fast-path quote already caches its Solution (in #4678). This works on the /settle part. At settle time the driver re-encodes the cached solution against the real signed order and submits via the unchanged mempool path.

Changes

  • Added an optional real signed order and its native prices to /settle. When the order is present, the driver re-encodes the cached quote solution against it before the (unchanged) settle path submits.
  • Re-encoding reuses the quote's work instead of re-solving: it swaps the quote's placeholder order for the real signed order, keeps the cached route + clearing prices, and adds the native prices onto the auction's tokens so the settlement gets a slippage buffer.
  • The resulting settlement is cached by (auction_id, solution_id), so the existing /settle lookup + mempool submission consume it unchanged.

How to test

  • unit and e2e tests

@AryanGodara AryanGodara self-assigned this Aug 6, 2026
@linear-code

linear-code Bot commented Aug 6, 2026

Copy link
Copy Markdown

BE-58

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

Reminder: Please consider backward compatibility when modifying the API specification.
If breaking changes are unavoidable, ensure:

  • You explicitly pointed out breaking changes.
  • You communicate the changes to affected teams (at least Frontend team and SAFE team).
  • You provide proper versioning and migration mechanisms.

Resolved

@AryanGodara
AryanGodara changed the base branch from main to aryan/be-58-cache-quote-solutions August 6, 2026 14:34
@AryanGodara
AryanGodara force-pushed the aryan/be-58-settle-fastpath-quote branch from ad645bf to 1b8d082 Compare August 6, 2026 14:41
@AryanGodara
AryanGodara marked this pull request as ready for review August 6, 2026 14:59
@AryanGodara
AryanGodara requested a review from a team as a code owner August 6, 2026 14:59
@claude

claude Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @AryanGodara's task in 5m 23s —— View job


PR Review — Settle fast-path quote solutions

  • Read pr-review skill
  • Gather diff & context
  • Review changed files
  • Post inline comments
  • Post summary

The design is sound and, importantly, fail-safe: rebind_quote_order only swaps the order while keeping the cached route/prices, and Fulfillment::new re-validates executed_with_fee == order.target(), so a real order whose amounts/side/tokens/kind don't match the quote is rejected rather than mis-settled. The settle/reveal lookup keys on (auction_id, solution_id), which the re-encoded settlement inherits from the cached quote auction, so the existing mempool path consumes it unchanged. The solve_request.rs change is a clean extract-to-into_domain refactor with no behavior change. Nice test coverage for the happy path, missing-order, and mismatch cases.

Two minor points posted inline (silent dropping of invalid native prices → missing slippage buffer; and all fast-path failures collapsing into Kind::Unknown, hurting prod diagnosability). Both are non-blocking.

One item not inline-able (file not in diff):

  • crates/driver/openapi.ymlSettleRequest (around line 593) was not updated with the new optional order and prices fields. Given the API-change reminder on this PR, worth adding them (documented as optional / fast-path-only) so the spec stays in sync.

Nothing here blocks merge — the amount-mismatch guard makes the risky part safe. LGTM once the openapi doc is updated.

Comment thread crates/driver/src/infra/api/routes/settle/mod.rs Outdated
Comment thread crates/driver/src/infra/api/error.rs

@MartinquaXD MartinquaXD 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.

I'm positively surprised. A few things seem more complicated than they need to and some edge cases are not handled but overall the approach seems relatively non invasive. 👍

Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/mod.rs
Comment thread crates/driver/src/domain/competition/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/mod.rs Outdated
Comment thread crates/driver/src/infra/api/routes/solve/dto/solve_request.rs Outdated
Comment thread crates/driver/src/tests/cases/quote.rs Outdated
Comment thread crates/driver/src/infra/api/routes/settle/dto/settle_request.rs Outdated
Comment thread crates/driver/src/infra/api/routes/settle/mod.rs Outdated
@AryanGodara
AryanGodara requested a review from MartinquaXD August 6, 2026 19:56

@MartinquaXD MartinquaXD 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.

Things are more complicated than I thought. Will have to think more about it and do another pass tomorrow.

Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/infra/api/routes/settle/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/pre_processing.rs Outdated
Comment thread crates/driver/src/domain/competition/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/mod.rs
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Base automatically changed from aryan/be-58-cache-quote-solutions to main August 7, 2026 14:06
…stpath-quote

# Conflicts:
#	crates/driver/openapi.yml
#	crates/driver/src/domain/competition/mod.rs
#	crates/driver/src/domain/quote.rs
#	crates/driver/src/infra/api/routes/quote/dto/quote.rs
#	crates/driver/src/infra/api/routes/quote/mod.rs
#	crates/driver/src/tests/cases/quote.rs
#	crates/driver/src/tests/setup/mod.rs
@github-actions

Copy link
Copy Markdown

Reminder: Please consider backward compatibility when modifying the API specification.
If breaking changes are unavoidable, ensure:

  • You explicitly pointed out breaking changes.
  • You communicate the changes to affected teams (at least Frontend team and SAFE team).
  • You provide proper versioning and migration mechanisms.

Caused by:

Comment thread crates/driver/src/domain/competition/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/pre_processing.rs Outdated
Comment on lines +562 to +563
order::Side::Sell => user.buy_amount(&clearing)?.0 >= limit_prices.buy,
order::Side::Buy => user.sell_amount(&clearing)?.0 <= limit_prices.sell,

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.

it's not enough to ensure that the original solution is at least as good as the required limit prices.
The driver also has to make sure the order gets executed EXACTLY at that limit price otherwise the circuit breaker will complain that the order did not get filled as it was intended.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I see. Now >= is only a feasibility gate (can the cached route cover the limit?),
so after the check I pin the order's two clearing prices to the signed limit, so it fills at exactly that.
also added a small test for this

Comment thread crates/driver/src/infra/api/routes/settle/mod.rs Outdated
Comment thread crates/driver/openapi.yml Outdated
Comment thread crates/driver/openapi.yml Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment on lines +781 to +782
#[error("invalid fast-path trade: {0:?}")]
FastPathTrade(#[from] Trade),

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.

Can we get a reason as to why it was invalid?

Comment thread crates/driver/src/domain/competition/solution/mod.rs Outdated
Comment thread crates/driver/src/tests/setup/driver.rs Outdated
Comment thread crates/driver/src/infra/api/error.rs Outdated
Comment on lines +67 to +68
Kind::InvalidFastPathOrder => {
"the settle order does not match the quoted fast-path solution"

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.

If this is the respective error message, the error should be called "FastPathOrderQuoteMismatch" or similar, it's much closer and less general than just "invalid order"

}

impl Order {
#[expect(deprecated)]

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.

why add a new function if its already deprecated?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

it's not deprecated, that attribute is only there because it still maps the old Balancer Internal/External balance variants which are marked deprecated but not removed yet. i pulled it out into its own function so /settle can reuse the same conversion /solve does. (so when those are removed, expect will error out, reminding to remove this attirbute as well)

Comment on lines +1194 to +1195
#[error("fast-path order does not match the quoted solution: {0:?}")]
FastPathInvalidOrder(solution::Error),

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.

again specific message vs generic error

impl DataAggregator {
/// Resolves the order's app-data hash to the underlying JSON if it isn't
/// already resolved.
pub async fn resolve_app_data(&self, order: &mut Order) {

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.

not the biggest fan of the mut reference mutation, personally i'd rather take ownership for mutation and returning it afterwards

leaving this to your judgement

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

keeping &mut for now, as it just updates one field and does nothing when there's nothing to fetch, so passing the whole order in and out didn't seem worth it

@AryanGodara
AryanGodara requested a review from jmg-duarte August 11, 2026 13:46

@jmg-duarte jmg-duarte 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.

LGTM

@AryanGodara
AryanGodara added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit 623396b Aug 13, 2026
22 checks passed
@AryanGodara
AryanGodara deleted the aryan/be-58-settle-fastpath-quote branch August 13, 2026 07:09
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants