v0.4
#
Simple SummaryDefines the construction and usage of MEV bundles by miners. Provides a specification for custom implementations of the required node changes so that MEV bundles can be used correctly.
#
AbstractMEV bundles
are stored by the node and the bundles that are providing extra profit for miners are added to the block in front of other transactions.
#
MotivationWe believe that without the adoption of neutral, public, open-source infrastructure for permissionless MEV extraction, MEV risks becoming an insiders' game. We commit as an organisation to releasing reference implementations for participation in fair, ethical, and politically neutral MEV extraction.
#
SpecificationThe key words MUST
, MUST NOT
, REQUIRED
, SHALL
, SHALL NOT
, SHOULD
, SHOULD NOT
, RECOMMENDED
, MAY
, and OPTIONAL
in this document are to be interpreted as described in RFC-2119.
#
Miner ConfigurationMiner MUST
accept the following configuration options:
- miner.maxmergedbundles (int) - max number of
MEV bundles
to be included within a single block - miner.trustedrelays (string) - comma separated, hex encoded Ethereum addresses of trusted relays that the miner will be able to accept megabundles from, being reasonably certain about DDoS safety
#
DefinitionsRelay
#
An external system delivering MEV bundles
and/or MEV megabundles
to the node. Relay provides protection against DoS attacks.
MEV bundle
or bundle
#
A list of transactions that MUST
be executed together and in the same order as provided in the bundle, MUST
be executed before any non-bundle transactions and only after other bundles that have a higher bundle adjusted gas price
.
Transactions in the bundle MUST
execute without failure (return status 1 on transaction receipts) unless their hashes are included in the revertingTxHashes
list.
When representing a bundle in communication between the relay
and the node we use an object with the following properties:
Property | Type | Description |
---|---|---|
txs | Array<RLP(SignedTransaction)> | A list of transactions in the bundle. Each transaction is signed and RLP-encoded. |
blockNumber | uint64 | The exact block number at which the bundle can be executed |
minTimestamp | uint64 | Minimum block timestamp (inclusive) at which the bundle can be executed |
maxTimestamp | uint64 | Maximum block timestamp (inclusive) at which the bundle can be executed |
revertingTxHashes | Array<bytes32> | List of hashes of transactions that are allowed to return status 0 on transaction receipts |
MEV megabundle
or megabundle
#
A pre-merged set of bundles
coming from a relay
. Megabundles are not mixed or merged with normal MEV bundles
but instead used for a separate block construction.
When representing a megabundle in communication between the relay
and the node we use an object with the following properties:
Property | Type | Description |
---|---|---|
txs | Array<RLP(SignedTransaction)> | A list of transactions in the bundle. Each transaction is signed and RLP-encoded. |
blockNumber | uint64 | The exact block number at which the bundle can be executed |
minTimestamp | uint64 | Minimum block timestamp (inclusive) at which the bundle can be executed |
maxTimestamp | uint64 | Maximum block timestamp (inclusive) at which the bundle can be executed |
revertingTxHashes | Array<bytes32> | List of hashes of transactions that are allowed to return status 0 on transaction receipts |
relaySignature | Array<Data> | An secp256k1 signature signed with an address from the miner.trustedrelays . Message signed is a Keccak hash of RLP serialized sequence that contains the following items: array of txs (a sequence of byte arrays representing RLP serialized txs); blockNumber serialized as an uint64, minTimestamp serialized as an int256, like in the devp2p specification; maxTimestamp serialized as an int256, like in the devp2p specification; revertingTxHashes serialized as an array of byte arrays. |
MEV block
#
A block containing more than zero MEV bundles
.
Whenever we say that a block contains a bundle
we mean that the block includes all transactions of that bundle in the same order as in the bundle
.
Unit of work
#
A transaction
, a bundle
, megabundle
or a block
.
Subunit
#
A discernible unit of work
that is a part of a bigger unit of work
. A transaction
is a subunit
of a bundle
or a block
. A bundle
is a subunit
of a block
.
Total gas used
#
The sum of gas units used by each transaction from the unit of work
.
Average gas price
#
For a transaction it is equivalent to the transaction minerFee := Min(feeCapPerGas - BASEFEE, priorityFeePerGas) - and for other units of work
it is a sum of (average gas price
* total gas used
) of all subunits
divided by the total gas used
by the unit.
Direct coinbase payment
#
The value of a transaction with a recipient set to be the same as the coinbase
address.
Contract coinbase payment
#
A payment from a smart contract to the coinbase
address.
Coinbase payment
#
A sum of all direct coinbase payments
and contract coinbase payments
within the unit of work
.
Eligible coinbase payment
#
A sum of all direct coinbase payments
and contract coinbase payments
within the unit of work
.
Gas fee payment
#
An average gas price
* total gas used
within the unit of work
.
Eligible gas fee payment
#
A gas fee payment
excluding gas fee payments
from transactions that can be spotted by the miner in the publicly visible transaction pool.
Bundle scoring profit
#
A sum of all eligible coinbase payments
and eligible gas payments
of a bundle
.
Profit
#
A difference between the balance of the coinbase
account at the end and at the beginning of the execution of a unit of work
. We can measure a transaction profit
, a bundle profit
, and a block profit
.
Balance of the coinbase
account changes in the following way
Unit of work | Balance Change |
---|---|
Transaction | average gas price * total gas used + direct coinbase payment + contract coinbase payment |
Bundle | average gas price * total gas used + direct coinbase payment + contract coinbase payment |
Megabundle | average gas price * total gas used + direct coinbase payment + contract coinbase payment |
Block | block reward + average gas price * total gas used + direct coinbase payment + contract coinbase payment |
Adjusted gas price
#
Unit of work
profit
divided by the total gas used
by the unit of work
.
Bundle adjusted gas price
#
Bundle scoring profit
divided by the total gas used
by the bundle
.
: bundle score used to sort bundles.
: ordered list of transactions in a bundle.
: set of transactions in the mempool.
: gas used by transaction .
: fee cap per gas of transaction .
: priority fee per gas of transaction .
: effective fee per gas of transaction equal (, BASEFEE + ).
: miner fee per gas of transaction equal - BASEFEE.
: coinbase difference from direct payment.
#
Bundle constructionA bundle SHOULD
contain transactions with nonces that are following the current nonces of the signing addresses or other transactions preceding them in the same bundle.
A bundle MUST
contain at least one transaction. There is no upper limit for the number of transactions in the bundle, however bundles that exceed the block gas limit will always be rejected.
A bundle MAY
include eligible coinbase payments
. Bundles that do not contain such payments may be discarded when their bundle adjusted gas price
is compared with other bundles.
The maxTimestamp
value MUST
be greater or equal the minTimestamp
value.
#
Accepting bundles from the network#
JSON RPCNode MUST
provide a way of exposing a JSON RPC endpoint accepting eth_sendBundle
calls (specified here). Such endpoint SHOULD
only be accepting calls from a relay
but there is no requirement to restrict it through the node source code as it can be done on the infrastructure level.
Node MUST
provide a way of exposing a JSON RPC endpoint accepting eth_sendMegabundle
calls (specified here). Such endpoint SHOULD
only be accepting calls from a relay
but there is no requirement to restrict it through the node source code as it can be done on the infrastructure level. For each relay only the last megabundle SHOULD
be stored in memory.
#
Bundle eligibilityAny bundle that is correctly constructed MUST
have a blockNumber
field set which specifies in which block it can be included. If the node has already progressed to a later block number then such bundle MAY
be removed from memory.
Each transaction in the bundle MUST
have maxFeePerGas equal or greater than block.BASEFEE + 1 GWei to be selected for the block.
Any bundle that is correctly constructed MAY
have a minTimestamp
and/or a maxTimestamp
field set. Default values for both of these fields are 0
and the meaning of 0
is that any block timestamp value is accepted. When these values are not 0
, then block.timestamp
is compared with them. If the current block.timestamp
is greater than the maxTimestamp
then the bundle MUST NOT
be included in the block and MAY
be removed from memory. If the block.timestamp
is less than minTimestamp
then the bundle MUST NOT
be included in the block and SHOULD NOT
be removed from memory (it awaits future blocks).
#
Block constructionIn order to prevent starvation of less frequently used relays, incoming MEV megabundles
MUST
be given a priority value equal to the time in milliseconds since the previous MEV megabundle
sent by the same relay and redirected to a pool of MEV megabundle
block producers (called workers in MEV-Geth). Whenever the worker is idle and there are MEV megabundles
available, a bundle with the highest priority MUST
be picked for evaluation. Megabundles are never merged with other bundles and can only be combined with transactions from the mempool.
MEV bundles
MUST
be sorted by their bundle adjusted gas price
first and then one by one added to the block as long as there is any gas left in the block and the number of bundles added is less or equal the MaxMergedBundles
parameter. The remaining block gas SHOULD
be used for non-MEV transactions.
When constructing a block each next bundle added after the first bundle MUST
generate at least 99% of the bundle adjusted gas price
from the time of the sorting (the first bundle will naturally provide 100% of this value).
Block MUST
contain between 0 and MaxMergedBundles
bundles.
A block with bundles MUST
place the bundles at the beginning of the block and MUST NOT
insert any transactions between the bundles or bundle transactions.
When constructing a block the node MUST
reject any bundle or megabundle that has a reverting transaction unless its hash is included in the RevertingTxHashes
list of the bundle / megabundle object.
The node SHOULD
be able to compare the block profit
for each number of bundles between 0 and MaxMergedBundles
and choose a block with the highest profit
, e.g. if MaxMergedBundles
is 3 then the node SHOULD
build 4 different blocks - with the maximum of respectively 0, 1, 2, and 3 bundles and choose the one with the highest profit
.
The node MUST
be able to compare the block profit
from the best megabundles
with the block profit
of otherwise winning block.
#
Bundle evictionNode SHOULD
be able to limit the number of bundles kept in memory and apply an algorithm for selecting bundles to be evicted when too many eligible bundles have been received.
#
Rationale#
Naive bundle mergingThe bundle merging process is not necessarily picking the most profitable combination of bundles but only the best guess achievable without degrading latency. The first bundle included is always the bundle with the highest bundle adjusted gas price
#
Using bundle adjusted gas price instead of adjusted gas priceThe bundle adjusted gas price
is used to prevent bundle creators from artificially increasing the adjusted gas price
by adding unrelated high gas price transactions from the publicly visible transaction pool.
#
Each bundle needs a blockNumberThis allows specifying bundles to be included in the future blocks (e.g. just after some smart contracts change their state). This cannot be used to ensure a specific parent block / hash.
#
Future Considerations#
Full block submissionA proposal to allow MEV-Geth accepting fully constructed blocks as well as bundles is considered for inclusion in next versions.
#
Backwards CompatibilityThis change is not affecting consensus and is fully compatible with Ethereum specification.
Bundle formats are not backwards compatible and the v0.2 bundles would be rejected by v0.1 MEV clients.
#
Security ConsiderationsThe node SHOULD
ensure that MEV bundles
and megabundles
that are awaiting future blocks are evicted when at risk of reaching the storage limits (memory or persistent storage).