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: 0xf2 Introduced: Frontier (EVM genesis) Status: DEPRECATED - Use DELEGATECALL (0xf4) instead CALLCODE executes code from another account in the caller’s storage context. Unlike CALL, storage modifications affect the caller. This opcode has confusing semantics and was superseded by DELEGATECALL in Homestead. WARNING: CALLCODE is deprecated and should not be used in new contracts. Use DELEGATECALL for library calls and code reuse patterns.

Specification

Stack Input:
Stack Output:
Gas Cost: 700 + value_transfer + cold_access + memory_expansion Operation:

Behavior

CALLCODE executes foreign code with confusing context semantics:
  1. Pop 7 stack arguments (same as CALL)
  2. Calculate gas cost:
    • Base: 700 gas (Tangerine Whistle+)
    • Value transfer: +9,000 gas if value > 0
    • Cold access: +2,600 gas for first access (Berlin+)
    • Memory expansion for input and output regions
  3. Read calldata from memory
  4. Forward gas: Up to 63/64 of remaining gas (EIP-150)
  5. Execute target’s code in caller’s context:
    • msg.sender = caller (NOT preserved from parent!)
    • msg.value = specified value
    • Storage = caller’s storage (modifications affect caller!)
    • Code = target’s code
    • address(this) = caller’s address
  6. Value handling: ETH sent to caller’s own address (weird!)
  7. Copy returndata to memory
  8. Push success flag
Key differences from CALL:
  • Storage operations affect caller, not target
  • msg.sender is caller (not preserved from parent)
  • Value sent to caller’s own address
Key differences from DELEGATECALL:
  • msg.sender is caller (DELEGATECALL preserves original sender)
  • msg.value is specified value (DELEGATECALL preserves original value)
  • Value handling is confusing

Examples

Basic CALLCODE (Don’t Do This!)

Why CALLCODE is Confusing

Correct Pattern: Use DELEGATECALL

Migration Example

Gas Cost

Total cost: 700 + value_transfer + cold_access + memory_expansion + forwarded_gas

Base Cost: 700 gas (Tangerine Whistle+)

Pre-Tangerine Whistle: 40 gas

Value Transfer: +9,000 gas

Charged when value > 0 (even though value sent to self):
Note: No new account cost - value sent to caller’s own address.

Cold Access: +2,600 gas (Berlin+)

EIP-2929 (Berlin+): First access to target address:

Memory Expansion

Same as CALL - charges for both input and output regions.

Gas Forwarding

Same as CALL - 63/64 rule applies (EIP-150).

Common Usage

None - this opcode is deprecated. Historical uses included:
  • Library pattern (replaced by DELEGATECALL)
  • Code reuse (replaced by DELEGATECALL)
  • Upgradeable contracts (replaced by DELEGATECALL + proxy patterns)

Security

Deprecated - Do Not Use

The primary security issue with CALLCODE is that it should not be used at all. Use DELEGATECALL instead.

Confusing msg.sender Semantics

CALLCODE sets msg.sender to the caller, not the original transaction sender:

Storage Collision

Same storage collision risks as DELEGATECALL:

Value Transfer Confusion

Value sent to caller’s own address creates confusing semantics:

Why DELEGATECALL is Better

DELEGATECALL advantages:
  • Preserves full execution context (msg.sender, msg.value)
  • Clear semantics for library pattern
  • No confusing value-to-self transfers
  • Industry standard for proxies and libraries

Implementation

References