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

Breakdown fees protocol 3/3: DB field and returning on /get_trades #2910

Merged
merged 32 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
03d92da
Initial commit
sunce86 Aug 15, 2024
d1b74ad
Add executed protocol fees to get_trades
sunce86 Aug 15, 2024
12c2cfd
self cr
sunce86 Aug 15, 2024
c3c059b
unit tests
sunce86 Aug 15, 2024
4734065
update db docs
sunce86 Aug 19, 2024
5062b98
update openapi
sunce86 Aug 19, 2024
dac52c7
optional executed fees
sunce86 Aug 19, 2024
92b8929
update tests
sunce86 Aug 19, 2024
917522c
revert optionallity
sunce86 Aug 19, 2024
bee9fda
Merge branch 'main' into breakdown-fees-protocol
sunce86 Sep 3, 2024
15385d0
merge conflict
sunce86 Sep 3, 2024
7e22acb
refactor scheme
sunce86 Sep 3, 2024
6d25a2e
small refactor
sunce86 Sep 3, 2024
b6027ed
remove option
sunce86 Sep 3, 2024
c2e15d6
save protocol fee
sunce86 Sep 3, 2024
2508c1f
fix tests
sunce86 Sep 3, 2024
6e91f19
revert ignore
sunce86 Sep 3, 2024
f2853c6
Merge branch 'main' into breakdown-fees-protocol
sunce86 Sep 4, 2024
f8ae556
protocol fees are in surplus token
sunce86 Sep 4, 2024
0910437
refactor
sunce86 Sep 4, 2024
f3f2f8b
ExecutedProtocolFee object
sunce86 Sep 4, 2024
2dc555d
docs update
sunce86 Sep 4, 2024
6dcb6ae
add comment for ordering
sunce86 Sep 4, 2024
ab183c9
fix e2e test
sunce86 Sep 4, 2024
fa6fe2a
fmt
sunce86 Sep 4, 2024
0baf80c
small fixes
sunce86 Sep 4, 2024
adaf2e0
martin's review comments
sunce86 Sep 5, 2024
43d809f
cr fixes
sunce86 Sep 6, 2024
1dc1960
remove comment
sunce86 Sep 6, 2024
24cb713
Merge branch 'main' into breakdown-fees-protocol
sunce86 Sep 6, 2024
1236347
fix conflict
sunce86 Sep 6, 2024
a2a2c6b
fix conflicts
sunce86 Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl super::Postgres {
settlement_update.auction_id,
settlement_update.block_number,
&u256_to_big_decimal(&executed_fee),
None,
)
.await
.context("save_order_executions")?;
Expand Down
116 changes: 110 additions & 6 deletions crates/database/src/order_execution.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,91 @@
use {
crate::{auction::AuctionId, OrderUid},
crate::{auction::AuctionId, Address, OrderUid},
bigdecimal::BigDecimal,
sqlx::PgConnection,
sqlx::{
postgres::{PgHasArrayType, PgTypeInfo},
PgConnection,
},
std::collections::HashMap,
};

#[derive(Clone, Debug, Eq, PartialEq, sqlx::Type, sqlx::FromRow)]
pub struct FeeAsset {
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
pub amount: BigDecimal,
pub token: Address,
}

// explains that the equivalent Postgres type is already defined in the database
impl PgHasArrayType for FeeAsset {
fn array_type_info() -> PgTypeInfo {
PgTypeInfo::with_name("_feeasset")
}
}

pub async fn save(
ex: &mut PgConnection,
order: &OrderUid,
auction: AuctionId,
block_number: i64,
executed_fee: &BigDecimal,
executed_protocol_fees: Option<&[FeeAsset]>,
) -> Result<(), sqlx::Error> {
const QUERY: &str = r#"
INSERT INTO order_execution (order_uid, auction_id, reward, surplus_fee, block_number)
VALUES ($1, $2, $3, $4, $5)
INSERT INTO order_execution (order_uid, auction_id, reward, surplus_fee, block_number, protocol_fees)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (order_uid, auction_id)
DO UPDATE SET reward = $3, surplus_fee = $4, block_number = $5
DO UPDATE SET reward = $3, surplus_fee = $4, block_number = $5, protocol_fees = $6
;"#;
sqlx::query(QUERY)
.bind(order)
.bind(auction)
.bind(0.) // reward is deprecated but saved for historical analysis
.bind(Some(executed_fee))
.bind(block_number)
.bind(executed_protocol_fees)
.execute(ex)
.await?;
Ok(())
}

// fetch protocol fees for all keys in the filter
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
pub async fn executed_protocol_fees(
ex: &mut PgConnection,
keys_filter: &[(AuctionId, OrderUid)],
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<HashMap<(AuctionId, OrderUid), Vec<FeeAsset>>, sqlx::Error> {
if keys_filter.is_empty() {
return Ok(HashMap::new());
}

let mut fees = HashMap::new();
for (auction_id, order_uid) in keys_filter {
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
let protocol_fees = get_protocol_fees(ex, order_uid, *auction_id).await?;
fees.insert((*auction_id, *order_uid), protocol_fees.unwrap_or_default());
}

Ok(fees)
}

// executed procotol fee for a single <order, auction> pair
async fn get_protocol_fees(
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
ex: &mut PgConnection,
order: &OrderUid,
auction: AuctionId,
) -> Result<Option<Vec<FeeAsset>>, sqlx::Error> {
const QUERY: &str = r#"
SELECT protocol_fees
FROM order_execution
WHERE order_uid = $1 AND auction_id = $2
"#;

let row = sqlx::query_scalar(QUERY)
.bind(order)
.bind(auction)
.fetch_optional(ex)
.await?;

Ok(row)
}

#[cfg(test)]
mod tests {
use {super::*, sqlx::Connection};
Expand All @@ -39,8 +97,54 @@ mod tests {
let mut db = db.begin().await.unwrap();
crate::clear_DANGER_(&mut db).await.unwrap();

save(&mut db, &Default::default(), 1, 0, &Default::default())
save(
&mut db,
&Default::default(),
1,
0,
&Default::default(),
Some(&[
FeeAsset {
amount: Default::default(),
token: Default::default(),
},
FeeAsset {
amount: Default::default(),
token: Default::default(),
},
]),
)
.await
.unwrap();

// save entry but without protocol fees (we are still not calculating them)
save(
&mut db,
&Default::default(),
2,
0,
&Default::default(),
None,
)
.await
.unwrap();

let protocol_fees = get_protocol_fees(&mut db, &Default::default(), 1)
.await
.unwrap()
.unwrap();
assert_eq!(protocol_fees.len(), 2);

// existing order but without protocol fees
let protocol_fees = get_protocol_fees(&mut db, &Default::default(), 2)
.await
.unwrap();
assert!(protocol_fees.is_none());

// non-existing order
let protocol_fees = get_protocol_fees(&mut db, &Default::default(), 3)
.await
.unwrap();
assert!(protocol_fees.is_none());
}
}
2 changes: 1 addition & 1 deletion crates/database/src/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,7 @@ mod tests {
assert_eq!(order.executed_surplus_fee, 0.into());

let fee: BigDecimal = 1.into();
crate::order_execution::save(&mut db, &order_uid, 1, 0, &fee)
crate::order_execution::save(&mut db, &order_uid, 1, 0, &fee, None)
.await
.unwrap();

Expand Down
11 changes: 7 additions & 4 deletions crates/e2e/tests/e2e/limit_orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,9 +809,12 @@ async fn no_liquidity_limit_order(web3: Web3) {
let trades = services.get_trades(&order_id).await.unwrap();
assert_eq!(
trades.first().unwrap().fee_policies,
vec![model::fee_policy::FeePolicy::Surplus {
factor: 0.5,
max_volume_factor: 0.01
}],
vec![(
model::fee_policy::FeePolicy::Surplus {
factor: 0.5,
max_volume_factor: 0.01
},
None
)],
);
}
12 changes: 11 additions & 1 deletion crates/model/src/fee_policy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
number::serialization::HexOrDecimalU256,
primitive_types::U256,
primitive_types::{H160, U256},
serde::Serialize,
serde_with::serde_as,
};
Expand Down Expand Up @@ -34,3 +34,13 @@ pub struct Quote {
#[serde_as(as = "HexOrDecimalU256")]
pub fee: U256,
}

#[serde_as]
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[cfg_attr(any(test, feature = "e2e"), derive(serde::Deserialize))]
#[serde(rename_all = "camelCase")]
pub struct ExecutedFee {
#[serde_as(as = "HexOrDecimalU256")]
pub amount: U256,
pub token: H160,
}
57 changes: 36 additions & 21 deletions crates/model/src/trade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
//! as described by the openapi documentation.

use {
crate::{fee_policy::FeePolicy, order::OrderUid},
crate::{
fee_policy::{ExecutedFee, FeePolicy},
order::OrderUid,
},
num::BigUint,
primitive_types::{H160, H256},
serde::Serialize,
Expand Down Expand Up @@ -30,7 +33,7 @@ pub struct Trade {
// Settlement Data
pub tx_hash: Option<H256>,
// Fee Policy Data
pub fee_policies: Vec<FeePolicy>,
pub fee_policies: Vec<(FeePolicy, Option<ExecutedFee>)>,
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
}

#[cfg(test)]
Expand Down Expand Up @@ -58,18 +61,18 @@ mod tests {
"buyToken": "0x0000000000000000000000000000000000000009",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000040",
"feePolicies": [
{
[{
"surplus": {
"factor": 1.1,
"maxVolumeFactor": 2.2
}
},
{
}, null],
[{
"volume": {
"factor": 0.9
}
},
{
}, null],
[{
"priceImprovement": {
"factor": 1.2,
"maxVolumeFactor": 1.5,
Expand All @@ -79,7 +82,10 @@ mod tests {
"fee": "5"
}
}
}
}, {
"amount": "5",
"token": "0x000000000000000000000000000000000000000a"
}]
]
});
let expected = Trade {
Expand All @@ -94,20 +100,29 @@ mod tests {
sell_token: H160::from_low_u64_be(10),
tx_hash: Some(H256::from_low_u64_be(64)),
fee_policies: vec![
FeePolicy::Surplus {
factor: 1.1,
max_volume_factor: 2.2,
},
FeePolicy::Volume { factor: 0.9 },
FeePolicy::PriceImprovement {
factor: 1.2,
max_volume_factor: 1.5,
quote: Quote {
sell_amount: U256::from(100u64),
buy_amount: U256::from(150u64),
fee: U256::from(5u64),
(
FeePolicy::Surplus {
factor: 1.1,
max_volume_factor: 2.2,
},
},
None,
),
(FeePolicy::Volume { factor: 0.9 }, None),
(
FeePolicy::PriceImprovement {
factor: 1.2,
max_volume_factor: 1.5,
quote: Quote {
sell_amount: U256::from(100u64),
buy_amount: U256::from(150u64),
fee: U256::from(5u64),
},
},
Some(ExecutedFee {
amount: U256::from(5u64),
token: H160::from_low_u64_be(10),
}),
),
],
};

Expand Down
24 changes: 22 additions & 2 deletions crates/orderbook/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1194,10 +1194,10 @@ components:
nullable: true
feePolicies:
description: |
The fee policies that were used to compute the fees for this trade. Listed in the order they got applied.
The fee policies that were used to compute the fees for this trade, together with the executed amount of protocol fee. Listed in the order they got applied.
type: array
items:
$ref: "#/components/schemas/FeePolicy"
$ref: "#/components/schemas/FeePolicyWithExecutedFee"
required:
- blockNumber
- logIndex
Expand Down Expand Up @@ -1667,3 +1667,23 @@ components:
- $ref: "#/components/schemas/Surplus"
- $ref: "#/components/schemas/Volume"
- $ref: "#/components/schemas/PriceImprovement"
ExecutedFee:
type: object
properties:
amount:
description: "Fee amount taken"
$ref: "#/components/schemas/TokenAmount"
token:
description: "The token in which the fee is taken"
$ref: "#/components/schemas/Address"
required:
- amount
- token
FeePolicyWithExecutedFee:
type: object
properties:
fee_policy:
$ref: '#/components/schemas/FeePolicy'
executed_fee:
$ref: '#/components/schemas/ExecutedFee'
nullable: true
Loading
Loading