ethers-flashbots

repository·master·Indexed 19 days ago

https://github.com/onbjerg/ethers-flashbots

An ethers-rs middleware for sending transactions as Flashbots bundles to interact with Flashbots relays. It provides FlashbotsMiddleware for single relay interaction and BroadcasterMiddleware for sending bundles to multiple builders. Key features include BundleRequest construction for standard and revertible transactions, bundle simulation via eth_callBundle, and tracking bundle status through BundleStats and SimulatedBundle metrics. Note: This package is deprecated alongside ethers-rs.

Tokens
6.3K
Snippets
21
Records
31
Agent score
63%

What's inside ethers-flashbots

  1. Install ethers-flashbots

    master

    To use the development version of ethers-flashbots, add the following dependency to your Cargo.toml. Note that this package is deprecated alongside ethers-rs and will no longer be maintained. For stable releases, refer to crates.io.

    ethers-flashbots = { git = "https://github.com/onbjerg/ethers-flashbots" }
  2. Handle JSON-RPC notifications and subscriptions

    master

    The module provides types for handling asynchronous updates from the relay:

    • Notification<R>: Represents a JSON-RPC notification (a message without an id).
    • Subscription<R>: Represents the payload of a notification, containing a subscription ID (as a U256) and the result of type R.
    // Structure of a Notification:
    // {
    //   "jsonrpc": "2.0",
    //   "method": "subscription_method",
    //   "params": {
    //     "subscription": "...",
    //     "result": ...
    //   }
    // }
  3. Interpret SimulatedBundle and SimulatedTransaction results

    master

    When a bundle is simulated, the relay returns a SimulatedBundle containing a list of SimulatedTransaction objects.

    Key metrics for evaluating a bundle's profitability:

    • coinbase_diff: The difference in coinbase's balance due to the bundle (includes tips and gas fees).
    • eth_sent_to_coinbase: The amount of ETH sent directly to coinbase.
    • effective_gas_price(): A method on both SimulatedTransaction and SimulatedBundle that returns coinbase_diff / gas_used. This is an approximation of the bundle's score.
  4. Use BroadcasterMiddleware to broadcast bundles to multiple builders

    master

    The BroadcasterMiddleware is designed to send the same bundle to multiple relay URLs simultaneously. This is useful for increasing the chances of your bundle being picked up by different builders.

    Important: Like FlashbotsMiddleware, this does NOT sign transactions. You must use a signer middleware first.

    When using Middleware::send_transaction, it defaults to targeting the next block and does not perform simulation.

    use ethers::prelude::*;
    use std::convert::TryFrom;
    use ethers_flashbots::BroadcasterMiddleware;
    use url::Url;
    
    // ... setup provider, signer, and wallet ...
    
    let mut client = SignerMiddleware::new(
        BroadcasterMiddleware::new(
            provider,
            vec![Url::parse("https://rpc.titanbuilder.xyz")?, Url::parse("https://relay.flashbots.net")?],
            Url::parse("https://relay.flashbots.net")?, // simulation relay
            signer
        ),
        wallet
    );
    
    let tx = TransactionRequest::pay("vitalik.eth", 100);
    let pending_tx = client.send_transaction(tx, None).await?;
  5. Use FlashbotsMiddleware to send bundles to a single relay

    master

    The FlashbotsMiddleware allows you to send custom bundles or standard transactions to a single Flashbots relay.

    Important: This middleware does NOT sign your transactions. You must wrap the FlashbotsMiddleware in a SignerMiddleware (or similar) to ensure transactions are signed before they reach the Flashbots layer. The relay_signer provided during initialization is used specifically for signing requests to the Flashbots relay (your searcher identity).

    When using Middleware::send_transaction, the middleware automatically constructs a bundle with these defaults:

    • The transaction is assumed not to revert.
    • No minimum or maximum timestamp is set.
    • The target block is the next block (latest_block + 1).
    • No bundle simulation is performed before sending.
    use ethers::prelude::*;
    use std::convert::TryFrom;
    use ethers_flashbots::FlashbotsMiddleware;
    use url::Url;
    
    // ... setup provider, signer (searcher identity), and wallet (transaction signer) ...
    
    // Note: The order is important! The signer middleware must sign transactions 
    // BEFORE they are sent to the Flashbots middleware.
    let mut client = SignerMiddleware::new(
        FlashbotsMiddleware::new(
            provider,
            Url::parse("https://relay.flashbots.net")?,
            signer
        ),
        wallet
    );
    
    // This transaction will now be sent as a Flashbots bundle!
    let tx = TransactionRequest::pay("vitalik.eth", 100);
    let pending_tx = client.send_transaction(tx, None).await?;
  6. Use FlashbotsMiddleware to send bundles

    master

    You can send transactions as Flashbots bundles by wrapping an ethers Provider with FlashbotsMiddleware and then wrapping that in a SignerMiddleware.

    To do this, you need:

    1. A Provider (e.g., Provider<Http>) connected to a network.
    2. A bundle_signer (a LocalWallet) used to sign the bundle itself.
    3. A wallet (a LocalWallet) used to sign the actual transactions within the bundle.
    4. The Flashbots relay URL (e.g., https://relay.flashbots.net).

    Once configured, you can use client.send_transaction(tx, None) to submit the transaction as part of a bundle.

    use eyre::Result;
    use ethers::core::rand::thread_rng;
    use ethers::prelude::*;
    use ethers_flashbots::*;
    use std::convert::TryFrom;
    use url::Url;
    
    #[tokio::main]
    async fn main() -> Result<()> {
        // Connect to the network
        let provider = Provider::<Http>::try_from("https://mainnet.eth.aragon.network")?;
    
        // This is your searcher identity
        let bundle_signer = LocalWallet::new(&mut thread_rng());
        // This signs transactions
        let wallet = LocalWallet::new(&mut thread_rng());
    
        // Add signer and Flashbots middleware
        let client = SignerMiddleware::new(
            FlashbotsMiddleware::new(
                provider,
                Url::parse("https://relay.flashbots.net")?,
                bundle_signer,
            ),
            wallet,
        );
    
        // Pay Vitalik using a Flashbots bundle!
        let tx = TransactionRequest::pay("vitalik.eth", 100);
        let pending_tx = client.send_transaction(tx, None).await?;
    
        // Get the receipt
        let receipt = pending_tx
            .await?
            .ok_or_else(|| eyre::format_err!("tx not included"))?;
        let tx = client.get_transaction(receipt.transaction_hash).await?;
    
        println!("Sent transaction: $\\n", serde_json::to_string(&tx)?);
        println!("Receipt: $\\n", serde_json::to_string(&receipt)?);
    
        Ok(())
    }
  7. Construct a BundleRequest to submit to a Flashbots relay

    master

    A BundleRequest is used to submit a bundle of transactions to a Flashbots relay. To be valid, a bundle must include at least one transaction (via push_transaction) and a target block (via set_block).

    Transactions can be added as:

    • Standard transactions: The bundle is rejected if they revert.
    • Revertible transactions: The bundle remains valid even if these transactions revert.

    You can also provide simulation parameters (set_simulation_block, set_simulation_timestamp, set_simulation_basefee) to test the bundle against a specific state before submission.

    let bundle = BundleRequest::new()
        .push_transaction(my_signed_tx)
        .push_revertible_transaction(revertible_tx)
        .set_block(target_block_number);
  8. Get bundle and user statistics

    master

    The FlashbotsMiddleware provides methods to query statistics from the relay:

    • get_bundle_stats(bundle_hash, block_number): Retrieves stats for a specific bundle using flashbots_getBundleStatsV2.
    • get_user_stats(): Retrieves stats for your searcher identity (the signer used to initialize the middleware) using flashbots_getUserStatsV2.
  9. Simulate a bundle with FlashbotsMiddleware

    master

    You can simulate a bundle using simulate_bundle. This uses the eth_callBundle RPC method.

    To use this, the BundleRequest must have the following parameters set:

    • block
    • simulation_block
    • simulation_timestamp

    You can optionally call set_simulation_relay to use a different endpoint (e.g., a local node) for simulations instead of the primary relay.

    // Assuming 'client' is a FlashbotsMiddleware
    let result = client.simulate_bundle(&bundle).await?;