flashbots / ethers-provider-flashbots-bundle

Flashbots provider for ethers.js
543 stars 212 forks source link

Error: bad response #107

Closed alexisdavidson closed 9 months ago

alexisdavidson commented 11 months ago

When trying to interact with a smart contract and do a sendPrivateTransaction() on ethereum mainnet, I get the error below:

Error: bad response (status=400, headers={"date":"Wed, 04 Oct 2023 17:34:08 GMT","content-type":"application/json","content-length":"29","connection":"close","x-amzn-requestid":"c96167df-a3fa-4186-89a709d7e2e","x-amz-apigw-id":"MSZiYcFfEw=","vary":"Origin","x-amzn-trace-id":"Root=1-6a210-46af8f6c40db38e426a04;Sampled=0;lineage=17d26d3c:0"}, body="{\"error\":\"incorrect request\"}", requestBody="{\"method\":\"eth_sendPrivateTransaction\",\"params\":[{\"tx\":\"0xf901a5071da6bf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bad5227ba8cae1c10a8e16f1c6920ae89ac5054df695d8cdce7c1c67e81c7612f95db155de0bd8bbe482046fa74f9f432b6c212622b4d73a6a562a8bc7225e0c3c63c7638efd28aff17c7bec9fbeb2c2e24ceb6cca75ff7a060caa0825de0b79c99654d2086bf8f67a1bb70eb753db17ae1465547e88\"}],\"id\":42,\"jsonrpc\":\"2.0\"}", requestMethod="POST", url="https://relay.flashbots.net/", code=SERVER_ERROR, version=web/5.7.1)

Here is my code

const tx = { from: wall.address, to: contractAddress, data: router.interface.encodeFunctionData('functionName', [ parameters... ]), };

    const privateTx = {
      transaction: tx,
      signer: wall,
    }
    const authSigner = ethers.Wallet.createRandom();
    const flashbotsProvider = await FlashbotsBundleProvider.create(
      provider, // a normal ethers.js provider, to perform gas estimiations and nonce lookups
      authSigner // ethers.js signer wallet, only for signing request payloads, not transactions
    )
    const txResponse = await flashbotsProvider.sendPrivateTransaction(privateTx)
pixelpawnshop commented 10 months ago

I get the very same error trying to find solution as well. Discord is sadly very inactive.

Were you able to solve this problem? @alexisdavidson

alexisdavidson commented 10 months ago

Unfortunately not yet @pixelpawnshop ☹️ This got me stuck on my project and made me work on something else

pixelpawnshop commented 9 months ago

Hey @alexisdavidson I was able to solve it. Let me know if this works for you

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

// Standard json rpc provider directly from ethers.js (NOT Flashbots)
const provider = new providers.JsonRpcProvider({ url: "https://eth-mainnet.g.alchemy.com/v2/KEY" }, 1)

const authSigner = Wallet.createRandom();
const PRIVATE_KEY = process.env.nftastic;
const signer = new Wallet(`${PRIVATE_KEY}`);

async function sendAsyncTransaction() {
  try {
    // Flashbots provider requires passing in a standard provider
    const flashbotsProvider = await FlashbotsBundleProvider.create(
      provider, // a normal ethers.js provider, to perform gas estimations and nonce lookups
      authSigner // ethers.js signer wallet, only for signing request payloads, not transactions
    );

    const pending = await provider.getTransactionCount(signer.address, "pending");

    const exampleTx = {
      to: "0x0C7172c8c5C000F39E2A11b04c52805aF29d945b",
      value: 1,
      gasLimit: "21000",
      maxFeePerGas: 50000000000,
      nonce: pending,
      type: 2,
      chainId: 1,
    };

    const rawTransaction: FlashbotsBundleRawTransaction = {
      signedTransaction: await signer.signTransaction(exampleTx),
    };

    // Log the request payload just before sending
    console.log("Request Payload:", JSON.stringify({
      rawTransaction,
      signer,
    }));

    const res = await (flashbotsProvider.sendPrivateTransaction(rawTransaction,
      {
        maxBlockNumber: (await provider.getBlockNumber() + 1)
      },
    ));

    console.log(res)

  } catch (error) {
    console.error(error);
  }
}
// Call the async function
sendAsyncTransaction();
alexisdavidson commented 9 months ago

@pixelpawnshop Thanks a lot, it looks like I was missing the chainId field in the tx!

Now the code runs without error but the tx doesn't get through. On etherscan, when searching for the tx hash provided by the result, this is shown:

"This transaction was forwarded to Flashbots Protect RPC but was not mined and has expired."

pixelpawnshop commented 9 months ago

Hey @alexisdavidson nice to hear it works for you now!

So the thing with private transaction like this is they do not get send to the public mempool thatswhy you do not find the transaction on etherscan unless its minted. In the pending state you can only use flashbots api endpoint to check the transaction. The flashbots api call looks like this:

https://protect.flashbots.net/tx/INSERT_TX_HERE

The output should look something like this

{"status":"FAILED","hash":"0xfe8eb90cb019c6aa3b8787c75c342a6ff7a37598f8155dc6bba56b882bd9f5c2","maxBlockNumber":18548051,"transaction":{"from":"","to":"","gasLimit":"","maxFeePerGas":"","maxPriorityFeePerGas":"","nonce":"","value":""},"fastMode":false,"seenInMempool":false,"simError":"MaxFeePerGasTooLow"}

There you also see why the tx failed. Could be a bunch of reason: gas loo low, wrong nonce, or something more common maybe you have set maxBlockNumber too low. In the default setting the transaction is only getting sent to flashbot builders and flashbots only provides very few blocks. Not always the same but maybe every 20 - 25 block is mined by flashbots. So when you set the max block only to 10 and the 12th block would be the one flashbots mines then the tx will fail. A workaround would be to not use default settings but to expand to all available builders so that your tx is not only included from flashbot builder but also from all the other. You can find more about speeding up the transaction in the docs from flashbots :

https://docs.flashbots.net/flashbots-protect/quick-start

When you do not depend on transaction speed then you could also just bump up the maxBlockNumber to something like currentblock + 25. With this setting you are very likely to hit a flashbots block and your transaction will be included.

Hope this helps.

alexisdavidson commented 9 months ago

@pixelpawnshop I got a transaction through! Your answer helped me a lot, seems the docs example are not that uptodate :) Thanks for the detailed help and good luck on your project!!