Coin Brief ENDE

EIP-7979 gets opcode numbers for CALLSUB, CALLDEST and RETURNSUB in the EVM

EIP-7979, "Call and Return Opcodes for the EVM", saw a run of six merged pull requests in the EIPs repository between 11 and 12 October. The central one, PR 12481 by author Greg Colvin, assigns the three new instructions their opcode values — CALLDEST = 0xBB, CALLSUB = 0xBC, RETURNSUB = 0xBF — and updates every reference implementation and test that still used placeholder values. The EIP remains a draft; nothing here schedules it for a network upgrade.

The problem it addresses. The EVM has no instruction for calling a subroutine and returning. Compilers synthesise both with JUMP, taking the return address from the data stack. The proposal argues this costs bytes and gas, and — its main point — hides control flow: a return is a jump whose destination is data, so a tool analysing a contract must consider every possible destination. Its companion EIP-8173 argues that such analysis can take quadratic or worse time, which for online uses — bytecode validation, ahead-of-time compilation at deployment, JIT compilation — is a denial-of-service risk.

What the three opcodes do.

  • CALLSUB pops a destination from the data stack, pushes PC + 1 onto a separate return stack and jumps. If the destination is not a CALLDEST, or the return stack already holds 1,024 entries, execution halts exceptionally.
  • CALLDEST marks a subroutine entry; like JUMPDEST it is otherwise a no-op and costs the same 1 gas. It is also a valid JUMP target, which lets a compiler turn a call into a tail jump.
  • RETURNSUB pops the return stack and continues there.
EIP-7979 gets opcode numbers for CALLSUB, CALLDEST and RETURNSUB in the EVM
EIP-7979 gets opcode numbers for CALLSUB, CALLDEST and RETURNSUB in the EVM — Coin Brief

The return stack is not readable or writable by contract code. The authors say the change is backwards compatible, and that 0xBD and 0xBE are deliberately left free for possible multi-way call and jump instructions.

Claimed gains. In the EIP's simple example, calling a routine that squares a number, the CALLSUB version uses 29% fewer bytes and 32% less gas than the jump-based one; the authors note the savings shrink as code grows and is better optimised. The larger benefit they claim is for compilers: code without dynamic jumps can be checked in one linear pass and compiled ahead of time or just in time. They also state the design does not preclude EOF, RISC-V or zero-knowledge execution.

What the merges changed. Besides the numbering, the PRs ported the per-entry "framing" rule to the C validator, reconciled the text with EIP-8173 and made editorial fixes. The author reports 47 of 47 test vectors and 500 fuzz cases passing, with a further 4,000 control-flow-heavy programs agreeing between the Python and C validators. The EIP itself notes that AI assistance was used, mainly for the reference implementation and tests.

Sources: EIPs PR 12481 — https://github.com/ethereum/EIPs/pull/12481 ; EIP-7979 — https://eips.ethereum.org/EIPS/eip-7979

Primary source
Ethereum EIPs (GitHub)
https://github.com/ethereum/EIPs/pull/12481