8000 Charge accurate fees by voltrevo · Pull Request #418 · getwax/bls-wallet · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Nov 5, 2023. It is now read-only.

Charge accurate fees #418

Merged
merged 28 commits into from
Jan 6, 2023
Merged

Charge accurate fees #418

merged 28 commits into from
Jan 6, 2023

Conversation

voltrevo
Copy link
Collaborator
@voltrevo voltrevo commented Dec 7, 2022

What is this PR doing?

Changes the way we make bundles and charge for them, so that the aggregator has a good handle on the fees it needs to be charging and is able to turn a profit without charging more than necessary.

There's a fair bit of detail in the issue about this: #415.

Previously estimateFee would report the fee required to submit the user's bundle in isolation, which defeats the whole purpose of saving money by aggregating with other users. This has been fixed so that the required fee reported includes only the marginal cost of the bundle and a configurable share of the bundle's overhead (basically the block space for the single signature and validating it).

When forming an aggregate bundle, we used to put all available bundles together and check that it satisfies our estimateFee calculation as a whole. Then, if it didn't work, we'd do a binary search to figure out how many of those bundles we could include, exclude the next one, and then try to add more recursively.

The binary search method had the advantage of processing bundles in order, allowing for things like chaining dependent bundles together (e.g. consecutive nonces). However, this relies on the idea that all the bundles are supposed to be self-sufficient (e.g. even just one bundle pays enough to cover itself), which is wrong. I decided to simplify this by evaluating bundles individually to make sure they satisfy estimateFee, and then just checking once that the overall bundle is profitable (or just letting it through regardless if ALLOW_LOSSES is true).

How can these changes be manually tested?

Use ./manualTests/mintNViaAggregator.ts <N> with different values of N and check the profitability output is acceptable.

For example, here's some output I got from the aggregator with BREAKEVEN_OPERATION_COUNT=4.5 and ./manualTests/mintNViaAggregator 5:

submission-confirmed {
  hash: "0x3e06b8dd8ee59458d076d6aeb35cac83161ef9018355b2c68fdf71a65515f4a6",
  bundleHashes: [
    "0xc46e7eeae05caf5912980f5ef4e5f2977dda5203ee2571d10f357fb6ea92203a",
    "0xfba88c9e99d96b454204dc1fbe510e0d0e785bacba516e5b382e56269385af94",
    "0xf34eb24ab1f4fdf01ece625f5e80838888b89b8bbb8957aa9b50ce6a193742fb",
    "0xab6d3299ff437e61a8615421e5cf0173099f158eb71822a1cd50662032884ce1",
    "0xd53760964fecba10a3b08a4afeaeebad39367e874e8986bb686a7338ff2acf54"
  ],
  blockNumber: 166,
  profit: "0.00005934235",
  cost: "0.000483594",
  expectedMaxCost: "0.000483594",
  actualFee: "0.00054293635",
  expectedFee: "0.00054293635"
}

When N is greater than BREAKEVEN_OPERATION_COUNT, bundles should be profitable. Note that due to fluctuations, mintNViaAggregator is additionally adding 10% to the fee, so smaller values of N may be profitable too.

You can also check that if ALLOW_LOSSES is false, then the aggregator generally won't submit unprofitable bundles, and will at least not submit bundles it expects to make losses on (expectedFee should be higher than expectedMaxCost (both of these may deviate from their actual values)).

Does this PR resolve or contribute to any issues?

Resolves #415

Checklist

  • I have manually tested these changes
  • Post a link to the PR in the group chat

Guidelines

  • If your PR is not ready, mark it as a draft
  • The resolve conversation button is for reviewers, not authors
    • (But add a 'done' comment or similar)

@github-actions github-actions bot added the aggregator Aggregator backend related label Dec 7, 2022
@voltrevo voltrevo marked this pull request as ready for review December 7, 2022 05:42
Copy link
Contributor
@blakecduncan blakecduncan left a comment

Choose a reason for hiding this comment

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

Tested out your script and looks like everything is working. I also really like the events you added 💯 .

The comments I added are non-blocking, they are just around being more descriptive. I think some added comments describing some of the logic and maybe breaking some things out into variables could be useful for readability.

].join(" "));
}

await (await VerificationGateway__factory.connect(
Copy link
Contributor

Choose a reason for hiding this comment

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

nit but this double await with a .wait() at the end is confusing to read. Could we break this up into multiple variables/lines?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a pretty common pattern, so my vote is to keep it compact like this. Might be worth putting this to the team though.

Copy link
Contributor

Choose a reason for hiding this comment

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

No worries, if it's common to do it like this I'm cool with it 👍

return {
maxFeePerGas: previousBaseFee
.add(
previousBaseFee.mul(env.PREVIOUS_BASE_FEE_PERCENT_INCREASE).div(100),
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be nice to give this a variable for readability. ex:

const feeIncrease = previousBaseFee.mul(env.PREVIOUS_BASE_FEE_PERCENT_INCREASE).div(100);

Copy link
Collaborator Author
@voltrevo voltrevo Jan 6, 2023

Choose a reason for hiding this comment

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

Fixed in #438

assert(previousBaseFee !== null && previousBaseFee !== nil);

return {
maxFeePerGas: previousBaseFee
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be useful to have a comment that mentions why we set maxFeePerGas to the previousBaseFee + a fee increase + a priority fee per gas.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in #438

return filteredRows;
}

async #pickBest(rows: BundleRow[]) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we add a comment here explaining how we pick the best?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in #438

return {
aggregateBundle: nil,
includedRows: [],
bundleOverheadCost: bundleOverheadGas.mul(
Copy link
Contributor

Choose a reason for hiding this comment

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

My brain is moving a little slow 😅 why is this the bundleOverheadGas * maxFeePerGas ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

A36C

It's just the basic gas mechanism - transactions consume gas, and you pay a fee per unit of gas, therefore the cost is the amount of gas times the fee paid per gas.


return rows[bestExcessFeeIndex];
}

async #augmentAggregateBundle(
Copy link
Contributor
@blakecduncan blakecduncan Jan 2, 2023

Choose a reason for hiding this comment

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

I know you didn't edit this, but it might be nice to note what are we augmenting

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in #438

@blakecduncan
Copy link
Contributor

Also, I really like your description of the PR and the description in the linked issue. Do you think we should add any of that explanation to the Readme?

@voltrevo voltrevo merged commit 7423b28 into main Jan 6, 2023
@voltrevo voltrevo deleted the bw-415-charge-accurate-fees branch January 6, 2023 04:17
@voltrevo
Copy link
Collaborator Author
voltrevo commented Jan 6, 2023

Also, I really like your description of the PR and the description in the linked issue. Do you think we should add any of that explanation to the Readme?

Cheers. Fixed in #438.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
aggregator Aggregator backend related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Charge accurate fees in aggregator
2 participants
0