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

Standardize Bid Pricing Calculation for PBS Bids #708

Open
benhenryhunter opened this issue Dec 12, 2024 · 14 comments
Open

Standardize Bid Pricing Calculation for PBS Bids #708

benhenryhunter opened this issue Dec 12, 2024 · 14 comments

Comments

@benhenryhunter
Copy link

Description

There is currently an inconsistency in how bid prices are calculated for blocks and how relays simulate bid accuracy. Specifically, the process of using a validator’s balance difference to determine the bid value can lead to inaccuracies.

This issue aims to standardize how validator balance differences are applied, ensuring consistent and transparent calculation of bid values across all builders and relays.

The goal isn't to force this proposal through, if there is a better method we can all agree on and point to moving forward then I will be content. After chatting with many teams it doesn't seem that any are bidding or verifying bids the exact same way.

Background / Context

Previously, it was proposed that bid values should consider only the positive balance change to the block’s coinbase, excluding any outgoing transfers and withdrawals.

If the validator is the coinbase, using the validator’s balance difference (excluding withdrawals) is acceptable. However, when a builder is the coinbase, the correct method is to rely solely on the builder’s final transaction transfer.

Below is an example where a validator balance difference was used while a block builder's address was set to the block coinbase.
Example:
In the BTCS block at slot 10575868, there was a payment of 0.18532 ETH to Lido and a builder payment of 0.02161 ETH. The intended bid should have been 0.02161 ETH, but due to the current logic, it was mistakenly interpreted as 0.20693 ETH.

This occurred because the rbuilder simulation used the validator’s balance difference even though the coinbase was a builder address, not the validator.

This kind of bidding can be misleading to validators believing they are accepting a block that pays them 0.20693 meanwhile it's using incoming funds of 0.18532 that they would have received either way.

Furthermore this kind of bidding is incompatible with bloXroute relays currently and results in being demoted from optimistic submissions.

Proposed Standardization

To achieve consistency, I'm proposing the following:

  1. When the validator is the coinbase:
    Use the positive balance difference (excluding withdrawals) as the bid price.
    • Calculation: Determine the validator’s balance before and after the block is built. Exclude incoming withdrawals from the balance increase and adjust for outgoing transfers, ensuring the final figure reflects the net positive gain.

If the validator decides to give some money to his poor grandmother we ignore this tx since counting it would appear as negative profit.

  1. When the builder is the coinbase:
    Use only the final transaction’s transfer value to determine the bid price.
    • Calculation: The last transaction’s transfer amount (e.g., from gas, MEV rewards, or subsidies) serves as the bid value. This is the simplest and most direct indicator of the builder’s intended payment.

Impact / Implementation Details

Implementing this standardization should involve minimal changes to both Go and Rust simulation code.

Once adopted, validators, builders, and relays will have a unified and transparent method for determining bid values, reducing confusion and promoting fairness and consistency within the PBS ecosystem.

As of time of posting I have gathered feedback and support from multiple teams and will ask them to provide their support or any discussions below to get everything finalized.

@gd-0
Copy link

gd-0 commented Dec 12, 2024

@benhenryhunter, thanks for the proposal!

Titan relay definitely supports standardising bid pricing. We think this proposal makes sense, so happy to help make the changes required. Withdrawals are already excluded from our pricing calculations, but we will need to implement the additional handling for outgoing transfers.

It’s also worth noting that our builder already adheres to this standard.

@jzblox
Copy link

jzblox commented Dec 12, 2024

@benhenryhunter Want to adjust for incoming transfers as well (not just incoming withdrawals and outgoing transfers) when the validator is the coinbase?

@benhenryhunter
Copy link
Author

Here I'm proposing we include all incoming transfers in the net positive balance change.

There was discussion a long time ago in various telegram groups that were meant to standardize this in the past. Those groups decided to include the incoming transfers in the bid due to some complexities on the relay side to know if the transfer was an MEV tip or just a normal tx transferring to the validator.

I am not against excluding them because I think they cause the most confusion in bid value, but we would need clear agreement on what we exclude.

i.e. exclude any transfer txs but include any that happen to come from an internal transaction?

@austonst
Copy link

austonst commented Dec 12, 2024

I'd like to offer some historical context and opinions. The question of relay block scoring goes back a long ways, with some good public conversation in this Flashbots Collective thread. Mostly it comes down to block level scoring (i.e. "fee recipient difference") vs transaction output scoring. Benjamin summarizes each in the proposed standardization. There hasn't been a formalized specification for how mev-boost relays should score blocks, it's always been agreed on via informal consensus. General trend was that relays started with tx output scoring, and gradually opened to block-level scoring due to demand from builders (a good argument for the status quo here).

One of the downsides of block-level scoring is that incidental transfers in or out of the validator's fee recipient address affect the total bid value. If a validator receives some ETH via an unrelated transaction, then builders can use that to inflate the value of their own bids. This is fine as long as all builders are aware of the strategy and bid accordingly, but it means that the bid does not reflect the true builder -> proposer value transfer. Likewise, builders will probably exclude any transaction where value is transferred out of the fee recipient address. But the big upside is that builders can build however they want: a single payment transaction, validator as coinbase, or whatever else, and have all those methods be scored by the same algorithm.

The most recent standardization effort was initiated about a year ago when jgm reported incorrect bids being selected because some builders were including CL withdrawals in their bid value while others weren't, causing cases where the bids with the highest true value did not win the auction. This was discussed in the Flashbots thread and in MEV-Boost community calls. The solution most generally agreed upon was to standardize such that relays would always exclude CL withdrawals from block value calculation. Some code to do this was written, and Aestus has been running that as our block validation logic ever since.

It was news to me that not all relays adopted this standardization, and I think we'll be quite fortunate if discrepancies haven't caused loss of value for proposers or excessive, unnecessary builder demotions. Getting relays on the same page would be my primary goal here and, as we've implemented validation logic respecting standardization efforts in the past, we are more than happy to do so again whenever there is broad support.


That said, I'm unsure about this particular standard. Mainly that it implements both block scoring methods and uses them in different scenarios. Let's look at how the reference BTCS x Lido block would be handled here:

We have true transferred value ~= 0.02 ETH and an incidental transfer into the Lido fee recipient ~= 0.18 ETH.

  • Builder A builds a block with Lido as the coinbase, so the standard dictates that it uses block-level scoring. Builder A is therefore allowed to include the value of the incidental transfer in their bid value, so their final bid is 0.02 + 0.18 = 0.2 ETH.
  • Builder B builds a block with themselves as the coinbase, so the standard dictates that it uses tx output scoring. Builder B is not able to include the incidental transfer in their bid, so they bid 0.02 ETH.

Builder A wins. Now what if Builder B actually had a slight edge in MEV extraction over builder A such that their true transferred value is 0.03 ETH instead? Builder A's bid was 0.2 ETH, and now Builder B can bid 0.03 ETH. Builder A still wins the auction, and the validator receives a block value of 0.02, losing out on the extra 0.01 ETH they would have received under an ideal auction.

Under the simpler "fee_diff - withdrawals" scoring for all submissions, Builder B could construct the same block, with themselves as coinbase and the single 0.03 ETH payment transaction at the end, but would be allowed to include the value of the incidental transfer. So their total bid of 0.21 ETH is fairly compared against Builder A's bid of 0.2 ETH, since both scores mean the same thing. The higher true value block wins the auction and the proposer gets paid 0.03 ETH.

EDIT: Got some clarifications on this section. If Builder A sets Lido as coinbase they don't get to keep any value for themselves so the use case is more situational and less clearly profitable. It also sounds like some builders today may be building with themselves as coinbase and then voluntarily foregoing the option of including other transfers in their bid. This leaves the option for another builder to set themselves as coinbase, include the extra value, and win the auction while pocketing the block value. While with the proposed changes, if the attacker wants to include the extra value in their bid, they have to use the validator's coinbase and forego any rewards themselves, possibly limiting the incentive to do so. It also sounds like a solution could be that builders should just start playing the game fully, and always include extra transfer value in their bids, so nobody else can hop in to exploit it. But that would take some explanation for validators.


The other change suggested here, which I think can be separated out cleanly from the split-scoring suggestion, is to adjust block value by outgoing transfers from the fee recipient address. I don't see any particular problems with this other than added complexity. It would need a stricter definition: would any transaction that results in a decrease in fee recipient balance have its value excluded, or only basic transfers? I'm not sure it's practically all that useful of a change, but I don't see any harm in it.

The option of excluding the value transfers into the fee recipient address is in my mind not feasible. It would be hard to differentiate between which transactions are actually MEV and which ones are incidental, and it shouldn't be a relay's role to draw that distinction.

So in the end it seems we can generally resolve today's problems with block level scoring (but fully embraced with builders bidding the value + transfers), or with this as a more complex option that stays more true to bids=value. I'd like to get some validator thoughts in here as well, as they may have some preferences of their own.

But as I mentioned, priority number one is standardization. If other relays like this, I'm fine following suit.

@benhenryhunter
Copy link
Author

benhenryhunter commented Dec 12, 2024

The option of excluding the value transfers into the fee recipient address is in my mind not feasible. It would be hard to differentiate between which transactions are actually MEV and which ones are incidental, and it shouldn't be a relay's role to draw that distinction.

Agreed ☝️ – it is too difficult for relays to decide which transactions to include/exclude with mev payments.

I'm definitely on board with switching to a single calculation for block scoring if we can come to a consensus (though I doubt we will be able to).

If I had it my way we would only allow the builder to be the block coinbase and the bid must be the exact amount being transferred to the validator in the last transaction.

I understand the reasoning for using validator as block coinbase but that has been the cause of these issues in the first place to save some gas, albeit a not too insignificant amount of gas.

If we choose to switch to only the total validator balance diff:

Calculations open up to negative value bids unless outgoing transactions are censored from the block by the builder. This is why we decide to use the net positive balance increase, but this leads to very misleading bid values.

@mcdee
Copy link
Contributor

mcdee commented Dec 13, 2024

If I had it my way we would only allow the builder to be the block coinbase and the bid must be the exact amount being transferred to the validator in the last transaction.

This would certainly simplify things in terms of calculations. Perhaps the conversation should start here: are all relays willing to demand and enforce this behavior?

If the proposer fee recipient address is used then things definitely become a lot harder. Over time we have added a number of rules that attempt to cover various situations that this creates, most of which have already been discussed above, but it definitely makes the calculation significantly more costly (we fetch transaction traces for every transaction to pick apart what's going on). It is possible that a collaborative effort can agree on all of these conditions, but we always have the chance of missing some and/or disagreeing on their allocation.

@benhenryhunter
Copy link
Author

I do think that would be the best solution but I honestly didn't think we would get agreement on that.

Using the validator balance difference is only necessary if we allow validators to be the coinbase and I was hoping we could limit that to being used only in that specific scenario. In my opinion this would be better than using both whenever we want.

@jzblox
Copy link

jzblox commented Dec 13, 2024

If everyone can somehow all agree then yeah only allowing the builder to be the block coinbase would be fantastic.

@gd-0
Copy link

gd-0 commented Dec 13, 2024

No strong opinion from our side.
On a high level, continuing to allow the proposer fee recipient to be set as the coinbase seems reasonable, as it potentially enables validators to receive slightly higher rewards due to the base fee cost saving. However, the additional amount is minimal, so if it introduces significant overhead we are happy to stop accepting those submissions.

@mcdee
Copy link
Contributor

mcdee commented Dec 18, 2024

There hasn't been any pushback against the idea that we move to the situation where for a builder to supply a valid payload it must have a tx paying the proposer fee recipient address the full value of the payload. Although it's a little restrictive, as people have noted, it makes everything a lot simpler for accounting purposes and the delta is, in my opinion, minimal (and not relevant in most situations as long as all relays only accept such payloads).

Given it's the holiday season, I think that we wait for the new year to see if anyone wants to voice a different view on this. If nothing is forthcoming then it seems reasonable to inform builders of the plan, and to update the MEV relay codepaths to only accept such payloads at some point in the near future (end of 1Q25?)

@alextes
Copy link

alextes commented Dec 18, 2024

not the biggest expert here. at a glance, simple sounds nice. 1. final tx counts for bid only.

i would want to take builders into account. glad to hear this could work for titan (heavyweight builder) and attestant (heavyweight node operator). if a builder shows up with a strong case for a proposer balance based calculation i'd want to consider it. numbers on how much proposers would miss out on would also be interesting. although let's not forget inflating bids could lead to missed rewards too 😅.

then 2. if we're accepting proposer recipient delta based bids, from the sound of it, i'm pretty ambivalent what the logic is as long as we clearly standardize. keeping it super simple makes the gaming plain and obvious, easy to enforce. eventually every builder would apply every trick and true value should be revealed again. the interim may come at the proposer's expense. seems this already lead to complaints about withdrawal inflated bids and simple didn't work well. on the other hand, making this scoring / valuing very complex leads to relay / builder complaints that things become game-able in unclear ways / hard to enforce. i'm sure we can agree on some middle-ground. happy to enforce the standard. prefer just doing 1.

@benhenryhunter
Copy link
Author

🎉 Happy new year to everyone 🎉

Now that we're well past the holiday season I want to bring the attention back to this issue! Surprisingly we haven't had any objections to removing validator as coinbase for payments.

Does it make sense to restrict that and is it possible that we can have achieve removing this behavior by the end of Q1?

Being as this is mainly a relay enforced change, @alextes, @jzblox, @gd-0, @metachris, @austonst do you all believe that is a possible timeline?

@jzblox
Copy link

jzblox commented Jan 7, 2025

Perhaps @ericsanchirico can weigh in here for the Bloxroute Relay team?

@alextes
Copy link

alextes commented Jan 11, 2025

Mostly hinges on broad builder support for me. If we have that we could move even faster.

Explicit green light from the top 5 builders would be nice. That'd be 99% market share. Happy to help reach any builder.

Could even throw in a sixth if you stay ahead of bob, ben. I have a feeling BTCS'll quickly say yes :p

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

No branches or pull requests

6 participants