Skip to main content
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.

Overview

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

Specification

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

Behavior

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

Examples

Basic Usage

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

// Duplicate 16th item
const frame = createFrame({
  stack: [1600n, 1500n, 1400n, 1300n, 1200n, 1100n, 1000n, 900n, 800n, 700n, 600n, 500n, 400n, 300n, 200n, 100n],
  gasRemaining: 1000n
});

const err = handler_0x8F_DUP16(frame);

console.log(frame.stack); // [1600n, 1500n, 1400n, 1300n, 1200n, 1100n, 1000n, 900n, 800n, 700n, 600n, 500n, 400n, 300n, 200n, 100n, 100n] - 16th 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 16 items
            dup16  // Duplicate 16th item to top
        }
    }
}

Assembly Usage

assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    push1 0x09
    push1 0x0a
    push1 0x0b
    push1 0x0c
    push1 0x0d
    push1 0x0e
    push1 0x0f
    push1 0x10
    // Stack: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10]

    dup16
    // Stack: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x01] - first item duplicated
}

Gas Cost

Cost: 3 gas (GasFastestStep) All DUP1-16 operations cost the same despite different stack depths accessed. Comparison:
OperationGasNote
DUP163Duplicate 16th 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
        let v9 := 9
        let v10 := 10
        let v11 := 11
        let v12 := 12
        let v13 := 13
        let v14 := 14
        let v15 := 15
        let v16 := 16

        // Access v1 from depth 16
        dup16
    }
}```

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

// DUP16 requires 16 items on stack
assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    push1 0x09
    push1 0x0a
    push1 0x0b
    push1 0x0c
    push1 0x0d
    push1 0x0e
    push1 0x0f
    // Only 15 items - DUP16 will fail!
    dup16  // StackUnderflow
}

Safe Usage

assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    push1 0x09
    push1 0x0a
    push1 0x0b
    push1 0x0c
    push1 0x0d
    push1 0x0e
    push1 0x0f
    push1 0x10
    // Exactly 16 items - safe
    dup16  // Success
}

Implementation

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

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

  const value = frame.stack[frame.stack.length - 16];
  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, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n]  // Only 15 items
});

const err = handler_0x8F_DUP16(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_0x8F_DUP16(frame);
console.log(err); // { type: "StackOverflow" }

Out of Gas

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

const err = handler_0x8F_DUP16(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, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, MAX]
});

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

References