Delegation | Ethernaut Level 6 Walk-Through

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
https://ethernaut.openzeppelin.com/level/6

We are given the following Solidity file that contains two contracts Delegate and Delegation.

Get your new instance and open your console.

Get new instance

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 msg.sender and msg.value do not change their values.

https://docs.soliditylang.org/en/v0.8.6/introduction-to-smart-contracts.html?#delegatecall-callcode-and-libraries

Further reading from solidity-by-example:

When contract A executes delegatecall to contract BB‘s code is executed with contract A‘s storage, msg.sender and msg.value.

https://solidity-by-example.org/delegatecall/

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

Success, I am the new owner of the contract.
Submit your instance, that’s it for this level.

Until the next one.

DAVE

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top