Flashbots can move tokens from a compromised wallet to a safe address in one block if an ordered bundle containing the funding and transfer lands. Flashbots sends the pair privately to a builder, hiding the gas deposit from a public-mempool sweeper. The Flashbots Auction bundle executes both transactions together or misses its target block and needs resubmission.
When Does a Flashbots Bundle Keep Gas Out of Reach?
An ordered private bundle protects the funding transaction when a builder includes the whole pair. If you send the safe wallet’s ETH deposit publicly, a sweeper can see it in the mempool and sign a competing spend before your transfer. In the bundle, the builder executes the deposit first. That raises the compromised account’s balance during block execution, and the next transaction uses that balance to call the token contract. Bundle transactions stay adjacent even if the builder places them halfway through a block, so no unrelated transaction can run between them. Unless you explicitly allow a revert, a reverting transfer makes the whole bundle ineligible, leaving the deposit out too.
This removes the funding window visible to a sweeper watching public transactions. It does not give you exclusive control of a stolen key: a competing private transaction or an already pending transaction can still win inclusion first. Inclusion also depends on the builder and the block the validator chooses.
How Much ETH Should the Safe Wallet Send?
Fund the compromised account for its ERC-20 transfer gas. Build the call as transfer(safeAddress, amount) against the correct token contract on the correct chain. Set a gas limit that covers that contract call and an EIP-1559 maxFeePerGas high enough for the target block’s base fee plus a priority fee. If the compromised account starts with no ETH, the deposit must cover gasLimit times maxFeePerGas. Any ETH left after execution can be swept, so keep the deposit close to that requirement.
The safe wallet pays gas for its own funding transaction as well. A priority fee on the included transactions is the simplest builder incentive. Flashbots Protect RPC handles single private transactions; it does not supply this ordered two-transaction rescue. A direct payment to block.coinbase inside the bundle is another way to pay the validator, but it requires another signed action and enough ETH. A bare token transfer cannot make that payment. Judge the bid using the simulation’s gas use and coinbase payment, not the size of the deposit.
What Must Be Signed Before Submission?
Sign two raw Ethereum transactions in order: the safe wallet’s ETH funding transaction, then the compromised wallet’s token transfer. Read each account’s next on-chain nonce through a normal Ethereum RPC. Sign the funding transaction with the safe wallet’s next nonce and the transfer with the compromised account’s next nonce, directing the remaining movable tokens to an address you control.
A sweeper’s pending transaction can make a provider’s pending nonce misleading. If the on-chain nonce is 7 and a hostile transaction at 7 is pending, signing your transfer at 8 creates a nonce gap that invalidates the bundle. Use 7 to compete for that nonce, then reassess after each block. Check the chain ID, token address, amount, and destination before signing; valid signatures cannot correct a transfer to the wrong place.
Use a separate, fresh key to authenticate the relay request. The X-Flashbots-Signature header carries that key’s address and an EIP-191 signature of the JSON-RPC body’s hash. The key establishes searcher reputation; it signs neither on-chain transaction and needs no funds. Keep the compromised key out of this header.
How Do You Simulate, Submit, and Confirm Each Target Block?
Simulate the signed pair before submission. Send eth_callBundle with both raw signed transactions in txs order, a hex blockNumber for the next block, and stateBlockNumber set to latest. Read the per-transaction results: a revert reason, nonce error, or insufficient funds identifies an assumption to fix. Leave revertingTxHashes unset; allowing the token transfer to revert would defeat the rescue. Once simulation succeeds, send eth_sendBundle with the same txs array and that block’s hex blockNumber. A returned bundleHash acknowledges submission, not inclusion.
Each eth_sendBundle request targets one block. Submit separately for each of the next several blocks. If one misses, resimulate against current state and sign again when a nonce or fee cap needs to change. Keep both transactions out of the public mempool. Use a normal Ethereum RPC to watch their receipts and the safe address’s token balance. A successful transaction status alone may not prove delivery if a token call returns false; the rescue is complete when the transfer is on-chain and the safe address holds the tokens.
The useful distinction is between a private bundle that removes the visible gas window and an included transfer that actually delivers the tokens.
