Quick Start
This quickstart guide contains all the information necessary to get up and running as a searcher on Flashbots. If you have any questions, do not hesitate to ask in the '#🐣 newcomers' or '#🤖 searchers' discord channels, or in the Searcher Self-Support Forum.
See you on-chain! ⚡🤖
Bundle Relay URLS
Network | URL |
---|---|
Mainnet | https://relay.flashbots.net |
Goerli | https://relay-goerli.flashbots.net |
Sepolia | https://relay-sepolia.flashbots.net |
Who should use Flashbots Auction?
- Ethereum bot operators (we call them "searchers") looking for fast, and risk free access to blockspace (for example, arbitrage and liquidation bots)
- Ethereum users looking for frontrunning protection on their transactions (for example, Uniswap traders)
- Ethereum Dapps with advanced use cases like account abstraction or gasless transactions
How does Flashbots work for searchers?
Flashbots connects searchers to validators (previously "miners") while allowing them to avoid the public tx pool. Searchers with transactions they would like to send first craft what we call "bundles" and send these to a block builder such as Flashbots. The builder simulates the bundles to ensure there are no reverts, and then builds a full block with the available bundles and transactions. Via mev-boost and the network of relays and builders, these blocks are received by validators while maintaining pre-trade privacy.
Getting onboarded to Flashbots is easy for searchers; you simply need to update how you send transactions.
How to send your first Flashbots bundle
To access the Flashbots network you will need three things:
- A private key that Flashbots can use to identify you
- A way to interact with the Flashbots network
- Alchemy offers an easy way to send single transactions to Flashbots.
- A "bundle" for your transactions
Let's begin with the private key Flashbots uses for identity. When you send bundles to Flashbots you will sign them with a private key so that we can establish identity for searchers and establish reputation for them over time. This private key does not store funds and is not the primary private key you use for executing transactions. Again, it is only used for identity, and it can be any private key.
Second, you'll need a way to interact with Flashbots. The Flashbots builder receives bundles at relay.flashbots.net
, and we have specific RPC endpoints you'll need to use to send us transactions. We've integrated with a few popular developer tools like Ethers.js or web3.py to make interacting with Flashbots as easy as possible. Here are a few examples of how to set up a Flashbots provider:
- ethers.js
- web3.py
- go
const ethers = require("ethers.js");
const {
FlashbotsBundleProvider,
} = require("@flashbots/ethers-provider-bundle");
const provider = new ethers.providers.JsonRpcProvider({
url: ETHEREUM_RPC_URL,
});
// Standard json rpc provider directly from ethers.js. For example you can use Infura, Alchemy, or your own node.
const authSigner = new ethers.Wallet(
"0x0000000000000000000000000000000000000000000000000000000000000000"
);
// `authSigner` is an Ethereum private key that does NOT store funds and is NOT your bot's primary key.
// This is an identifying key for signing payloads to establish reputation and whitelisting
const flashbotsProvider = await FlashbotsBundleProvider.create(
provider,
authSigner
);
// Flashbots provider requires passing in a standard provider and an auth signer
import os
from eth_account.account import Account
from eth_account.signers.local import LocalAccount
from flashbots import flashbot
from web3 import Web3, HTTPProvider
# Create a web3 object with a standard json rpc provider, such as Infura, Alchemy, or your own node.
w3 = Web3(HTTPProvider("http://localhost:8545"))
# ETH_ACCOUNT_SIGNATURE is an Ethereum private key that does NOT store funds and is NOT your bot's primary key.
# This is an identifying key for signing payloads to establish reputation and whitelisting
ETH_ACCOUNT_SIGNATURE: LocalAccount = Account.from_key(os.environ.get("ETH_SIGNATURE_KEY"))
# Flashbots providers require both a standard provider and ETH_ACCOUNT_SIGNATURE (to establish reputation)
flashbot(w3, ETH_ACCOUNT_SIGNATURE)
package main
import (
"bytes"
"crypto/ecdsa"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"net/http"
"time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
const (
j = "application/json"
flashbotURL = "https://relay.flashbots.net"
stats = "flashbots_getUserStats"
flashbotXHeader = "X-Flashbots-Signature"
p = "POST"
)
var (
privateKey, _ = crypto.HexToECDSA(
"2e19800fcbbf0abb7cf6d72ee7171f08943bc8e5c3568d1d7420e52136898154",
)
)
func flashbotHeader(signature []byte, privateKey *ecdsa.PrivateKey) string {
return crypto.PubkeyToAddress(privateKey.PublicKey).Hex() +
":" + hexutil.Encode(signature)
}
func main() {
mevHTTPClient := &http.Client{
Timeout: time.Second * 3,
}
currentBlock := big.NewInt(12_900_000)
params := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"method": stats,
"params": []interface{}{
fmt.Sprintf("0x%x", currentBlock.Uint64()),
},
}
payload, _ := json.Marshal(params)
req, _ := http.NewRequest(p, flashbotURL, bytes.NewBuffer(payload))
headerReady, _ := crypto.Sign(
accounts.TextHash([]byte(hexutil.Encode(crypto.Keccak256(payload)))),
privateKey,
)
req.Header.Add("content-type", j)
req.Header.Add("Accept", j)
req.Header.Add(flashbotXHeader, flashbotHeader(headerReady, privateKey))
resp, _ := mevHTTPClient.Do(req)
res, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(res))
}
Now that we have a private key to identify ourselves with and a Flashbots provider we can create and send a bundle. Here's an example in node.js
const ethers = require("ethers.js");
const {
FlashbotsBundleProvider,
} = require("@flashbots/ethers-provider-bundle");
const provider = new ethers.providers.JsonRpcProvider({
url: ETHEREUM_RPC_URL,
});
const authSigner = new ethers.Wallet(
"0x2000000000000000000000000000000000000000000000000000000000000000"
);
const flashbotsProvider = await FlashbotsBundleProvider.create(
provider,
authSigner
);
const signedBundle = await flashbotsProvider.signBundle([
{
signer: SOME_SIGNER_TO_SEND_FROM,
transaction: SOME_TRANSACTION_TO_SEND,
},
]);
const bundleReceipt = await flashbotsProvider.sendRawBundle(
signedBundle,
TARGET_BLOCK_NUMBER
);
That's it!
Next steps
Congrats! You should now have everything you need to start sending transactions to the Flashbots network.
- If you are looking to interact with Flashbots without using one of the libraries, check out the RPC endpoint documentation and other advanced concepts.
- For examples of advanced usage of Flashbots, check out the example searchers.
- For additional tools, check out the searcher libraries.
- For potential MEV opportunities, check out the MEV job board 🤠