From cf1506d2e4434b7dce3e637037cc812920fa5641 Mon Sep 17 00:00:00 2001 From: Prithviraj8 Date: Wed, 7 Sep 2022 15:39:05 +0530 Subject: [PATCH] add flashbots file --- components/flashbots.py | 105 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 components/flashbots.py diff --git a/components/flashbots.py b/components/flashbots.py new file mode 100644 index 0000000..5078bd4 --- /dev/null +++ b/components/flashbots.py @@ -0,0 +1,105 @@ +from eth_account.signers.local import LocalAccount +from web3.middleware import construct_sign_and_send_raw_middleware + +from flashbots import flashbot +from flashbots.types import SignTx +from eth_account.account import Account +from web3 import Web3, HTTPProvider +from web3.types import TxParams, Wei + +import os + +""" +In this example we setup a transaction for 0.1 eth with a gasprice of 1 +From here we will use Flashbots to pass a bundle with the needed content +""" + +# 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")) +ETH_ACCOUNT_FROM: LocalAccount = Account.from_key(os.environ.get("ETH_PRIVATE_FROM")) +ETH_ACCOUNT_TO: LocalAccount = Account.from_key(os.environ.get("ETH_PRIVATE_TO")) + +print("Connecting to RPC") + +# Create a web3 object with a standard json rpc provider, such as Infura, Alchemy, or your own node. +w3 = Web3(HTTPProvider("http://localhost:8545")) +w3.middleware_onion.add(construct_sign_and_send_raw_middleware(ETH_ACCOUNT_FROM)) + +# Flashbots providers require both a standard provider and ETH_ACCOUNT_SIGNATURE (to establish reputation) +flashbot(w3, ETH_ACCOUNT_SIGNATURE) + +print(f"From account {ETH_ACCOUNT_FROM.address}: {w3.eth.get_balance(ETH_ACCOUNT_FROM.address)}") +print(f"To account {ETH_ACCOUNT_TO.address}: {w3.eth.get_balance(ETH_ACCOUNT_TO.address)}") + +# Setting up an transaction with 1 in gasPrice where we are trying to send +print("Sending request") +params: TxParams = { + "from": ETH_ACCOUNT_FROM.address, + "to": ETH_ACCOUNT_TO.address, + "value": w3.toWei("1.0", "gwei"), + "gasPrice": w3.toWei("1.0", "gwei"), + "nonce": w3.eth.get_transaction_count(ETH_ACCOUNT_FROM.address), +} + +try: + tx = w3.eth.send_transaction( + params, + ) + print("Request sent! Waiting for receipt") +except ValueError as e: + # Skipping if TX already is added and pending + if "replacement transaction underpriced" in e.args[0]["message"]: + print("Have TX in pool we can use for the example") + else: + raise + + +print("Setting up flashbots request") +nonce = w3.eth.get_transaction_count(ETH_ACCOUNT_FROM.address) +bribe = w3.toWei("0.01", "ether") + +signed_tx: SignTx = { + "to": ETH_ACCOUNT_TO.address, + "value": bribe, + "nonce": nonce + 1, + "gasPrice": 0, + "gas": 25000, +} + +signed_transaction = ETH_ACCOUNT_TO.sign_transaction(signed_tx) + +bundle = [ + # some transaction + { + "signer": ETH_ACCOUNT_FROM, + "transaction": { + "to": ETH_ACCOUNT_TO.address, + "value": Wei(123), + "nonce": nonce, + "gasPrice": 0, + }, + }, + # the bribe + { + "signed_transaction": signed_transaction.rawTransaction, + }, +] + +block = w3.eth.block_number + +result = w3.flashbots.send_bundle(bundle, target_block_number=w3.eth.blockNumber + 3) +result.wait() +receipts = result.receipts() +block_number = receipts[0].blockNumber + +# the miner has received the amount expected +bal_before = w3.eth.get_balance(ETH_ACCOUNT_FROM.address, block_number - 1) +bal_after = w3.eth.get_balance(ETH_ACCOUNT_FROM.address, block_number) +profit = bal_after - bal_before - w3.toWei("2", "ether") # sub block reward +print("Balance before", bal_before) +print("Balance after", bal_after) +assert profit == bribe + +# the tx is successful +print(w3.eth.get_balance(ETH_ACCOUNT_TO.address))