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

# MUL (0x02)

> Multiplication with wrapping overflow for 256-bit unsigned integers

<Warning>
  **This page is a placeholder.** All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
</Warning>

## Overview

**Opcode:** `0x02`
**Introduced:** Frontier (EVM genesis)

MUL performs multiplication on two 256-bit unsigned integers with wrapping overflow semantics. When the result exceeds 2^256 - 1, only the lower 256 bits are kept, effectively computing `(a * b) mod 2^256`.

This operation is fundamental for scaling calculations, area/volume computations, and fixed-point arithmetic in smart contracts.

## Specification

**Stack Input:**

```
a (top)
b
```

**Stack Output:**

```
(a * b) mod 2^256
```

**Gas Cost:** 5 (GasFastStep)

**Operation:**

```
result = (a * b) & ((1 << 256) - 1)
```

## Behavior

MUL pops two values from the stack, multiplies them, and pushes the lower 256 bits of the result. The upper bits are discarded:

* If `a * b < 2^256`: Result is the mathematical product
* If `a * b >= 2^256`: Result is the lower 256 bits (truncated)

No exceptions are thrown for overflow. Information in the upper 256 bits is lost.

## Examples

### Basic Multiplication

```typescript theme={null}
import { mul } from '@tevm/voltaire/evm/arithmetic';
import { createFrame } from '@tevm/voltaire/evm/Frame';

// 5 * 10 = 50
const frame = createFrame({ stack: [5n, 10n] });
const err = mul(frame);

console.log(frame.stack); // [50n]
console.log(frame.gasRemaining); // Original - 5
```

### Overflow Truncation

```typescript theme={null}
// Large multiplication overflows
const MAX = (1n << 256n) - 1n;
const frame = createFrame({ stack: [MAX, 2n] });
const err = mul(frame);

// Result: Only lower 256 bits kept
// (MAX * 2) mod 2^256 = 2^256 - 2 = MAX - 1
console.log(frame.stack); // [MAX - 1n]
```

### Powers of Two

```typescript theme={null}
// Multiplying by 2 is left shift
const frame = createFrame({ stack: [0x0Fn, 2n] });
const err = mul(frame);

console.log(frame.stack); // [0x1En] (15 * 2 = 30)
```

### Identity Element

```typescript theme={null}
// Multiplying by 1
const frame = createFrame({ stack: [42n, 1n] });
const err = mul(frame);

console.log(frame.stack); // [42n]
```

### Zero Element

```typescript theme={null}
// Multiplying by 0
const frame = createFrame({ stack: [42n, 0n] });
const err = mul(frame);

console.log(frame.stack); // [0n]
```

## Gas Cost

**Cost:** 5 gas (GasFastStep)

MUL costs slightly more than ADD/SUB due to increased computational complexity:

**Comparison:**

* ADD/SUB: 3 gas
* **MUL/DIV/MOD/SDIV/SMOD/SIGNEXTEND:** 5 gas
* ADDMOD/MULMOD: 8 gas
* EXP: 10 + 50 per byte

MUL is one of the most gas-efficient ways to multiply in the EVM, but still \~67% more expensive than addition.

## Edge Cases

### Maximum Overflow

```typescript theme={null}
// MAX * MAX overflows significantly
const MAX = (1n << 256n) - 1n;
const frame = createFrame({ stack: [MAX, MAX] });
mul(frame);

// Only lower 256 bits: (2^256-1)^2 mod 2^256 = 1
console.log(frame.stack); // [1n]
```

### Square Operations

```typescript theme={null}
// Squaring a number
const frame = createFrame({ stack: [12n, 12n] });
mul(frame);

console.log(frame.stack); // [144n]
```

### Multiplication by Powers of Two

```typescript theme={null}
// Efficient scaling
const frame = createFrame({ stack: [100n, 1n << 10n] }); // * 1024
mul(frame);

console.log(frame.stack); // [102400n]
```

### Stack Underflow

```typescript theme={null}
// Not enough stack items
const frame = createFrame({ stack: [5n] });
const err = mul(frame);

console.log(err); // { type: "StackUnderflow" }
```

## Common Usage

### Fixed-Point Arithmetic

```solidity theme={null}
// 18 decimal fixed-point multiplication
uint256 constant WAD = 1e18;

function wmul(uint256 x, uint256 y) pure returns (uint256) {
    return (x * y) / WAD;
}

// Example: 1.5 * 2.5 = 3.75
// (1.5e18 * 2.5e18) / 1e18 = 3.75e18
```

### Percentage Calculations

```solidity theme={null}
// Calculate 5% fee
function calculateFee(uint256 amount) pure returns (uint256) {
    return (amount * 5) / 100;
}

// Calculate with basis points (0.01%)
function feeInBps(uint256 amount, uint256 bps) pure returns (uint256) {
    return (amount * bps) / 10000;
}
```

### Area/Volume Calculations

```solidity theme={null}
// Rectangle area
function area(uint256 width, uint256 height) pure returns (uint256) {
    return width * height;
}

// Cube volume
function volume(uint256 side) pure returns (uint256) {
    return side * side * side;
}
```

### Scaling and Conversion

```solidity theme={null}
// Convert tokens between decimal precisions
function convertDecimals(
    uint256 amount,
    uint8 fromDecimals,
    uint8 toDecimals
) pure returns (uint256) {
    if (fromDecimals > toDecimals) {
        return amount / (10 ** (fromDecimals - toDecimals));
    } else {
        return amount * (10 ** (toDecimals - fromDecimals));
    }
}
```

## Implementation

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * MUL opcode (0x02) - Multiplication with overflow wrapping
     */
    export function mul(frame: FrameType): EvmError | null {
      // Consume gas (GasFastStep = 5)
      frame.gasRemaining -= 5n;
      if (frame.gasRemaining < 0n) {
        frame.gasRemaining = 0n;
        return { type: "OutOfGas" };
      }

      // Pop operands
      if (frame.stack.length < 2) return { type: "StackUnderflow" };
      const a = frame.stack.pop();
      const b = frame.stack.pop();

      // Compute result with wrapping (modulo 2^256)
      const result = (a * b) & ((1n << 256n) - 1n);

      // Push result
      if (frame.stack.length >= 1024) return { type: "StackOverflow" };
      frame.stack.push(result);

      // Increment PC
      frame.pc += 1;

      return null;
    }
    ```
  </Tab>
</Tabs>

## Testing

### Test Coverage

```typescript theme={null}
import { describe, it, expect } from 'vitest';
import { mul } from './0x02_MUL.js';

describe('MUL (0x02)', () => {
  it('multiplies two numbers', () => {
    const frame = createFrame([5n, 10n]);
    expect(mul(frame)).toBeNull();
    expect(frame.stack).toEqual([50n]);
  });

  it('handles overflow wrapping', () => {
    const MAX = (1n << 256n) - 1n;
    const frame = createFrame([MAX, 2n]);
    expect(mul(frame)).toBeNull();
    expect(frame.stack).toEqual([MAX - 1n]);
  });

  it('squares numbers correctly', () => {
    const frame = createFrame([12n, 12n]);
    expect(mul(frame)).toBeNull();
    expect(frame.stack).toEqual([144n]);
  });

  it('handles multiplication by zero', () => {
    const frame = createFrame([42n, 0n]);
    expect(mul(frame)).toBeNull();
    expect(frame.stack).toEqual([0n]);
  });

  it('handles multiplication by one', () => {
    const frame = createFrame([42n, 1n]);
    expect(mul(frame)).toBeNull();
    expect(frame.stack).toEqual([42n]);
  });

  it('returns StackUnderflow with insufficient stack', () => {
    const frame = createFrame([5n]);
    expect(mul(frame)).toEqual({ type: 'StackUnderflow' });
  });

  it('consumes correct gas (5)', () => {
    const frame = createFrame([5n, 10n], 100n);
    expect(mul(frame)).toBeNull();
    expect(frame.gasRemaining).toBe(95n);
  });
});
```

## Security

### Overflow Vulnerabilities

**Pre-Solidity 0.8.0 vulnerability:**

```solidity theme={null}
// VULNERABLE: No overflow protection
function calculateShares(uint256 price, uint256 quantity) returns (uint256) {
    return price * quantity;  // Can overflow!
}
```

**Attack scenario:**

```solidity theme={null}
// Attacker calls: calculateShares(2^200, 2^100)
// Expected: Massive value
// Actual: Overflows to small value, attacker pays less
```

**Mitigation (SafeMath):**

```solidity theme={null}
function calculateShares(uint256 price, uint256 quantity) returns (uint256) {
    uint256 result = price * quantity;
    require(price == 0 || result / price == quantity, "overflow");
    return result;
}
```

### Safe Fixed-Point Arithmetic

**Vulnerable pattern:**

```solidity theme={null}
// WRONG: Intermediate overflow
function wmul(uint256 x, uint256 y) pure returns (uint256) {
    return (x * y) / WAD;  // x * y can overflow!
}
```

**Safe pattern (using mulmod for intermediate):**

```solidity theme={null}
function wmul(uint256 x, uint256 y) pure returns (uint256 z) {
    // Use assembly to get full 512-bit intermediate result
    assembly {
        if iszero(or(iszero(x), eq(div(mul(x, y), x), y))) {
            revert(0, 0)  // Overflow
        }
        z := div(mul(x, y), WAD)
    }
}
```

**Better: Use MULMOD opcode:**

```solidity theme={null}
// Avoids overflow completely
function mulDivDown(uint256 x, uint256 y, uint256 denominator)
    pure returns (uint256 z) {
    assembly {
        // Equivalent to (x * y) / denominator with 512-bit intermediate
        z := div(mul(x, y), denominator)

        // Check for overflow: require(denominator > 0 &&
        //   (x == 0 || (x * y) / x == y))
        if iszero(and(
            gt(denominator, 0),
            or(iszero(x), eq(div(mul(x, y), x), y))
        )) { revert(0, 0) }
    }
}
```

### Modern Solidity (0.8.0+)

```solidity theme={null}
// Automatic overflow checks
function multiply(uint256 a, uint256 b) pure returns (uint256) {
    return a * b;  // Reverts on overflow
}

// Explicit wrapping when needed
function unsafeMultiply(uint256 a, uint256 b) pure returns (uint256) {
    unchecked {
        return a * b;  // Uses raw MUL, wraps on overflow
    }
}
```

## Benchmarks

MUL performance characteristics:

**Relative execution time:**

* ADD: 1.0x
* MUL: 1.2x
* DIV: 2.5x
* ADDMOD: 3.0x

**Gas efficiency:**

* 5 gas per 256-bit multiplication
* \~200,000 multiplications per million gas
* Significantly faster than repeated addition

**Optimization tip:**

```solidity theme={null}
// Prefer MUL over repeated ADD
uint256 result = x * 10;  // 5 gas

// Instead of:
uint256 result = x + x + x + x + x + x + x + x + x + x;  // 30 gas
```

## References

* [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) - Section 9.1 (Arithmetic Operations)
* [EVM Codes - MUL](https://www.evm.codes/#02)
* [Solidity Fixed-Point Math](https://docs.soliditylang.org/en/latest/units-and-global-variables.html)
* [PRBMath Library](https://github.com/PaulRBerg/prb-math) - Safe fixed-point math
