-
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
Price improvement tests #2467
Price improvement tests #2467
Conversation
5042984
to
666f4fe
Compare
e103df2
to
dd233e2
Compare
Still not quite sure this PR should replace all of the unit tests |
quote_sell_amount: quote_sell_amount.into(), | ||
quote_buy_amount: quote_buy_amount.into(), | ||
executed: quote_buy_amount.into(), |
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.
How can we charge any fee here? The quote amount is equal to the executed amount so there is no price improvement. Doesn't this test framework now need a way of differentiating between the quoted and executed price? Also, are we even using an executed amount that is lower than the full amount in any test case (ie are we testing partial fills somewhere)
Overall, I still find these test cases a bit hard to parse (imagine someone trying to debug a failing test case and trying to reproduce the assumptions and math that is going on here).
I don't think we necessarily have to find the nicest abstraction that leads to the least code (e.g. I think we could have a different TestCase setup for price improvement fee vs. surplus fee if one is structurally more complex), but let's please make those tests easier to comprehend.
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.
Before refactoring, now I understand that I am confused about a condition when an order is inside or outside market price.
Can out of market orders be defined as (order.sell + order.fee) * quote.buy < (quote.sell + quote.fee) * order.buy
?
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 so, yes (looking at @sunce86 to confirm)
order_side: order::Side::Sell, | ||
fee_policy, | ||
order_sell_amount: order_sell_amount.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), |
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: I think it would be clearer to call this network_fee
in this context.
I do see now that the price improvement comes from the network fee being different than the quoted fee. This is very clever but not something I'd expect someone maintaining this code in 3 month to just guess without context, so please let's help your future colleague to understand how this test work more intuitively.
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} |
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.
Partially fillable orders are missing.
Also can we add a test that shows shifting surplus into network fees doesn't change the protocol fee charged? E.g. the following two executions pay the same fee (assuming same underlying orders & quotes)
- Sell 0.1 ETH receive 3500 DAI, pay 0.9 ETH in network fees
- Sell 1 ETH receive 3500 DAI, pay 0 in network fees
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.
Partially fillable orders require some further refactoring. I will create a separate issue for this.
Co-authored-by: Felix Leupold <[email protected]>
Co-authored-by: Felix Leupold <[email protected]>
4c68e5c
to
4d4ad2f
Compare
4d4ad2f
to
38135e8
Compare
2a20508
to
287c1f9
Compare
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.
Can we capture the follow up item of adding tests for partial fills (I believe this might also be missing for the surplus fee policy)?
nvm #2480
order_side: order::Side::Buy, | ||
fee_policy, | ||
order_sell_amount, | ||
network_fee: Some(2000000000000000000u128.into()), |
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 will likely be easier to see with #2472, but can you comment in code how the price improvement is achieved (realized network fee lower than quote, leading to X price improvement). This will help understand the expected executed sell amount (compared to the quoted one), but maybe you can add a comment for this expectation as well.
Should be done for each test.
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.
Started writing the comments and found out that the results look pretty weird. Found this code which applies a default surplus factor. Not sure if it needs to be eliminated for the price improvement tests.
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.
Yes, either we need to set it in the test case or make sure it's set to 1. I think your trick with reducing the fee is good enough and allows us to more precisely reason about absolute surplus values (rather than a factor), so I'd slightly prefer setting the factor to 1 (but no strong feelings, as longs as it's clear from the main test how the calculation is carried out)
2390320
to
3a80fe6
Compare
# Conflicts: # crates/driver/src/tests/cases/protocol_fees.rs # crates/driver/src/tests/setup/blockchain.rs
} => quote.network_fee, | ||
_ => eth::U256::zero(), | ||
}; | ||
(self.buy * (self.sell - fee) / self.sell) / self.order.surplus_factor |
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.
Is it valid?
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 think we should always incorporate some network fee here (and not have an if branch just for PriceImprovement fees. That feels way too hacky.
} => quote.network_fee, | ||
_ => eth::U256::zero(), | ||
}; | ||
(self.sell + fee) * self.order.surplus_factor |
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.
Is it valid?
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.
Same
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 still find the whole setup very hacky and cannot see myself maintaining these tests.
Can we limit our price improvement for now to be only based on the difference in estimted network fee and actually network fee?
Then, a test case just needs a quote (which determines the order amounts and the expected fee), an actual fee amount (which determines the price improvement), a side and the expected amounts.
We shouldn't create if branches deep inside the test setup to cater to one specific test case but instead rethink the setup to make it work with all fee models.
.sell_amount(test_case.order_sell_amount) | ||
.buy_amount(test_case.order_buy_amount); |
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.
Why is that set from the order amounts and not from the quote?
quote, | ||
order_sell_amount, | ||
order_buy_amount, | ||
network_fee: Some(1.ether().into_wei()), |
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.
You are still not saying anywhere that this is the little detail that leads to price improvement. This is way to hidden to leave this uncommented.
network_fee: Some(network_fee), | ||
executed: order_sell_amount - network_fee, | ||
executed_sell_amount: order_sell_amount, | ||
// todo: how to prove the value? |
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.
Well how is it calculated? Comment with the math that leads to this value.
Let's maybe start by "where is the price improvement coming from in this test"? I see sell amount and buy amounts and network fees are equal for quote and orders. Unclear why there is any price improvement fee here?
} => quote.network_fee, | ||
_ => eth::U256::zero(), | ||
}; | ||
(self.buy * (self.sell - fee) / self.sell) / self.order.surplus_factor |
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 think we should always incorporate some network fee here (and not have an if branch just for PriceImprovement fees. That feels way too hacky.
} => quote.network_fee, | ||
_ => eth::U256::zero(), | ||
}; | ||
(self.sell + fee) * self.order.surplus_factor |
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.
Same
Actually maybe this wasn't a good idea to begin with (assuming it's the reason for the conditional refactoring). In this case, you can also work with explicit order and quote amounts and just assume 0 network everywhere. |
@squadgazzz I created #2510 as a suggestion on how I would implement these tests. Can you take a look, tell me what you think about this approach and if it works and if convert the remaining tests? |
Description
Fixes #2479