Skip to content

Instantly share code, notes, and snippets.

@merlox
Created November 6, 2022 16:07
Show Gist options
  • Save merlox/c425bf236738b40f0d390644e8167456 to your computer and use it in GitHub Desktop.
Save merlox/c425bf236738b40f0d390644e8167456 to your computer and use it in GitHub Desktop.
// 1. Import everything
import { Wallet, BigNumber, ethers, providers } from 'ethers'
const { FlashbotsBundleProvider, FlashbotsBundleResolution } = require('@flashbots/ethers-provider-bundle')
/*
Mainnet
const provider = new providers.JsonRpcProvider('https://eth-mainnet.g.alchemy.com/v2/cmHEQqWnoliAP0lgTieeUtwHi0KxEOlh')
const wsProvider = new providers.WebSocketProvider('wss://eth-mainnet.g.alchemy.com/v2/cmHEQqWnoliAP0lgTieeUtwHi0KxEOlh')
*/
// 2. Setup a standard provider in goerli
const provider = new providers.JsonRpcProvider(
'https://eth-goerli.g.alchemy.com/v2/wOB3tqbHfs_RGAeFJqomylXrUOH_MrVT'
)
const wsProvider = new providers.WebSocketProvider(
'wss://eth-goerli.g.alchemy.com/v2/wOB3tqbHfs_RGAeFJqomylXrUOH_MrVT'
)
// 3. The unique ID for flashbots to identify you and build trust over time
const authSigner = new Wallet(
'0x83565a9dafb10577ed43b2a0b911656e18fbc25cf35f211db891f23815ff7c45',
provider
)
// The address of the authSigner is 0x09Dad4e56b1B2A7eeD9C41691EbDD4EdF0D80a46
const start = async () => {
// 4. Create the flashbots provider
const flashbotsProvider = await FlashbotsBundleProvider.create(
provider,
authSigner,
'https://relay-goerli.flashbots.net',
)
const GWEI = BigNumber.from(10).pow(9)
const LEGACY_GAS_PRICE = GWEI.mul(13)
const PRIORITY_FEE = GWEI.mul(100)
const blockNumber = await provider.getBlockNumber()
const block = await provider.getBlock(blockNumber)
const maxBaseFeeInFutureBlock =
FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, 6) // 100 blocks in the future
console.log('maxBaseFeeInFutureBlock', String(maxBaseFeeInFutureBlock), String(maxBaseFeeInFutureBlock.div('100000000000000000')))
const amountInEther = '0.001'
// 5. Setup the transactions to send and sign
const signedTransactions = await flashbotsProvider.signBundle([
{ // Both transactions are the same but one is type 1 and the other type 2 after the gas changes
signer: authSigner,
transaction: {
to: '0x2c3fF32c7F6C7f83fFd13C76Cfef67C0E9811240',
type: 2,
maxFeePerGas: PRIORITY_FEE.add(maxBaseFeeInFutureBlock),
maxPriorityFeePerGas: PRIORITY_FEE,
data: '0x',
chainId: 5,
value: ethers.utils.parseEther(amountInEther),
// gasLimit: 300000,
},
},
// we need this second tx because flashbots only accept bundles that use at least 42000 gas.
{
signer: authSigner,
transaction: {
to: '0x2c3fF32c7F6C7f83fFd13C76Cfef67C0E9811240',
gasPrice: LEGACY_GAS_PRICE,
data: '0x',
value: ethers.utils.parseEther(amountInEther),
// gasLimit: 300000,
},
},
])
// 6. We run a simulation for the next block number with the signed transactions
console.log(new Date())
console.log('Starting to run the simulation...')
const simulation = await flashbotsProvider.simulate(
signedTransactions,
blockNumber + 1,
)
console.log(new Date())
// 7. Check the result of the simulation
if (simulation.firstRevert) {
console.log(`Simulation Error: ${simulation.firstRevert.error}`)
} else {
console.log(
`Simulation Success: ${blockNumber}}`
)
}
// 8. Send 10 bundles to get this working for the next blocks in case flashbots doesn't become the block producer
for (var i = 1; i <= 10; i++) {
const bundleSubmission = await flashbotsProvider.sendRawBundle(
signedTransactions,
blockNumber + i
)
console.log('bundle submitted, waiting', bundleSubmission.bundleHash)
const waitResponse = await bundleSubmission.wait()
console.log(`Wait Response: ${FlashbotsBundleResolution[waitResponse]}`)
if (
waitResponse === FlashbotsBundleResolution.BundleIncluded ||
waitResponse === FlashbotsBundleResolution.AccountNonceTooHigh
) {
console.log('Bundle included!')
process.exit(0)
} else {
console.log({
bundleStats: await flashbotsProvider.getBundleStats(
simulation.bundleHash,
blockNumber + 1,
),
userStats: await flashbotsProvider.getUserStats(),
})
}
}
console.log('bundles submitted')
}
start()
@SrinivasJoshi
Copy link

@haroonabbhas you should know javascript and solidity as programming languages. Also you should know what happens behind the scenes when a transaction is submitted.

@Psykepro
Copy link

Psykepro commented Feb 4, 2024

Guys I don't understand why I get the following error when trying to send the bundled txs:

var error = new Error(message);
                    ^

Error: bad response (status=400, headers={"date":"Sun, 04 Feb 2024 17:42:51 GMT","content-type":"application/json","content-length":"32","connection":"keep-alive","x-amzn-requestid":"d22c4e95-340c-400c-aa84-fdd4d9f12fba","x-amz-apigw-id":"SnzoRFH1iYcEGqw=","vary":"Origin","x-amzn-trace-id":"Root=1-65bfcc9b-0478538370ab13ec3ad74318;Sampled=0;lineage=3d257173:0"}, body="{\"error\":\"unable to decode txs\"}", requestBody="{\"method\":\"eth_callBundle\",\"params\":[{\"txs\":[\"0x02f873050285174876e80085174876e81982520894aaa9f42beeb20291b1d2729a61bddc271ed45ea387038d7ea4c6800080c080a0010eb5f694c3047e304c9e6362ff5cf365462c473e9c7e38225b86913cb94d67a055a1764412b709cd7eb5792109e53620d3d6729c84ed08b2e7542bfc95c4e662\",\"0xf86b03850306dc420082520894aaa9f42beeb20291b1d2729a61bddc271ed45ea387038d7ea4c68000801ca0c1c9d56354e4218436df12dad81a681d1b95c3b8cad2f46f0c2a64a9b9a1a17da03d75ad4a7358174f531d27e929fdaf03da18ad4d14e3d1c2f5e68b9c87a49dbd\"],\"blockNumber\":\"0x9ffc53\",\"stateBlockNumber\":\"latest\"}],\"id\":42,\"jsonrpc\":\"2.0\"}", requestMethod="POST", url="https://relay-goerli.flashbots.net/", code=SERVER_ERROR, version=web/5.7.1)
    at Logger.makeError (F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\logger\lib\index.js:238:21)
    at Logger.throwError (F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\logger\lib\index.js:247:20)
    at F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\web\lib\index.js:275:36
    at step (F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\web\lib\index.js:33:23)
    at Object.next (F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\web\lib\index.js:14:53)
    at fulfilled (F:\Programming\Blockchain\MEV\mev-mastery\node_modules\@ethersproject\web\lib\index.js:5:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  reason: 'bad response',
  code: 'SERVER_ERROR',
  status: 400,
  headers: {
    date: 'Sun, 04 Feb 2024 17:42:51 GMT',
    'content-type': 'application/json',
    'content-length': '32',
    connection: 'keep-alive',
    'x-amzn-requestid': 'd22c4e95-340c-400c-aa84-fdd4d9f12fba',
    'x-amz-apigw-id': 'SnzoRFH1iYcEGqw=',
    vary: 'Origin',
    'x-amzn-trace-id': 'Root=1-65bfcc9b-0478538370ab13ec3ad74318;Sampled=0;lineage=3d257173:0'
  },
  body: '{"error":"unable to decode txs"}',
  requestBody: '{"method":"eth_callBundle","params":[{"txs":["0x02f873050285174876e80085174876e81982520894aaa9f42beeb20291b1d2729a61bddc271ed45ea387038d7ea4c6800080c080a0010eb5f694c3047e304c9e6362ff5cf365462c473e9c7e38225b86913cb94d67a055a1764412b709cd7eb5792109e53620d3d6729c84ed08b2e7542bfc95c4e662","0xf86b03850306dc420082520894aaa9f42beeb20291b1d2729a61bddc271ed45ea387038d7ea4c68000801ca0c1c9d56354e4218436df12dad81a681d1b95c3b8cad2f46f0c2a64a9b9a1a17da03d75ad4a7358174f531d27e929fdaf03da18ad4d14e3d1c2f5e68b9c87a49dbd"],"blockNumber":"0x9ffc53","stateBlockNumber":"latest"}],"id":42,"jsonrpc":"2.0"}',
  requestMethod: 'POST',
  url: 'https://relay-goerli.flashbots.net/'
}

Please help fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment