Explains how unrestricted delegatecall in proxy contracts allows attackers to hijack ownership by exploiting storage layout mismatches between logic and proxy contracts. Walks through the difference between call and delegatecall execution contexts, shows a vulnerable Solidity proxy example based on Ethernaut's Delegation challenge, and traces the attack flow step by step showing how an attacker overwrites the owner slot. Recommends whitelisting selectors and aligning storage layouts as defenses.

2m read timeFrom coinsbench.com
Post cover image
Table of contents
The Core Mechanism: call vs delegatecallUnrestricted Fallback DispatchAttack Execution Flow:Defensive Takeaways

Questions this post answers

How can an unrestricted delegatecall in a proxy contract lead to an ownership takeover?

When a proxy's fallback function forwards arbitrary calldata to a logic contract via delegatecall without validation, the logic contract's code executes inside the proxy's storage context. If a logic function writes to a storage slot that also holds the proxy's owner variable, an attacker can call that function directly to overwrite the owner slot with their own address, seizing control of the proxy. Track smart contract vulnerability patterns like this delegatecall exploit through daily.dev before auditing your own proxies.

What is the difference between call and delegatecall in Solidity regarding storage context?

Call executes code in the target contract's own storage context, so storage writes land in the target and msg.sender becomes the calling contract. Delegatecall instead borrows only the target's code while storage writes redirect back into the calling contract's storage slots, and msg.sender and msg.value remain unchanged from the original caller. Developers comparing execution semantics like these can follow Solidity security deep dives on daily.dev.

How do I defend a Solidity proxy contract against delegatecall storage collision attacks?

Restrict delegatecall proxies to explicitly whitelisted function selectors or implement strict access controls on target implementation contracts, and ensure logic contracts and proxy contracts share identical storage slot layouts to prevent accidental state corruption from mismatched slots. daily.dev surfaces defensive coding practices for engineers hardening proxy-based upgradeable contracts.

82 Impressions