Skip to main content

Overview

Opcode: 0x87 Introduced: Frontier (EVM genesis) DUP8 duplicates the 8th stack item and pushes it to the top of the stack. The original 8th item remains in place.

Specification

Stack Input:
[..., value, item7, ..., item1]
Stack Output:
[..., value, item7, ..., item1, value]
Gas Cost: 3 (GasFastestStep) Operation:
value = stack[depth - 8]
stack.push(value)

Behavior

DUP8 copies the 8th-from-top stack item without removing it. Requires stack depth ≥ 8. Key characteristics:
  • Requires stack depth ≥ 8
  • Original value unchanged
  • New copy pushed to top
  • StackUnderflow if depth < 8
  • Stack depth increases by 1

Examples

Basic Usage

import { handler_0x87_DUP8 } from '@tevm/voltaire/evm/stack/handlers';
import { createFrame } from '@tevm/voltaire/evm/Frame';

// Duplicate 8th item
const frame = createFrame({
  stack: [800n, 700n, 600n, 500n, 400n, 300n, 200n, 100n],
  gasRemaining: 1000n
});

const err = handler_0x87_DUP8(frame);

console.log(frame.stack); // [800n, 700n, 600n, 500n, 400n, 300n, 200n, 100n, 100n] - 8th item duplicated
console.log(frame.gasRemaining); // 997n (3 gas consumed)

Solidity Compilation

contract Example {
    function deepAccess() public pure {
        // Access deep stack value
        assembly {
            // Stack has 8 items
            dup8  // Duplicate 8th item to top
        }
    }
}

Assembly Usage

assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    // Stack: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]

    dup8
    // Stack: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01] - first item duplicated
}

Gas Cost

Cost: 3 gas (GasFastestStep) All DUP1-16 operations cost the same despite different stack depths accessed. Comparison:
OperationGasNote
DUP83Duplicate 8th item
PUSH1-323Same cost tier
POP2Cheaper

Common Usage

Deep Stack Access

function complex() public pure {
    assembly {
        // Build deep stack
        let v1 := 1
        let v2 := 2
        let v3 := 3
        let v4 := 4
        let v5 := 5
        let v6 := 6
        let v7 := 7
        let v8 := 8

        // Access v1 from depth 8
        dup8
    }
}```

### Efficient Copies

```solidity
// Instead of multiple loads
assembly {
    let value := sload(slot)  // Expensive
    // Use value
    let value2 := sload(slot) // Wasteful!
}

// Use DUP to reuse
assembly {
    let value := sload(slot)  // Load once
    dup1                       // Copy
    // Use both copies
}

Conditional Logic

assembly {
    let condition := calldataload(0)
    dup1  // Keep condition for later
    iszero
    jumpi(skip)
    // Use condition again
    skip:
}

Stack Depth Requirements

Minimum Depth

// DUP8 requires 8 items on stack
assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    // Only 7 items - DUP8 will fail!
    dup8  // StackUnderflow
}

Safe Usage

assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    // Exactly 8 items - safe
    dup8  // Success
}

Implementation

/**
 * DUP8 opcode (0x87) - Duplicate 8th stack item
 *
 * Stack: [..., value, ...] => [..., value, ..., value]
 * Gas: 3 (GasFastestStep)
 */
export function handler_0x87_DUP8(frame: FrameType): EvmError | null {
  const gasErr = consumeGas(frame, FastestStep);
  if (gasErr) return gasErr;

  if (frame.stack.length < 8) {
    return { type: "StackUnderflow" };
  }

  const value = frame.stack[frame.stack.length - 8];
  const pushErr = pushStack(frame, value);
  if (pushErr) return pushErr;

  frame.pc += 1;
  return null;
}

Edge Cases

Stack Underflow

// Insufficient stack depth
const frame = createFrame({
  stack: [100n, 100n, 100n, 100n, 100n, 100n, 100n]  // Only 7 items
});

const err = handler_0x87_DUP8(frame);
console.log(err); // { type: "StackUnderflow" }

Stack Overflow

// Stack at maximum, can't add more
const frame = createFrame({
  stack: new Array(1024).fill(0n)
});

const err = handler_0x87_DUP8(frame);
console.log(err); // { type: "StackOverflow" }

Out of Gas

// Insufficient gas
const frame = createFrame({
  stack: [100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n],
  gasRemaining: 2n  // Need 3
});

const err = handler_0x87_DUP8(frame);
console.log(err); // { type: "OutOfGas" }

Maximum Value

// Duplicate max uint256
const MAX = (1n << 256n) - 1n;
const frame = createFrame({
  stack: [0n, 0n, 0n, 0n, 0n, 0n, 0n, MAX]
});

handler_0x87_DUP8(frame);
console.log(frame.stack[frame.stack.length - 1]); // MAX (duplicated)

References