EIP-7 Adding the DELEGATECALL Instruction (DELEGATECALL)

Final · EVM & execution · EIP status Final · created 2015-11-15

Adds a new instruction, DELEGATECALL (0xf4), to the EVM. It executes another contract's code while preserving the original call's sender and value information.

Why it is needed

There was already a way for a contract to borrow another contract's code. The CALLCODE instruction lets you run code located at another address on top of your own storage. The problem with this is that the sender and value information ends up reflecting the intermediate contract rather than the original user. As a result, the borrowed code has no way to know who the original user was. Avoiding this requires a workaround of embedding the sender address in the first 20 bytes of the call data, which means the code must be compiled separately for delegation and the same code cannot be used for both delegate calls and normal calls at once. DELEGATECALL passes the sender and value from the parent call straight through to the child call, letting a contract execute code at another address almost as if it were running in its own environment.

What changes

Today

After EIP-7

Who is affected

In depth

Instruction and Operands

DELEGATECALL is a new opcode assigned to 0xf4 that takes six operands from the stack: gas (the gas available to the child code), to (the destination address holding the code to execute), in_offset (the memory offset where the input begins), in_size (the input size in bytes), out_offset (the memory offset to write the output to), and out_size (the size of the output scratch pad). The code is fetched from the to address, but the execution context (storage, etc.) belongs to the caller.

Gas Rules

Unlike CALL, it provides no basic stipend. The gas passed as an operand is all the callee receives. As with CALLCODE, no account creation occurs, so the upfront gas cost is always fixed at schedule.callGas + gas. Unused gas is refunded as usual.

Sender/Value Propagation and Depth Limit

In the callee's environment, CALLER and VALUE behave exactly as they did in the caller's environment. In other words, the parent call's sender and value propagate unchanged into the child call. The call depth limit of 1024 remains unchanged, so DELEGATECALL also increases the call stack depth by 1.

Difference from CALLCODE and Design Intent

The concept itself is similar to CALLCODE, but it differs in that it propagates sender and value from the parent scope to the child scope. This makes it much easier for a contract to treat another, replaceable address as a code store and pass calls straight through. Aside from reduced gas and an increased call stack depth, the child code runs in an environment essentially identical to the parent's, so it can freely reference msg.sender and msg.value.

Two Usage Examples from the Original Text

The first is splitting code to avoid the 3 million gas barrier. Depending on the value range in the call data, the delegate_call branches to several addresses such as ADDR1 and ADDR2, letting large code be split across multiple contracts while still behaving as one. The second is a contract whose code address can be changed. When the owner calls with a specific function selector (0x12345678), self.delegate is updated; all other calls are forwarded to the code at the self.delegate address.

Counterarguments and Responses

One counterargument is that the same functionality could be mimicked by putting the sender address in the first 20 bytes of the call data. The original text responds that this approach requires compiling the delegate contract's code separately, and the same code cannot be used in both delegate and normal contexts at once.

Activation and Status

Activated by the Homestead hard fork. It applies from block 1,150,000 on mainnet, from block 494,000 on the Morden testnet, and from block 0 on subsequent testnets. Its status is Final, a finalized specification.

Original EIP · ← EIPs