> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# CALLCODE (0xf2)

> Execute code in current context - DEPRECATED, use DELEGATECALL instead

<Warning>
  **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.
</Warning>

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

```
gas       (max gas to forward)
address   (target account code to execute)
value     (wei to send to caller's own address)
inOffset  (calldata memory offset)
inLength  (calldata size)
outOffset (returndata memory offset)
outLength (returndata size)
```

**Stack Output:**

```
success   (1 if call succeeded, 0 if failed)
```

**Gas Cost:** 700 + value\_transfer + cold\_access + memory\_expansion

**Operation:**

```
calldata = memory[inOffset:inOffset+inLength]
success = execute_code_in_caller_context(address.code, value, calldata, gas * 63/64)
memory[outOffset:outOffset+outLength] = returndata[0:min(outLength, returndata.length)]
push(success)
```

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

```typescript theme={null}
import { CALLCODE } from '@tevm/voltaire/evm/system';

// DON'T USE - deprecated opcode
const frame = createFrame({
  gasRemaining: 1000000n,
  address: Address("0x1234..."),
});

// Stack: [gas=100000, address, value=0, inOffset=0, inLength=0, outOffset=0, outLength=0]
frame.stack.push(0n);                               // outLength
frame.stack.push(0n);                               // outOffset
frame.stack.push(0n);                               // inLength
frame.stack.push(0n);                               // inOffset
frame.stack.push(0n);                               // value
frame.stack.push(BigInt("0x742d35Cc..."));          // address (code source)
frame.stack.push(100000n);                          // gas

// USE DELEGATECALL INSTEAD!
```

### Why CALLCODE is Confusing

```solidity theme={null}
contract Library {
    uint256 public value;

    function setValue(uint256 _value) external {
        value = _value;  // Modifies storage at slot 0
    }
}

contract Caller {
    uint256 public myValue;  // Storage slot 0

    function useCallCode(address library) external {
        // CALLCODE execution context:
        // - msg.sender = address(this) (NOT tx.origin!)
        // - msg.value = sent value
        // - storage = Caller's storage
        // - code = Library's code

        assembly {
            let success := callcode(
                gas(),
                library,
                0,        // Value sent to self (weird!)
                0,        // calldata
                0,
                0,        // returndata
                0
            )
        }

        // Library's setValue modified Caller.myValue!
        // But msg.sender in Library was Caller, not original caller
    }
}
```

### Correct Pattern: Use DELEGATECALL

```solidity theme={null}
contract Library {
    uint256 public value;

    function setValue(uint256 _value) external {
        value = _value;
    }
}

contract Caller {
    uint256 public myValue;

    // ✅ CORRECT: Use DELEGATECALL
    function useDelegateCall(address library) external {
        // DELEGATECALL execution context:
        // - msg.sender = original caller (preserved!)
        // - msg.value = original value (preserved!)
        // - storage = Caller's storage
        // - code = Library's code

        (bool success, ) = library.delegatecall(
            abi.encodeWithSignature("setValue(uint256)", 42)
        );
        require(success);

        // Clear semantics: Library code runs as if part of Caller
    }
}
```

### Migration Example

```solidity theme={null}
// ❌ OLD: Using CALLCODE (deprecated)
contract OldPattern {
    function callLibrary(address lib, bytes memory data) external {
        assembly {
            let success := callcode(
                gas(),
                lib,
                0,
                add(data, 0x20),
                mload(data),
                0,
                0
            )
            if iszero(success) { revert(0, 0) }
        }
    }
}

// ✅ NEW: Using DELEGATECALL
contract NewPattern {
    function callLibrary(address lib, bytes memory data) external {
        (bool success, ) = lib.delegatecall(data);
        require(success, "Delegatecall failed");
    }
}
```

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

```
if (value > 0) {
  cost += 9000  // CallValueTransferGas
}
```

**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:

```
if (firstAccess(address)) {
  cost += 2600  // ColdAccountAccess
} else {
  cost += 100   // WarmStorageRead
}
```

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

```solidity theme={null}
// VULNERABLE: Unexpected msg.sender
contract VulnerableAuth {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function updateOwner(address newOwner) external {
        // Assumes msg.sender is the transaction sender
        require(msg.sender == owner);
        owner = newOwner;
    }
}

contract Attacker {
    function exploit(address vulnerable, address lib) external {
        // Call library code via CALLCODE
        assembly {
            // In library code, msg.sender will be Attacker contract
            // NOT the original transaction sender!
            callcode(gas(), lib, 0, 0, 0, 0, 0)
        }
    }
}
```

### Storage Collision

Same storage collision risks as DELEGATECALL:

```solidity theme={null}
contract Library {
    address public implementation;  // Slot 0

    function upgrade(address newImpl) external {
        implementation = newImpl;
    }
}

contract Caller {
    address public owner;  // Slot 0 - COLLISION!

    function callLibrary(address lib) external {
        assembly {
            callcode(gas(), lib, 0, 0, 0, 0, 0)
        }
        // Library modified Caller.owner instead of implementation!
    }
}
```

### Value Transfer Confusion

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

```solidity theme={null}
contract ConfusingValue {
    function sendToSelf() external payable {
        assembly {
            // This sends msg.value to self - pointless!
            callcode(gas(), target, callvalue(), 0, 0, 0, 0)
        }
    }
}
```

## Why DELEGATECALL is Better

| Aspect         | CALLCODE           | DELEGATECALL           |
| -------------- | ------------------ | ---------------------- |
| msg.sender     | Caller (confusing) | Preserved (clear)      |
| msg.value      | Specified value    | Preserved (clear)      |
| Value transfer | To self (weird)    | No value transfer      |
| Use case       | NONE (deprecated)  | Library calls, proxies |
| Introduced     | Frontier           | Homestead (EIP-7)      |
| Status         | Deprecated         | Standard               |

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

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    /**
     * CALLCODE opcode (0xf2) - DEPRECATED
     * Execute code in current context
     */
    export function callcode(frame: FrameType): EvmError | null {
      // Pop 7 arguments (same as CALL)
      const gas = popStack(frame);
      const address = popStack(frame);
      const value = popStack(frame);
      const inOffset = popStack(frame);
      const inLength = popStack(frame);
      const outOffset = popStack(frame);
      const outLength = popStack(frame);

      // Calculate gas cost
      let gasCost = 700n;  // Base (Tangerine Whistle+)

      // Value transfer (even though to self)
      if (value > 0n) {
        gasCost += 9000n;
        // No new account cost - value sent to self
      }

      // Cold access cost (Berlin+)
      const accessCost = getAccessCost(address);
      gasCost += accessCost;

      // Memory expansion
      const inEnd = inLength > 0 ? inOffset + inLength : 0;
      const outEnd = outLength > 0 ? outOffset + outLength : 0;
      const maxEnd = Math.max(inEnd, outEnd);

      if (maxEnd > 0) {
        gasCost += memoryExpansionCost(frame, maxEnd);
        updateMemorySize(frame, maxEnd);
      }

      // Calculate forwarded gas (63/64 rule)
      const afterCharge = frame.gasRemaining - gasCost;
      const maxForward = afterCharge - afterCharge / 64n;
      const forwardedGas = min(gas, maxForward);

      // Charge total cost
      consumeGas(frame, gasCost + forwardedGas);

      // Read calldata
      const calldata = readMemory(frame, inOffset, inLength);

      // Execute in caller context with target's code
      const result = executeCallCode({
        codeAddress: address,      // Code to execute
        storageAddress: frame.address,  // Storage to modify
        sender: frame.address,     // msg.sender = caller
        value: value,              // msg.value = specified
        data: calldata,
        gas: forwardedGas
      });

      // Refund unused gas
      frame.gasRemaining += result.gasLeft;

      // Copy returndata
      const copySize = min(outLength, result.returnData.length);
      writeMemory(frame, outOffset, result.returnData.slice(0, copySize));

      // Set return_data buffer
      frame.returnData = result.returnData;

      // Push success flag
      pushStack(frame, result.success ? 1n : 0n);

      frame.pc += 1;
      return null;
    }
    ```
  </Tab>
</Tabs>

## References

* **[Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)** - Section 9.4.4 (CALLCODE)
* **[EIP-7](https://eips.ethereum.org/EIPS/eip-7)** - DELEGATECALL (replacement)
* **[evm.codes - CALLCODE](https://www.evm.codes/#f2)** - Interactive reference
* **[Solidity Docs](https://docs.soliditylang.org/)** - Deprecation notice
