diff --git a/crates/autopilot/src/domain/settlement/mod.rs b/crates/autopilot/src/domain/settlement/mod.rs index c26b1aa544..a572770023 100644 --- a/crates/autopilot/src/domain/settlement/mod.rs +++ b/crates/autopilot/src/domain/settlement/mod.rs @@ -84,10 +84,27 @@ impl Settlement { } /// Per order fees breakdown. Contains all orders from the settlement - pub fn fee_breakdown(&self) -> HashMap> { + pub fn fee_breakdown(&self) -> HashMap { self.trades .iter() - .map(|trade| (*trade.uid(), trade.fee_breakdown(&self.auction).ok())) + .map(|trade| { + let fee_breakdown = trade.fee_breakdown(&self.auction).unwrap_or_else(|err| { + tracing::warn!( + ?err, + trade = %trade.uid(), + "possible incomplete fee breakdown calculation", + ); + trade::FeeBreakdown { + total: eth::Asset { + // TODO surplus token + token: trade.sell_token(), + amount: num::zero(), + }, + protocol: vec![], + } + }); + (*trade.uid(), fee_breakdown) + }) .collect() } @@ -312,7 +329,7 @@ mod tests { trade.surplus_in_ether(&auction.prices).unwrap().0, eth::U256::from(52937525819789126u128) ); - // fee read from "executedSurplusFee" https://api.cow.fi/mainnet/api/v1/orders/0x10dab31217bb6cc2ace0fe601c15d342f7626a1ee5ef0495449800e73156998740a50cf069e992aa4536211b23f286ef88752187ffffffff + // fee read from "executedFee" https://api.cow.fi/mainnet/api/v1/orders/0x10dab31217bb6cc2ace0fe601c15d342f7626a1ee5ef0495449800e73156998740a50cf069e992aa4536211b23f286ef88752187ffffffff // but not equal to 6890975030480504 anymore, since after this tx we switched to // convert the fee from surplus token directly to ether assert_eq!( diff --git a/crates/autopilot/src/domain/settlement/trade/math.rs b/crates/autopilot/src/domain/settlement/trade/math.rs index 9a1d40c093..fcca0b5275 100644 --- a/crates/autopilot/src/domain/settlement/trade/math.rs +++ b/crates/autopilot/src/domain/settlement/trade/math.rs @@ -134,9 +134,15 @@ impl Trade { /// Total fee (protocol fee + network fee). Equal to a surplus difference /// before and after applying the fees. - pub fn fee_in_sell_token(&self) -> Result { + /// + /// Denominated in SELL token + pub fn fee_in_sell_token(&self) -> Result { let fee = self.fee()?; self.fee_into_sell_token(fee.amount) + .map(|amount| eth::Asset { + token: self.sell.token, + amount: amount.into(), + }) } /// Total fee (protocol fee + network fee). Equal to a surplus difference diff --git a/crates/autopilot/src/domain/settlement/trade/mod.rs b/crates/autopilot/src/domain/settlement/trade/mod.rs index 0e41ad4236..31c43d6687 100644 --- a/crates/autopilot/src/domain/settlement/trade/mod.rs +++ b/crates/autopilot/src/domain/settlement/trade/mod.rs @@ -75,6 +75,13 @@ impl Trade { Ok(FeeBreakdown { total, protocol }) } + pub fn sell_token(&self) -> eth::TokenAddress { + match self { + Self::Fulfillment(trade) => trade.sell.token, + Self::Jit(trade) => trade.sell.token, + } + } + pub fn new(trade: transaction::EncodedTrade, auction: &super::Auction, created: u32) -> Self { if auction.orders.contains_key(&trade.uid) { Trade::Fulfillment(Fulfillment { @@ -150,8 +157,8 @@ pub struct Jit { #[derive(Debug, Clone)] pub struct FeeBreakdown { /// Total fee the trade was charged (network fee + protocol fee) - // TODO: express in surplus token - pub total: eth::SellTokenAmount, + // TODO surplus token + pub total: eth::Asset, /// Breakdown of protocol fees. pub protocol: Vec, } diff --git a/crates/autopilot/src/infra/persistence/mod.rs b/crates/autopilot/src/infra/persistence/mod.rs index 8db2f827b6..35f6217b29 100644 --- a/crates/autopilot/src/infra/persistence/mod.rs +++ b/crates/autopilot/src/infra/persistence/mod.rs @@ -545,28 +545,23 @@ impl Persistence { .await; for (order, order_fee) in fee_breakdown { - let total_fee = order_fee - .as_ref() - .map(|fee| u256_to_big_decimal(&fee.total.0)) - .unwrap_or_default(); - let executed_protocol_fees = order_fee - .map(|fee| { - fee.protocol - .into_iter() - .map(|executed| Asset { - token: ByteArray(executed.fee.token.0 .0), - amount: u256_to_big_decimal(&executed.fee.amount.0), - }) - .collect::>() - }) - .unwrap_or_default(); database::order_execution::save( &mut ex, &ByteArray(order.0), auction_id, block_number, - &total_fee, - &executed_protocol_fees, + Asset { + token: ByteArray(order_fee.total.token.0 .0), + amount: u256_to_big_decimal(&order_fee.total.amount.0), + }, + &order_fee + .protocol + .into_iter() + .map(|executed| Asset { + token: ByteArray(executed.fee.token.0 .0), + amount: u256_to_big_decimal(&executed.fee.amount.0), + }) + .collect::>(), ) .await?; } diff --git a/crates/database/src/jit_orders.rs b/crates/database/src/jit_orders.rs index 12f79a0e6d..6725527b61 100644 --- a/crates/database/src/jit_orders.rs +++ b/crates/database/src/jit_orders.rs @@ -31,7 +31,8 @@ ARRAY[]::record[] AS post_interactions, NULL AS ethflow_data, NULL AS onchain_user, NULL AS onchain_placement_error, -COALESCE((SELECT SUM(surplus_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_surplus_fee, +COALESCE((SELECT SUM(total_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_fee, +COALESCE((SELECT total_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_fee_token, -- TODO surplus token NULL AS full_app_data "#; diff --git a/crates/database/src/order_execution.rs b/crates/database/src/order_execution.rs index 18d81a7cbc..541e05e1a2 100644 --- a/crates/database/src/order_execution.rs +++ b/crates/database/src/order_execution.rs @@ -18,25 +18,26 @@ pub async fn save( order: &OrderUid, auction: AuctionId, block_number: i64, - executed_fee: &BigDecimal, - executed_protocol_fees: &[Asset], + total_fee: Asset, + protocol_fees: &[Asset], ) -> Result<(), sqlx::Error> { - let (protocol_fee_tokens, protocol_fee_amounts): (Vec<_>, Vec<_>) = executed_protocol_fees + let (protocol_fee_tokens, protocol_fee_amounts): (Vec<_>, Vec<_>) = protocol_fees .iter() .map(|entry| (entry.token, entry.amount.clone())) .unzip(); const QUERY: &str = r#" -INSERT INTO order_execution (order_uid, auction_id, reward, surplus_fee, block_number, protocol_fee_tokens, protocol_fee_amounts) -VALUES ($1, $2, $3, $4, $5, $6, $7) +INSERT INTO order_execution (order_uid, auction_id, reward, total_fee, total_fee_token, block_number, protocol_fee_tokens, protocol_fee_amounts) +VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (order_uid, auction_id) -DO UPDATE SET reward = $3, surplus_fee = $4, block_number = $5, protocol_fee_tokens = $6, protocol_fee_amounts = $7 +DO UPDATE SET reward = $3, total_fee = $4, total_fee_token = $5, block_number = $6, protocol_fee_tokens = $7, protocol_fee_amounts = $8 ;"#; sqlx::query(QUERY) .bind(order) .bind(auction) .bind(0.) // reward is deprecated but saved for historical analysis - .bind(Some(executed_fee)) + .bind(total_fee.amount) + .bind(total_fee.token) .bind(block_number) .bind(protocol_fee_tokens) .bind(protocol_fee_amounts) @@ -126,17 +127,29 @@ mod tests { &Default::default(), 1, 0, - &Default::default(), + Asset { + amount: BigDecimal::from(3), + token: Default::default(), + }, protocol_fees.as_slice(), ) .await .unwrap(); - // save entry without protocol fees (simulate case when we are still not - // calculating them) - save(&mut db, &Default::default(), 2, 0, &Default::default(), &[]) - .await - .unwrap(); + // save entry for an order without protocol fees + save( + &mut db, + &Default::default(), + 2, + 0, + Asset { + amount: BigDecimal::from(3), + token: Default::default(), + }, + &[], + ) + .await + .unwrap(); let keys: Vec<(AuctionId, OrderUid)> = vec![ (1, Default::default()), diff --git a/crates/database/src/orders.rs b/crates/database/src/orders.rs index 28ce989119..b61eb71263 100644 --- a/crates/database/src/orders.rs +++ b/crates/database/src/orders.rs @@ -485,7 +485,8 @@ pub struct FullOrder { pub ethflow_data: Option<(Option, i64)>, pub onchain_user: Option
, pub onchain_placement_error: Option, - pub executed_surplus_fee: BigDecimal, + pub executed_fee: BigDecimal, + pub executed_fee_token: Address, pub full_app_data: Option>, } @@ -560,7 +561,8 @@ array(Select (p.target, p.value, p.data) from interactions p where p.order_uid = where eth_o.uid = o.uid limit 1) as ethflow_data, (SELECT onchain_o.sender from onchain_placed_orders onchain_o where onchain_o.uid = o.uid limit 1) as onchain_user, (SELECT onchain_o.placement_error from onchain_placed_orders onchain_o where onchain_o.uid = o.uid limit 1) as onchain_placement_error, -COALESCE((SELECT SUM(surplus_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_surplus_fee, +COALESCE((SELECT SUM(total_fee) FROM order_execution oe WHERE oe.order_uid = o.uid), 0) as executed_fee, +COALESCE((SELECT total_fee_token FROM order_execution oe WHERE oe.order_uid = o.uid), o.sell_token) as executed_fee_token, -- TODO surplus token (SELECT full_app_data FROM app_data ad WHERE o.app_data = ad.contract_app_data LIMIT 1) as full_app_data "#; @@ -808,6 +810,7 @@ mod tests { events::{Event, EventIndex, Invalidation, PreSignature, Settlement, Trade}, onchain_broadcasted_orders::{insert_onchain_order, OnchainOrderPlacement}, onchain_invalidations::insert_onchain_invalidation, + order_execution::Asset, PgTransaction, }, bigdecimal::num_bigint::{BigInt, ToBigInt}, @@ -1885,18 +1888,28 @@ mod tests { .await .unwrap() .unwrap(); - assert_eq!(order.executed_surplus_fee, fee); + assert_eq!(order.executed_fee, fee); let fee: BigDecimal = 1.into(); - crate::order_execution::save(&mut db, &order_uid, 1, 0, &fee, &[]) - .await - .unwrap(); + crate::order_execution::save( + &mut db, + &order_uid, + 1, + 0, + Asset { + amount: fee.clone(), + token: Default::default(), + }, + &[], + ) + .await + .unwrap(); let order = single_full_order(&mut db, &order_uid) .await .unwrap() .unwrap(); - assert_eq!(order.executed_surplus_fee, fee); + assert_eq!(order.executed_fee, fee); } #[tokio::test] @@ -2010,7 +2023,10 @@ mod tests { &ByteArray([1u8; 56]), 1, 1, - &BigDecimal::from(1), + Asset { + amount: BigDecimal::from(1), + token: Default::default(), + }, Default::default(), ) .await @@ -2020,7 +2036,10 @@ mod tests { &ByteArray([1u8; 56]), 2, 2, - &BigDecimal::from(2), + Asset { + amount: BigDecimal::from(2), + token: Default::default(), + }, Default::default(), ) .await @@ -2030,7 +2049,10 @@ mod tests { &ByteArray([1u8; 56]), 3, 0, - &BigDecimal::from(4), + Asset { + amount: BigDecimal::from(4), + token: Default::default(), + }, Default::default(), ) .await @@ -2040,7 +2062,10 @@ mod tests { &ByteArray([3u8; 56]), 2, 3, - &BigDecimal::from(4), + Asset { + amount: BigDecimal::from(4), + token: Default::default(), + }, Default::default(), ) .await diff --git a/crates/e2e/tests/e2e/ethflow.rs b/crates/e2e/tests/e2e/ethflow.rs index 5a2347e8ea..81c201f4de 100644 --- a/crates/e2e/tests/e2e/ethflow.rs +++ b/crates/e2e/tests/e2e/ethflow.rs @@ -112,7 +112,7 @@ async fn eth_flow_tx(web3: Web3) { .get_order(ðflow_order.uid(onchain.contracts()).await) .await .unwrap(); - order.metadata.executed_surplus_fee > U256::zero() + order.metadata.executed_fee > U256::zero() }; wait_for_condition(TIMEOUT, fee_charged).await.unwrap(); diff --git a/crates/e2e/tests/e2e/partial_fill.rs b/crates/e2e/tests/e2e/partial_fill.rs index a1491e03ab..17d2e221ef 100644 --- a/crates/e2e/tests/e2e/partial_fill.rs +++ b/crates/e2e/tests/e2e/partial_fill.rs @@ -92,7 +92,7 @@ async fn test(web3: Web3) { let settlement_event_processed = || async { onchain.mint_block().await; let order = services.get_order(&uid).await.unwrap(); - order.metadata.executed_surplus_fee > U256::zero() + order.metadata.executed_fee > U256::zero() }; wait_for_condition(TIMEOUT, settlement_event_processed) .await diff --git a/crates/e2e/tests/e2e/partially_fillable_pool.rs b/crates/e2e/tests/e2e/partially_fillable_pool.rs index 728d7a15cf..a656d228ff 100644 --- a/crates/e2e/tests/e2e/partially_fillable_pool.rs +++ b/crates/e2e/tests/e2e/partially_fillable_pool.rs @@ -116,7 +116,7 @@ async fn test(web3: Web3) { let metadata_updated = || async { onchain.mint_block().await; let order = services.get_order(&uid).await.unwrap(); - !order.metadata.executed_surplus_fee.is_zero() + !order.metadata.executed_fee.is_zero() && order.metadata.executed_buy_amount != Default::default() && order.metadata.executed_sell_amount != Default::default() }; diff --git a/crates/e2e/tests/e2e/protocol_fee.rs b/crates/e2e/tests/e2e/protocol_fee.rs index ddded7a0bf..8a1049001f 100644 --- a/crates/e2e/tests/e2e/protocol_fee.rs +++ b/crates/e2e/tests/e2e/protocol_fee.rs @@ -277,7 +277,7 @@ async fn combined_protocol_fees(web3: Web3) { services .get_order(uid) .await - .is_ok_and(|order| !order.metadata.executed_surplus_fee.is_zero()) + .is_ok_and(|order| !order.metadata.executed_fee.is_zero()) }), ) .await @@ -293,39 +293,38 @@ async fn combined_protocol_fees(web3: Web3) { .get_order(&market_price_improvement_uid) .await .unwrap(); - let market_executed_surplus_fee_in_buy_token = - surplus_fee_in_buy_token(&market_price_improvement_order, &market_quote_after.quote); + let market_executed_fee_in_buy_token = + fee_in_buy_token(&market_price_improvement_order, &market_quote_after.quote); let market_quote_diff = market_quote_after .quote .buy_amount .saturating_sub(market_quote_before.quote.buy_amount); // see `market_price_improvement_policy.factor`, which is 0.3 - assert!(market_executed_surplus_fee_in_buy_token >= market_quote_diff * 3 / 10); + assert!(market_executed_fee_in_buy_token >= market_quote_diff * 3 / 10); let partner_fee_order = services.get_order(&partner_fee_order_uid).await.unwrap(); - let partner_fee_executed_surplus_fee_in_buy_token = - surplus_fee_in_buy_token(&partner_fee_order, &partner_fee_quote_after.quote); + let partner_fee_executed_fee_in_buy_token = + fee_in_buy_token(&partner_fee_order, &partner_fee_quote_after.quote); assert!( // see `--fee-policy-max-partner-fee` autopilot config argument, which is 0.02 - partner_fee_executed_surplus_fee_in_buy_token - >= partner_fee_quote.quote.buy_amount * 2 / 100 + partner_fee_executed_fee_in_buy_token >= partner_fee_quote.quote.buy_amount * 2 / 100 ); let limit_quote_diff = partner_fee_quote_after .quote .buy_amount .saturating_sub(partner_fee_order.data.buy_amount); // see `limit_surplus_policy.factor`, which is 0.3 - assert!(partner_fee_executed_surplus_fee_in_buy_token >= limit_quote_diff * 3 / 10); + assert!(partner_fee_executed_fee_in_buy_token >= limit_quote_diff * 3 / 10); let limit_surplus_order = services.get_order(&limit_surplus_order_uid).await.unwrap(); - let limit_executed_surplus_fee_in_buy_token = - surplus_fee_in_buy_token(&limit_surplus_order, &limit_quote_after.quote); + let limit_executed_fee_in_buy_token = + fee_in_buy_token(&limit_surplus_order, &limit_quote_after.quote); let limit_quote_diff = limit_quote_after .quote .buy_amount .saturating_sub(limit_surplus_order.data.buy_amount); // see `limit_surplus_policy.factor`, which is 0.3 - assert!(limit_executed_surplus_fee_in_buy_token >= limit_quote_diff * 3 / 10); + assert!(limit_executed_fee_in_buy_token >= limit_quote_diff * 3 / 10); let [market_order_token_balance, limit_order_token_balance, partner_fee_order_token_balance] = futures::future::try_join_all( @@ -344,16 +343,10 @@ async fn combined_protocol_fees(web3: Web3) { .unwrap() .try_into() .expect("Expected exactly four elements"); + assert_approximately_eq!(market_executed_fee_in_buy_token, market_order_token_balance); + assert_approximately_eq!(limit_executed_fee_in_buy_token, limit_order_token_balance); assert_approximately_eq!( - market_executed_surplus_fee_in_buy_token, - market_order_token_balance - ); - assert_approximately_eq!( - limit_executed_surplus_fee_in_buy_token, - limit_order_token_balance - ); - assert_approximately_eq!( - partner_fee_executed_surplus_fee_in_buy_token, + partner_fee_executed_fee_in_buy_token, partner_fee_order_token_balance ); } @@ -386,8 +379,8 @@ async fn get_quote( services.submit_quote("e_request).await } -fn surplus_fee_in_buy_token(order: &Order, quote: &OrderQuote) -> U256 { - order.metadata.executed_surplus_fee * quote.buy_amount / quote.sell_amount +fn fee_in_buy_token(order: &Order, quote: &OrderQuote) -> U256 { + order.metadata.executed_fee * quote.buy_amount / quote.sell_amount } fn sell_order_from_quote(quote: &OrderQuoteResponse) -> OrderCreation { @@ -516,13 +509,13 @@ async fn volume_fee_buy_order_test(web3: Web3) { let metadata_updated = || async { onchain.mint_block().await; let order = services.get_order(&uid).await.unwrap(); - !order.metadata.executed_surplus_fee.is_zero() + !order.metadata.executed_fee.is_zero() }; wait_for_condition(TIMEOUT, metadata_updated).await.unwrap(); let order = services.get_order(&uid).await.unwrap(); let fee_in_buy_token = quote.fee_amount * quote.buy_amount / quote.sell_amount; - assert!(order.metadata.executed_surplus_fee >= fee_in_buy_token + quote.sell_amount / 10); + assert!(order.metadata.executed_fee >= fee_in_buy_token + quote.sell_amount / 10); // Check settlement contract balance let balance_after = token_gno @@ -530,5 +523,5 @@ async fn volume_fee_buy_order_test(web3: Web3) { .call() .await .unwrap(); - assert_eq!(order.metadata.executed_surplus_fee, balance_after); + assert_eq!(order.metadata.executed_fee, balance_after); } diff --git a/crates/model/src/order.rs b/crates/model/src/order.rs index 078df93bb6..e9f06854d8 100644 --- a/crates/model/src/order.rs +++ b/crates/model/src/order.rs @@ -701,6 +701,9 @@ pub struct OrderMetadata { pub executed_fee_amount: U256, #[serde_as(as = "HexOrDecimalU256")] pub executed_surplus_fee: U256, + #[serde_as(as = "HexOrDecimalU256")] + pub executed_fee: U256, + pub executed_fee_token: H160, pub invalidated: bool, pub status: OrderStatus, #[serde(flatten)] @@ -1061,6 +1064,8 @@ mod tests { "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", "feeAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "executedSurplusFee": "1", + "executedFee": "1", + "executedFeeToken": "0x000000000000000000000000000000000000000a", "fullFeeAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "solverFee": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "kind": "buy", @@ -1092,6 +1097,8 @@ mod tests { executed_sell_amount_before_fees: 4.into(), executed_fee_amount: 1.into(), executed_surplus_fee: 1.into(), + executed_fee: 1.into(), + executed_fee_token: H160::from_low_u64_be(10), invalidated: true, status: OrderStatus::Open, settlement_contract: H160::from_low_u64_be(2), diff --git a/crates/orderbook/openapi.yml b/crates/orderbook/openapi.yml index 00639e36b0..58dd420f5a 100644 --- a/crates/orderbook/openapi.yml +++ b/crates/orderbook/openapi.yml @@ -885,7 +885,17 @@ components: description: Surplus fee that the limit order was executed with. allOf: - $ref: "#/components/schemas/BigUint" - nullable: true + nullable: false + executedFee: + description: Total fee charged for execution of the order. Contains network fee and protocol fees. + allOf: + - $ref: "#/components/schemas/BigUint" + nullable: false + executedTotalFeeToken: + description: Token the total fee was captured in. + allOf: + - $ref: "#/components/schemas/Address" + nullable: false fullAppData: description: | Full `appData`, which the contract-level `appData` is a hash of. See `OrderCreation` diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 2814664825..0152def257 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -582,8 +582,11 @@ fn full_order_into_model_order(order: FullOrder) -> Result { )?, executed_fee_amount: big_decimal_to_u256(&order.sum_fee) .context("executed fee amount is not a valid u256")?, - executed_surplus_fee: big_decimal_to_u256(&order.executed_surplus_fee) - .context("executed surplus fee is not a valid u256")?, + executed_surplus_fee: big_decimal_to_u256(&order.executed_fee) + .context("executed fee is not a valid u256")?, + executed_fee: big_decimal_to_u256(&order.executed_fee) + .context("executed fee is not a valid u256")?, + executed_fee_token: H160(order.executed_fee_token.0), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, @@ -706,7 +709,8 @@ mod tests { ethflow_data: None, onchain_user: None, onchain_placement_error: None, - executed_surplus_fee: Default::default(), + executed_fee: Default::default(), + executed_fee_token: ByteArray([1; 20]), // TODO surplus token full_app_data: Default::default(), }; diff --git a/crates/shared/src/db_order_conversions.rs b/crates/shared/src/db_order_conversions.rs index 5128c1e190..80cd71f171 100644 --- a/crates/shared/src/db_order_conversions.rs +++ b/crates/shared/src/db_order_conversions.rs @@ -90,8 +90,11 @@ pub fn full_order_into_model_order(order: database::orders::FullOrder) -> Result )?, executed_fee_amount: big_decimal_to_u256(&order.sum_fee) .context("executed fee amount is not a valid u256")?, - executed_surplus_fee: big_decimal_to_u256(&order.executed_surplus_fee) - .context("executed surplus fee is not a valid u256")?, + executed_surplus_fee: big_decimal_to_u256(&order.executed_fee) + .context("executed fee is not a valid u256")?, + executed_fee: big_decimal_to_u256(&order.executed_fee) + .context("executed fee is not a valid u256")?, + executed_fee_token: H160(order.executed_fee_token.0), invalidated: order.invalidated, status, is_liquidity_order: class == OrderClass::Liquidity, diff --git a/database/README.md b/database/README.md index ae938215dc..f066a6a2a5 100644 --- a/database/README.md +++ b/database/README.md @@ -175,7 +175,8 @@ Protocol fee tokens/amounts are stored in the same order as fee policies in fee_ order\_uid | bytea | not null | which order this trade execution is related to auction\_id | bigint | not null | in which auction this trade was initiated reward | double | not null | revert adjusted solver rewards, deprecated in favor of [CIP-20](https://snapshot.org/#/cow.eth/proposal/0x2d3f9bd1ea72dca84b03e97dda3efc1f4a42a772c54bd2037e8b62e7d09a491f) - surplus\_fee | numeric | nullable | dynamic fee computed by the protocol that should get taken from the surplus of a trade, this value only applies and is set for fill-or-kill limit orders. + total\_fee | numeric | not null | total fee taken for execution of the trade + total\_fee\_token | bytea | not null | token in which the surplus fee is taken block\_number | bigint | not null | block in which the order was executed protocol\_fee\_tokens | bytea[] | not null | tokens in which the protocol fees are taken protocol\_fee\_amounts | numeric[] | not null | amounts of protocol fees taken, aligned protocol\_fee\_tokens array diff --git a/database/sql/V072__total_fee_token.sql b/database/sql/V072__total_fee_token.sql new file mode 100644 index 0000000000..4510a07300 --- /dev/null +++ b/database/sql/V072__total_fee_token.sql @@ -0,0 +1,24 @@ +ALTER TABLE order_execution +RENAME COLUMN surplus_fee TO total_fee; + +-- Add a new column to the order_execution table to store the total fee token +ALTER TABLE order_execution +ADD COLUMN total_fee_token bytea NOT NULL DEFAULT '\x0000000000000000000000000000000000000000'; + +-- Now populate existing rows with the sell token taken from the 'orders' table, or if it doesn't exist, try from 'jit_orders'. +UPDATE order_execution oe +SET total_fee_token = COALESCE( + sub.sell_token, '\x0000000000000000000000000000000000000000' +) +FROM ( + SELECT o.uid, o.sell_token + FROM orders o + UNION + SELECT j.uid, j.sell_token + FROM jit_orders j + WHERE NOT EXISTS (SELECT 1 FROM orders WHERE orders.uid = j.uid) +) AS sub +WHERE oe.order_uid = sub.uid; + +-- Drop the default value for the total_fee_token column +ALTER TABLE order_execution ALTER COLUMN total_fee_token DROP DEFAULT;