-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ON HOLD] Build domain::Settlement
based on /solve
response
#2730
Conversation
@@ -147,6 +147,42 @@ impl RunLoop { | |||
} | |||
}; | |||
|
|||
{ | |||
// Also calculate the score from the solution itself |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a temporary code that will be replaced when we switch to using autopilot calculated score. So did not spend too much time polishing it. It's used to detect differences in driver/autopilot score calculations.
/// | ||
/// Since `competition::Solution` does not contain JIT orders, the resulting | ||
/// settlement might be a subset of it's onchain observable twin. | ||
pub fn from_solution( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: would you prefer this functionality to be part of the competition::Solution
constructor and used solely for Score
calculation? This way it would be prevented from reuse, as I am afraid it's not clear enough that this constructor might build Settlement
object that doesn't have JIT orders = meaning it's potentially different from it's onchain settled brother.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between Settlement
and Solution
conceptually? Are we able to compute the score
on a Solution
or do we need a Settlement
? I think we should clarify this nomenclature more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solution
should represent a solver's response to /solve
request, in whatever form the autopilot requests this answer to be (so some cow protocol API format of data).
Settlement
should represent the decoded tx calldata solely (and, as an exception, it can contain data that is deductible from calldata, like it has OrderUid
right now). All other data that would be needed to calculate something on this struct is passed through arguments (example). The reason is reusability and higher decoupling of onchain/offchain data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With that in mind, creating Settlement
from Solution
is cheating since Solution
doesn't contain all data Settlement
would contain, BUT it contains enough data to calculate the score. So, my point is that we should consider not impementing this conversion as a public method on Settlement
, but rather enclose it in a Solution
constructor to calculate the score and that's it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would really appreciate some more clarity/consensus around the different data types and their semants:
- Settlement
- Solutions
- Transaction
...etc
Otherwise I feel like we are entering a world of pain and confusion.
/// | ||
/// Since `competition::Solution` does not contain JIT orders, the resulting | ||
/// settlement might be a subset of it's onchain observable twin. | ||
pub fn from_solution( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between Settlement
and Solution
conceptually? Are we able to compute the score
on a Solution
or do we need a Settlement
? I think we should clarify this nomenclature more.
#[derive(Debug, thiserror::Error)] | ||
pub enum Encoding { | ||
#[error("unable to decode settlement calldata: {0}")] | ||
Decoding(#[from] web3::ethabi::Error), | ||
#[error("unable to tokenize calldata into expected format: {0}")] | ||
Tokenizing(#[from] ethcontract::tokens::Error), | ||
#[error("unable to recover order uid: {0}")] | ||
OrderUidRecover(#[from] tokenized::Error), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use this type for anything else than the blanket from
implementations?
I don't think those #[from]
s are generally very good to use (they are convenient but bad), since now whenever you run into a tokenized::Error
it will auto converted into OrderUidRecover
even if let's say you are trying to parse the AuctionId
at the end of the calldata. At the risk of writing 3 more lines of code, I think each callsite should decide which error type to throw (instead of making ?
work everywhere)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this was refactored as part of #2746, so [from]
is removed for OrderUidRecover
variant.
auction: &auction::Auction, | ||
auction_id: auction::Id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a struct called AuctionWithId
which may be appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, but it would require unnecessary copy of the whole Auction
object. I can do it if you think it's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, but it would require unnecessary copy of the whole Auction object.
Really? Why does the auction exist without its ID in the runloop? Can we not move it into type AuctionWithId and then pass a reference to that around? This shouldn't require a clone.
As soon as an auction has an ID why do we still pass it around without?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we can just adjust the code in the run_loop that eagerly destructures the AuctionWithId
to get around the clone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments have been addressed.
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
Reopening as I think it will be needed for autopilot refactor. |
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the description:
This is fine, as converting will, (for now) be used solely to calculate the score, for which only user trades are considered anyway.
With the imminent launch of CoW AMMs this is no longer true, is it? Is this PR still supposed to be merged as is (we should update the description the reflect the most recent considerations though)?
Generally the code looks good imo.
/// Since `competition::Solution` does not contain JIT orders, the resulting | ||
/// `settlement::Solution` might be a subset of it's onchain observable | ||
/// twin. | ||
pub fn from_competition_solution( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
pub fn from_competition_solution( | |
pub fn from_competition( |
// settlement contract uses this formula to convert executed amounts: | ||
// SELL order: executedBuyAmount = executed * sellPrice / buyPrice; | ||
// BUY order: executedSellAmount = executed * buyPrice / sellPrice; | ||
// | ||
// With an example of converting 1 GNO for 100 DAI: | ||
// SELL order: executedBuyAmount = 1 * 100 / 1 = 100 => | ||
// (sellPrice = 100, buyPrice = 1) | ||
// BUY order: executedSellAmount = 100 * 1 / 100 = 1 => | ||
// (sellPrice = 100, buyPrice = 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nanonit: if it was for me you could remove this comment (I think it's quite clear that the exchange rate can be represented with the effective buy/sell amounts)
We discussed this here. Copy pasting the text to be visible here as well:
So, the conclusion is that this PR can't be merged until |
domain::Settlement
based on /solve
responsedomain::Settlement
based on /solve
response
domain::Settlement
based on /solve
responsedomain::Settlement
based on /solve
response
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
Can this be closed? |
Not yet. Waiting for #3001 to land and then we can add this logic that is crucial for calculating score on autopilot side. |
# Description A follow up for #2984 where we added a new format of /solve response, after which there were two ways to submit /solve response. This PR deprecates the old way and uses only the new format and adjusts the autopilot domain code to use it (which is needed so we can finally merge #2730 Will not merge it until all solvers switch to new format.
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
Edit: blocked by #2839 and #3001
Description
Fixes #2718
Driver responds to
/solve
withcompetition::Solution
.competition::Solution
contains traded amounts for user trades only (JIT orders are skipped). Therefore, it is expected that converting intosettlement::Solution
isn't always 1:1, as the same solution when settled onchain might contain JIT orders..This is fine, as converting will, (for now) be used solely to calculate the
score
, for which only user trades are considered anyway.Changes
settlement::Solution
based oncompetition::Solution
How to test
I tested locally limit order, partial limit order, multiple protocol fees order. Every time, the autopilot calculated score was identical to driver provided score.
However, since this is crucial part of the competition, I've added a log to Runloop that will detect differences. I want to leave this running for a week in production to make sure no regression bugs are introduced, before continuing with #2720