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:Behavior
CALLCODE executes foreign code with confusing context semantics:- Pop 7 stack arguments (same as CALL)
- 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
- Read calldata from memory
- Forward gas: Up to 63/64 of remaining gas (EIP-150)
- 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
- Value handling: ETH sent to caller’s own address (weird!)
- Copy returndata to memory
- Push success flag
- Storage operations affect caller, not target
- msg.sender is caller (not preserved from parent)
- Value sent to caller’s own address
- 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_gasBase Cost: 700 gas (Tangerine Whistle+)
Pre-Tangerine Whistle: 40 gasValue Transfer: +9,000 gas
Charged whenvalue > 0 (even though value sent to self):
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 setsmsg.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
- TypeScript
References
- Yellow Paper - Section 9.4.4 (CALLCODE)
- EIP-7 - DELEGATECALL (replacement)
- evm.codes - CALLCODE - Interactive reference
- Solidity Docs - Deprecation notice

