Skip to content

Commit

Permalink
Merge pull request #98 from cowprotocol/multiple_protocol_fees
Browse files Browse the repository at this point in the history
Fix multiple protocol fees
  • Loading branch information
harisang authored Jul 1, 2024
2 parents f4660ef + f1587cc commit 6edb54a
Show file tree
Hide file tree
Showing 7 changed files with 648 additions and 42 deletions.
2 changes: 2 additions & 0 deletions src/models/order_rewards_schema.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Model for Order Rewards Data"""

from __future__ import annotations

from dataclasses import dataclass
Expand Down Expand Up @@ -35,6 +36,7 @@ def from_pdf_to_dune_records(cls, rewards_df: DataFrame) -> list[dict[str, Any]]
"quote_buy_amount": str(row["quote_buy_amount"]),
"quote_gas_cost": float(row["quote_gas_cost"]),
"quote_sell_token_price": float(row["quote_sell_token_price"]),
"partner_fee": str(row["partner_fee"]),
"partner_fee_recipient": row["partner_fee_recipient"],
"protocol_fee_kind": row["protocol_fee_kind"],
},
Expand Down
169 changes: 159 additions & 10 deletions src/sql/orderbook/barn_batch_rewards.sql
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ order_surplus AS (
CASE
WHEN o.kind = 'sell' THEN o.buy_token
WHEN o.kind = 'buy' THEN o.sell_token
END AS surplus_token
END AS surplus_token,
ad.full_app_data as app_data
FROM
settlements s
JOIN settlement_scores ss -- contains block_deadline
Expand All @@ -73,22 +74,70 @@ order_surplus AS (
AND s.auction_id = oe.auction_id
LEFT OUTER JOIN order_quotes oq -- contains quote amounts
ON o.uid = oq.order_uid
LEFT OUTER JOIN app_data ad -- contains full app data
on o.app_data = ad.contract_app_data
WHERE
ss.block_deadline > {{start_block}}
AND ss.block_deadline <= {{end_block}}
),
order_protocol_fee AS (
fee_policies_first_proxy as (
select
auction_id,
order_uid,
max(application_order) as application_order,
count (*) as num_policies
from fee_policies
where auction_id in (select auction_id from order_surplus)
group by order_uid, auction_id
),
fee_policies_first as (
select
fp.auction_id,
fp.order_uid,
fp.application_order,
fp.kind,
fp.surplus_factor,
fp.surplus_max_volume_factor,
fp.volume_factor,
fp.price_improvement_factor,
fp.price_improvement_max_volume_factor
from fee_policies_first_proxy fpmp join fee_policies fp on fp.auction_id = fpmp.auction_id and fp.order_uid = fpmp.order_uid and fp.application_order = fpmp.application_order
),
fee_policies_temp as (
select
*
from fee_policies
where auction_id in (select auction_id from order_surplus)
except (select * from fee_policies_first )
),
fee_policies_second as (
select
*
from fee_policies_temp
UNION
select
auction_id,
order_uid,
0 as application_order,
'volume' as kind,
null as surplus_factor,
null as surplus_max_volume_factor,
0 as volume_factor,
null as price_improvement_factor,
null as price_improvement_max_volume_factor
from fee_policies_first_proxy where num_policies = 1
),
order_protocol_fee_first AS (
SELECT
os.auction_id,
os.solver,
os.tx_hash,
os.order_uid,
os.sell_amount,
os.buy_amount,
os.sell_token,
os.observed_fee,
os.surplus,
os.surplus_token,
os.price_improvement,
os.kind,
convert_from(os.app_data, 'UTF8')::JSONB->'metadata'->'partnerFee'->>'recipient' as partner_fee_recipient,
fp.kind as protocol_fee_kind_first,
CASE
WHEN fp.kind = 'surplus' THEN CASE
WHEN os.kind = 'sell' THEN
Expand Down Expand Up @@ -135,11 +184,106 @@ order_protocol_fee AS (
WHEN os.kind = 'buy' THEN
fp.volume_factor / (1 + fp.volume_factor) * os.sell_amount
END
END AS protocol_fee_first,
os.surplus_token AS protocol_fee_token
FROM
order_surplus os
JOIN fee_policies_first fp -- contains protocol fee policy
ON os.auction_id = fp.auction_id
AND os.order_uid = fp.order_uid
),
order_surplus_intermediate as (
select
auction_id,
order_uid,
CASE
WHEN kind = 'sell' then sell_amount
ELSE sell_amount - protocol_fee_first
END as sell_amount,
CASE
WHEN kind = 'sell' then buy_amount + protocol_fee_first
ELSE buy_amount
END as buy_amount,
surplus + protocol_fee_first as surplus,
price_improvement + protocol_fee_first as price_improvement,
protocol_fee_kind_first,
protocol_fee_first,
partner_fee_recipient
from order_protocol_fee_first
),
order_protocol_fee as (
SELECT
os.auction_id,
os.solver,
os.tx_hash,
os.order_uid,
os.sell_amount,
os.buy_amount,
os.sell_token,
os.observed_fee,
os.surplus,
os.surplus_token,
protocol_fee_kind_first,
fp.kind as protocol_fee_kind_second,
protocol_fee_first,
CASE
WHEN fp.kind = 'surplus' THEN CASE
WHEN os.kind = 'sell' THEN
-- We assume that the case surplus_factor != 1 always. In
-- that case reconstructing the protocol fee would be
-- impossible anyways. This query will return a division by
-- zero error in that case.
protocol_fee_first + LEAST(
fp.surplus_max_volume_factor / (1 - fp.surplus_max_volume_factor) * osi.buy_amount,
-- at most charge a fraction of volume
fp.surplus_factor / (1 - fp.surplus_factor) * osi.surplus -- charge a fraction of surplus
)
WHEN os.kind = 'buy' THEN protocol_fee_first + LEAST(
fp.surplus_max_volume_factor / (1 + fp.surplus_max_volume_factor) * osi.sell_amount,
-- at most charge a fraction of volume
fp.surplus_factor / (1 - fp.surplus_factor) * osi.surplus -- charge a fraction of surplus
)
END
WHEN fp.kind = 'priceimprovement' THEN CASE
WHEN os.kind = 'sell' THEN
protocol_fee_first + LEAST(
-- at most charge a fraction of volume
fp.price_improvement_max_volume_factor / (1 - fp.price_improvement_max_volume_factor) * osi.buy_amount,
-- charge a fraction of price improvement, at most 0
GREATEST(
fp.price_improvement_factor / (1 - fp.price_improvement_factor) * osi.price_improvement
,
0
)
)
WHEN os.kind = 'buy' THEN protocol_fee_first + LEAST(
-- at most charge a fraction of volume
fp.price_improvement_max_volume_factor / (1 + fp.price_improvement_max_volume_factor) * osi.sell_amount,
-- charge a fraction of price improvement
GREATEST(
fp.price_improvement_factor / (1 - fp.price_improvement_factor) * osi.price_improvement,
0
)
)
END
WHEN fp.kind = 'volume' THEN CASE
WHEN os.kind = 'sell' THEN
protocol_fee_first + fp.volume_factor / (1 - fp.volume_factor) * osi.buy_amount
WHEN os.kind = 'buy' THEN
protocol_fee_first + fp.volume_factor / (1 + fp.volume_factor) * osi.sell_amount
END
END AS protocol_fee,
osi.partner_fee_recipient,
CASE
WHEN osi.partner_fee_recipient IS NOT NULL THEN osi.protocol_fee_first
ELSE 0
END AS partner_fee,
os.surplus_token AS protocol_fee_token
FROM
order_surplus os
JOIN fee_policies fp -- contains protocol fee policy
JOIN order_surplus_intermediate osi
ON os.order_uid = osi.order_uid AND os.auction_id = osi.auction_id
JOIN fee_policies_second fp -- contains protocol fee policy
ON os.auction_id = fp.auction_id
AND os.order_uid = fp.order_uid
),
Expand All @@ -152,6 +296,12 @@ order_protocol_fee_prices AS (
opf.surplus,
opf.protocol_fee,
opf.protocol_fee_token,
CASE
WHEN opf.partner_fee_recipient IS NOT NULL THEN opf.protocol_fee_kind_second
ELSE opf.protocol_fee_kind_first
END AS protocol_fee_kind,
opf.partner_fee,
opf.partner_fee_recipient,
CASE
WHEN opf.sell_token != opf.protocol_fee_token THEN (opf.sell_amount - opf.observed_fee) / opf.buy_amount * opf.protocol_fee
ELSE opf.protocol_fee
Expand All @@ -161,7 +311,7 @@ order_protocol_fee_prices AS (
ap_protocol.price / pow(10, 18) as protocol_fee_token_native_price,
ap_sell.price / pow(10, 18) as network_fee_token_native_price
FROM
order_protocol_fee opf
order_protocol_fee as opf
JOIN auction_prices ap_sell -- contains price: sell token
ON opf.auction_id = ap_sell.auction_id
AND opf.sell_token = ap_sell.token
Expand All @@ -176,7 +326,6 @@ batch_protocol_fees AS (
SELECT
solver,
tx_hash,
-- sum(surplus * surplus_token_price) as surplus,
sum(protocol_fee * protocol_fee_token_native_price) as protocol_fee,
sum(network_fee_correction * network_fee_token_native_price) as network_fee_correction
FROM
Expand Down
Loading

0 comments on commit 6edb54a

Please sign in to comment.