MEV access on Goerli/Prater testnet

→ updated on 09/28/2022 for long-term Goerli/Prater testnet (previously Ropsten)

Shoutout to realbigsean from SigmaPrime for his guidance and insights and Yorick from EthStaker for feedback and review

This post aims to provide a quick and minimalistic setup guide on how to test accessing MEV as a validator on the Goerli/Prater testnet.

In a preceding guide I tried to highlight essential requirements for running an Ethereum node post-merge using Ubuntu & Docker. With mev-boost as an optional, additional piece of software in the node stack, I try to leverage docker-compose this time.


Maximum Extractable Value is a controversial topic within the Ethereum ecosystem. As the network has experienced increased adoption and settlement value, profitable opportunities to insert TXs at particular places of a block have become more prevalent.

These practices are often referred to as front-running, among others, implying centralisation vectors and even chain instabilities. Hence, the ultimate goal for blockchain R&D is to minimize (or eliminate?!) such negative externalities for users and the network as a whole. A first step towards mitigating them is to democratize access to MEV.

In essence, MEV boils down to the fundamental question of how the process of fair transaction ordering in a block is supposed to happen in the most trust-minimised fashion.

Technically, a validator -representing the proposer of a block- defaults to asking the local execution client for a particular transaction order (typically ranked by the highest paying TX fees). However, there’s also the option to ask a third-party relay for a pre-constructed block, e.g. Flashbots, a collective operating an external block builder protocol. A relay is a doubly-trusted intermediary matching specialised builders on the one hand with validators on the other hand.


Node operators can access MEV with the help of a software called mev-boost by Flashbots. In the given case, if it’s the validator’s turn to propose a block, the CL client Lighthouse will ask both mev-boost and the EL client Besu for a block, ultimately opting for the better paying one.


In case a relay provided the validator with an invalid pre-constructed block (‘execution payload header’), which turned out to be invalid after the validator client had signed it, this does not represent a slashable event (rather leads to a missed proposal).

Read about how Flashbots argues for running mev-boost. And feel free to dive deeper into the woods here, here and here. There’s a bunch of open social, technical and cryptoeconomic research and design questions to be tackled.

How to access MEV on Goerli/Prater

For the sake of this demo, I chose Besu by ConsenSys as an EL client. It comes with a lean new database structure called “Bonsai tries” and offers implicit pruning functionality, lowering disk space usage and avoiding potential downtimes for manual pruning. Snap sync is also about to hit the latest release. Lighthouse by SigmaPrime serves as CL client (i.e. Beacon Node & Validator Client).


Run a complete node stack with mev-boost

1) Navigate to your /home directory. Create a project directory with subfolders:

$ mkdir -p ETHclient/{besu,lighthouse-bn,lighthouse-vc,validator_keys,JWT}; cd ETHclient

2) Generate a JasonWebToken (JWT) so that the execution and consensus client can communicate securely:

$ openssl rand -hex 32 | tr -d "\n" > "$(pwd)/JWT/jwtsecret"

3) Paste the validator keystore(s) in the host directory ./validator_keys

4) Add the validator key to Lighthouse

$ docker run -it -v $(pwd)/lighthouse-vc:/root/.lighthouse -v $(pwd)/validator_keys:/validator_keys sigp/lighthouse:latest-modern lighthouse --network prater account validator import --directory /validator_keys

5) Copy & Paste the below attached docker-compose code in a newly created file to be named besu-lh-mevboost.yaml in the project directory.

6) Start the docker-compose environment:

$ docker-compose -f besu-lh-mevboost.yaml -p prater up -d

7) Eventually, stop the docker-compose environment:

$ docker-compose -f besu-lh-mevboost.yaml -p prater stop

version: "3.0"

        image: sigp/lighthouse:latest-modern
            - ETHclient_net
        container_name: prater-bn
        restart: unless-stopped
            - ./lighthouse-bn:/root/.lighthouse
            - ./JWT:/JWT            
            - 9000:9000/tcp # consensus p2p, open to internet
            - 9000:9000/udp # consensus p2p, open to internet
        command: >
          --debug-level info
          --network prater
          --datadir /root/.lighthouse/prater
          --execution-endpoint http://goerli-besu:8551
          --execution-jwt /JWT/jwtsecret
          --builder http://prater-mevboost:18550
        image: sigp/lighthouse:latest-modern
            - ETHclient_net
        container_name: prater-vc
        restart: unless-stopped
            - ./lighthouse-vc:/root/.lighthouse
            - beacon_node
        command: >
          --debug-level info
          --network prater
          --beacon-nodes http://prater-bn:5052
          --suggested-fee-recipient 0x0000000000000000000000000000000000000000
        image: hyperledger/besu:latest
            - ETHclient_net
        container_name: goerli-besu
        restart: on-failure
            - "JAVA_OPTS=-Xmx4g"
            - ./besu:/opt/besu/data
            - ./JWT:/JWT
            - 30303:30303/tcp # consensus p2p, open to internet
            - 30303:30303/udp # consensus p2p, open to internet
        command: >
          --network goerli
          --data-path /opt/besu/data
          --data-storage-format BONSAI
          --sync-mode X_SNAP
        image: flashbots/mev-boost:latest
            - ETHclient_net
        container_name: prater-mevboost
        restart: on-failure
            - /app/mev-boost
            - -addr
            - -prater
            - -relay-check
            - -relays
        driver: bridge

Closing Remarks

Obviously, the more testnet validators you run, the higher the likelihood of being randomly selected to propose a block (i.e. you likely have to wait less long)

Watch out for the following logs in mev-boost:

level=info msg="getHeader: successfully got more valuable payload header"

level=info msg="getPayload: received payload from relay"

And check if your block has made it on-chain:<yourblocknumber>


Please keep in mind this is a testnet guide that may contain mistakes and that takes shortcuts which come with trade-offs. It could quickly become outdated as it’s subject to ever evolving network and client changes.


This post was supported by a grant from a CLR funding round held by EthStaker, mainly matched by the EF.

Subscribe to Ladislaus
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
This entry has been permanently stored onchain and signed by its creator.