Call bid
, placing a bet by setting value
, and send the highest bid (which may be in addition to others' bids in the block) before calling claim
. The winner (the person who called bid with the highest value
this round), upon calling claim
gets the entire balance of the contract, at which point highest_bid
(also the minimum to land a new bid) resets (to 1 gwei). claim
will also only pay out if you placed the most recent bid.
mev-flood is a multi-daemon project, and is designed to be run in parallel with other instances, each using the same source code but different params.
- 100 test accounts to send from (excluding accounts set in .env)
claim
does not revert when called by a non-winner (on purpose, to add technical complexity to the game)
- dumb-search: blindly sends bid (constant
value
) & claim txs on every block- helpful for stress-testing on testnet (don't run on mainnet!)
- mostly fails and wastes money on bids (for others to take)
- sends to FB builder, may also send to mempool (pending how/what we want to test)
- smart-search: finds winning bid amount and uses a smart contract that atomically executes bid+claim to win the pool
- helpful for stress-testing on testnet (don't run on mainnet!)
- if only one instance is run, it's practically guaranteed to win every round
- if more than one instance is run, they will generate "conflicting" bundles
- technically all the bundles will land but their profits will be affected by who gets included first
- fake-search sends a uniswap v2 swap that will always revert
- helpful for early testing (not stress-testing)
- mainnet-friendly (use an empty account for
ADMIN_PRIVATE_KEY
) - this sends a single-transaction bundle to Flashbots from the admin wallet (env:
ADMIN_PRIVATE_KEY
)
- swapd generates a random swap for each wallet in the specified array, for every new block
- createWallets: creates new
wallets.json
file populated w/ 100 wallets - fundWallets: send 0.1 ETH to each wallet in
wallets.json
from admin wallet (ADMIN_PRIVATE_KEY
) - sendPrivateTx: send a private transaction to the bundle API
- cancelPrivateTx: cancel a private transaction sent to the bundle API given
txHash
- getBundleStats: get bundle stats for a given
bundleHash
- getUserStats: get user stats for admin wallet (
ADMIN_PRIVATE_KEY
) - sendProtectTx: send a tx to Protect RPC
- createTestBundle: prints a test bundle without sending or signing it (txs are signed)
- liquid: bootstrap a complete uniswap v2 environment
Scripts with optional params are explained with the help
flag:
yarn script.sendProtectTx --help
yarn script.sendPrivateTx --help
yarn script.cancelPrivateTx --help
yarn install
# pick your poison:
cp .env.example .env.goerli
cp .env.example .env.sepolia
cp .env.example .env.mainnet
vim .env.goerli
vim .env.sepolia
vim .env.mainnet
Set preferred environment:
export NODE_ENV=sepolia
Generate test accounts:
mkdir src/output
yarn script.createWallets
Fund test accounts (careful, it sends 0.1 ETH to 100 accounts):
yarn script.fundWallets
Run dumb-search simulator with 5 accounts (careful, it currently sends without checking for profit):
yarn dumb-dev 0 5
Note: 5 is the exclusive end index, meaning that arguments (0 5
) will use wallets[0, 1, 2, 3, 4]
.
Run smart-search simulator.
yarn smart-dev
Run fake-search simulator.
yarn fake-dev
Daemons that have params/options include the help
flag:
yarn dumb-dev --help
yarn smart-dev --help
yarn build
yarn dumb-search $i $j
yarn smart-search $i $j
yarn fake-search
You might need to use the mempool to test your transactions' validity before trying to use the bundle API.
yarn dumb-dev 13 14 mempool
yarn smart-dev 13 14 mempool
Run 49 dumb searchers and 2 smart searchers (a relatively realistic case):
# terminal 1 (49 test wallets)
yarn dumb-dev 0 49
# terminal 2 (49 test wallets)
yarn dumb-dev 49 98
# terminal 3 (2 test wallets)
yarn smart-dev 98 100
# if you haven't already, deploy univ2 environment
yarn script.liquid
# if you haven't already, fund your wallets
yarn script.fundWallets
# generate orderflow w/ 10 wallets
yarn swapd 10 20
Note: if you didn't run yarn build
you can run yarn swapd-dev
instead of yarn swapd
.
Get bundle stats:
yarn script.getBundleStats 0x40d83aebb63f61730eb6309e1a806624cf6d52ff666d1b13d5ced535397f9a46 0x7088e9
# alternatively you can use int block number
yarn script.getBundleStats 0x40d83aebb63f61730eb6309e1a806624cf6d52ff666d1b13d5ced535397f9a46 7375081
Send private tx:
# send a lottery tx
yarn script.sendPrivateTx
# send a reverting univ2 swap
yarn script.sendPrivateTx dummy
Cancel private tx:
yarn script.cancelPrivateTx 0xca79f3114de50a77e42dd595c0ba4e786d3ddf782c62075ec067fe32329e3ea2
Print a test bundle (sends ETH from test wallet to itself):
yarn script.createTestBundle
Send tx to Protect:
yarn script.sendProtectTx
# send uniswapV2 router tx to Protect (works on any chain)
yarn script.sendProtectTx dummy
# send lottery contract tx to Protect with fast mode
yarn script.sendProtectTx fast
# send uniswapV2 router tx to Protect w/ fast mode
yarn script.sendProtectTx fast dummy
# or
yarn script.sendProtectTx dummy fast
Bootstrap a uniswap V2 environment:
yarn script.liquid
In addition to deploying the contracts to the environment specified by NODE_ENV, this script will create a file at src/output/uniBootstrap.json
containing all the details of the deployment, including pre-calculated contract addresses and a list of all signed transactions.