Skip to content

Return error on order replacement when it's not safe#3323

Merged
mrnaveira merged 15 commits intomainfrom
order-replacement-check-unsafe
Mar 13, 2025
Merged

Return error on order replacement when it's not safe#3323
mrnaveira merged 15 commits intomainfrom
order-replacement-check-unsafe

Conversation

@mrnaveira
Copy link
Copy Markdown
Contributor

@mrnaveira mrnaveira commented Mar 12, 2025

Description

We want to allow users to "edit" orders, implemented by canceling a previous order when creating a new one. We have a replacedOrder property for this.

One concern is that this could lead to double spending when the old order is part of the current auction and the winning solver intends to settle it.

The goal of this PR is to mitigate this issue as much as possible by checking whether any solver has bid on the original order in the last few auctions. The POST /orders method now returns a 400 Bad Request in that case.

A follow-up PR can extend this logic to the cancellation endpoint. In this case, instead of rejecting the cancellation outright, we may prefer to return a warning message instead.

Changes

  • Added a new database operation load_latest_competitions to fetch all the competitions from the last N auctions.
  • Updated order replacement logic in the orderbook to verify that the order is not included in any recent competitions (using the new order_is_actively_bid_on function).
  • Introduced a more granular order replacement error specification via the new OrderReplacementError enum.
  • Updated openapi.yml specification with a new error variant in OrderPostError.
  • New orderbook argument active_order_competition_threshold.

How to test

Created a new e2e scenario, try_replace_active_order_test, under the replace_order e2e module, which triggers the new error.

However, the ideal scenario would be to test this when the old order is included in any solution by using a mock solver that always returns a bad solution containing the old order. However, achieving this would require the ability to mock the driver in e2e tests, which we currently lack. A follow-up PR can address this.

Related Issues

Fixes #3315

@mrnaveira mrnaveira requested a review from a team as a code owner March 12, 2025 10:22
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 12, 2025

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@mrnaveira
Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

Comment on lines +440 to +441
// The number of past solver competitions we want to look back at
const COMPETITIONS_COUNT: u32 = 2;
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.

Would be nice to make this a configurable option.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I created a new active_order_competition_threshold argument for the orderbook

squadgazzz
squadgazzz previously approved these changes Mar 12, 2025
Copy link
Copy Markdown
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

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

I am not sure that checking the 2 solver competitions is enough here. Since we are able to settle auctions in parallel for different winning solvers and also have a settlement queue, we should probably also check all the competitions with the deadline above the current block. The deadline is stored in the competition_auctions table. That would return all the ongoing competitions and then they can be joined with the solver_competitions table. That way we won't miss anything unless I am overthinking.

upd: that way, the threshold config can be dropped.

run_test(try_replace_active_order_test).await;
}

async fn try_replace_active_order_test(web3: Web3) {
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.

nit: It seems like it tests not an active but already executed order replacement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You are right. The test is not ideal.

As I mentioned in the PR testing section, achieving proper testing requires the ability to mock the driver in e2e tests, which we currently lack. A follow-up PR can address this.

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.

A follow-up PR can address this.

I already implemented the mock. The PR is not ready yet. So to avoid working on the same thing, please wait for it.

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.

You are right. The test is not ideal.

The test name should reflect that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@MartinquaXD any thoughts on the competition_auctions proposal?

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.

The concern with the settle queue and parallel auctions makes sense to me but I think given how relatively rarely this feature will probably be used we shouldn't over engineer it. The submission deadline is currently roughly as long as 3 auctions so if we want to be safe without over-engineering we can just set the lookback to 5 and call it a day. If the frontend reports that people often run into this error we can revise the strategy.

@squadgazzz squadgazzz dismissed their stale review March 12, 2025 12:50

Accidentally pressed the wrong button

@mrnaveira mrnaveira marked this pull request as draft March 12, 2025 13:00
@mrnaveira mrnaveira marked this pull request as ready for review March 12, 2025 13:00
Copy link
Copy Markdown
Contributor

@MartinquaXD MartinquaXD left a comment

Choose a reason for hiding this comment

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

LGTM. I believe just one last thing missing. The orderbook/openapi.yml should reference the new error type in the OrderPostErrors.

Approved assuming this gets addressed.

@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:

@mrnaveira mrnaveira merged commit efb55ae into main Mar 13, 2025
11 checks passed
@mrnaveira mrnaveira deleted the order-replacement-check-unsafe branch March 13, 2025 08:27
@github-actions github-actions bot locked and limited conversation to collaborators Mar 13, 2025
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.

Return error on order replacement when it's not safe

3 participants