For searchers

Participating validators

  • 0x88c5e96c1459d224383dcb1fe0cedd1fcee25ffb

Endpoint

Searchers can use the following relay endpoint for sending bundles:

Searchers will want to run their nodes near Germany to get good latency to the relay and the validator.

mev-bor spec

mev-bor follows the Flashbots v0.3 spec (https://docs.flashbots.net/flashbots-auction/miners/mev-geth-spec/v03-rpc) with the following changes:

  • the RPC methods have been moved from the `eth` namespace to a new `mev` namespace. This was done to enable validators to not expose the `eth` namespace which contains a lot more unrelated RPC methods as well as security critical methods like signing using the unlocked validator key.

mev relay spec

The MEV relay is designed to work with the flashbots bundle formats, RPC calls and the flashbots ethers provider (https://github.com/flashbots/ethers-provider-flashbots-bundle) with the following notable changes:

  • The relay only supports the `eth_sendBundle` RPC call at the moment. This means methods like `eth_callBundle` and related calls like `simulate` in the flashbots provider are not supported. Searchers will need their own instance or bor/mev-bor if they require the use of these methods.
  • The relay currently only accepts bundles with up to 5 transactions with a cumulative gas limit of 2.5M gas. These limits are expected to go up in the future as we collect more metrics regarding usage and capacity requirements.
  • The `revertingTxHashes` field in the bundle isn't supported currently.

Note that bundle delivery and inclusion is best effort, and searchers still have to make sure that bundles do not spam the endpoints and are economically enticing for validators to include, moreso than transactions from other bundles and public mempool.

Example usage

import { providers, Wallet } from "ethers";
import { FlashbotsBundleProvider } from "@flashbots/ethers-provider-bundle";

async function main() {
  // Standard json rpc provider directly from ethers.js (NOT Flashbots)
  // create the base provider
  let base = new ethers.providers.JsonRpcProvider({url: "http://<polygonbor-ip>:8545"}, 137)
  await base.ready
  const user = new ethers.Wallet('a2..<privkey>..40', base)
  // wrap it with the marlin relay provider
  let provider = new FlashbotsBundleProvider(base, user, {url: 'http://bor.txrelay.marlin.org/'}, 137)


  const CONTRACT_ADDRESS = "0x0a..<contract-address>"
  const ABI = ["function coinbasetransfer() payable"]
  const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, user)

  const txs = [
    {
      signer: user,
      transaction: await contract.populateTransaction.coinbasetransfer({
        value: ethers.utils.parseEther("0.1"),
        gasPrice: "31000000000",
      })
    },
    {
      signer: user,
      transaction: await contract.populateTransaction.coinbasetransfer({
        value: ethers.utils.parseEther("0.2"),
        gasPrice: "31000000000",
      })
    },
  ];

  const blk = await base.getBlockNumber()

  // send bundle to marlin relay
  const result = await provider.sendBundle(txs, blk + 1);
  console.log(result)
}

main().catch(console.error)