-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Driver tests refactoring for protocol fees (#2404)
# Description Refactors driver tests to be able to use them in UT fashion by providing custom quotes and explicit expected results without replicating original protocol fees logic in the tests. The easiest approach is to continue using Uniswap on-chain interactions, but it turned out that it has some limitations where the pool's executed amounts ratio should be the same as the pool's reserves ratio. The proposed approach addresses this limitation by adjusting the pool's reserves by providing precalculated executed amounts using a reversed function. The precision issue with calculations without a floating point adds complexity to the implemented functions. # Changes - [ ] Adds ability to provide custom pool's executed amounts - [ ] Results are now compared with precalculated values - [ ] Minor refactoring to operate with WEI values for better readability - [ ] Pool's reserve token `a` or `b` adjustment functions could be used interchangeably ## Related Issues Fixed #2267
- Loading branch information
1 parent
4d571b9
commit 8f8ef93
Showing
11 changed files
with
421 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
use crate::{ | ||
domain::{competition::order, eth}, | ||
tests::{ | ||
self, | ||
setup::{ | ||
ab_adjusted_pool, | ||
ab_liquidity_quote, | ||
ab_order, | ||
ab_solution, | ||
ExpectedOrderAmounts, | ||
FeePolicy, | ||
Test, | ||
}, | ||
}, | ||
}; | ||
|
||
struct TestCase { | ||
order_side: order::Side, | ||
fee_policy: FeePolicy, | ||
order_sell_amount: eth::U256, | ||
solver_fee: Option<eth::U256>, | ||
quote_sell_amount: eth::U256, | ||
quote_buy_amount: eth::U256, | ||
executed: eth::U256, | ||
executed_sell_amount: eth::U256, | ||
executed_buy_amount: eth::U256, | ||
} | ||
|
||
async fn protocol_fee_test_case(test_case: TestCase) { | ||
let test_name = format!( | ||
"Protocol Fee: {:?} {:?}", | ||
test_case.order_side, test_case.fee_policy | ||
); | ||
let quote = ab_liquidity_quote() | ||
.sell_amount(test_case.quote_sell_amount) | ||
.buy_amount(test_case.quote_buy_amount); | ||
let pool = ab_adjusted_pool(quote); | ||
let expected_amounts = ExpectedOrderAmounts { | ||
sell: test_case.executed_sell_amount, | ||
buy: test_case.executed_buy_amount, | ||
}; | ||
let order = ab_order() | ||
.kind(order::Kind::Limit) | ||
.sell_amount(test_case.order_sell_amount) | ||
.side(test_case.order_side) | ||
.solver_fee(test_case.solver_fee) | ||
.fee_policy(test_case.fee_policy) | ||
.executed(test_case.executed) | ||
.expected_amounts(expected_amounts); | ||
let test: Test = tests::setup() | ||
.name(test_name) | ||
.pool(pool) | ||
.order(order.clone()) | ||
.solution(ab_solution()) | ||
.done() | ||
.await; | ||
|
||
test.solve().await.ok().orders(&[order]); | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn surplus_protocol_fee_buy_order_not_capped() { | ||
let fee_policy = FeePolicy::Surplus { | ||
factor: 0.5, | ||
// high enough so we don't get capped by volume fee | ||
max_volume_factor: 1.0, | ||
}; | ||
let test_case = TestCase { | ||
order_side: order::Side::Buy, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 100000000000000000000u128.into(), | ||
executed_buy_amount: 40000000000000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn surplus_protocol_fee_sell_order_not_capped() { | ||
let fee_policy = FeePolicy::Surplus { | ||
factor: 0.5, | ||
// high enough so we don't get capped by volume fee | ||
max_volume_factor: 1.0, | ||
}; | ||
let test_case = TestCase { | ||
order_side: order::Side::Sell, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 50000000000000000000u128.into(), | ||
executed_buy_amount: 20000000002000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn surplus_protocol_fee_buy_order_capped() { | ||
let fee_policy = FeePolicy::Surplus { | ||
factor: 0.5, | ||
// low enough so we get capped by volume fee | ||
max_volume_factor: 0.1, | ||
}; | ||
let test_case = TestCase { | ||
order_side: order::Side::Buy, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 55000000000000000000u128.into(), | ||
executed_buy_amount: 40000000000000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn surplus_protocol_fee_sell_order_capped() { | ||
let fee_policy = FeePolicy::Surplus { | ||
factor: 0.5, | ||
// low enough so we get capped by volume fee | ||
max_volume_factor: 0.1, | ||
}; | ||
let test_case = TestCase { | ||
order_side: order::Side::Sell, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 50000000000000000000u128.into(), | ||
executed_buy_amount: 35000000000000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn volume_protocol_fee_buy_order() { | ||
let fee_policy = FeePolicy::Volume { factor: 0.5 }; | ||
let test_case = TestCase { | ||
order_side: order::Side::Buy, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 75000000000000000000u128.into(), | ||
executed_buy_amount: 40000000000000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} | ||
|
||
#[tokio::test] | ||
#[ignore] | ||
async fn volume_protocol_fee_sell_order() { | ||
let fee_policy = FeePolicy::Volume { factor: 0.5 }; | ||
let test_case = TestCase { | ||
order_side: order::Side::Sell, | ||
fee_policy, | ||
order_sell_amount: 50000000000000000000u128.into(), | ||
solver_fee: Some(10000000000000000000u128.into()), | ||
quote_sell_amount: 50000000000000000000u128.into(), | ||
quote_buy_amount: 40000000000000000000u128.into(), | ||
executed: 40000000000000000000u128.into(), | ||
executed_sell_amount: 50000000000000000000u128.into(), | ||
executed_buy_amount: 15000000000000000000u128.into(), | ||
}; | ||
|
||
protocol_fee_test_case(test_case).await; | ||
} |
Oops, something went wrong.