✅Delegation
delegatecall
Last updated
delegatecall
Last updated
The goal of this level is for you to claim ownership of the instance you are given.
Things that might help:
Look into Solidity's documentation on the delegatecall
low level function, how it works, how it can be used to delegate operations to on-chain libraries, and what implications it has on execution scope.
Fallback methods
Method ids
My comment: It is important to understand why delegatecall
is useful. Recall that if a smart contract is deployed to the blockchain then we can't be modified its code no more. All the logic implemented in the contract will stay there forever, unless we selfdestruct the contract and deploy a new one. To get around this, we can use delegatecall
to call a "library" contract where new logic is implemented.
Two key points:
The contract Delegation
implements a fallback()
function that executes delegatecall()
.
The contract Delegate
implements a suspicious function pwn()
that sets msg.sender
as the owner.
For convenience, lets define the following aliases:
The attacker -> A
Delegation -> B
Delegate -> C
The idea is A calls B (delegate)calls C. Symbolically, A -> B -> C. When A -> B, we send a transaction to trigger the fallback()
function in B. Here B initializes the delegatecall B -> C. If you watch Smart Contract Programmer's video, you should know that:
The delegatecall preserves A's context. In this case, we have msg.sender == A
.
The delegatecall acts on B's state variable (in contrast, a normal "call" acts on C's state variable).
In C, when pwn()
is called, the owner
state variable refers to B's owner
(instead of C's owner, since it is a delegatecall). The msg.sender
here is A. In other words, the function pwn()
sets A as B's owner, and we are done.
Send a transaction to Delegation
and calls the pwn()
function:
Since pwn()
is not defined in Delegation
, the fallback()
function will be triggered. After that, Delegation
does delegatecall()
and calls the pwn()
function in Delegate
. When pwn()
is called, it updates owner
to msg.sender
, which is the attacker.
Note that this owner
refers to the owner of Delegation
since Delegation
is doing the delegatecall()
.
Confirm the owner:
Click "Submit instance" and move on to the next level.
Usage of delegatecall
is particularly risky and has been used as an attack vector on multiple historic hacks. With it, your contract is practically saying "here, -other contract- or -other library-, do whatever you want with my state". Delegates have complete access to your contract's state. The delegatecall
function is a powerful feature, but a dangerous one, and must be used with extreme care.
Please refer to the The Parity Wallet Hack Explained article for an accurate explanation of how this idea was used to steal 30M USD.