> ## 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.

# Bytecode.prettyPrint

> Generate annotated, human-readable disassembly with colors and metadata

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/bytecode.ts">
  Run Bytecode examples in the interactive playground
</Card>

<Tabs />

## Output Format

```
╔══════════════════════════════════════╗
║     EVM Bytecode Disassembly         ║
╚══════════════════════════════════════╝

📊 Length: 145 bytes
📍 Legend: ●=JUMPDEST  ⚡=Fusion  ✗=Invalid Jump

 #   | PC   | Stack | Hex          | Opcode    | Jump | Details
-----|------|-------|--------------|-----------|------|------------------
   1 |    0 |     0 | 60 01        | PUSH1     |      | 0x1 (1) [gas: 3]
   2 |    2 |     1 | 60 02        | PUSH1     |      | 0x2 (2) [gas: 3]
   3 |    4 |     2 | 01           | ADD       |      | [gas: 3] [stack: -2, +1]

[Block 0] gas: 9 stack: [0, 2] len: 3

   4 |    5 |     1 | ● 5b         | JUMPDEST  | ←●   | [target: PC=5] [gas: 1]
   5 |    6 |     1 | 00           | STOP      |      | [gas: 0]

╔══════════════════════════════════════╗
║            Summary                   ║
╚══════════════════════════════════════╝

📈 Basic blocks: 2
🎯 Jump destinations: 1
➡️  Unconditional jumps: 0
❓ Conditional jumps: 0
⚡ Fusion candidates: 0
📝 Total instructions: 5
```

## Options

```typescript theme={null}
interface PrettyPrintOptions {
  /** Use ANSI colors (default: true if terminal supports) */
  colors?: boolean

  /** Show gas costs inline (default: true) */
  showGas?: boolean

  /** Show stack depth column (default: true) */
  showStack?: boolean

  /** Show block boundaries and metadata (default: true) */
  showBlocks?: boolean

  /** Show jump arrows and targets (default: true) */
  showJumpArrows?: boolean

  /** Show fusion annotations (default: true) */
  showFusions?: boolean

  /** Show line numbers (default: true) */
  lineNumbers?: boolean

  /** Include summary footer (default: true) */
  showSummary?: boolean

  /** Maximum width for output (default: 120) */
  maxWidth?: number

  /** Compact mode (fewer columns) (default: false) */
  compact?: boolean
}
```

## Usage Patterns

### Basic Disassembly

```typescript theme={null}
const code = Bytecode("0x60016002015b00");

// Simple output (no colors, no annotations)
console.log(code.prettyPrint({
  colors: false,
  showGas: false,
  showStack: false,
  showBlocks: false
}));

// Full output (all annotations)
console.log(code.prettyPrint());
```

### Gas-Focused View

```typescript theme={null}
const output = code.prettyPrint({
  showGas: true,
  showStack: false,
  showJumpArrows: false,
  showFusions: false
});

// Highlights gas costs for optimization analysis
```

### Stack-Focused View

```typescript theme={null}
const output = code.prettyPrint({
  showStack: true,
  showGas: false,
  showBlocks: true
});

// Shows stack depth evolution for validation
```

### Compact Mode

```typescript theme={null}
const output = code.prettyPrint({
  compact: true,
  maxWidth: 80
});

// Fits in narrow terminals (80 columns)
```

### Save to File

```typescript theme={null}
import { writeFileSync } from 'fs';

const disassembly = code.prettyPrint({ colors: false });
writeFileSync('bytecode.asm', disassembly);
```

<Note>
  Disable colors when saving to file to avoid ANSI escape sequences in text files.
</Note>

## Color Coding

Instructions are color-coded by category:

| Category         | Color          | Opcodes                          |
| ---------------- | -------------- | -------------------------------- |
| **PUSH**         | Blue           | PUSH0-PUSH32                     |
| **Arithmetic**   | Cyan           | ADD, SUB, MUL, DIV, MOD, EXP     |
| **Comparison**   | Magenta        | LT, GT, EQ, ISZERO               |
| **Bitwise**      | Bright Cyan    | AND, OR, XOR, NOT, SHL, SHR      |
| **Memory**       | Bright Blue    | MLOAD, MSTORE, MSTORE8           |
| **Storage**      | Bright Magenta | SLOAD, SSTORE, TLOAD, TSTORE     |
| **Stack**        | Green          | DUP1-16, SWAP1-16, POP           |
| **Jump (JUMP)**  | Yellow         | JUMP                             |
| **Jump (JUMPI)** | Gold           | JUMPI                            |
| **JUMPDEST**     | Green BG       | JUMPDEST (green background)      |
| **Flow Control** | Red            | STOP, RETURN, REVERT, INVALID    |
| **System**       | Bright Yellow  | CALL, CREATE, SELFDESTRUCT, etc. |

<Tip>
  Color scheme optimized for dark terminals. Colors automatically disabled if stdout is not a TTY.
</Tip>

## Block Visualization

Basic blocks shown with metadata header:

```
[Block 0] gas: 21 stack: [0, 3] len: 7
   1 |    0 |     0 | 60 01        | PUSH1     |      | ...
   2 |    2 |     1 | 60 02        | PUSH1     |      | ...
   ...

[Block 1] gas: 156 stack: [1, 5] len: 12
 ● Begin
   8 |   23 |     1 | ● 5b         | JUMPDEST  | ←●   | ...
   ...
```

**Block Header Format:**

* `gas: N` - Total gas for block (sequential execution)
* `stack: [min, max]` - Min required, max reached
* `len: N` - Instruction count

**Block Markers:**

* `● Begin` - Marks JUMPDEST blocks (entry points)
* Blank line separates blocks visually

## Jump Visualization

Jump instructions show arrows connecting to targets:

```
  12 |   45 |     2 | 60 32        | PUSH1     | ┐→50 | 0x32 (50)
  13 |   47 |     3 | 56           | JUMP      |     | [unconditional jump]
  ...
  15 |   50 |     2 | ● 5b         | JUMPDEST  | ←●  | [target: PC=50]
```

**Jump Symbols:**

* `┐→N` - Forward jump (down in code) to PC N
* `┘→N` - Backward jump (up in code) to PC N
* `←●` - Jump target (valid JUMPDEST)
* `←✗` - **Invalid jump target** (not JUMPDEST) - highlights bugs!
* `→?` - Jump target unknown or outside bytecode

<Warning title="Invalid Jump Detection">
  Pretty print highlights jumps to non-JUMPDEST locations with red `✗` marker. This indicates malformed bytecode that will revert at runtime.
</Warning>

## Fusion Annotations

Detected fusion patterns annotated inline:

```
   1 |    0 |     0 | ⚡ 60 01        | PUSH1     |      | 0x1 ⚡ PUSH+ADD
   2 |    2 |     1 | 01             | ADD       |      | [gas: 3]
```

**Fusion Markers:**

* `⚡` prefix on hex column - Fusion opportunity
* `⚡ PUSH+ADD` suffix - Pattern type
* Green background for fusion marker

See [Fusion Detection](/primitives/bytecode/detect-fusions) for all 20+ patterns.

## Inline Metadata

### PUSH Values

```
PUSH1     |      | 0x42 (66) [gas: 3]
```

Shows both hex (`0x42`) and decimal (`66`) for values ≤ 0xFFFF.

### Gas Costs

```
SSTORE    |      | [gas: 20000]
```

Base gas cost from [Opcode.getGasCost()](/primitives/opcode/getGasCost).

### Stack Effects

```
ADD       |      | [gas: 3] [stack: -2, +1]
```

Shows inputs consumed (`-2`) and outputs produced (`+1`).

### Jump Targets

```
JUMPDEST  | ←●   | [target: PC=50] [gas: 1]
```

Shows this is a valid jump destination at PC 50.

## Summary Section

Footer shows aggregate statistics:

```
╔══════════════════════════════════════╗
║            Summary                   ║
╚══════════════════════════════════════╝

📈 Basic blocks: 5
🎯 Jump destinations: 3
➡️  Unconditional jumps: 2
❓ Conditional jumps: 1
⚠️  Invalid jumps: 1 (!)
⚡ Fusion candidates: 4
📝 Total instructions: 47
⚠️  Final stack depth: 2 (expected 0)
```

**Warnings:**

* `⚠️ Invalid jumps` - Jumps to non-JUMPDEST (red, critical)
* `⚠️ Final stack depth` - Non-zero final depth (yellow, warning)
* `❌ Stack underflow` - Popping from empty stack (red, critical)

## Comparison with formatInstructions

| Feature          | prettyPrint() | formatInstructions() |
| ---------------- | ------------- | -------------------- |
| ANSI colors      | ✅             | ❌                    |
| Gas costs        | ✅             | ❌                    |
| Stack depth      | ✅             | ❌                    |
| Block boundaries | ✅             | ❌                    |
| Jump arrows      | ✅             | ❌                    |
| Fusion detection | ✅             | ❌                    |
| Summary stats    | ✅             | ❌                    |
| Array output     | ❌             | ✅                    |
| Parseable        | ❌             | ✅                    |

**Use `prettyPrint()` for:**

* Debugging and visualization
* Terminal output
* Understanding control flow
* Gas analysis
* Educational purposes

**Use `formatInstructions()` for:**

* Programmatic parsing
* Simple disassembly
* Integration with other tools
* Machine-readable output

## Advanced Usage

### Debug Specific Range

```typescript theme={null}
// Extract and print specific block
const instructions = code.parseInstructions();
const blockInsts = instructions.filter(inst =>
  inst.position >= 100 && inst.position < 150
);

// Create temporary bytecode from range
const range = code.raw().slice(100, 150);
const blockCode = Bytecode(range);
console.log(blockCode.prettyPrint());
```

### Compare Bytecode Versions

```typescript theme={null}
const v1 = Bytecode(contractV1Bytecode);
const v2 = Bytecode(contractV2Bytecode);

console.log("=== Version 1 ===");
console.log(v1.prettyPrint({ colors: false }));

console.log("\n=== Version 2 ===");
console.log(v2.prettyPrint({ colors: false }));
```

### Extract Function Bodies

```typescript theme={null}
// Find function dispatch pattern
const functions = new Map<number, number>();
for (const inst of code.scan({ detectFusions: true })) {
  if (inst.type === 'function_dispatch') {
    functions.set(inst.selector, Number(inst.target));
  }
}

// Print each function
functions.forEach((target, selector) => {
  console.log(`\n=== Function 0x${selector.toString(16)} ===`);

  // Find block ending at target
  const blocks = code.analyzeBlocks();
  const funcBlock = blocks.find(b => b.startPc === target);

  if (funcBlock) {
    const funcCode = code.raw().slice(funcBlock.startPc, funcBlock.endPc);
    console.log(Bytecode(funcCode).prettyPrint());
  }
});
```

### Integration with Logger

```typescript theme={null}
import { createLogger } from 'your-logger';

const logger = createLogger();

// Conditional pretty print based on log level
if (logger.level === 'debug') {
  logger.debug('Bytecode analysis:\n' + code.prettyPrint());
} else {
  logger.info(`Bytecode size: ${code.size()} bytes`);
}
```

## Terminal Compatibility

### Color Support Detection

```typescript theme={null}
import { supportsColor } from 'supports-color';

const useColors = supportsColor.stdout !== false;

const output = code.prettyPrint({ colors: useColors });
```

### Width Detection

```typescript theme={null}
const termWidth = process.stdout.columns || 120;

const output = code.prettyPrint({
  maxWidth: termWidth,
  compact: termWidth < 100
});
```

### Unicode Fallback

If terminal doesn't support Unicode box-drawing characters:

```typescript theme={null}
const output = code.prettyPrint({ unicode: false });

// Uses ASCII instead:
// +======================================+
// |     EVM Bytecode Disassembly         |
// +======================================+
```

## Performance

Pretty printing is optimized for readability over speed:

* **Small bytecode (\<1KB)**: \<5ms
* **Medium bytecode (10KB)**: \~50ms
* **Large bytecode (24KB)**: \~120ms

<Note>
  Use `formatInstructions()` if performance is critical and visual output not needed.
</Note>

<Note>
  **TypeScript-only:** Pretty printing requires complex string formatting with ANSI colors and Unicode drawing. Use simpler APIs like `Scanner` in Zig for bytecode iteration.
</Note>

## See Also

* [formatInstructions](/primitives/bytecode/formatInstructions) - Simple array-based disassembly
* [analyzeBlocks](/primitives/bytecode/analyze-blocks) - Block metadata used in output
* [detectFusions](/primitives/bytecode/detect-fusions) - Fusion patterns annotated
* [scan](/primitives/bytecode/scan) - Underlying iterator
* [parseInstructions](/primitives/bytecode/parseInstructions) - Zig Scanner for iteration
