An Ethers middleware for submitting Flashbots bundles

Overview

Ethers Flashbots

CI Status Crates.io Docs.rs

An Ethers middleware to send transactions as Flashbots bundles.

Installation

Add ethers-flashbots to your Cargo.toml.

# This is the development version, for the stable release refer
# to crates.io
ethers-flashbots = { git = "https://github.com/onbjerg/ethers-flashbots" }

Usage

use anyhow::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(|| anyhow::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(())
}

See the examples for more in-depth examples.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure that the tests and lints pass (cargo test && cargo clippy -- -D clippy::all && cargo fmt -- --check).

Make sure to add your changes to the "Unreleased" section of the changelog.

Comments
  • rlp: expected input string or byte for *big.Int, decoding into (types.LegacyTx).GasPrice

    rlp: expected input string or byte for *big.Int, decoding into (types.LegacyTx).GasPrice

    Simulating a bundle with a Signed(Transaction) (e.g. from mempool) does result in geth node complaining with:

    `err="rlp: expected input string or byte for *big.Int, decoding into (types.LegacyTx).GasPrice"
    

    Here is a random example tx:

    [src/main.rs:63] &tx = Transaction {
        hash: 0xb272f320f1676befa7e15a8c734c071d52811512c2bb34b475705cf02a88a1ba,
        nonce: 223,
        block_hash: None,
        block_number: None,
        transaction_index: None,
        from: 0xcea4e31e1ca4b6d2391c41a7cb9afc72c81bda3f,
        to: Some(
            0x96ed81c7f4406eff359e27bff6325dc3c9e042bd,
        ),
        value: 0,
        gas_price: Some(
            86624081747,
        ),
        gas: 46258,
        input: Bytes(
            b"\xa2,\xb4e\0\0\0\0\0\0\0\0\0\0\0\0Mt\x1c(\xc4\r\x06(\xe3\xd0\x94S$]\xf7\x7fQ\xfd\xf9]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01",
        ),
        v: 38,
        r: 36074129442019506630029011189037493110736900376526272647848390443457751355846,
        s: 39883350964482382363729019514337022956052712241672243746553175159300450949706,
        transaction_type: Some(
            0,
        ),
        access_list: None,
        max_priority_fee_per_gas: None,
        max_fee_per_gas: None,
        chain_id: None,
    }
    

    This is the tx inside bundle.transactions():

    [src/main.rs:72] tx = Signed(
        Transaction {
            hash: 0xb272f320f1676befa7e15a8c734c071d52811512c2bb34b475705cf02a88a1ba,
            nonce: 223,
            block_hash: None,
            block_number: None,
            transaction_index: None,
            from: 0xcea4e31e1ca4b6d2391c41a7cb9afc72c81bda3f,
            to: Some(
                0x96ed81c7f4406eff359e27bff6325dc3c9e042bd,
            ),
            value: 0,
            gas_price: Some(
                86624081747,
            ),
            gas: 46258,
            input: Bytes(
                b"\xa2,\xb4e\0\0\0\0\0\0\0\0\0\0\0\0Mt\x1c(\xc4\r\x06(\xe3\xd0\x94S$]\xf7\x7fQ\xfd\xf9]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01",
            ),
            v: 38,
            r: 36074129442019506630029011189037493110736900376526272647848390443457751355846,
            s: 39883350964482382363729019514337022956052712241672243746553175159300450949706,
            transaction_type: Some(
                0,
            ),
            access_list: None,
            max_priority_fee_per_gas: None,
            max_fee_per_gas: None,
            chain_id: None,
        },
    )
    

    Running

    let bundle = BundleRequest::new()
        .push_transaction(tx)
        .set_simulation_block(block_number)
        .set_block(block_number + 1);
    
    let simulated_bundle = client.inner().simulate_bundle(&bundle).await;
    

    will result in:

    `err="rlp: expected input string or byte for *big.Int, decoding into (types.LegacyTx).GasPrice"
    

    Somewhere along the way the GasPrice is wrongly set to 0 or None, I assume. I am not sure how to debug this. I think to the core writer the position in code to check should be obvious? I am a bit new to rust... I think this is due to EIP1559 changes, which might result in setting the GasPrice to None, as if BaseFee/... is set this would lead to an error if GasPrice has a value as well...

    If it helps to have a working example, please tell me.

    bug 
    opened by avocadochicken 18
  • jsonrpc.rs Error(

    jsonrpc.rs Error("data did not match any variant of untagged enum ResponseData")

    I simulated some random tx from mempool before they were include in a block. The line client.inner().simulate_bundle(&bundle).await; throwed following errors

    tx 0x28c338e677518eb9a3b0ce150a54a787464b1e0ee6407ca9a2cfca3e7f1da08f reverted and some log messages (from SushiSwap Router) "Fail with error 'TransferHelper: TRANSFER_FROM_FAILED'" are inside value field.

    RelayError(
        ResponseSerdeJson {
            err: Error("data did not match any variant of untagged enum ResponseData", line: 1, column: 1249),
            text: "{\"jsonrpc\":\"2.0\",\"id\":20,\"result\":{\"bundleGasPrice\":\"1500000000\",\"bundleHash\":\"0xac94fedbf37d864f006c12945e7a50fe9e712ec25a5da833666337bca3fcecf1\",\"coinbaseDiff\":\"86709000000000\",\"ethSentToCoinbase\":\"0\",\"gasFees\":\"86709000000000\",\"results\":[{\"coinbaseDiff\":\"86709000000000\",\"error\":\"execution reverted\",\"ethSentToCoinbase\":\"0\",\"fromAddress\":\"0xb97dC3cd69a7Daf67cF3f11A9CB8BE368Bc46C6f\",\"gasFees\":\"86709000000000\",\"gasPrice\":\"1500000000\",\"gasUsed\":57806,\"revert\":\"\\u0008\\ufffdy\\ufffd\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000 \\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000$TransferHelper: TRANSFER_FROM_FAILED\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\",\"toAddress\":\"0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F\",\"txHash\":\"0x28c338e677518eb9a3b0ce150a54a787464b1e0ee6407ca9a2cfca3e7f1da08f\"}],\"stateBlockNumber\":13125885,\"totalGasUsed\":57806}}\n",
        },
    )
    

    tx 0x05261313ae0b76dc336dac8e63d66a3b348fca5d36a77418a5a94713d0bd8aa0 reverted (ouf of gas).

    RelayError(
        ResponseSerdeJson {
            err: Error("data did not match any variant of untagged enum ResponseData", line: 1, column: 647),
            text: "{\"jsonrpc\":\"2.0\",\"id\":257,\"result\":{\"bundleGasPrice\":\"1500000000\",\"bundleHash\":\"0x9cf150b16c37243d6c3a5b31113e47f1bbe20f8cb3fee40c43263092644269bd\",\"coinbaseDiff\":\"310987500000000\",\"ethSentToCoinbase\":\"0\",\"gasFees\":\"310987500000000\",\"results\":[{\"coinbaseDiff\":\"310987500000000\",\"error\":\"execution reverted\",\"ethSentToCoinbase\":\"0\",\"fromAddress\":\"0x3438ea7671A46A493672595C0E2FB23E4C3aaA66\",\"gasFees\":\"310987500000000\",\"gasPrice\":\"1500000000\",\"gasUsed\":207325,\"toAddress\":\"0x1A2a1c938CE3eC39b6D47113c7955bAa9DD454F2\",\"txHash\":\"0x05261313ae0b76dc336dac8e63d66a3b348fca5d36a77418a5a94713d0bd8aa0\"}],\"stateBlockNumber\":13125898,\"totalGasUsed\":207325}}\n",
        },
    )
    

    tx 0x27757cbf58e8eedd881a0d2f4b99a340d689269e74d3bf93690b3f1f35f8546e succeeded, but log messages are inside value field. https://etherscan.io/tx/0x27757cbf58e8eedd881a0d2f4b99a340d689269e74d3bf93690b3f1f35f8546e#eventlog

    RelayError(
        ResponseSerdeJson {
            err: Error("data did not match any variant of untagged enum ResponseData", line: 1, column: 951),
            text: "{\"jsonrpc\":\"2.0\",\"id\":662,\"result\":{\"bundleGasPrice\":\"2050000000\",\"bundleHash\":\"0xb14a4c5fba855329ba679d512717e538927b7b21bf67504b3015ad5fbd18af6f\",\"coinbaseDiff\":\"386078550000000\",\"ethSentToCoinbase\":\"0\",\"gasFees\":\"386078550000000\",\"results\":[{\"coinbaseDiff\":\"386078550000000\",\"ethSentToCoinbase\":\"0\",\"fromAddress\":\"0x3D78aeBfEB21286B38E8E158bE77d2990715651a\",\"gasFees\":\"386078550000000\",\"gasPrice\":\"2050000000\",\"gasUsed\":188331,\"toAddress\":\"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D\",\"txHash\":\"0x27757cbf58e8eedd881a0d2f4b99a340d689269e74d3bf93690b3f1f35f8546e\",\"value\":\"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000002037c9eaac64e4519eb0b3c90000000000000000000000000000000000000000000000002fd89477d0ab3cab000000000000000000000000000000000000000000000000000000028e3825cc\"}],\"stateBlockNumber\":13125900,\"totalGasUsed\":188331}}\n",
        },
    )
    

    Looks like ethers-flashbots/src/jsonrpc.rs could see some tweaking.

    bug 
    opened by avocadochicken 5
  • Calling

    Calling "flashbots_getBundleStatsV2" sometimes fails

    Ty for updating the new endpoints @onbjerg!

    Just did some testing on Goerli and it works fine most of the time, it does seem tough that sometimes the JSON response from flashbots is lacking some fields resulting in a parsing error:

        Error {
            msg: "flashbots.get_bundle_stats(<hash>, <block>)",
            source: RelayError(
                ResponseSerdeJson {
                    err: Error("data did not match any variant of untagged enum ResponseData", line: 1, column: 156),
                    text: "{\"id\":3,\"result\":{\"isSimulated\":true,\"isHighPriority\":true,\"simulatedAt\":\"2022-12-24T17:18:52.689Z\",\"receivedAt\":\"2022-12-24T17:18:52.68Z\"},\"jsonrpc\":\"2.0\"}",
                },
            ),
        },
    

    Other times the response is as expected:

    Good response example
        BundleStats {
            is_high_priority: true,
            is_simulated: true,
            simulated_at: Some(
                2022-12-24T17:20:15.387Z,
            ),
            received_at: Some(
                2022-12-24T17:20:15.380Z,
            ),
            considered_by_builders_at: [
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:30.707Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:31.207Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:31.707Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:32.207Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:32.707Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:33.211Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:33.712Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:34.207Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:34.707Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:30.964Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:31.464Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:31.963Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:32.463Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:32.964Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:33.463Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:34.464Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:35.464Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:35.963Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:35.207Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:35.707Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:36.207Z,
                    ),
                },
            ],
            sealed_by_builders_at: [
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:30.828Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:31.254Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:31.755Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:32.289Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:32.756Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:33.292Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:33.876Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:34.257Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:34.757Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:31.031Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:31.500Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:32.002Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:32.506Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:33.011Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:33.505Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:34.502Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:35.510Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xb67a5148a03229926e34b190af81a82a81c4df66831c98c03a139778418dd09a3b542ced0022620d19f35781ece6dc36),
                    timestamp: Some(
                        2022-12-24T17:20:36.007Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:35.260Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:35.760Z,
                    ),
                },
                BuilderEntry {
                    pubkey: Bytes(0xa1dead01e65f0a0eee7b5170223f20c8f0cbf122eac3324d61afbdb33a8885ff8cab2ef514ac2c7698ae0d6289ef27fc),
                    timestamp: Some(
                        2022-12-24T17:20:36.258Z,
                    ),
                },
            ],
        },
    

    It seems that the fields considered_by_builders_at and sealed_by_builders_at are not always present in the response causing the deserialization error.

    bug good first issue 
    opened by ibhagwan 4
  • Add option to use different relay for simulation

    Add option to use different relay for simulation

    Adds the option to set a different relay URL for bundle simulations.

    The relay URL can also be a node that implements the eth_callBundle remote procedure call.

    enhancement 
    opened by onbjerg 4
  • Errors with the advanced example

    Errors with the advanced example

    When I run the advanced example with a real funded wallet, the call to simulate (client.inner().simulate_bundle(&bundle).await?;) returns Error: Some parameters were missing.

    The first thing that simulate_bundle runs is

    bundle
                .block()
                .and(bundle.simulation_block())
                .and(bundle.simulation_timestamp())
                .ok_or(FlashbotsMiddlewareError::MissingParameters)?;
    

    so I added a simulation_block and simulation_timestamp to the bundle:

        let bundle = BundleRequest::new()
            .push_transaction(tx.rlp_signed(client.signer().chain_id(), &signature))
            .set_block(block_number + 1)
            // these next 2 lines are new
            .set_simulation_block(block_number + 1)
            .set_simulation_timestamp(0);
    

    And testing on goerli (https://relay-goerli.flashbots.net) I still get an error which I don't understand:

    Error: (code: -32000, message: header not found, data: None)
    
    opened by samlaf 3
  • Address/H160 needs serializer

    Address/H160 needs serializer

    In case a new contract is spawned the toAddress / Address field will contain the string "0x". The current implementation does not support this and responds with an error. I do not know if a number might be returned and the H160::from_low_u64_ne is not recommended. Please change if desired.

    It might be not best practice to set the address value to zeros. We could also calculate the contract address based off the nonce. I can make the calculation, but I do not know where in code this needs to be added. I am open for suggestions.

    bug 
    opened by avocadochicken 3
  • Unable to add git =

    Unable to add git = "https://github.com/onbjerg/ethers-flashbots to cargo.toml

    error: failed to run custom build command for sha2-asm v0.6.2

    i think its because i'm running windows..

    found this in ethers-rs and it seems related, wonder if ethers-flashbots need similar fix https://github.com/gakonst/ethers-rs/pull/679/files

    opened by ChainsightLabs 2
  • Include targeted blocknumber for bundle.

    Include targeted blocknumber for bundle.

    This is needed to pass check on https://github.com/onbjerg/ethers-flashbots/blob/master/src/middleware.rs#L157:L159

    The example as existing is not working otherwise (I think). Thanks for this project!

    opened by neandertha1er 2
  • Bump ethers-rs version to add Windows support

    Bump ethers-rs version to add Windows support

    Hi,

    The previous version of Ethers (0.5.1) is unable to build on Windows due to a lack of IPC support (which it assumes). By upgrading to 0.5.2 and disabling the default features this crate works again.

    For context see: https://github.com/gakonst/ethers-rs/issues/393#issuecomment-944389805

    Kind regards,

    Tim

    bug enhancement 
    opened by TimvanScherpenzeel 2
  • Add naive sandwiching example

    Add naive sandwiching example

    It could probably go like this:

    1. Get pending transactions
    2. Filter them for transactions that perform a swap by checking the 4bytes
    3. Attempt to parse swap parameters
    4. Construct front and back transactions within parameters
    5. Construct the bundle
    6. Simulate and submit the bundle

    To simplify things a bit, we can just bribe the miner using gas prices instead of using coinbase.transfer.

    documentation enhancement 
    opened by onbjerg 2
  • calling flashbots_getUserStats fails

    calling flashbots_getUserStats fails

    Calling get_user_stats fails with:

            RelayError(
                RequestError(
                    reqwest::Error {
                        kind: Status(
                            500,
                        ),
                        url: Url {
                            scheme: "https",
                            cannot_be_a_base: false,
                            username: "",
                            password: None,
                            host: Some(
                                Domain(
                                    "relay-goerli.flashbots.net",
                                ),
                            ),
                            port: None,
                            path: "/",
                            query: None,
                            fragment: None,
                        },
                    },
                ),
            )
    

    Might be related to the failure of flashbots_getBundleStats I reported in https://github.com/flashbots/rpc-endpoint/issues/108, specifically this comment.

    bug 
    opened by ibhagwan 1
  • Nonce management strategies

    Nonce management strategies

    Wondering if this is something we can build into this lib and also ignite some discussion around the same.

    What is the nonce management strategy that you are using with flashbots? When I think about it there are some challenges:

    1. If you discover multiple opportunities / bundles to send at same block, if you set nonces x, x + 1, if x bundle doesn't get included because a conflicting bundle outbid, then x + 1 won't be a valid bundle because correct nonce for next tx to land on chain would be x.
    2. If your bundle don't gets included you have to either keep retrying(but only if the bundle is still valid, so maybe there even needs some way to check if the opportunity still exists), again the nonce problem remains, more bundles may have landed in your queue and you would need their nonces to be correct and land in same order.

    I think the simple fix here is:

    1. Use multiple EOAs, so if you have 10 EOAs, you can at max have 10 bundles you can keep trying, so a queue with number of EOAs equal to servers and everything more than that falls in the queue, which maybe limiting because the ones in queue may be non-competitive and could've landed in first try, etc. Multiple EOAs are not ideal because now you'd need to have more complicated RBAC auth on chain.

    The middleware for the above alternative would probably queue bundles whenever send_transaction or send_bundle gets called? Watch for blocks and every new block, check if any previously sent block got confirmed and remove them from queue if they did, check if the tx is valid(maybe closures? or just drop this for now), set relevant nonce and sign them with nth EOA and submit all of the bundles. Repeat.

    enhancement help wanted 
    opened by meetmangukiya 2
  • Transaction validation

    Transaction validation

    Currently there is nothing preventing anyone from adding arbitrary invalid bytes to their bundle, even by mistake. We should try to decode the RLP encoded transactions and make sure they have all the necessary parameters (nonce, gas_price, gas, to, value, input, v, r, s).

    enhancement 
    opened by onbjerg 0
Releases(0.12.1)
  • 0.12.1(Dec 25, 2022)

  • 0.12.0(Dec 24, 2022)

    Added

    • It is now possible to use your own endpoint for simulating bundles. Bundles will be sent over JSON-RPC to the given endpoint. The JSON-RPC method used is eth_callBundle. See Middleware::set_simulation_relay.

    Changed

    • The library now uses the new flashbots_getUserStatsV2 and flashbots_getBundleStatsV2 endpoints. If you need the old endpoints, pin your version to 0.11.0.
    Source code(tar.gz)
    Source code(zip)
  • 0.11.0(Dec 24, 2022)

    Changed

    • Addd a rustls feature flag to use native TLS over OpenSSL
    • Bumped thiserror to 1.0.37
    • Bumped chrono to 0.4.22
    • Bumped url to 2.3.1
    • Bumped async-trait to 0.1.58
    • Bumped ethers to 1.0.0
    Source code(tar.gz)
    Source code(zip)
  • 0.10.0(Dec 24, 2022)

  • 0.9.0(Dec 24, 2022)

  • 0.8.2(Dec 24, 2022)

  • 0.8.1(Dec 24, 2022)

  • 0.8.0(Dec 24, 2022)

  • 0.7.0(Dec 24, 2022)

  • 0.6.0(Dec 24, 2022)

    Changed

    • Relaxed version requirement for Ethers - version requirement is now ^0.5.0.
    • Disabled default Ethers features to allow for building on Windows (which lacks IPC support, see https://github.com/gakonst/ethers-rs/issues/393)
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Dec 24, 2022)

    Added

    • Revert reason is now parsed, if there is any.

    Fixed

    • value on a simulated transaction was incorrectly assumed to be the amount of Ether sent in a transaction. It is now correctly parsed as Bytes, since it represents the return data (if any) of the transaction.
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Dec 24, 2022)

    Changed

    • Parameters are now validated before bundles are sent to the relay. Check the documentation for more information.
    • Bumped ethers to 0.5.1

    Added

    • Added a helper to get the effective gas price of bundles and bundle transactions (SimulatedBundle::effective_gas_price and SimulatedTransaction::effective_gas_price).
    Source code(tar.gz)
    Source code(zip)
  • 0.3.1(Dec 24, 2022)

    Added

    • Added a way to get stats about bundles (FlashbotsMiddleware::get_bundle_stats)
    • Added a getter for the bundle hash of a pending bundle
    • Added a way to get stats about your searcher identity (FlashbotsMiddleware::get_user_stats)
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Dec 24, 2022)

    Fixes

    • If your bundle contains a transaction that deploys a contract, the SimulatedTransaction will now have a destination (to) of None to distinguish this from the zero address.
    Source code(tar.gz)
    Source code(zip)
Owner
Oliver Nordbjerg
Self-taught programmer
Oliver Nordbjerg
Ethers-rs CCIP-Read Middleware

Ethers-rs CCIP-Read Middleware Ready to dive into the world of cross-chain data access? Look no further! This Rust library provides an Ethers middlewa

Ethereum Name Service (ENS) 14 May 28, 2023
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Dister builds and bundles your wasm web app.

dister Dister builds and bundles your wasm web app. Installation cargo install dister Requirements wasm32-unknown-unknown target: rustup target add wa

Mohammed Alyousef 1 Apr 9, 2022
Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844blobs.

stress4844 Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844 blobs. ca

Paradigm 50 Jan 4, 2023
Kinda functional block engine for testing bundles on jito-solana locally

Half Baked Block Engine About This is a half-baked block engine. It can be used for testing bundles running through jito-solana. Shortcomings The bare

null 8 Nov 16, 2022
Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer

Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844blobs.

Paradigm 50 Jan 4, 2023
Using flashbots to mint Otherside metaverse land safely with purchased KYC'd wallets.

Work in progress. Hardcoded to mint 2 lands for 610 APE and approves 100k ape for spending atm, will be updated. Building Install rust, https://rustup

cc 6 May 5, 2022
A Rust client for Flashbots Relay.

flashbots-relay-rs Rust client for interacting directly with the Flashbots Relays. How does it work ? Using a client from the reqwest crate, you can u

Luca G.F. 16 Jun 22, 2022
Rust client library for Flashbots MEV-Share

Flashbots MEV-Share Client   Rust client library for Flashbots MEV-Share. Based on the MEV-Share specs and the TypeScript reference implementation. Us

null 4 Aug 22, 2023
Utils for flashbots/mempool-dumpster

Intro This is a helper library and cli tool to work with https://github.com/flashbots/mempool-dumpster/, provider of historical mempool data for Ether

Vitaly Drogan 30 Oct 10, 2023
Structopt derived ethers-rs types, useful for building Ethereum CLIs

ethers-structopt Provides ethers-compatible Structopt derives, useful for building Ethereum CLIs. Contributing Pull requests are welcome. For major ch

Georgios Konstantopoulos 6 Dec 27, 2022
Ethernaut solutions with ethers-rs

the full repository is using Ethers-rs for the finding of CTF unless requirement of smart contract like in case of re-entrancy. best way get good at e

Advock 4 Dec 30, 2022
ethers-rs signer using GCP KMS

ethers-gcp-kms-signer Installation Cargo cargo add ethers-gcp-kms-signer Usage Signer use ethers::prelude::*; use ethers_gcp_kms_signer::{GcpKeyRingRe

null 12 Apr 16, 2023
An MEV back-running template for ethers-rs

MEV price prediction I show how to predict ChainLink price updates from the mempool. For the sake of illustration I work with AAVE V2 price oracles. E

Andrea Simeoni 54 Apr 19, 2023
An extensible and practical demonstration of constructing evm-based sandwich attacks built with ethers-rs and Huff language.

subway-rs • Construct evm-based sandwich attacks using Rust and Huff. Getting Started subway-rs is a port of libevm's original subway, implemented wit

refcell.eth 230 Apr 25, 2023
An open source, high performance limit order book for the Seaport smart contracts. Implemented in Rust using ethers-rs, this offers a turnkey option for digital asset marketplaces.

Quay Quay is an open source, high performance backend for the Seaport smart contracts. The project is implemented in Rust, using Postgres as a storage

Valorem Labs Inc. 169 Jun 23, 2023
ethers-rs scripting boilerplate

ethers-rs script boilerplate ethers-rs is a great blockchain scripting framework! This repo contains the essentials I find are useful when reading/wri

null 38 Sep 5, 2023
Key derivation and cryptographic signing functionality for Ethereum applications (ethers-rs)

ethers-signer-factory ethers-signer-factory is a Rust crate that provides functions for key derivation and signing of Ethereum transactions and messag

Ilia 3 Sep 27, 2023
Wrapper around reqwest to allow for client middleware chains.

reqwest-middleware A crate implementing a wrapper around reqwest to allow for client middleware chains. Overview The reqwest-middleware client exposes

TrueLayer 113 Dec 7, 2022
A cookie manager middleware built on top of tower.

tower-cookies A cookie manager middleware built on top of tower. Example With axum: use axum::{handler::get, Router}; use std::net::SocketAddr; use to

Imbolc 47 Dec 9, 2022