# Damn Vulnerable DeFI 11 - 13 Solutions

By [kyrers](https://paragraph.com/@kyrers) · 2022-10-05

---

In this post, I will share my explanations for DamnVulnerableDeFI challenges 6 through 10.

You can find the code [here](https://github.com/kyrers/damn-vulnerable-defi).

Let’s begin.

Backdoor
--------

This took me a long time to solve, the main reason being unfamiliarity with the `GnosisSafe` contracts. So don't take this explanation as a fact. It did involve a lot of trial and error, and maybe luck was a key factor.

First things first - the challenge consists of 4 users that upon creating a `GnosisSafe` wallet according to the `WalletRegistry` specifications will receive `10 DVT` tokens. Our goal is to steal them all in one transaction. This is our first clue, we will need a smart contract to do the dirty work.

Since I did not know the `GnosisSafe` contracts, I started by checking the setup for this challenge. Unexpectedly, it is quite easy. There are four contracts: `WalletRegistry`, `GnosisSafeProxyFactory` aka `walletFactory`, `GnosisSafe` aka `masterCopy`, and the `DamnValuableToken` contract. We also know who the allowed users are.

Next, I decided to look through the contracts. `GnosisSafeProxyFactory` and `GnosisSafe` contracts do not contain code exploits as far as I can tell. `WalletRegistry` was the only contract left to check, and after spending more time than I care to admit looking for code exploits, I couldn't find one in this contract either.

Not sure what to do, I decided to list what I found out while looking through the contracts:

1.  We know that `WalletRegistry` is the contract that has the tokens, so we'll have to execute the `proxyCreated(...)` function to get them;
    
2.  The `proxyCreated(...)` function makes sure that the wallet was created using the `GnosisSafe` `setup(...)` function;
    
3.  To execute the `proxyCreated(...)` function we have to create the wallet using `GnosisSafeProxyFactory createProxyWithCallback(...)` function;
    

I decided to take a deeper look at the `createProxyWithCallback(...)` function, which has to be executed first. According to the comments, `createProxyWithCallback(...)` allows us to create a new `GnosisSafeProxy` and call it after it is initialized. It also allows us to call a specified `callback` function afterward.

From that, I assumed two things: the `callback` must be the `WalletRegistry` `proxyCreated(...)` function and that this is how we reach the `GnosisSafe` `setup(...)` function.

After making the above assumptions, I decided to look at the `setup(...)` function. I noticed two more things: some parameters weren't important and it also allows us to perform a `delegatecall` to a specified address.

This looked promising. If I'm able to successfully pass the verifications on the `WalletRegistry` `proxyCreated(...)` function, I can then execute a `callback` defined by me on the `proxy` itself, which by now will have the `10 DVT` according to the `WalletRegistry` `proxyCreated(...)` function.

All that was left was implementing the contract. Most of it was pretty easy, but I was having trouble making a correct call to the `setup(...)`. The `initializer` variable passed to the `createProxyWithCallback(...)` must contain the `setup(...)` function selector and parameters. Most of it can be ignored, but I was also ignoring the `threshold` parameter - which was a mistake. The `proxyCreated(...)` callback verifies that, so don't make the same mistake as I did.

I realize that this isn't a very clear explanation. It might even contain errors. But it was most of my thought process until finally reaching a solution. I rather find a solution myself even if it involves luck and trial and error than simply copy someone else's. Besides, after solving this I looked online for explanations and couldn't find much better explanations. I did find contract improvements though, so there's that.

Climber
-------

he goal of this challenge is clearly stated: steal 10 million `DVT` from the `ClimberVault` contract.

We are also given a couple of extra hints:

1.  The `ClimberVault` is upgradeable, following the `UUPS` pattern;
    
2.  `ClimberVault` has the role of `Sweeper` which can sweep all funds from the vault;
    
3.  The owner of `ClimberVault` is the `ClimberTimelock` contract;
    
4.  The `ClimberTimelock` contract can withdraw a limited amount of tokens from the vault every 15 days;
    
5.  The `ClimberTimelock` contract allows accounts with the `Proposer` role to `schedule` actions that will be executed 1 hour later;
    

Since we are given so much information, I instantly assumed this would be a tough challenge.

First I used my very limited knowledge of the `UUPS` pattern to look for a pattern error in the `ClimberVault` contract. However, it does have an empty constructor and instead is initialized by a `initialize` function. This is not the way in.

I then tried to find a way to get the `Sweeper` role. I couldn't find any. If you can, let me know.

However, while looking through the `ClimberTimelock` contract, I did notice that it has the role of `Admin` of itself, meaning it can grant the roles defined. I also noticed that anyone can call `execute()` to execute a proposal, as long as it has been scheduled. This function contains an enormous error, it only checks that a given proposal was ready for execution after executing it!

This is the point at which I knew I was onto something. Theoretically, we could create a contract to execute a proposal that grants itself the `Proposer` role and transfers the ownership of the `ClimberVault` to an account controlled by us. After that, it would be a simple matter of creating a new `ClimberVault` that allows us to call the `sweepFunds()` function, and upgrading the proxy to use our new `ClimberVault`.

While implementing the proposal I forgot one thing: we know from the challenge description that the delay to execute a proposal is 1 hour. Fortunately, we can just set it to 0 without any issue.

Also, don't forget that even though the `checks-effects-interaction` pattern is violated, the `ClimberTimelock` does check that the proposal is ready to be executed, so we'll have to schedule it otherwise it will revert and the attack won't work. Plus, the proposal can't call the `schedule()` function itself because the parameters won't match. So, we need to set a task that calls a function in our attacker contract that schedules the task, which will work because we already have the `Proposer` role.

So, to recap:

1.  Implement a `ClimberVault` version that allows us to call the `sweepFunds()` function;
    
2.  Create a contract that executes a proposal with the following tasks:
    
    *   Set the delay to 0;
        
    *   Grant the contract the proposer role;
        
    *   Transfer the ownership of the vault to our attacker account;
        
    *   Schedule the proposal;
        
3.  Execute the proposal;
    
4.  Update the proxy to use our `ClimberVault`
    
5.  Sweep the funds;
    

Safe Miners
-----------

This is not an explanation of the solution, this is an unfiltered account of how I reached a solution. This is because I don't really understand this challenge. Then again, even the challenge description says it will be modified for a future version of [damnvulnerabledefi](https://www.damnvulnerabledefi.xyz/).

With that caveat, let me explain how I reached a solution.

From the description, I immediately assumed I had to deploy a contract using the `attacker` to the specified address, because it clearly says that the address that has the tokens is empty.

My first instinct was to use `CREATE2`, but then it occurred to me it probably would take eternities to find the correct salt to get that same address.

So I decided to try brute forcing it first using `CREATE`, since paying for gas is not a concern in this scenario.

My first attempt consisted of having the `attacker` deploy 100k contracts that just transferred the `DVT` tokens to the attacker. Not only did this take a long time, but it also didn't work.

Since I am not sure how hardhat deploys contracts, I decided to give it another shot using a `SafeMinersAttackerFactory` to deploy the `SafeMinersAttacker` before giving up.

At first, I tried having the factory deploy 1000 instances of the attacker until the `attacker` account had the tokens. This ran into an out-of-gas error because I, naively, forgot that there's a limit to the gas I can send to the contract.

So I decided to modify how this would work. The `attacker` account would deploy a `SafeMinersAttackerFactory` that would create 500 instances of the `SafeMinersAttacker`. Then, if the `attacker` had the tokens, I would stop, otherwise, I would have the `attacker` deploy another factory.

I was expecting this to run for a while, but since I had to leave my computer at the time it was cool. If it didn't work, I would know brute force was the wrong approach. To my surprise, it worked on the second batch of 500 `SafeMinersAttacker` deployments.

---

*Originally published on [kyrers](https://paragraph.com/@kyrers/damn-vulnerable-defi-11-13-solutions)*
