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

# EQ (0x14)

> Bitwise equality comparison for 256-bit values

<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:** `0x14`
**Introduced:** Frontier (EVM genesis)

EQ performs bitwise equality comparison on two 256-bit values. Returns 1 if the values are exactly equal, 0 otherwise. This is a fundamental operation for implementing conditional logic, address validation, and state checks.

Unlike comparison operations (LT/GT), EQ works identically for both signed and unsigned interpretations since it performs exact bitwise equality.

## Specification

**Stack Input:**

```
a (top)
b
```

**Stack Output:**

```
a == b ? 1 : 0
```

**Gas Cost:** 3 (GasFastestStep)

**Operation:**

```
result = (a == b) ? 1 : 0
```

## Behavior

EQ pops two values from the stack, compares them bitwise, and pushes 1 if they are exactly equal, otherwise 0:

* If `a == b` (all 256 bits identical): Result is 1 (true)
* If `a != b` (any bit differs): Result is 0 (false)

Comparison is bitwise - no interpretation as signed/unsigned is needed.

## Examples

### Basic Equality

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

// 42 == 42 = 1 (true)
const frame = createFrame({ stack: [42n, 42n] });
const err = eq(frame);

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

### Inequality

```typescript theme={null}
// 10 == 20 = 0 (false)
const frame = createFrame({ stack: [10n, 20n] });
const err = eq(frame);

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

### Zero Equality

```typescript theme={null}
// 0 == 0 = 1 (true)
const frame = createFrame({ stack: [0n, 0n] });
eq(frame);
console.log(frame.stack); // [1n]

// 0 == 1 = 0 (false)
const frame2 = createFrame({ stack: [0n, 1n] });
eq(frame2);
console.log(frame2.stack); // [0n]
```

### Maximum Value

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

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

### Address Comparison

```typescript theme={null}
// Common use case: checking addresses
const addr1 = 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb3n;
const addr2 = 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb3n;
const frame = createFrame({ stack: [addr1, addr2] });
eq(frame);

console.log(frame.stack); // [1n] (addresses match)
```

### Sign-Independent

```typescript theme={null}
// EQ doesn't care about signed interpretation
const value1 = (1n << 256n) - 1n;  // All bits set
const value2 = (1n << 256n) - 1n;

// As unsigned: 2^256 - 1
// As signed: -1
// EQ: bitwise equal = 1
const frame = createFrame({ stack: [value1, value2] });
eq(frame);

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

## Gas Cost

**Cost:** 3 gas (GasFastestStep)

EQ shares the lowest gas tier with all comparison operations:

* LT, GT, SLT, SGT, EQ (comparisons)
* ISZERO, NOT
* ADD, SUB

**Comparison:**

* EQ: 3 gas
* LT/GT: 3 gas
* MUL/DIV: 5 gas

## Edge Cases

### Identical Values

```typescript theme={null}
// Any value equals itself
eq(createFrame({ stack: [0n, 0n] }));  // [1n]
eq(createFrame({ stack: [42n, 42n] }));  // [1n]

const MAX = (1n << 256n) - 1n;
eq(createFrame({ stack: [MAX, MAX] }));  // [1n]
```

### Different Values

```typescript theme={null}
// Different values are never equal
eq(createFrame({ stack: [1n, 2n] }));  // [0n]
eq(createFrame({ stack: [0n, 1n] }));  // [0n]

const MAX = (1n << 256n) - 1n;
eq(createFrame({ stack: [MAX, MAX - 1n] }));  // [0n]
```

### Large Values

```typescript theme={null}
// Arbitrary precision equality
const a = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFn;
const b = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFn;

const frame = createFrame({ stack: [a, b] });
eq(frame);
console.log(frame.stack); // [1n]

// One bit different
const c = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEEn;
const frame2 = createFrame({ stack: [a, c] });
eq(frame2);
console.log(frame2.stack); // [0n]
```

### Stack Underflow

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

console.log(err); // { type: "StackUnderflow" }
console.log(frame.stack); // [42n] (unchanged)
```

### Out of Gas

```typescript theme={null}
// Insufficient gas
const frame = createFrame({ stack: [42n, 42n], gasRemaining: 2n });
const err = eq(frame);

console.log(err); // { type: "OutOfGas" }
console.log(frame.gasRemaining); // 0n
```

## Common Usage

### Address Validation

```solidity theme={null}
// require(addr != address(0))
assembly {
    if eq(addr, 0) {
        revert(0, 0)
    }
}

// Check specific address
assembly {
    if iszero(eq(caller(), expectedAddr)) {
        revert(0, 0)
    }
}
```

### State Checks

```solidity theme={null}
// Check if storage value matches expected
assembly {
    let value := sload(slot)
    if iszero(eq(value, expected)) {
        revert(0, 0)
    }
}
```

### Conditional Execution

```solidity theme={null}
// if (a == b)
assembly {
    let equal := eq(a, b)
    if equal {
        // Execute if equal
    }
}
```

### Enum Comparison

```solidity theme={null}
// Check enum state
enum State { Pending, Active, Closed }

assembly {
    let state := sload(stateSlot)
    if eq(state, 1) {  // State.Active
        // Handle active state
    }
}
```

### Hash Verification

```solidity theme={null}
// Verify hash matches
assembly {
    let computed := keccak256(dataPtr, dataLen)
    if iszero(eq(computed, expectedHash)) {
        revert(0, 0)
    }
}
```

## Implementation

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * EQ opcode (0x14) - Equality comparison
     */
    export function handle(frame: FrameType): EvmError | null {
      // Consume gas (GasFastestStep = 3)
      const gasErr = consumeGas(frame, FastestStep);
      if (gasErr) return gasErr;

      // Pop operands (b is top, a is second)
      const bResult = popStack(frame);
      if (bResult.error) return bResult.error;
      const b = bResult.value;

      const aResult = popStack(frame);
      if (aResult.error) return aResult.error;
      const a = aResult.value;

      // Compare: a == b (bitwise equality)
      const result = a === b ? 1n : 0n;

      // Push result
      const pushErr = pushStack(frame, result);
      if (pushErr) return pushErr;

      // Increment PC
      frame.pc += 1;
      return null;
    }
    ```
  </Tab>
</Tabs>

## Testing

### Test Coverage

```typescript theme={null}
import { describe, it, expect } from 'vitest';
import { handle as EQ } from './0x14_EQ.js';

describe('EQ (0x14)', () => {
  it('returns 1 when values are equal', () => {
    const frame = createFrame([42n, 42n]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([1n]);
    expect(frame.pc).toBe(1);
    expect(frame.gasRemaining).toBe(997n);
  });

  it('returns 0 when values are not equal', () => {
    const frame = createFrame([10n, 20n]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([0n]);
  });

  it('handles zero equality', () => {
    const frame = createFrame([0n, 0n]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([1n]);
  });

  it('handles zero inequality', () => {
    const frame = createFrame([0n, 1n]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([0n]);
  });

  it('handles max uint256 equality', () => {
    const MAX = (1n << 256n) - 1n;
    const frame = createFrame([MAX, MAX]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([1n]);
  });

  it('handles large value comparison', () => {
    const val = 0xDEADBEEFn;
    const frame = createFrame([val, val]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([1n]);
  });

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

  it('returns OutOfGas when insufficient gas', () => {
    const frame = createFrame([42n, 42n], 2n);
    expect(EQ(frame)).toEqual({ type: 'OutOfGas' });
  });

  it('preserves stack below compared values', () => {
    const frame = createFrame([100n, 200n, 42n, 42n]);
    expect(EQ(frame)).toBeNull();
    expect(frame.stack).toEqual([100n, 200n, 1n]);
  });
});
```

### Edge Cases Tested

* Equal values (42 == 42)
* Unequal values (10 != 20)
* Zero equality (0 == 0)
* Zero inequality (0 != 1)
* Maximum value equality
* Large value comparison
* Stack underflow (\< 2 items)
* Out of gas (\< 3 gas)
* Stack preservation

## Security

### Zero Address Checks

**CRITICAL:** Always validate addresses are not zero:

```solidity theme={null}
// VULNERABLE: Missing zero address check
function transfer(address to, uint256 amount) {
    balances[to] += amount;  // Can burn tokens to 0x0
}

// CORRECT: Explicit zero check
function transfer(address to, uint256 amount) {
    require(to != address(0), "zero address");
    balances[to] += amount;
}

// Assembly version
assembly {
    if eq(to, 0) {
        revert(0, 0)
    }
}
```

### Access Control

```solidity theme={null}
// VULNERABLE: Missing ownership check
function withdraw() {
    // Anyone can call!
    payable(msg.sender).transfer(address(this).balance);
}

// CORRECT: Owner validation
function withdraw() {
    require(msg.sender == owner, "not owner");
    payable(msg.sender).transfer(address(this).balance);
}

// Assembly version
assembly {
    if iszero(eq(caller(), owner)) {
        revert(0, 0)
    }
}
```

### State Validation

```solidity theme={null}
// VULNERABLE: Missing state check
function execute() {
    // Execute regardless of state
    doAction();
}

// CORRECT: State validation
enum State { Pending, Active, Closed }
State public state;

function execute() {
    require(state == State.Active, "not active");
    doAction();
}
```

### Hash Comparison

```solidity theme={null}
// VULNERABLE: Using incorrect hash
bytes32 public secretHash;

function reveal(bytes32 secret) {
    // Wrong: comparing unhashed value to hash
    require(secret == secretHash);  // Never matches!
}

// CORRECT: Hash before comparison
function reveal(bytes32 secret) {
    require(keccak256(abi.encodePacked(secret)) == secretHash);
}
```

## Optimizations

### Commutative Property

```solidity theme={null}
// EQ is commutative: a == b is same as b == a
assembly {
    let equal := eq(a, b)
    // Same as:
    let equal := eq(b, a)
}

// Choose order to minimize stack operations
```

### Zero Check Pattern

```solidity theme={null}
// Checking equality to zero
assembly {
    let isZero := eq(value, 0)  // 3 gas
}

// Equivalent using ISZERO (same gas, clearer intent)
assembly {
    let isZero := iszero(value)  // 3 gas
}

// Prefer ISZERO for zero checks (more readable)
```

### Inverted Logic

```solidity theme={null}
// Check inequality: a != b
assembly {
    let notEqual := iszero(eq(a, b))  // 6 gas (EQ + ISZERO)
}

// Sometimes more efficient to structure logic around equality
assembly {
    if eq(a, b) {
        // Equal case
    } else {
        // Not equal case (no ISZERO needed)
    }
}
```

### Multiple Comparisons

```solidity theme={null}
// Check if value equals any of multiple options
assembly {
    let match := or(
        eq(value, option1),
        or(eq(value, option2), eq(value, option3))
    )
}

// More efficient with structured checks
assembly {
    let match := 0
    if eq(value, option1) { match := 1 }
    if eq(value, option2) { match := 1 }
    if eq(value, option3) { match := 1 }
}
```

## Benchmarks

EQ is one of the fastest EVM operations:

**Execution time (relative):**

* EQ: 1.0x (baseline)
* LT/GT: 1.0x
* ISZERO: 0.95x
* ADD: 1.0x
* MUL: 1.5x

**Gas efficiency:**

* 3 gas per equality check
* \~333,333 comparisons per million gas
* Highly optimized in all EVM implementations

## References

* [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) - Section 9.1 (Comparison Operations)
* [EVM Codes - EQ](https://www.evm.codes/#14)
* [Solidity Docs - Comparison Operators](https://docs.soliditylang.org/en/latest/types.html#comparisons)

## Related Documentation

* [ISZERO](/evm/instructions/comparison/iszero) - Zero check (specialized EQ)
* [LT](/evm/instructions/comparison/lt) - Less than (unsigned)
* [GT](/evm/instructions/comparison/gt) - Greater than (unsigned)
* [SLT](/evm/instructions/comparison/slt) - Signed less than
* [SGT](/evm/instructions/comparison/sgt) - Signed greater than
