> For the complete documentation index, see [llms.txt](https://ret2basic.gitbook.io/ctfwriteup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/ethernaut/delegation.md).

# Delegation

## Description

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

## Background Knowledge

### delegatecall

{% embed url="<https://youtu.be/uawCDnxFJ-0>" %}
Delegatecall - Smart Contract Programmer
{% endembed %}

**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.

### delegatecall vulnerability

{% embed url="<https://github.com/ethereumbook/ethereumbook/blob/develop/09smart-contracts-security.asciidoc#delegatecall>" %}
DELEGATECALL - Mastering Ethereum
{% endembed %}

## Code Audit

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Delegate {

  address public owner;

  constructor(address _owner) public {
    owner = _owner;
  }

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

contract Delegation {

  address public owner;
  Delegate delegate;

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

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

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.

## Solution

Send a transaction to `Delegation` and calls the `pwn()` function:

```javascript
await contract.sendTransaction({data: web3.utils.keccak256("pwn()")})
```

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:

```javascript
await contract.owner()
```

Click "Submit instance" and move on to the next level.

## Summary

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](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) article for an accurate explanation of how this idea was used to steal 30M USD.
