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

# AND (0x16)

> Bitwise AND operation for bit masking and flag management 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:** `0x16`
**Introduced:** Frontier (EVM genesis)

AND performs bitwise AND on two 256-bit unsigned integers. Each bit in the result is 1 only if the corresponding bits in both operands are 1. This operation is fundamental for bit masking, extracting specific bit ranges, and checking flags.

Primary uses: extracting addresses from uint256, applying bit masks, checking flag combinations.

## 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 |   0
1 | 0 |   0
1 | 1 |   1
```

## Behavior

AND pops two values from the stack, performs bitwise AND 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 & MAX\_UINT256 = a
* **Null element:** a & 0 = 0

## Examples

### Basic Masking

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

// Extract lower 8 bits (least significant byte)
const value = 0x123456789ABCDEFn;
const mask = 0xFFn;
const frame = createFrame({ stack: [value, mask] });
const err = and(frame);

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

### Extract Address from uint256

```typescript theme={null}
// Extract 160-bit address from packed uint256
const packed = 0x000000000000000000000000dEaDbEeFcAfE1234567890abcdef1234567890ABn;
const addressMask = (1n << 160n) - 1n;  // 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
const frame = createFrame({ stack: [packed, addressMask] });
and(frame);

console.log(frame.stack[0].toString(16));
// 'deadbeefcafe1234567890abcdef1234567890ab'
```

### Check Multiple Flags

```typescript theme={null}
// Check if both FLAG_A and FLAG_B are set
const FLAGS_AB = (1n << 0n) | (1n << 1n);  // 0b11
const value = 0b1011n;  // Has flags 0, 1, 3
const frame = createFrame({ stack: [value, FLAGS_AB] });
and(frame);

const hasBoth = frame.stack[0] === FLAGS_AB;
console.log(hasBoth);  // true (bits 0 and 1 are both set)
```

### Isolate Specific Bytes

```typescript theme={null}
// Extract bytes 12-15 (middle 4 bytes of address-like value)
const value = 0x1122334455667788990011223344556677889900n;
const mask = 0xFFFFFFFF00000000000000000000000000000000n;
const frame = createFrame({ stack: [value, mask] });
and(frame);

const extracted = frame.stack[0] >> 160n;
console.log(extracted.toString(16));  // '11223344'
```

### Commutative Property

```typescript theme={null}
// a & b = b & a
const a = 0xAAAAAAAAn;
const b = 0x55555555n;

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

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

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

## Gas Cost

**Cost:** 3 gas (GasFastestStep)

AND shares the lowest gas tier with:

* OR (0x17), XOR (0x18), NOT (0x19)
* BYTE (0x1a)
* SHL (0x1b), SHR (0x1c), SAR (0x1d)
* ADD (0x01), SUB (0x03)
* Comparison operations (LT, GT, EQ, etc.)

## Edge Cases

### Identity Element

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

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

### Null Element

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

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

### Maximum Values

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

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

### Alternating Bits

```typescript theme={null}
// Alternating bit patterns
const pattern1 = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn;
const pattern2 = 0x5555555555555555555555555555555555555555555555555555555555555555n;
const frame = createFrame({ stack: [pattern1, pattern2] });
and(frame);

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

### Stack Underflow

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

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

### Out of Gas

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

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

## Common Usage

### Extract Address from Storage Value

```solidity theme={null}
// Storage packs address (160 bits) + flags (96 bits)
assembly {
    let packed := sload(slot)
    let addr := and(packed, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
    let flags := shr(160, packed)
}
```

### Check Permission Flags

```solidity theme={null}
// Check if user has both READ and WRITE permissions
uint256 constant READ = 1 << 0;
uint256 constant WRITE = 1 << 1;
uint256 constant EXECUTE = 1 << 2;

function hasReadWrite(uint256 permissions) pure returns (bool) {
    return (permissions & (READ | WRITE)) == (READ | WRITE);
}
```

### Align to Boundary

```solidity theme={null}
// Align pointer to 32-byte boundary (clear lower 5 bits)
function alignTo32(uint256 ptr) pure returns (uint256) {
    return ptr & ~uint256(0x1F);  // Clear bits 0-4
}
```

### Extract Nibble (4 bits)

```solidity theme={null}
// Extract specific nibble from bytes32
function getNibble(bytes32 data, uint256 index) pure returns (uint8) {
    require(index < 64, "index out of range");
    uint256 shift = (63 - index) * 4;
    return uint8((uint256(data) >> shift) & 0xF);
}
```

### Color Channel Extraction

```solidity theme={null}
// Extract RGB channels from packed uint24 (0xRRGGBB)
function unpackRGB(uint24 color) pure returns (uint8 r, uint8 g, uint8 b) {
    r = uint8((color >> 16) & 0xFF);
    g = uint8((color >> 8) & 0xFF);
    b = uint8(color & 0xFF);
}
```

## Implementation

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * AND opcode (0x16) - Bitwise AND operation
     */
    export function op_and(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 AND
      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_and } from './and.js';

describe('AND (0x16)', () => {
  it('performs basic AND', () => {
    const frame = createFrame({ stack: [0b1100n, 0b1010n] });
    expect(op_and(frame)).toBeNull();
    expect(frame.stack[0]).toBe(0b1000n);
  });

  it('extracts address mask', () => {
    const packed = 0x000000000000000000000000deadbeefn;
    const mask = (1n << 160n) - 1n;
    const frame = createFrame({ stack: [packed, mask] });
    expect(op_and(frame)).toBeNull();
    expect(frame.stack[0]).toBe(0xdeadbeefn);
  });

  it('handles identity (AND with all ones)', () => {
    const MAX = (1n << 256n) - 1n;
    const value = 0x123456n;
    const frame = createFrame({ stack: [value, MAX] });
    expect(op_and(frame)).toBeNull();
    expect(frame.stack[0]).toBe(value);
  });

  it('handles null element (AND with zero)', () => {
    const frame = createFrame({ stack: [0x123456n, 0n] });
    expect(op_and(frame)).toBeNull();
    expect(frame.stack[0]).toBe(0n);
  });

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

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

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

### Edge Cases Tested

* Basic AND operations (truth table)
* Identity element (AND with MAX\_UINT256)
* Null element (AND with 0)
* Address extraction from uint256
* Flag checking
* Commutative property
* Alternating bit patterns
* Stack underflow
* Out of gas

## Security

### Incorrect Mask Size

```solidity theme={null}
// VULNERABLE: Mask doesn't cover full address
function extractAddress(uint256 packed) pure returns (address) {
    return address(uint160(packed & 0xFFFFFFFF));  // Only 32 bits!
}

// CORRECT: Full 160-bit mask
function extractAddress(uint256 packed) pure returns (address) {
    return address(uint160(packed & type(uint160).max));
}
```

### Flag Checking Logic Errors

```solidity theme={null}
// WRONG: Checks if ANY flag is set (should be AND)
function hasPermission(uint256 perms, uint256 required) pure returns (bool) {
    return (perms | required) != 0;  // Using OR instead of AND
}

// CORRECT: Checks if ALL required flags are set
function hasPermission(uint256 perms, uint256 required) pure returns (bool) {
    return (perms & required) == required;
}
```

### Off-by-One in Bit Positions

```solidity theme={null}
// WRONG: Flag indices off by one
uint256 constant FLAG_0 = 1 << 1;  // Should be 1 << 0
uint256 constant FLAG_1 = 1 << 2;  // Should be 1 << 1

// CORRECT: Proper flag definitions
uint256 constant FLAG_0 = 1 << 0;  // Bit 0
uint256 constant FLAG_1 = 1 << 1;  // Bit 1
```

### Endianness Confusion

```solidity theme={null}
// Be aware: BYTE opcode uses big-endian (byte 0 = MSB)
// But bitwise operations are position-agnostic
bytes32 data = 0x0123456789ABCDEF;
assembly {
    // This extracts byte 0 (0x01), not byte 31!
    let b := and(shr(248, data), 0xFF)  // Correct
}
```

## Benchmarks

AND is one of the fastest EVM operations:

**Execution time (relative):**

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

**Gas efficiency:**

* 3 gas per 256-bit AND operation
* \~333,333 AND 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 - AND](https://www.evm.codes/#16)
* [Solidity Docs - Bitwise Operators](https://docs.soliditylang.org/en/latest/types.html#integers)

## Related Documentation

* [OR (0x17)](/evm/instructions/bitwise/or) - Bitwise OR operation
* [XOR (0x18)](/evm/instructions/bitwise/xor) - Bitwise XOR operation
* [NOT (0x19)](/evm/instructions/bitwise/not) - Bitwise NOT operation
* [SHL (0x1b)](/evm/instructions/bitwise/shl) - Shift left operation
