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

# ADD (0x01)

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

ADD performs addition on two 256-bit unsigned integers with wrapping overflow semantics. When the result exceeds 2^256 - 1, it wraps around modulo 2^256, matching hardware integer register behavior.

This is the most fundamental arithmetic operation in the EVM, used extensively in array indexing, counter increments, and numeric calculations.

## Specification

**Stack Input:**

```
a (top)
b
```

**Stack Output:**

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

**Gas Cost:** 3 (GasFastestStep)

**Operation:**

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

## Behavior

ADD pops two values from the stack, adds them, and pushes the result back. Overflow wraps around without throwing exceptions:

* If `a + b < 2^256`: Result is the mathematical sum
* If `a + b >= 2^256`: Result is `(a + b) mod 2^256`

No exceptions are thrown for overflow. The result always fits in 256 bits.

## Examples

### Basic Addition

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

// 5 + 10 = 15
const frame = createFrame({ stack: [5n, 10n] });
const err = add(frame);

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

### Overflow Wrapping

```typescript theme={null}
// Maximum value + 1 wraps to 0
const MAX_U256 = (1n << 256n) - 1n;
const frame = createFrame({ stack: [MAX_U256, 1n] });
const err = add(frame);

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

### Large Overflow

```typescript theme={null}
// MAX + MAX wraps around
const MAX_U256 = (1n << 256n) - 1n;
const frame = createFrame({ stack: [MAX_U256, MAX_U256] });
const err = add(frame);

console.log(frame.stack); // [MAX_U256 - 1n]
// Because: (MAX + MAX) mod 2^256 = (2^256 - 2)
```

### Identity Element

```typescript theme={null}
// Adding zero
const frame = createFrame({ stack: [42n, 0n] });
const err = add(frame);

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

### Commutative Property

```typescript theme={null}
// a + b = b + a
const frame1 = createFrame({ stack: [5n, 10n] });
add(frame1);

const frame2 = createFrame({ stack: [10n, 5n] });
add(frame2);

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

## Gas Cost

**Cost:** 3 gas (GasFastestStep)

ADD is one of the cheapest operations in the EVM, sharing the lowest gas tier with:

* SUB (0x03)
* NOT (0x19)
* ISZERO (0x15)
* LT, GT, SLT, SGT, EQ (comparison ops)

**Comparison:**

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

## Edge Cases

### Maximum Overflow

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

// Result: 0xFFFF...FFFE (2^256 - 2)
```

### Zero Addition

```typescript theme={null}
// 0 + 0 = 0
const frame = createFrame({ stack: [0n, 0n] });
add(frame);

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

### Stack Underflow

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

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

### Out of Gas

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

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

## Common Usage

### Array Index Calculation

```solidity theme={null}
// Accessing array[i + offset]
assembly {
    let index := add(i, offset)
    let value := sload(add(arraySlot, index))
}
```

### Counter Increments

```solidity theme={null}
// Loop counter
for (uint i = 0; i < n; i++) {
    // Compiler generates: ADD i, 1
}
```

### Memory Pointer Arithmetic

```solidity theme={null}
assembly {
    let ptr := mload(0x40)  // Free memory pointer
    mstore(ptr, value)
    mstore(0x40, add(ptr, 0x20))  // Update pointer
}
```

### Safe vs Unchecked

**Pre-Solidity 0.8.0:**

```solidity theme={null}
// Manual overflow check
uint256 result = a + b;
require(result >= a, "overflow");
```

**Solidity 0.8.0+:**

```solidity theme={null}
// Default: checked arithmetic (adds overflow checks)
uint256 result = a + b;  // Reverts on overflow

// Explicit wrapping (uses raw ADD)
unchecked {
    uint256 result = a + b;  // Wraps on overflow
}
```

## Implementation

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * ADD opcode (0x01) - Addition with overflow wrapping
     */
    export function add(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 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 { add } from './0x01_ADD.js';

describe('ADD (0x01)', () => {
  it('adds two numbers', () => {
    const frame = createFrame([5n, 10n]);
    expect(add(frame)).toBeNull();
    expect(frame.stack).toEqual([15n]);
  });

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

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

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

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

### Edge Cases Tested

* Basic addition (5 + 10 = 15)
* Overflow wrapping (MAX + 1 = 0)
* Large overflow (MAX + MAX)
* Zero addition (0 + 0 = 0, 42 + 0 = 42)
* Stack underflow (\< 2 items)
* Out of gas (\< 3 gas)
* Commutative property (a + b = b + a)

## Security

### Overflow Vulnerabilities

**Before Solidity 0.8.0:**

```solidity theme={null}
// VULNERABLE: No overflow protection
function transfer(address to, uint256 amount) public {
    balances[msg.sender] -= amount;  // Can underflow!
    balances[to] += amount;          // Can overflow!
}
```

**Attack scenario:**

* User with balance 5 transfers amount = 10
* `balances[msg.sender] -= 10` wraps to MAX\_UINT256
* Attacker now has infinite tokens

**Mitigation (pre-0.8.0):**

```solidity theme={null}
// Use SafeMath library
function transfer(address to, uint256 amount) public {
    balances[msg.sender] = balances[msg.sender].sub(amount);  // Reverts
    balances[to] = balances[to].add(amount);                  // Reverts
}
```

**Modern Solidity (0.8.0+):**

```solidity theme={null}
// Automatic overflow checks
function transfer(address to, uint256 amount) public {
    balances[msg.sender] -= amount;  // Reverts on underflow
    balances[to] += amount;          // Reverts on overflow
}

// Opt-in to wrapping when needed
function unsafeIncrement(uint256 x) pure returns (uint256) {
    unchecked {
        return x + 1;  // Uses raw ADD, wraps on overflow
    }
}
```

### Safe Patterns

**Check-Effects-Interactions:**

```solidity theme={null}
function withdraw(uint256 amount) public {
    require(balances[msg.sender] >= amount);  // Check
    balances[msg.sender] -= amount;           // Effect
    payable(msg.sender).transfer(amount);     // Interaction
}
```

**Explicit Bounds Checking:**

```solidity theme={null}
function add(uint256 a, uint256 b) pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, "addition overflow");
    return c;
}
```

## Benchmarks

ADD is one of the fastest EVM operations:

**Execution time (relative):**

* ADD: 1.0x (baseline)
* MUL: 1.2x
* DIV: 2.5x
* ADDMOD: 3.0x
* EXP: 10x+

**Gas efficiency:**

* 3 gas per 256-bit addition
* \~0.33 million additions per million gas
* Highly optimized in all EVM implementations

## References

* [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) - Section 9.1 (Arithmetic Operations)
* [EVM Codes - ADD](https://www.evm.codes/#01)
* [Solidity Docs - Checked vs Unchecked](https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic)
* [SWC-101: Integer Overflow and Underflow](https://swcregistry.io/docs/SWC-101)
