delegatecall is a low-level Solidity operation that executes another contract’s code in the calling contract’s own storage, balance, and `msg.sender` context. It powers upgradeable proxies, but it is dangerous: if the target is attacker-controlled, or the called code modifies storage slots that mean something different in the caller, an attacker can overwrite critical state (like the owner) or take over the contract. The fix is to delegatecall only trusted, immutable targets and align storage layouts. It maps to SWC-112.
What it is
A normal call runs the other contract’s code in its own context. `delegatecall` is different: it runs the other contract’s code but with the caller’s storage, balance, and `msg.sender`. In effect, "borrow that code and run it as if it were mine."
This is how upgradeable proxy patterns work (a proxy delegatecalls to an implementation). The danger is that the borrowed code can write the caller’s storage, so if it is malicious or mismatched, it can corrupt or hijack the calling contract.
How it works and example
Two classic failures:
- Untrusted target: a contract delegatecalls to an address the attacker controls (for example, set via an unprotected function). The attacker’s code runs in the contract’s context and overwrites the owner slot, then drains it. The Parity multisig incidents stemmed from delegatecall/
selfdestructon shared library code. - Storage collision: the implementation’s variable layout does not match the proxy’s, so writing one variable corrupts another (for example the admin slot). See proxy storage collision.
Documented for defensive context.
How to defend
- Only delegatecall trusted, immutable targets, never an address an attacker can set or influence.
- Use battle-tested proxy patterns (standard upgradeable proxy libraries) rather than hand-rolling delegatecall.
- Align storage layouts between proxy and implementation (use unstructured/EIP-1967 storage slots) to avoid collisions.
- Protect upgrade and target-setting functions with strong access control.
- Audit every delegatecall path and the proxy/implementation pairing.
References
- [1]SWC Registry: Smart Contract Weakness Classification(SWC Registry)
- [2]Solidity docs: Security considerations(Solidity)
- [3]MITRE CWE-829: Inclusion of Functionality from Untrusted Control Sphere(MITRE CWE)