Skip to content
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

Closed
wants to merge 14 commits into from
147 changes: 139 additions & 8 deletions crates/driver/src/tests/cases/protocol_fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
ab_solution,
ExpectedOrderAmounts,
FeePolicy,
PriceImprovementQuote,
Test,
},
},
Expand All @@ -18,7 +19,7 @@ struct TestCase {
order_side: order::Side,
fee_policy: FeePolicy,
order_sell_amount: eth::U256,
solver_fee: Option<eth::U256>,
network_fee: Option<eth::U256>,
quote_sell_amount: eth::U256,
quote_buy_amount: eth::U256,
executed: eth::U256,
Expand All @@ -43,7 +44,7 @@ async fn protocol_fee_test_case(test_case: TestCase) {
.kind(order::Kind::Limit)
.sell_amount(test_case.order_sell_amount)
.side(test_case.order_side)
.solver_fee(test_case.solver_fee)
.solver_fee(test_case.network_fee)
.fee_policy(test_case.fee_policy)
.executed(test_case.executed)
.expected_amounts(expected_amounts);
Expand All @@ -70,7 +71,7 @@ async fn surplus_protocol_fee_buy_order_not_capped() {
order_side: order::Side::Buy,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -93,7 +94,7 @@ async fn surplus_protocol_fee_sell_order_not_capped() {
order_side: order::Side::Sell,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -116,7 +117,7 @@ async fn surplus_protocol_fee_buy_order_capped() {
order_side: order::Side::Buy,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -139,7 +140,7 @@ async fn surplus_protocol_fee_sell_order_capped() {
order_side: order::Side::Sell,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -158,7 +159,7 @@ async fn volume_protocol_fee_buy_order() {
order_side: order::Side::Buy,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -177,7 +178,7 @@ async fn volume_protocol_fee_sell_order() {
order_side: order::Side::Sell,
fee_policy,
order_sell_amount: 50000000000000000000u128.into(),
solver_fee: Some(10000000000000000000u128.into()),
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: 50000000000000000000u128.into(),
quote_buy_amount: 40000000000000000000u128.into(),
executed: 40000000000000000000u128.into(),
Expand All @@ -187,3 +188,133 @@ async fn volume_protocol_fee_sell_order() {

protocol_fee_test_case(test_case).await;
}

#[tokio::test]
#[ignore]
async fn price_improvement_fee_buy_out_of_market_order() {
let fee_policy = FeePolicy::PriceImprovement {
factor: 0.5,
max_volume_factor: 1.0,
quote: PriceImprovementQuote {
sell_amount: 50000000000000000000u128.into(),
buy_amount: 35000000000000000000u128.into(),
network_fee: 20000000000000000000u128.into(),
},
};
// (order.sell + order.fee) * quote.buy < (quote.sell + quote.fee) * order.buy
// (45 + 10) * 35 < (50 + 20) * 35
// 1925 < 2450
let order_sell_amount = 45000000000000000000u128.into();
let order_buy_amount = 35000000000000000000u128.into();
let test_case = TestCase {
order_side: order::Side::Buy,
fee_policy,
order_sell_amount,
network_fee: Some(10000000000000000000u128.into()),
quote_sell_amount: order_sell_amount,
quote_buy_amount: order_buy_amount,
executed: order_buy_amount,
executed_sell_amount: 57500000000000000000u128.into(),
executed_buy_amount: order_buy_amount,
};

protocol_fee_test_case(test_case).await;
}

#[tokio::test]
#[ignore]
async fn price_improvement_fee_sell_out_of_market_order() {
let fee_policy = FeePolicy::PriceImprovement {
factor: 0.5,
max_volume_factor: 1.0,
quote: PriceImprovementQuote {
sell_amount: 50000000000000000000u128.into(),
buy_amount: 35000000000000000000u128.into(),
network_fee: 20000000000000000000u128.into(),
},
};
// (order.sell + order.fee) * quote.buy < (quote.sell + quote.fee) * order.buy
// (50 + 10) * 35 < (50 + 20) * 40
// 2100 < 2800
let order_sell_amount = 50000000000000000000u128.into();
let order_buy_amount = 40000000000000000000u128.into();
let network_fee = 10000000000000000000u128.into();
let test_case = TestCase {
order_side: order::Side::Sell,
fee_policy,
order_sell_amount,
network_fee: Some(network_fee),
quote_sell_amount: order_sell_amount,
quote_buy_amount: order_buy_amount,
executed: order_sell_amount - network_fee,
executed_sell_amount: order_sell_amount,
executed_buy_amount: 32500000000000000000u128.into(),
};

protocol_fee_test_case(test_case).await;
}
Copy link
Contributor

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)

  1. Sell 0.1 ETH receive 3500 DAI, pay 0.9 ETH in network fees
  2. Sell 1 ETH receive 3500 DAI, pay 0 in network fees

Copy link
Contributor Author

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.


#[tokio::test]
#[ignore]
async fn price_improvement_fee_buy_in_market_order() {
let fee_policy = FeePolicy::PriceImprovement {
factor: 0.5,
max_volume_factor: 1.0,
quote: PriceImprovementQuote {
sell_amount: 45000000000000000000u128.into(),
buy_amount: 35000000000000000000u128.into(),
network_fee: 10000000000000000000u128.into(),
},
};
// (order.sell + order.fee) * quote.buy < (quote.sell + quote.fee) * order.buy
// (50 + 15) * 35 < (45 + 10) * 35
// 2275 < 1925
let order_sell_amount = 50000000000000000000u128.into();
let order_buy_amount = 35000000000000000000u128.into();
let test_case = TestCase {
order_side: order::Side::Buy,
fee_policy,
order_sell_amount,
network_fee: Some(15000000000000000000u128.into()),
quote_sell_amount: order_sell_amount,
quote_buy_amount: order_buy_amount,
executed: order_buy_amount,
executed_sell_amount: 52500000000000000000u128.into(),
executed_buy_amount: order_buy_amount,
};

protocol_fee_test_case(test_case).await;
}

#[tokio::test]
#[ignore]
async fn price_improvement_fee_sell_in_market_order() {
let fee_policy = FeePolicy::PriceImprovement {
factor: 0.5,
max_volume_factor: 1.0,
quote: PriceImprovementQuote {
sell_amount: 50000000000000000000u128.into(),
buy_amount: 40000000000000000000u128.into(),
network_fee: 10000000000000000000u128.into(),
},
};
// (order.sell + order.fee) * quote.buy < (quote.sell + quote.fee) * order.buy
// (50 + 15) * 40 < (50 + 10) * 35
// 2600 < 2100
let order_sell_amount: eth::U256 = 50000000000000000000u128.into();
let order_buy_amount: eth::U256 = 35000000000000000000u128.into();
let network_fee = 15000000000000000000u128.into();
let test_case = TestCase {
order_side: order::Side::Sell,
fee_policy,
order_sell_amount,
network_fee: Some(network_fee),
quote_sell_amount: order_sell_amount,
quote_buy_amount: order_buy_amount,
executed: order_sell_amount - network_fee,
executed_sell_amount: order_sell_amount,
executed_buy_amount: 34166666666666666667u128.into(),
};

protocol_fee_test_case(test_case).await;
}
30 changes: 30 additions & 0 deletions crates/driver/src/tests/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,28 @@ pub enum Score {
RiskAdjusted { success_probability: f64 },
}

#[serde_as]
#[derive(Debug, Clone, PartialEq, serde::Serialize)]
#[serde(rename_all = "camelCase", tag = "kind")]
pub struct PriceImprovementQuote {
pub buy_amount: eth::U256,
pub sell_amount: eth::U256,
pub network_fee: eth::U256,
}

#[serde_as]
#[derive(Debug, Clone, PartialEq, serde::Serialize)]
#[serde(rename_all = "camelCase", tag = "kind")]
pub enum FeePolicy {
#[serde(rename_all = "camelCase")]
Surplus { factor: f64, max_volume_factor: f64 },
#[serde(rename_all = "camelCase")]
PriceImprovement {
factor: f64,
max_volume_factor: f64,
quote: PriceImprovementQuote,
},
#[serde(rename_all = "camelCase")]
Volume { factor: f64 },
}

Expand All @@ -94,6 +109,21 @@ impl FeePolicy {
"maxVolumeFactor": max_volume_factor
}
}),
FeePolicy::PriceImprovement {
factor,
max_volume_factor,
quote,
} => json!({
"priceImprovement": {
"factor": factor,
"maxVolumeFactor": max_volume_factor,
"quote": {
"sellAmount": quote.sell_amount,
"buyAmount": quote.buy_amount,
"fee": quote.network_fee,
}
}
}),
FeePolicy::Volume { factor } => json!({
"volume": {
"factor": factor
Expand Down
Loading