> 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/secureum-amazex-dss-paris/crystal-dao.md).

# Crystal DAO

{% embed url="<https://github.com/ret2basic/AMAZEX-DSS-PARIS/tree/main/src/7_crystalDAO>" %}
crystalDAO
{% endembed %}

## Objective

The Crystal DAO is a transparent and non-profit DAO whose mission is to gather funds to support the development of different public goods in the Ethereum ecosystem. These funds are stored in custom treasury contracts that follow the ERC1176 minimal proxy standard, and are controlled by one DAO admin.

One of such treasuries was recently deployed, and has reached the target amount of 100 ETH in its balance. Therefore, the DAO admin has tried to retrieve the funds for their subsequent donations. However, the admin's signature is not being recognized by the treasury clone contract, and the funds are now stuck, putting the DAO's reputation at risk.

Can you help the DAO admin to retrieve the funds?

📌 Rescue `100 ETH` from the DAO treasury.

***Initial context***

* You will be in control of the `whitehat` address.
* The `whitehat` address has an initial balance of `0 ether`.

<details>

<summary>🗒️ <em>Concepts you should be familiar with (spoilers!)</em></summary>

* [*ERC1167 Minimal Proxy Contract*](https://coinsbench.com/minimal-proxy-contracts-eip-1167-9417abf973e3)*.*
* [*EIP712 Signatures*](https://medium.com/metamask/eip712-is-coming-what-to-expect-and-how-to-use-it-bb92fd1a7a26)*.*
* [*The \`ecrecover()\` function*](https://soliditydeveloper.com/ecrecover)*.*

</details>

***

**The contracts that you will hack are**:

* [**`crystalDAO.sol`**](https://github.com/ret2basic/AMAZEX-DSS-PARIS/blob/main/src/7_crystalDAO/crystalDAO.sol)

**The test script where you will have to write your solution is**:

* [**`Challenge7.t.sol`**](https://github.com/ret2basic/AMAZEX-DSS-PARIS/blob/main/test/Challenge7.t.sol)

## Writeup

First I poked around and found `owner` is always the zero address. Why is that?

After some debugging, I found that the `sstore` in `initialize()` fails to update the owner:

```solidity
    function initialize(address _owner) public initializer {
        // EIP712 init: name DaoWallet, version 1.0
        __EIP712_init("DaoWallet", "1.0");
        // postInit: set owner with gas optimizations
        assembly {
            sstore(0, _owner)
        }
    }
```

The storage slot is wrong here. Note that the contract inherits from `Initializable` and `EIP712Upgradeable`:

```solidity
contract DaoVaultImplementation is Initializable, EIP712Upgradeable {
    ...
}
```

In multiple inheritance scenario, the storage variables from `Initializable` are stored in storage slots first, then `EIP712Upgradeable`, then `DaoVaultImplementation`. Use `forge inspect` to verify this fact:

<figure><img src="/files/xBbOs37rW6rZhUcDPoDA" alt=""><figcaption></figcaption></figure>

## PoC

{% embed url="<https://github.com/ret2basic/AMAZEX-DSS-PARIS/blob/main/test/Challenge7.t.sol>" %}
Crystal DAO PoC
{% endembed %}
