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

Convert executed_fee_amount to surplus token #3224

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

sunce86
Copy link
Contributor

@sunce86 sunce86 commented Jan 8, 2025

Description

As part of the initiative to show all executed order fees in surplus tokens, we have to convert the executed_fee_amount from sell token to surplus token. This is needed by frontend and other integrators, so that ALL fees are in surplus token and easily summarized.

As a reminder, executed_fee_amount represents executed version of a fixed fee_amount fee that is part of the signed order and it's always assumed that it is expressed in sell token. But we can easily convert the EXECUTED REPRESENTATION of this fee into surplus token by following this math:

let executedFeeAmountInSurplusToken = match order.kind {
    Buy => executedFeeAmount,
    Sell => executedFeeAmount * executedBuyAmount / executedSellAmountBeforeFees,
};

This math is 100% equal to using uniform clearing prices to convert between fee in sell and buy tokens, as already used in the existing code:

https://github.com/cowprotocol/services/blob/main/crates/autopilot/src/domain/settlement/trade/math.rs#L126-L129 :

/// Converts given surplus fee into sell token fee.
    fn fee_into_sell_token(&self, fee: eth::TokenAmount) -> Result<eth::SellTokenAmount, Error> {
        let fee_in_sell_token = match self.side {
            order::Side::Buy => fee,
            order::Side::Sell => fee
                .checked_mul(&self.prices.uniform.buy.into())
                .ok_or(error::Math::Overflow)?
                .checked_div(&self.prices.uniform.sell.into())
                .ok_or(error::Math::DivisionByZero)?,
        }
        .into();
        Ok(fee_in_sell_token)
    }

Note 1: This PR only changes how the executed version of this fee is represented over the API. It does not change anything in the database, so it also does not change our assumption of how the fee_amount is saved internally.

Note 2: Only > ~2 year old orders are affected by this. All newer orders have executed_fee_amount = 0.

Note 3: These old orders will have a bad total fee shown when this PR is merged. We need #3184 merged as well (and all consequent data migrations) so that all fees are finally shown in surplus tokens.

Changes

  • Executed version of fee_amount is now shown in surplus token

How to test

Confirmed on several examples of orders that have fee_amount > 0.

@sunce86 sunce86 requested a review from a team as a code owner January 8, 2025 13:43
@sunce86 sunce86 self-assigned this Jan 8, 2025
Copy link

github-actions bot commented Jan 8, 2025

Reminder: Please consider backward compatibility when modifying the API specification.
If breaking changes are unavoidable, ensure:

  • You explicitly pointed out breaking changes.
  • You communicate the changes to affected teams.
  • You provide proper versioning and migration mechanisms.

Caused by:

@squadgazzz
Copy link
Contributor

The change looks trivial, but I don't have a full picture of these fee migrations and PRs ordering, so I can't think of any implications atm. I need to go over other PRs again.

Comment on lines +629 to +630
// convert to buy token using executed amounts which are a very good
// approximation of UCP prices conversion rate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be false for multiple reasons:

  1. I know of at least 1 integration that created their orders with buy_amount: 1 out of convenience since cow protocol's competition would still protect this order by giving it a good price
  2. applying a generous slippage to your price would introduce an error

I think in order to make this change correct we'd have to use the actual settlement's UCP to convert this price. For orders with partial fills even multiple prices of the respective settlements.
I believe this might not even be a huge change. Our big order SQL query already has to join all the relevant trades while computing sum_fee. If this logic would be moved into the SQL query we should get actually accurate prices while still not having to change how the underlying gets stored in the DB.

Is that correct / reasonable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For conversion we use executedBuyAmount which is not equal to signed buy_amount you mentioned.

Reference from settlement contract:
Screenshot 2025-01-10 at 11 49 46

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you are right. So effectively we'd be using an average of the actual UCPs of each fill for converting the fees. That makes sense to me and should indeed be accurate. 👍

Copy link
Contributor

@mstrug mstrug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question regarding Note 2: why we are not using executed_fee_amount anymore?

crates/shared/src/db_order_conversions.rs Show resolved Hide resolved
crates/orderbook/openapi.yml Outdated Show resolved Hide resolved
@sunce86
Copy link
Contributor Author

sunce86 commented Jan 10, 2025

Question regarding Note 2: why we are not using executed_fee_amount anymore?

This was how we used to model gas fees before, which was less accurate because the fee was determined at the order creation time, and kept fixed regardless if the order was settled right away or 10 minutes after, for example. Today, solvers define the amount of fee they want to take for each order at the solving time, and if order is not settled, next auction they can define a different fee for the same order if the gas price increased, for example. Solvers also have freedom to take more/less of a fee then what are the gas costs.

Copy link
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments above added more context.

Copy link

This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed.

@github-actions github-actions bot added the stale label Jan 18, 2025
@sunce86 sunce86 removed the stale label Jan 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants