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

# OR (0x17)

> Bitwise OR operation for combining flags and setting bits on 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:** `0x17`
**Introduced:** Frontier (EVM genesis)

OR performs bitwise OR on two 256-bit unsigned integers. Each bit in the result is 1 if either (or both) corresponding bits in the operands are 1. This operation is fundamental for combining flags, setting specific bits, and data packing.

Primary uses: enabling multiple flags, setting bits in bitmaps, combining packed data fields.

## Specification

**Stack Input:**

```
a (top)
b
```

**Stack Output:**

```
a | b
```

**Gas Cost:** 3 (GasFastestStep)

**Truth Table (per bit):**

```
a | b | a | b
--|---|------
0 | 0 |   0
0 | 1 |   1
1 | 0 |   1
1 | 1 |   1
```

## Behavior

OR pops two values from the stack, performs bitwise OR on each corresponding bit pair, and pushes the result. The operation is:

* **Commutative:** a | b = b | a
* **Associative:** (a | b) | c = a | (b | c)
* **Identity element:** a | 0 = a
* **Null element:** a | MAX\_UINT256 = MAX\_UINT256

## Examples

### Set Multiple Flags

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

// Enable flags at bits 0 and 2
const existing = 0b0000n;
const flags = 0b0101n;  // Bits 0 and 2
const frame = createFrame({ stack: [existing, flags] });
const err = or(frame);

console.log(frame.stack[0].toString(2));  // '101' (0b0101)
```

### Combine Two Bitmaps

```typescript theme={null}
// Merge two permission sets
const userPerms = 0b00001111n;   // Permissions 0-3
const groupPerms = 0b11110000n;  // Permissions 4-7
const frame = createFrame({ stack: [userPerms, groupPerms] });
or(frame);

console.log(frame.stack[0].toString(2));  // '11111111'
```

### Pack Data Fields

```typescript theme={null}
// Pack address (160 bits) + flags (96 bits) into uint256
const address = 0xdeadbeefcafe1234567890abcdef1234567890ABn;
const flags = 0x123456789ABCn << 160n;  // Shift flags to upper bits
const frame = createFrame({ stack: [address, flags] });
or(frame);

// Result: lower 160 bits = address, upper 96 bits = flags
console.log(frame.stack[0].toString(16));
```

### Set Specific Bit

```typescript theme={null}
// Set bit 5 in existing value
const value = 0b00001000n;  // Bit 3 is set
const setBit5 = 0b00100000n;  // Bit 5 mask
const frame = createFrame({ stack: [value, setBit5] });
or(frame);

console.log(frame.stack[0].toString(2));  // '101000' (bits 3 and 5)
```

### Commutative Property

```typescript theme={null}
// a | b = b | a
const a = 0b1100n;
const b = 0b1010n;

const frame1 = createFrame({ stack: [a, b] });
or(frame1);

const frame2 = createFrame({ stack: [b, a] });
or(frame2);

console.log(frame1.stack[0] === frame2.stack[0]);  // true (both 0b1110)
```

## Gas Cost

**Cost:** 3 gas (GasFastestStep)

OR shares the lowest gas tier with:

* AND (0x16), XOR (0x18), NOT (0x19)
* BYTE (0x1a)
* SHL (0x1b), SHR (0x1c), SAR (0x1d)
* ADD (0x01), SUB (0x03)
* Comparison operations

## Edge Cases

### Identity Element

```typescript theme={null}
// OR with zero
const value = 0x123456n;
const frame = createFrame({ stack: [value, 0n] });
or(frame);

console.log(frame.stack[0] === value);  // true (identity)
```

### Null Element

```typescript theme={null}
// OR with all ones
const MAX = (1n << 256n) - 1n;
const value = 0x123456n;
const frame = createFrame({ stack: [value, MAX] });
or(frame);

console.log(frame.stack[0] === MAX);  // true
```

### Self OR

```typescript theme={null}
// a | a = a (idempotent)
const value = 0x123456n;
const frame = createFrame({ stack: [value, value] });
or(frame);

console.log(frame.stack[0] === value);  // true
```

### Alternating Bits

```typescript theme={null}
// Complementary patterns OR to all ones
const pattern1 = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn;
const pattern2 = 0x5555555555555555555555555555555555555555555555555555555555555555n;
const frame = createFrame({ stack: [pattern1, pattern2] });
or(frame);

const MAX = (1n << 256n) - 1n;
console.log(frame.stack[0] === MAX);  // true (all bits set)
```

### Stack Underflow

```typescript theme={null}
// Insufficient stack items
const frame = createFrame({ stack: [0x123n] });
const err = or(frame);

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

### Out of Gas

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

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

## Common Usage

### Enable Multiple Permissions

```solidity theme={null}
// Grant READ and WRITE permissions
uint256 constant READ = 1 << 0;
uint256 constant WRITE = 1 << 1;
uint256 constant EXECUTE = 1 << 2;

function grantPermissions(uint256 current) pure returns (uint256) {
    return current | READ | WRITE;  // Enable both flags
}
```

### Set Bits in Bitmap

```solidity theme={null}
// Mark slots as occupied in storage bitmap
mapping(uint256 => uint256) public bitmap;

function markOccupied(uint256 index) internal {
    uint256 bucket = index / 256;
    uint256 bit = index % 256;
    bitmap[bucket] |= (1 << bit);  // Set bit
}
```

### Pack Multiple Values

```solidity theme={null}
// Pack timestamp (40 bits) + amount (216 bits)
function pack(uint40 timestamp, uint216 amount) pure returns (uint256) {
    return (uint256(timestamp) << 216) | uint256(amount);
}
```

### Combine Selectors

```solidity theme={null}
// Create function selector mask for multiple functions
bytes4 constant FUNC_A = 0x12345678;
bytes4 constant FUNC_B = 0x9ABCDEF0;

function getSelectorMask() pure returns (uint256) {
    return (uint256(uint32(FUNC_A)) << 224) |
           (uint256(uint32(FUNC_B)) << 192);
}
```

### Set Color Channels

```solidity theme={null}
// Combine RGB channels into packed uint24 (0xRRGGBB)
function packRGB(uint8 r, uint8 g, uint8 b) pure returns (uint24) {
    return uint24(r) << 16 | uint24(g) << 8 | uint24(b);
}
```

## Implementation

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * OR opcode (0x17) - Bitwise OR operation
     */
    export function op_or(frame: FrameType): EvmError | null {
      // Consume gas (GasFastestStep = 3)
      frame.gasRemaining -= 3n;
      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 bitwise OR
      const result = a | b;

      // 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 { op_or } from './or.js';

describe('OR (0x17)', () => {
  it('performs basic OR', () => {
    const frame = createFrame({ stack: [0b1100n, 0b1010n] });
    expect(op_or(frame)).toBeNull();
    expect(frame.stack[0]).toBe(0b1110n);
  });

  it('combines flags', () => {
    const flag1 = 0b0001n;
    const flag2 = 0b0100n;
    const frame = createFrame({ stack: [flag1, flag2] });
    expect(op_or(frame)).toBeNull();
    expect(frame.stack[0]).toBe(0b0101n);
  });

  it('handles identity (OR with zero)', () => {
    const value = 0x123456n;
    const frame = createFrame({ stack: [value, 0n] });
    expect(op_or(frame)).toBeNull();
    expect(frame.stack[0]).toBe(value);
  });

  it('handles null element (OR with MAX)', () => {
    const MAX = (1n << 256n) - 1n;
    const value = 0x123456n;
    const frame = createFrame({ stack: [value, MAX] });
    expect(op_or(frame)).toBeNull();
    expect(frame.stack[0]).toBe(MAX);
  });

  it('is idempotent (a | a = a)', () => {
    const value = 0x123456n;
    const frame = createFrame({ stack: [value, value] });
    expect(op_or(frame)).toBeNull();
    expect(frame.stack[0]).toBe(value);
  });

  it('is commutative', () => {
    const a = 0xAAAAn;
    const b = 0x5555n;
    const frame1 = createFrame({ stack: [a, b] });
    const frame2 = createFrame({ stack: [b, a] });
    op_or(frame1);
    op_or(frame2);
    expect(frame1.stack[0]).toBe(frame2.stack[0]);
  });

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

  it('returns OutOfGas when insufficient gas', () => {
    const frame = createFrame({ stack: [0x123n, 0x456n], gasRemaining: 2n });
    expect(op_or(frame)).toEqual({ type: 'OutOfGas' });
  });
});
```

### Edge Cases Tested

* Basic OR operations (truth table)
* Identity element (OR with 0)
* Null element (OR with MAX\_UINT256)
* Flag combining
* Idempotent property (a | a = a)
* Commutative property
* Complementary patterns (0xAAAA... | 0x5555... = MAX)
* Stack underflow
* Out of gas

## Security

### Flag Mismanagement

```solidity theme={null}
// WRONG: Using AND instead of OR to set flags
function addPermission(uint256 perms, uint256 flag) pure returns (uint256) {
    return perms & flag;  // Removes all other flags!
}

// CORRECT: Use OR to preserve existing flags
function addPermission(uint256 perms, uint256 flag) pure returns (uint256) {
    return perms | flag;
}
```

### Overlapping Bit Positions

```solidity theme={null}
// DANGEROUS: Flag definitions overlap
uint256 constant FLAG_A = 1 << 0;  // Bit 0
uint256 constant FLAG_B = 1 << 0;  // Also bit 0! (collision)

// SAFE: Unique bit positions
uint256 constant FLAG_A = 1 << 0;  // Bit 0
uint256 constant FLAG_B = 1 << 1;  // Bit 1
uint256 constant FLAG_C = 1 << 2;  // Bit 2
```

### Unintended Side Effects

```solidity theme={null}
// DANGEROUS: OR can never clear bits, only set them
function updateFlags(uint256 current, uint256 desired) pure returns (uint256) {
    return current | desired;  // Can't remove flags!
}

// BETTER: Explicit set/clear interface
function setFlags(uint256 current, uint256 flags) pure returns (uint256) {
    return current | flags;
}

function clearFlags(uint256 current, uint256 flags) pure returns (uint256) {
    return current & ~flags;
}
```

### Packed Data Corruption

```solidity theme={null}
// VULNERABLE: OR can corrupt existing packed fields
struct Packed {
    uint160 addr;   // Bits 0-159
    uint96 value;   // Bits 160-255
}

// Wrong: OR overwrites existing address
function updateValue(uint256 packed, uint96 newValue) pure returns (uint256) {
    return packed | (uint256(newValue) << 160);  // Address corrupted if newValue has lower bits!
}

// Correct: Clear field first, then OR
function updateValue(uint256 packed, uint96 newValue) pure returns (uint256) {
    uint256 addrMask = (1 << 160) - 1;
    uint256 addr = packed & addrMask;  // Extract address
    return addr | (uint256(newValue) << 160);  // Recombine
}
```

## Benchmarks

OR is one of the fastest EVM operations:

**Execution time (relative):**

* OR: 1.0x (baseline, fastest tier)
* AND/XOR: 1.0x (same tier)
* ADD: 1.0x (same tier)
* MUL: 1.2x
* DIV: 2.5x

**Gas efficiency:**

* 3 gas per 256-bit OR operation
* \~333,333 OR operations per million gas
* Native hardware instruction on all platforms

## References

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

## Related Documentation

* [AND (0x16)](/evm/instructions/bitwise/and) - Bitwise AND operation
* [XOR (0x18)](/evm/instructions/bitwise/xor) - Bitwise XOR operation
* [NOT (0x19)](/evm/instructions/bitwise/not) - Bitwise NOT operation
* [BYTE (0x1a)](/evm/instructions/bitwise/byte) - Extract byte operation
