Skip to main content

Documentation Index

Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt

Use this file to discover all available pages before exploring further.

MEV transaction bundles are atomic collections of transactions submitted to block builders via relays like Flashbots. All transactions in a bundle execute sequentially in the same block, or the entire bundle is discarded.

Overview

Bundle provides type-safe construction and manipulation of MEV bundles for strategies like arbitrage, liquidations, and backrunning. Bundles guarantee atomic execution - either all transactions succeed in order, or none are included.
type BundleType = {
  // Ordered array of signed transaction bytes
  readonly transactions: readonly Uint8Array[];

  // Target block number (optional)
  readonly blockNumber?: BlockNumberType;

  // Minimum block timestamp (optional)
  readonly minTimestamp?: Uint256Type;

  // Maximum block timestamp (optional)
  readonly maxTimestamp?: Uint256Type;

  // Transaction hashes allowed to revert (optional)
  readonly revertingTxHashes?: readonly HashType[];
};

Quick Start

import * as Bundle from '@tevm/voltaire/Bundle';

// Create from signed transactions
const bundle = Bundle.from({
  transactions: [signedTx1, signedTx2],
  blockNumber: 18500000n,
});

// From hex strings
const bundleFromHex = Bundle.from({
  transactions: [
    "0x02f8...", // EIP-1559 tx
    "0x02f8...", // Another tx
  ],
  blockNumber: 18500000n,
});

API Reference

Constructors

MethodDescription
Bundle.from(value)Create bundle from transactions and options

Methods

MethodDescription
addTransaction(bundle, tx)Add a transaction to the bundle (immutable)
size(bundle)Get number of transactions in bundle
toHash(bundle, { keccak256 })Compute bundle hash
toFlashbotsParams(bundle)Convert to Flashbots RPC format

Bundle Options

PropertyTypeDescription
transactions(Uint8Array | string)[]Signed transactions in execution order
blockNumberbigintTarget block for inclusion
minTimestampbigintEarliest valid block timestamp
maxTimestampbigintLatest valid block timestamp
revertingTxHashesHash[]Tx hashes allowed to revert

Practical Examples

Sandwich Attack Bundle

import * as Bundle from '@tevm/voltaire/Bundle';

// Sandwich structure: frontrun -> victim -> backrun
const sandwichBundle = Bundle.from({
  transactions: [
    frontrunTx,  // Buy before victim
    victimTx,    // Target transaction
    backrunTx,   // Sell after victim
  ],
  blockNumber: targetBlock,
});

const params = Bundle.toFlashbotsParams(sandwichBundle);

Arbitrage with Revert Protection

import * as Bundle from '@tevm/voltaire/Bundle';
import { keccak256 } from '@tevm/voltaire/Keccak256';

// Allow first tx to revert (price check might fail)
const arbBundle = Bundle.from({
  transactions: [
    priceCheckTx,  // May revert if arb opportunity gone
    swapTx1,       // DEX A -> DEX B
    swapTx2,       // DEX B -> DEX A
  ],
  blockNumber: 18500000n,
  revertingTxHashes: [
    "0x..." + keccak256(priceCheckTx), // Allow this to revert
  ],
});

Time-Bounded Bundle

import * as Bundle from '@tevm/voltaire/Bundle';

// Bundle valid only within 12-second window
const timedBundle = Bundle.from({
  transactions: [tx1, tx2],
  blockNumber: 18500000n,
  minTimestamp: 1700000000n,
  maxTimestamp: 1700000012n, // 12 second window
});

Computing Bundle Hash

import * as Bundle from '@tevm/voltaire/Bundle';
import { keccak256 } from '@tevm/voltaire/Keccak256';

const bundle = Bundle.from({
  transactions: [tx1, tx2, tx3],
});

// Bundle hash is keccak256(concat(tx1Hash, tx2Hash, tx3Hash))
const bundleHash = Bundle.toHash(bundle, { keccak256 });
console.log("Bundle hash:", bundleHash);

Building Bundle Incrementally

import * as Bundle from '@tevm/voltaire/Bundle';

// Start with base transaction
let bundle = Bundle.from({
  transactions: [baseTx],
  blockNumber: 18500000n,
});

// Add transactions based on conditions
if (needsFrontrun) {
  bundle = Bundle.addTransaction(bundle, frontrunTx);
}

bundle = Bundle.addTransaction(bundle, mainTx);

if (needsBackrun) {
  bundle = Bundle.addTransaction(bundle, backrunTx);
}

console.log(`Bundle contains ${Bundle.size(bundle)} transactions`);

Error Handling

Bundle provides typed errors that extend the Voltaire error hierarchy:
import * as Bundle from '@tevm/voltaire/Bundle';
import {
  InvalidBundleError,
  MissingCryptoDependencyError
} from '@tevm/voltaire/Bundle';

try {
  // Empty bundle throws
  Bundle.from({ transactions: [] });
} catch (e) {
  if (e instanceof InvalidBundleError) {
    console.log(e.name);     // "InvalidBundleError"
    console.log(e.code);     // "INVALID_BUNDLE"
    console.log(e.message);  // "Bundle must contain at least one transaction"
    console.log(e.value);    // The invalid value
    console.log(e.expected); // What was expected
  }
}

try {
  // Invalid transaction format
  Bundle.from({
    transactions: [123], // Not Uint8Array or string
  });
} catch (e) {
  if (e instanceof InvalidBundleError) {
    console.log(e.name);    // "InvalidBundleError"
    console.log(e.message); // "Transaction must be Uint8Array or hex string"
  }
}

try {
  // Missing crypto dependency
  Bundle.toHash(bundle, {}); // Missing keccak256
} catch (e) {
  if (e instanceof MissingCryptoDependencyError) {
    console.log(e.name);     // "MissingCryptoDependencyError"
    console.log(e.code);     // "MISSING_CRYPTO_DEPENDENCY"
    console.log(e.message);  // "keccak256 not provided"
    console.log(e.expected); // "{ keccak256: (data: Uint8Array) => Uint8Array }"
  }
}

Error Types

ErrorExtendsWhen Thrown
InvalidBundleErrorValidationErrorInvalid bundle format or transaction data
MissingCryptoDependencyErrorValidationErrorRequired crypto function not provided

Flashbots RPC Format

The toFlashbotsParams method converts bundles to the format expected by Flashbots relays:
// Input bundle
const bundle = Bundle.from({
  transactions: [tx1, tx2],
  blockNumber: 18500000n,
  minTimestamp: 1700000000n,
  maxTimestamp: 1700000012n,
  revertingTxHashes: [hash1],
});

// Output format
const params = Bundle.toFlashbotsParams(bundle);
// {
//   txs: ["0x02f8...", "0x02f8..."],
//   blockNumber: "0x11a5b20",
//   minTimestamp: 1700000000,
//   maxTimestamp: 1700000012,
//   revertingTxHashes: ["0x..."]
// }

Transaction

Transaction encoding and signing

Keccak256

Required for bundle hashing

Hash

32-byte hash type for tx hashes

Flashbots Docs

Flashbots Auction documentation