2

I've been trying to find how the EIP-1559 transactions gets prioritized in the same block. So I have few questions.

1 - What happens when the gas prices are the same (maxFee and maxPriority) ? How does geth queues those transactions ? (It would be great that someone could send the github source for the algorithm.)

2 - Sometimes even through the max gas price is less than the second transaction, for some reason the first one gets mined first and second gets after the first in the block. How that could happen ?

It is really hard to understand those miners so I would be very happy if someone can help me out. Thanks!

1
  • Did the answer below help? For Q2, miners might have modified code to give different senders (including themselves) priority. Flashbots might also be related.
    – eth
    Sep 4, 2022 at 0:59

1 Answer 1

1

I didn't know the answer to your questions but I took a look to the code to understand it and here is what I found out, don't hesitate if you see some code that contradicts what I'm going to summarize below.


1 - What happens when the gas prices are the same (maxFee and maxPriority) ? >How does geth queues those transactions ? (It would be great that someone could send the github source for the algorithm.)

Just as a reminder :

  • Base Fee - Defined by the network, must be paid and is burned.
  • (Max) Priority Fee - Defined by the user, can be paid and is forwarded to the miner
  • Max Fee - Defined by the user, Maximum to be paid in any circumstances

So if a tx is sent with Max Fee == (Max) Priority Fee, the effective gasTip will be computed here where :

if gasFeeCap.Cmp(baseFee) == -1 {
        err = ErrGasFeeCapTooLow
}

returns an error if Max Fee is lower than Base Fee (not enough gas provided to pay what must be paid) and :

return math.BigMin(tx.GasTipCap(), gasFeeCap.Sub(gasFeeCap, baseFee)), err

returns the minimum value between (Max) Priority Fee and Max Fee - Base Fee. So if Max Fee == (Max) Priority Fee, and Base Fee is non zero / positive, the minimum value must be Max Fee - Base Fee, ensuring that your tx can proceed and that you won't pay more than Max Fee in total. The returned value is what is left as a tip.


Now for the ordering, the original EIP-1559 states that :

Transaction Ordering

With most people not competing on priority fees and instead using a baseline fee to get included, transaction ordering now depends on individual client internal implementation details such as how they store the transactions in memory. It is recommended that transactions with the same priority fee be sorted by time the transaction was received to protect the network from spamming attacks where the attacker throws a bunch of transactions into the pending pool in order to ensure that at least one lands in a favorable position. Miners should still prefer higher gas premium transactions over those with a lower gas premium, purely from a selfish mining perspective.

From my understanding, geth orders them by price and account, the ordering itself is done here, called here in the miner logic, returning the following structure :

type TransactionsByPriceAndNonce struct {
    txs     map[common.Address]Transactions // Per account nonce-sorted list of transactions
    heads   TxByPriceAndTime                // Next transaction for each unique account (price heap)
    signer  Signer                          // Signer for the set of transactions
    baseFee *big.Int                        // Current base fee
}

The important fields are of course txs and heads. When selecting transactions the best candidate will be taken from heads (highest price) if any error happens it is popped and we also flush from that structure all remaining transactions from the same account (to respect nonce ordering / avoid nonce gap), and move to the next best price candidate.

Now in case no error happens, geth moves to the next transaction from the same account which as per my understanding might be a suboptimal selection strategy if the aim is to maximize the fees, but maybe I got it wrong ? that process code can be found here.


2 - Sometimes even though the max gas price is less than the second transaction, for some reason the first one gets mined first and second gets after the first in the block. How that could happen ?

Not 100% sure but from the code it really seems like the worker is polling the available txs and keeps pushing the higher priced one in the block while it still can, thus if you receive a very highly priced tx at any point you can take advantage of it and include it in the block, not necessarily respecting a perfectly increasing gas price order in the block. I'm pretty sure that miners are more concerned about maximizing their gains rather than creating a perfectly increasing set of transaction fees though...

I hope that answers your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.