Applied MEV or how to put things in order in the Ethereum block
On Habré, we have already entered the dark forest of MEV, but almost did not touch on its applied side. In this article, we will take a look at the main MEV infrastructure on the air and look at a few examples of how it works today.
Introduction
MEV (maximum extractable value) is the process of extracting profit from the blockchain network by adding, removing or reordering transactions included in a block. This concept was born in the Ethereum community a long time ago (of course, if calculated in crypto years), but MEV began to reach a new level of volume with the growth of DeFi infrastructure, which opened up more opportunities for servers.
In simple words, the MEV principle is as follows: “Hey miner, put my transaction next to the one for me to earn 1 ETH, and I will give you half of it for this.” Obviously, this is a win-win situation, both for those who found this transaction (servers), and for those who can change the order of the transaction when creating a block.
An important term in working with MEV is mempool. In blockchain terminology, a mempool is a waiting pool for transactions that have not yet been added to a block and are still not confirmed, that is, they are in the pending state. Of course, anyone can see all transactions that are pending and understand how they can affect certain states of contracts.
What are they looking for in the blockchain today?
At the time of writing, the most popular uses for MEV mechanics right now are:
DEX arbitrage and sandwiching. Mempul provides a unique opportunity for traders to anticipate prices on exchanges. Most decentralized exchanges operate on market making algorithms, which allows, knowing the current state of the pools (exchange contracts) and incoming transactions from the mempool, to find out the state of the price after each upcoming transaction in the block. Here, an opportunity opens up for surfers, both for ordinary arbitrage between different exchanges within the same block, and for sandwiching – buying and selling around one transaction or vice versa.
For example, a trader saw a large transaction in the mempool for the purchase of an AOWL token, after which he sent his 2 transactions to the miner: for his purchase of this token right before the big deal and an instant sale after this deal.
https://eigenphi.io/mev/ethereum/tx/0xaf55763add3e93292c9981aeca6a8e087c07d982005538e11ba43fd4c6d7e697 Liquidation. Lending protocols such as Maker, Compound, and Aave require users to deposit collateral (such as ETH). This deposited collateral is then used to provide credit to other users. Once a given collateral has the potential risk of not securing a loan (the risk parameters for this are determined in advance by the DAO community), then any network user can liquidate the debt by taking the collateral. In this case, for example, the debt can be $80k, and its security is $100k, thus the liquidator receives an instant profit.
NFTMEV. Having access to the general information of incoming transactions, it is also possible to detect the completion of NFT auctions or their drops, which opens up opportunities to extract profit from this. For example, if there is a popular NFT drop and the server wants a certain NFT or NFT bundle, he can place his transaction in such a way that he is first in line to buy NFTs, or he can buy the entire NFT bundle in one go.
Infrastructure

The flashbots community played a big role in the development of the MEV infrastructure. They offered mev-boost infrastructure – essentially an improved geth client (i.e. an Ethereum node node client). In this article, we will consider this particular infrastructure, since at the moment all builders in the Ether network use it. However, Flashbots Builder’s dominance has fallen heavily in block production, although at their peak they were collecting almost 80% of all Ether blocks.

Let’s briefly go through the process of “mining” in Ethereum 2.0 after the merge. Now 3 agents are responsible for creating blocks: a builder, a relay (retronizer) and a validator.
The block builder receives transactions from servers and users who, in addition to paying for gas, express their preferred position in the block by staking with a closed price. The task of the builder is to build the most profitable block using various strategies.
A relay is an agent responsible for validating blocks before passing them on to validators. Relay protects validators from spam by validating builder blocks and evaluating the MEV value of each block.
A mev-boost validator is a member of the Beacon Chain chosen to propose a block for a particular slot. The validator contacts the relay to get the most profitable block header, which it validates by signing it with its public key via escrow.

Thus, network users can directly influence block collection through the mev-boost infrastructure. To order transactions, bundles or bundles are used, which are an ordered set of transactions that the server sends to the builder via the API.
For an example, let’s see this liquidation transaction, which was executed through the flashbots builder. Let’s look at its position in the block and see that it is second in the block immediately after the public Transmit transaction, which updates the on-chain price of the asset. In this example, transactions 0xcc101… and 0xba0c4… are an atomic link.

Usage example
Mev-boost client has generic REST API methods, which can be found, for example, in the flashbots documentation. Consider an example of sending a bundle via go:
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"github.com/metachris/flashbotsrpc"
)
rpc := flashbotsrpc.New("https://relay.flashbots.net")
// Список подписанных raw транзакций в порядке исполнения бандла
txs := []string{"0x1234...", "0x4567.."}
// Номер блока, для которого бандл будет валиден
blockNumber := 13281018
sendBundleArgs := flashbotsrpc.FlashbotsSendBundleRequest{
Txs: txs,
BlockNumber: blockNumber,
}
// Приватный ключ, который используется в качестве подписи именно запроса в FB
var privateKey, _ = crypto.GenerateKey()
result, err := rpc.FlashbotsSendBundle(privateKey, sendBundleArgs)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)