The goal of this level is for you to claim ownership of the instance you are given.
Things that might help:https://ethernaut.openzeppelin.com/level/6
- 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
We are given the following Solidity file that contains two contracts Delegate
and Delegation
.
Get your new instance and open your console.
According to the Solidity docs, delegatecall is similar to a call except it passes the original msg.sender and msg.value, rather than the contract making the call:
There exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and
https://docs.soliditylang.org/en/v0.8.6/introduction-to-smart-contracts.html?#delegatecall-callcode-and-librariesmsg.sender
andmsg.value
do not change their values.
Further reading from solidity-by-example:
When contract
https://solidity-by-example.org/delegatecall/A
executesdelegatecall
to contractB
,B
‘s code is executed with contractA
‘s storage,msg.sender
andmsg.value
.
Now that we have an understanding of delegatecall
, let’s take a look at the fallback function in the delegation contract:
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
And the pwn()
function from the delegate contract, that looks like how we will take ownership:
function pwn() public {
owner = msg.sender;
}
So we need to activate the fallback function in order to delegatecall passing msg.data along to the function.
First we need to encode our msg.data, “pwn()” in this case, so that it passes the function on to the delegate contract.
After packing the data we stored it in a variable pwn_data
and all that’s left is to send a transaction with our packed data.
Wait for the transaction to be mined and then confirm you are the contract.owner().
Success, I am the new owner of the contract.
Submit your instance, that’s it for this level.
Until the next one.
DAVE