Update swaps average savings calculation#9662
Conversation
706cb17 to
94f1d16
Compare
Builds ready [94f1d16]
Page Load Metrics (432 ± 58 ms)
|
There was a problem hiding this comment.
@danjm noticed that we were effectively doubling the size of the fee savings (whether negative or positive) by calculating performance savings using ethValueOfTrade, which already has the fees subtracted.
I don't understand the problem here. Subtracting fees was intended, right? So that we account for the network fee in determining savings. How else are network fees accounted for? If we solely focus on the received value, we might end up in a place where the best quote has a lower received value than the median due to the median having a higher network fee.
Edit: Oh I see now. The part where it's double-counted is in calculating savings.total. I understand now.
| async _findTopQuoteAndCalculateSavings (quotes = {}) { | ||
| /** | ||
| * Calculates trade data in order to identify the best quotes and its savings. | ||
| * Modifies the passed-in quotes in place, adding the following decimal string |
There was a problem hiding this comment.
I'm curious why the quotes are modified in-place here, rather than being returned. I find it easier to understand what a function does if it doesn't rely upon mutating the parameters, and the types become much more informative as well.
There was a problem hiding this comment.
I also don't think any of these new values should be attached to the quote object before they're used either. This strategy of keeping state around for later has left us with a lot of unused state that we had forgotten to clean up. Best to add it only when we being actually using it.
There was a problem hiding this comment.
In my understanding, problems with mutating in place arise when the mutated data is accessed by many different contexts over its lifetime. In this instance, the mutation occurs at a single time and place, namely when _addTopQuoteAndTradeData is called in fetchAndSetQuotes.
I'd suggest that we return the modified quotes object from _addTopQuoteAndTradeData, while still modifying it in place. This would grant us the type benefits without having to reinstantiate the quotes object.
If we want to also reinstantiate the quotes object in _addTopQuoteAndTradeData as a matter of principle, I'm also fine with that, although I don't think it does us any good in this case.
There was a problem hiding this comment.
problems with mutating in place arise when the mutated data is accessed by many different contexts over its lifetime.
Nah I wasn't referring to anything like this. I meant it was hard to understand. Mutation makes the code hard to read.
I expect a function's type signature to give some hint as to what it's doing - stuff goes in, stuff comes out. It makes tracing the code easier as well. I would never have expected this to mutate the quotes before reading this doc comment. This is particularly problematic when reading where this function is used, as it wouldn't occur to me to read the definition of every function invoked just to follow what was going on with the quotes. I would see that it returned the ID of the top quote, and assume that's all it did.
We also lose any opportunity to describe the operation with types if we rely on mutation. With proper parameter and return types, we can express using the type system that these properties were not present before, but may be present afterwards.
There was a problem hiding this comment.
We also lose any opportunity to describe the operation with types if we rely on mutation.
I was suggesting that we can mutate the quotes in place and return them (altering the function's return type) to get this benefit:
we can express using the type system that these properties were not present before, but may be present afterwards.
There was a problem hiding this comment.
I'd suggest that we return the modified quotes object from _addTopQuoteAndTradeData, while still modifying it in place. This would grant us the type benefits without having to reinstantiate the quotes object.
Ah, right, this sounds fine. Sorry I only meant to take issue with the function signature, not the mutating of the parameter itself. I guess I don't feel strongly one way or the other about whether the parameter is mutated in this case, since it's a private function used in one place - I explained that poorly.
There was a problem hiding this comment.
Then we are in agreement, I shall alter the function signature!
Gudahtt
left a comment
There was a problem hiding this comment.
This still seems incorrect 🤔
We're now comparing the best quote against the median fee and the median received value, even if those two numbers are from different quotes. We should be comparing the best quote to the median quote when considering the total value. Once that quote is identified, we can extract the fee v.s. performance savings.
|
@Gudahtt, subtracting fees is necessary to get the ETH value of the trade, but in our performance savings calculations, we were subtracting them twice. Referring to the equations in the description of #9611: The problem is with the
You'll see that We still calculate the |
@Gudahtt what do you mean "even if those two numbers are from different quotes"? We first identify the best quote using the |
That last part is the problem - the quote with the median |
|
@Gudahtt is right: we have to identify the quote or pair of quotes that comprise the median Great catch! |
Builds ready [02d2fa2]
Page Load Metrics (413 ± 50 ms)
|
|
An alternative to this PR that avoids the need to calculate |
|
This will be superseded by a PR from @danjm some time today. |
@danjm noticed that we were effectively doubling the size of the fee savings (whether negative or positive) by calculating performance savings using
ethValueOfTrade, which already has the fees subtracted.This PR fixes our average savings calculation by using the existing intermediate value,
ethValueReceived, and its median to calculate performance savings.In addition, we add the following properties to all quotes, to avoid recalculating their values in the UI:
ethFeeethValueReceivedethValueOfTrade