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: 0x50
Introduced: Frontier (EVM genesis)
POP removes the top item from the stack without using its value. Used to discard unneeded computation results or clean up the stack.
Specification
Stack Input:
Stack Output:
Gas Cost: 2 (GasQuickStep)
Operation:
Behavior
POP discards the top stack item. The value is not returned or used - it simply removes one item from the stack depth.
Key characteristics:
- Requires stack depth ≥ 1
- Does not return the popped value
- Decreases stack depth by 1
- Cannot fail on empty stack (reverts with StackUnderflow)
Examples
Basic Usage
import { handler_0x50_POP } from '@tevm/voltaire/evm/stack/handlers';
import { createFrame } from '@tevm/voltaire/evm/Frame';
// Discard top value
const frame = createFrame({
stack: [42n, 100n],
gasRemaining: 1000n
});
const err = handler_0x50_POP(frame);
console.log(frame.stack); // [42n] - top value removed
console.log(frame.gasRemaining); // 998n
Solidity Compilation
contract Example {
function discard() public pure returns (uint256) {
uint256 a = 10;
uint256 b = 20;
// b not used - compiler inserts POP
return a;
}
}
// Generated bytecode:
// PUSH1 0x0a (push 10)
// PUSH1 0x14 (push 20)
// POP (discard b)
// ... (return a)
Assembly Usage
assembly {
// Clean up unused return values
let x := 100
let y := add(x, 50) // Stack: [150]
pop // Discard result
// Stack: []
}
Gas Cost
Cost: 2 gas (GasQuickStep)
POP is one of the cheapest stack operations, same tier as:
Cheaper than:
- PUSH1-32 (0x60-0x7f): 3 gas
- DUP1-16 (0x80-0x8f): 3 gas
- SWAP1-16 (0x90-0x9f): 3 gas
Common Usage
Discarding Return Values
contract TokenSwap {
IERC20 token;
function swap() public {
// Transfer returns bool, but we don't check it
assembly {
// CALL returns success on stack
// If we don't need it:
pop // Discard return value
}
}
}
Stack Cleanup
assembly {
// After complex computation
let a := add(1, 2) // Stack: [3]
let b := mul(a, 4) // Stack: [3, 12]
let c := div(b, 2) // Stack: [3, 12, 6]
// Only need final result
swap2 // Stack: [6, 12, 3]
pop // Stack: [6, 12]
pop // Stack: [6]
}
Optimizing Storage Reads
function getBalance(address user) public view returns (uint256) {
assembly {
// Load storage slot
mstore(0, user)
mstore(32, 0)
let slot := keccak256(0, 64)
let balance := sload(slot)
// Clean up memory (optional optimization)
mstore(0, 0) // Stack: [0]
pop // Clean stack
mstore(32, 0) // Stack: [0]
pop // Clean stack
// Return balance
mstore(0, balance)
return(0, 32)
}
}
Security
Stack Underflow Protection
// UNSAFE: Assumes stack has value
assembly {
pop // Reverts if stack empty!
}
// SAFE: Check before popping
function safePop() public pure {
assembly {
// Solidity ensures stack safety
let x := 100
pop // Safe, x on stack
}
}
Double Spending Prevention
// DANGEROUS: Forgetting to pop
contract Vulnerable {
mapping(address => uint256) balances;
function withdraw() public {
assembly {
// Load balance
let bal := sload(balances.slot)
// Transfer (leaves success on stack)
// Forgot to POP success value!
// Next operation uses wrong value!
}
}
}
Gas Waste
// INEFFICIENT: Unnecessary computation
function waste() public pure returns (uint256) {
uint256 x = expensiveComputation(); // Gas spent
pop(x); // Result discarded!
return 42;
}
// EFFICIENT: Don't compute if not needed
function efficient() public pure returns (uint256) {
return 42;
}
Optimization
Avoid Unnecessary Pushes
// BAD: Push then immediately pop
assembly {
push1 0x42
pop
}
// GOOD: Don't push at all
assembly {
// Nothing
}
Reorder to Minimize POPs
// INEFFICIENT: Many POPs
assembly {
let a := 1
let b := 2
let c := 3
pop // Discard c
pop // Discard b
// Use a
}
// EFFICIENT: Avoid intermediate variables
assembly {
let a := 1
// Use a directly
}
Implementation
import { consumeGas } from "../../Frame/consumeGas.js";
import { popStack } from "../../Frame/popStack.js";
import { FastestStep } from "../../../primitives/GasConstants/BrandedGasConstants/constants.js";
/**
* POP opcode (0x50) - Remove top item from stack
*
* Stack: [value] => []
* Gas: 2 (GasQuickStep)
*/
export function handler_0x50_POP(frame: FrameType): EvmError | null {
const gasErr = consumeGas(frame, FastestStep);
if (gasErr) return gasErr;
const { error } = popStack(frame);
if (error) return error;
frame.pc += 1;
return null;
}
Edge Cases
Empty Stack
// Stack underflow
const frame = createFrame({ stack: [] });
const err = handler_0x50_POP(frame);
console.log(err); // { type: "StackUnderflow" }
Single Item Stack
// Success case
const frame = createFrame({ stack: [100n] });
const err = handler_0x50_POP(frame);
console.log(err); // null
console.log(frame.stack); // []
Out of Gas
// Insufficient gas
const frame = createFrame({
stack: [42n],
gasRemaining: 1n
});
const err = handler_0x50_POP(frame);
console.log(err); // { type: "OutOfGas" }
Maximum Stack Depth
// Works at any depth
const frame = createFrame({
stack: new Array(1024).fill(0n)
});
const err = handler_0x50_POP(frame);
console.log(err); // null
console.log(frame.stack.length); // 1023
References