Delegatecall & Call Injection Attacks
Smart Contract Vulnerability Deep Dive
Delegatecall & Call Injection Attacks: Complete Guide to Detection and Prevention
The Parity Wallet hack didn't just freeze $150 million - it proved that a single delegatecall vulnerability can permanently destroy an entire protocol. In November 2017, an attacker exploited an unprotected initialization function to become the owner of a shared library contract, then called selfdestruct to brick hundreds of wallets forever.
If you're building smart contracts, understanding how delegatecall works isn't optional - it's a matter of survival. This comprehensive guide covers everything you need to know, from the mechanics of the iconic Parity disaster to modern, battle-tested prevention techniques that will protect your protocol from call injection attacks.
What Is a Delegatecall Attack?
A delegatecall attack in Solidity occurs when a malicious actor exploits a smart contract that performs a delegatecall to a target address they can control.
Unlike the standard call function, delegatecall executes the target code within the context of the calling contract. This means it preserves msg.sender, msg.value, and most critically, the caller's storage layout. It's an incredibly powerful feature for building upgradeable contracts and proxies, but it comes with massive risks.
The Bank Vault Analogy
Think of delegatecall like giving someone the keys to your bank vault and asking them to organize it for you inside the vault itself.
If that person is trustworthy (like a pre-approved library contract), they'll do exactly what you expect. But if they're malicious (an attacker-controlled contract), they can rearrange everything - or just empty the vault entirely. That's the danger of delegatecall: you are essentially executing someone else's code with full, unrestricted access to your contract's state.
Why Delegatecall Attacks Are So Dangerous
Delegatecall vulnerabilities have caused some of the most devastating permanent losses in crypto history:
| Attack | Year | Impact |
|---|---|---|
| Parity Wallet Hack | 2017 | $150M frozen forever |
| Parity Wallet (First Attack) | 2017 | $30M stolen |
| Various Proxy Exploits | 2018-2023 | $50M+ combined |
For seasoned auditors and attackers alike,
delegatecallis often considered the most dangerous opcode in Solidity because it hands foreign code complete access to your contract's storage without restriction.
Call vs Delegatecall: The Critical Difference
Understanding the distinction between these two opcodes is a non-negotiable requirement for secure Solidity development:
| Feature | call |
delegatecall |
|---|---|---|
| Execution Context | Target contract | Calling contract |
| Storage Access | Target's storage | Caller's storage |
| msg.sender | Caller's address | Original sender (preserved) |
| msg.value | Can be set | Preserved from original |
| Use Case | Calling external functions | Logic libraries & Proxies |
| Risk Level | Moderate | Critical |
Think of call as visiting a friend's house. You might ask them to do something, but you can't just rearrange their furniture. But delegatecall? That's inviting a complete stranger into your house and telling them to redecorate however they want.
The Parity Wallet Hack: The $150 Million Freeze
The Parity Wallet hack wasn't just a bug - it was a $150 million lesson that changed how we think about proxy patterns forever.
What Was Parity Wallet?
Parity was one of the most popular Ethereum wallets and node implementations, created by Gavin Wood (Ethereum co-founder).
The architecture was elegant:
-
Multi-signature wallets for enhanced security
-
Shared library contract to reduce deployment costs
-
Wallets used
delegatecallto access library functions
The scale was massive:
-
Hundreds of multi-sig wallets deployed
-
Millions in ETH stored across the network
-
Trusted by major projects and organizations
The First Attack: July 2017
In July 2017, the first Parity Wallet vulnerability was exploited. An attacker discovered that the library's initWallet() function could be called on individual wallet instances, allowing ownership takeover.
Result: $30 million stolen.
Parity patched the vulnerability, but in doing so, they introduced an even more catastrophic flaw.
The Second Attack: November 6, 2017
This is where disaster truly struck.
A user named "devops199" discovered that the library contract itself had never been initialized. The patched code allowed anyone to call initWallet() directly on the library - not through a proxy, but on the actual library contract.
"I accidentally killed it." - devops199, after triggering the vulnerability
Here's what happened:
-
devops199 called
initWallet()on the library contract -
They became the owner of the shared library
-
They called
kill()(selfdestruct) to "fix" the mistake -
The library code was permanently destroyed
-
All wallets delegating to that library became frozen
The Aftermath
Unlike a traditional hack where funds are stolen, this was permanent destruction.
The numbers were staggering:
-
$150 million in ETH frozen forever
-
587 wallets permanently disabled
-
No recovery mechanism possible
-
Funds remain locked to this day
The Parity Wallet hack demonstrated a terrifying truth: selfdestruct called via delegatecall destroys the calling contract, not the library. When the library was destroyed, every proxy contract pointing to it became a hollow shell - unable to execute any code, unable to move any funds.
This single rule would have prevented both Parity Wallet hacks. The $150 million frozen forever remains a permanent reminder that delegatecall grants foreign code complete access to your contract's storage.
How Delegatecall Attacks Work: Step-by-Step
Understanding the attack mechanism is crucial for prevention. Let's break down the anatomy of a delegatecall exploit.
The Attack Flow
| Step | What Happens | State |
|---|---|---|
| 1 | Attacker identifies vulnerable contract | Contract has delegatecall with user-controlled target |
| 2 | Attacker deploys malicious contract | Storage slots aligned with victim |
| 3 | Attacker calls vulnerable function | Passes malicious contract address |
| 4 | Victim executes delegatecall |
Code runs in victim's context |
| 5 | Malicious code modifies storage | owner variable overwritten |
| 6 | Attacker now owns the contract | Full control achieved |
The Four Critical Phases
Phase 1: Reconnaissance
The attacker identifies a contract with a delegatecall that accepts user input for the target address.
Phase 2: Payload Preparation The attacker deploys a malicious contract with a storage layout matching the victim's. This ensures variables align correctly during the attack.
Phase 3: Execution
The attacker calls the vulnerable function, passing their malicious contract address. The victim contract executes delegatecall, running the attacker's code with full access to the victim's storage.
Phase 4: Exploitation
The malicious code overwrites critical state variables (like owner) or executes selfdestruct to permanently destroy the contract.
The attacker identifies a contract with a delegatecall that accepts user input for the target address - or finds an uninitialized library contract.
Deploy a malicious contract with a storage layout matching the victim's. Storage Slot 0 must align with the victim's owner variable for the takeover to work.
Call the vulnerable function with the malicious contract address. The victim executes delegatecall, running the attacker's code with full access to the victim's storage.
The malicious code overwrites owner (takeover) or calls selfdestruct (permanent destruction). The attacker now controls - or has destroyed - the contract.
Want to execute this attack yourself in a safe lab? The Smart Contract Hacking course includes hands-on delegatecall exercises where you'll exploit vulnerable contracts - exactly like real security researchers do.
{
"title": "🎬 Storage collision: delegatecall overwrites the proxy's owner",
"stage": { "width": 920, "height": 440 },
"nodes": [
{ "id": "attacker", "label": "Attacker", "role": "deploys + calls", "emoji": "🧑💻", "x": 60, "y": 200, "color": "red" },
{ "id": "proxy", "label": "The Proxy", "role": "owner @ slot 0", "emoji": "🏦", "x": 440, "y": 60, "color": "cyan" },
{ "id": "evil", "label": "Malicious Lib", "role": "pwn() writes slot 0", "emoji": "📜", "x": 440, "y": 330, "color": "purple" }
],
"links": [
{ "from": "attacker", "to": "proxy" },
{ "from": "proxy", "to": "evil" },
{ "from": "evil", "to": "proxy" },
{ "from": "attacker", "to": "evil" }
],
"nets": [
{ "id": "ctrl", "label": "Proxy owner" }
],
"legend": [
{ "cls": "call", "label": "call / delegatecall" },
{ "cls": "token", "label": "value moved" },
{ "cls": "sig", "label": "storage write" },
{ "cls": "fail", "label": "reverted / destroyed" }
],
"scenarios": {
"Vulnerable (user-controlled target)": [
{ "note": "VulnerableDelegator keeps <b>owner</b> at storage slot 0 and exposes execute(target, data) that delegatecalls <b>any</b> address.", "hi": ["proxy"], "bal": { "proxy": "owner: deployer", "evil": "-" }, "net": { "ctrl": "deployer" } },
{ "note": "Attacker deploys a malicious lib whose slot 0 is also an address - layouts aligned.", "hi": ["attacker","evil"], "chip": { "from": "attacker", "to": "evil", "label": "deploy lib", "cls": "call" }, "bal": { "evil": "writes slot 0" } },
{ "note": "Attacker calls <b>execute(evilLib, pwn())</b> on the proxy.", "hi": ["attacker","proxy"], "chip": { "from": "attacker", "to": "proxy", "label": "execute(evil, pwn)", "cls": "call" } },
{ "note": "The proxy <b>delegatecalls</b> the lib: the lib's code runs in the proxy's storage context.", "tone": "bad", "hi": ["proxy","evil"], "chip": { "from": "proxy", "to": "evil", "label": "delegatecall", "cls": "call" } },
{ "note": "pwn() writes slot 0 - but slot 0 is the proxy's <b>owner</b>. The attacker is now owner.", "tone": "bad", "hi": ["evil","proxy"], "chip": { "from": "evil", "to": "proxy", "label": "slot 0 = attacker", "cls": "sig" }, "bal": { "proxy": "owner: ATTACKER" }, "net": { "ctrl": "ATTACKER" } },
{ "note": "Owning the proxy, the attacker drains it - or selfdestructs the library and freezes everything (Parity: $150M).", "tone": "bad", "hi": ["attacker","proxy"], "chip": { "from": "attacker", "to": "proxy", "label": "drain / selfdestruct", "cls": "fail" } }
],
"Fixed (fixed, trusted target)": [
{ "note": "The fix removes the user-controlled target: the proxy delegatecalls only a <b>fixed, audited</b> implementation - the address is hardcoded, not passed by the caller.", "hi": ["proxy"], "bal": { "proxy": "owner: deployer", "evil": "-" }, "net": { "ctrl": "deployer" } },
{ "note": "Attacker calls execute(evilLib, ...) - but the target is no longer caller-supplied, so the malicious address is rejected.", "tone": "ok", "hi": ["attacker","proxy"], "chip": { "from": "attacker", "to": "proxy", "label": "evil target rejected", "cls": "fail" } },
{ "note": "Any delegatecall now lands on trusted library code only - no attacker bytecode ever touches the proxy's storage.", "tone": "ok", "hi": ["proxy"] },
{ "note": "Slot 0 (owner) is never attacker-writable. The proxy stays under its rightful owner.", "tone": "ok", "hi": ["proxy"], "bal": { "proxy": "owner: safe" }, "net": { "ctrl": "deployer" } }
]
}
}
Delegatecall Vulnerable Code Example
Let's examine the classic vulnerability pattern that enables delegatecall attacks.
Warning: This contract is intentionally vulnerable. Never use this pattern in production.
The Vulnerable Execute Function
// VULNERABLE CONTRACT - DO NOT USE IN PRODUCTION
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract VulnerableDelegator {
// Storage Slot 0: Critical state variable
address public owner;
constructor() {
owner = msg.sender;
}
// VULNERABILITY: Allows delegatecall to arbitrary user-supplied address
function execute(address target, bytes memory data) public {
// This executes code at `target` inside THIS contract's context
// An attacker can pass a malicious contract that overwrites `owner`
(bool success, ) = target.delegatecall(data);
require(success, "Execution failed");
}
}
Why Is This Vulnerable?
The problem is the user-controlled target address:
-
Anyone can call
execute()with any address -
The target code runs with full access to this contract's storage
-
No validation of the target address
-
No access control on the function
-
Attacker can overwrite
ownerat storage slot 0
This single function is all an attacker needs to take complete control of the contract.

Delegatecall Attacker Contract Example
Here's how an attacker exploits the vulnerable delegator.
// ATTACKER CONTRACT - Educational purposes only
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract DelegatecallAttacker {
// CRITICAL: Must mirror the storage layout of the victim
// Storage Slot 0 must match VulnerableDelegator's 'owner' variable
address public owner;
// This function will be executed via delegatecall in victim's context
function pwn() public {
// When run via delegatecall, 'owner' refers to victim's storage slot 0
// msg.sender is preserved from the original transaction (the attacker)
owner = msg.sender;
}
// Alternative: Destroy the victim contract entirely (Parity-style)
function destroy() public {
// When called via delegatecall, selfdestruct destroys the CALLING contract
// This is how the Parity Wallet hack permanently froze $150M
selfdestruct(payable(msg.sender));
}
// Execute the attack
function attack(address vulnerable) external {
// Encode the call to pwn()
bytes memory payload = abi.encodeWithSignature("pwn()");
// Call the vulnerable contract's execute function
(bool success, ) = vulnerable.call(
abi.encodeWithSignature("execute(address,bytes)", address(this), payload)
);
require(success, "Attack failed");
}
}
Attack Execution Summary
-
Deploy attacker contract with matching storage layout
-
Call
attack()with the vulnerable contract's address -
Execute triggers
delegatecallto attacker'spwn()function -
Overwrite
ownervariable is set to attacker's address -
Control attacker now owns the vulnerable contract
In the Parity hack, the attacker used
destroy()instead ofpwn(), permanently bricking the contract rather than just taking ownership.
Ready to write exploits like this yourself? The Smart Contract Hacking course covers delegatecall attacks in-depth with real-world scenarios. Learn from JohnnyTime (12+ years in cybersecurity) and Trust (#1 Code4rena warden).
How to Prevent Delegatecall Attacks: Best Practices
Preventing delegatecall vulnerabilities requires a defense-in-depth strategy. Here are the industry-standard techniques.
What it does: Uses immutable or owner-only setter for the delegatecall target. Users can never control which code executes.
When to use: Every contract that uses delegatecall. This is the cardinal rule of delegatecall security.
Limitation: Immutable addresses can't be upgraded. Owner-only setters require trust in the admin.
What it does: Battle-tested proxy implementations (Transparent, UUPS, Beacon) with proper access controls and storage management.
When to use: Any upgradeable contract architecture. Never roll your own proxy logic.
Limitation: Added complexity. Must maintain consistent storage layouts across upgrades.
What it does: Uses OpenZeppelin's Initializable contract to ensure initialize() can only be called once. Prevents the exact Parity vulnerability.
When to use: Every proxy/library contract. Initialize the implementation contract in the constructor or immediately after deployment.
Limitation: Developers sometimes forget to initialize the implementation contract directly (not just through the proxy).
1. Never Accept User-Supplied Delegatecall Targets
This is the cardinal rule of delegatecall security.
Warning: Never use
delegatecallwith an address supplied by users or untrusted sources. This single rule prevents the majority of delegatecall exploits.
2. Hardcode Trusted Library Addresses
If your contract delegates logic to a library, hardcode the address or store it in a protected state variable:
| Approach | Security Level | Flexibility |
|---|---|---|
Hardcoded immutable |
Highest | None |
| Owner-only setter | High | Upgradeable |
| Governance-controlled | High | DAO-managed |
| User-supplied | Vulnerable | Maximum |
3. Use Access Control Modifiers
Restrict delegatecall-enabled functions:
modifier onlyOwner() {
require(msg.sender == owner, "Not authorized");
_;
}
function execute(bytes memory data) public onlyOwner {
// Only owner can trigger delegatecall
}
4. Implement Storage Layout Protection
When using proxy patterns, ensure storage layouts between proxy and implementation contracts are perfectly aligned:
// Use explicit storage slots (EIP-1967)
bytes32 private constant IMPLEMENTATION_SLOT =
bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
5. Use OpenZeppelin's Proxy Libraries
For upgradeable contracts, use battle-tested patterns:
-
Transparent Proxy Pattern - Admin functions separated from user calls
-
UUPS (Universal Upgradeable Proxy Standard) - Upgrade logic in implementation
-
Beacon Proxy - Multiple proxies sharing one implementation
Never roll your own delegatecall logic.
6. Protect Initialization Functions
Ensure initialization functions can only be called once:
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract SecureLibrary is Initializable {
function initialize() public initializer {
// Can only be called once
}
}
Delegatecall Secure Code Example
Here's a production-ready implementation combining multiple defense mechanisms.
// SECURE CONTRACT - Production-ready
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract SecureDelegator {
// Storage Slot 0: Protected owner address
address public owner;
// Storage Slot 1: Trusted library (not user-controllable)
address public trustedLibrary;
// Events for transparency and monitoring
event LibraryUpdated(address indexed oldLibrary, address indexed newLibrary);
event ExecutionCompleted(bytes data, bytes returnData);
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
constructor(address _trustedLibrary) {
require(_trustedLibrary != address(0), "Invalid library address");
owner = msg.sender;
trustedLibrary = _trustedLibrary;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not authorized");
_;
}
// SECURE: Users cannot choose the delegatecall target
function execute(bytes memory data) public returns (bytes memory) {
require(trustedLibrary != address(0), "Library not set");
// Delegatecall to pre-approved library only
(bool success, bytes memory returnData) = trustedLibrary.delegatecall(data);
require(success, "Execution failed");
emit ExecutionCompleted(data, returnData);
return returnData;
}
// PROTECTED: Only owner can update the library
function updateLibrary(address _newLibrary) public onlyOwner {
require(_newLibrary != address(0), "Invalid library address");
require(_newLibrary != trustedLibrary, "Same library");
address oldLibrary = trustedLibrary;
trustedLibrary = _newLibrary;
emit LibraryUpdated(oldLibrary, _newLibrary);
}
// Two-step ownership transfer for safety
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0), "Invalid new owner");
address oldOwner = owner;
owner = _newOwner;
emit OwnershipTransferred(oldOwner, _newOwner);
}
}
Security Features at a Glance
| Feature | Protection |
|---|---|
| Hardcoded library target | Prevents user-controlled delegatecall |
onlyOwner modifier |
Access control on sensitive functions |
| Address validation | Prevents zero-address attacks |
| Event emissions | Transparency and monitoring |
| Two-step ownership | Prevents accidental ownership loss |
This implementation would have prevented both Parity Wallet hacks and countless other delegatecall exploits.
Types of Call Attacks Beyond the Basics
As smart contract architectures become more complex, so do attack vectors.
1. Storage Collision Attacks
When proxy and implementation storage layouts don't align, attackers can manipulate critical variables:
// Proxy: Slot 0 = implementation address
// Implementation: Slot 0 = arbitrary value
// Setting Implementation.value overwrites Proxy.implementation!
Prevention: Use EIP-1967 storage slots and maintain consistent layouts across upgrades.
2. Selfdestruct via Delegatecall
The Parity hack's signature move. When selfdestruct is called via delegatecall, it destroys the calling contract:
contract Library {
function kill() public {
selfdestruct(payable(msg.sender)); // Destroys CALLER
}
}
Prevention: Never include selfdestruct in library contracts. Use access controls if absolutely necessary.
3. Constructor vs Initializer Confusion
Proxy patterns don't use constructors (they run during deployment only). Unprotected initialize() functions create vulnerabilities:
// VULNERABLE: Anyone can call initialize on the library directly
function initialize() public {
owner = msg.sender;
}
Prevention: Use OpenZeppelin's Initializable contract with the initializer modifier.
4. Delegatecall in Fallback Functions
Forwarding all calls via delegatecall in fallback functions is powerful but dangerous:
fallback() external payable {
address target = implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
// ...
}
}
Prevention: Ensure implementation can never be modified by untrusted parties.
These advanced patterns separate junior auditors from senior researchers. The Smart Contract Hacking course covers storage collisions, proxy vulnerabilities, and advanced delegatecall attacks alongside flash loans, oracle manipulation, and more. Join 2,000+ security researchers in our Discord community.
User-Controlled Target
Accepting delegatecall targets from user input gives attackers full storage access. This is the root cause of most delegatecall exploits and should never be allowed.
Owner-Only Upgrade
Restricting delegatecall targets to admin-set addresses helps, but centralization risk remains. Admin key compromise can still lead to exploitation.
OZ Proxy + Timelock + Audit
OpenZeppelin proxy patterns with governance timelocks and professional audits provide the safest upgradeable architecture available today.
Common Misconceptions About Delegatecall
"Delegatecall is inherently unsafe and should never be used."
Tap to revealDelegatecall is essential for upgradeable contracts and is used safely by major protocols. The danger is user-controlled targets - not the opcode itself.
"selfdestruct via delegatecall destroys the library."
Tap to revealWhen selfdestruct is called via delegatecall, it destroys the calling contract (the proxy), not the library. This is exactly how the Parity hack froze $150M permanently.
"Proxy patterns are safe as long as you use a well-known framework."
Tap to revealEven OpenZeppelin proxies require careful implementation - consistent storage layouts, proper initialization of both proxy and implementation, and correct access control configuration.
"The Parity wallet funds are lost forever."
Tap to reveal587 wallets holding $150M in ETH remain permanently frozen. The destroyed library contract cannot be restored, and no recovery mechanism exists on the Ethereum network.
Related Vulnerabilities
Delegatecall vulnerabilities share a common thread with reentrancy attacks - both exploit the dangers of external calls in smart contracts. While reentrancy abuses callback mechanisms during value transfers, delegatecall attacks exploit execution context preservation. Mastering one requires understanding the other, as both stem from Solidity's external call semantics.
In complex DeFi exploits, delegatecall vulnerabilities are sometimes combined with flash loan attacks to provide the capital needed to interact with proxy contracts at scale, or to manipulate governance systems that control upgradeable proxies.
Quick Reference: Delegatecall Prevention Checklist
Before deploying any contract that uses delegatecall:
-
Never accept user-supplied delegatecall targets - the cardinal rule
-
Hardcode trusted library addresses or use owner-only setters
-
Use OpenZeppelin proxy patterns for upgradeability (never roll your own)
-
Protect initialization functions with
initializermodifier -
Maintain consistent storage layouts between proxy and implementation
-
Use EIP-1967 storage slots for proxy-specific variables
-
Implement access controls on all delegatecall-enabled functions
-
Never include selfdestruct in library contracts
-
Emit events for all library updates and ownership changes
-
Get professional audits before mainnet deployment
-
Monitor deployed contracts for suspicious delegatecall patterns
Test Your Delegatecall Knowledge
5 questions - Do you understand the most dangerous opcode?
Frequently Asked Questions About Call Attacks
A delegatecall attack is when a malicious contract tricks another contract into running harmful code using delegatecall - like handing someone the keys to your house and having them rearrange or destroy everything inside.
call executes code in the target contract's context - changes happen in the target. delegatecall executes target code in the caller's context - changes happen in YOUR contract, making it dangerous when the target is untrusted.
Over $200 million has been lost or frozen due to delegatecall vulnerabilities. The Parity Wallet hack alone accounts for $150 million frozen permanently - funds that remain inaccessible to this day.
Yes, when implemented correctly using established standards like OpenZeppelin's Transparent Proxy or UUPS. Never implement custom proxy patterns without thorough security review. Proper initialization and consistent storage layouts are essential.
Yes, and it's devastating. When selfdestruct is called via delegatecall, it destroys the calling contract, not the library. The Parity Wallet hack used this to permanently freeze $150 million.
Conclusion: Learn From the $150 Million Mistake
The Parity Wallet hack isn't just a technical footnote - it's a permanent reminder that:
-
Delegatecall is the most dangerous opcode in Solidity
-
User-controlled delegatecall targets are critical vulnerabilities
-
Even "accidental" exploits can cause irreversible damage
-
The funds remain frozen to this day - a permanent monument to the risk
The good news? Delegatecall attacks are completely preventable.
Never accept user-supplied targets. Use battle-tested proxy libraries. Protect your initialization functions. Get professional audits.
Don't let your protocol become the next cautionary tale.
Take Your Security Skills to the Next Level
Understanding delegatecall attacks is just the beginning. To become a professional smart contract auditor, you need hands-on experience with real exploit scenarios.
The Smart Contract Hacking course delivers:
-
320+ videos covering delegatecall, reentrancy, flash loans, oracle manipulation, and more
-
40+ hands-on exercises exploiting and securing real contracts
-
Expert instruction from JohnnyTime, Trust (#1 Code4rena warden), and Pashov
-
2,000+ member Discord for support and job opportunities
-
SSCH Certification to validate your expertise
Our students win audit contests, land security jobs, and earn significant bug bounties. See their success stories.
Sources and editorial notes
Reviewed by JohnnyTime. Last updated .
Real Delegatecall & Call Injection Attacks hacks to study
A stable selection of high-signal incidents linked to this attack class, ordered by reported loss and recency.
Master Delegatecall & Call Injection Attacks in a safe lab
Practice the exploit path, debug the vulnerable code, and learn the prevention workflow auditors use in real reviews.