The Ethereum Virtual Machine

delegatecall

DELEGATECALL is a special way for one contract to run another contract's code as if it were its own. With an ordinary CALL, the callee executes in its own home — its storage, its identity. With DELEGATECALL the borrowed code executes inside the caller's context: it reads and writes the caller's storage, sees the caller's address as 'this', and keeps the original msg.sender and msg.value. The analogy is hiring a contractor who works in your house, with your tools, on your belongings — they bring the know-how, you keep the state.

This single property is the engine behind almost all upgradeable smart contracts. A proxy contract holds all the storage and the funds, but contains almost no logic; when called, it delegatecalls into a separate 'implementation' (logic) contract. Because the logic runs against the proxy's storage, you can deploy a new implementation and point the proxy at it to 'upgrade' behavior while preserving every balance and setting. Libraries use the same trick: a library's functions delegatecalled by a contract operate directly on that contract's state.

The power comes with a sharp edge: storage layout must line up. The borrowed code addresses storage by slot number, so if the proxy and implementation disagree about which variable lives in slot 0, the code will read and write the wrong data — a storage collision. A notorious class of bugs follows: an implementation contract left uninitialized can be seized, and an attacker who controls the delegatecalled code controls the proxy's entire state. The 2017 Parity multisig freeze, which locked roughly 513,000 ETH, stemmed from delegatecall to a library whose initialization was triggered and then selfdestructed.

Because of this, DELEGATECALL must only ever target trusted, layout-compatible code. Standards like the transparent proxy, UUPS, and the diamond pattern exist precisely to manage delegatecall safely — disciplining storage layout, guarding initialization, and routing admin versus user calls so they cannot collide.

// minimal proxy forwarding
(bool ok, ) = implementation.delegatecall(msg.data);
require(ok);  // implementation runs on THIS contract's storage

The basis of upgradeable contracts: borrowed logic, local storage.

DELEGATECALL preserves the value context too: msg.value inside the borrowed code is whatever the original frame had, even though no new ETH is being sent by the delegatecall itself.