DEV Community

Cover image for Damn Vulnerable DeFI 2022 Walkthrough — Challenge 1 Solution “Unstoppable”
JohnnyTime 🤓
JohnnyTime 🤓

Posted on • Edited on

Damn Vulnerable DeFI 2022 Walkthrough — Challenge 1 Solution “Unstoppable”

Master Smart Contract Hacking

Become a smart contract hacker 😎 → https://bit.ly/become-smh

Damn Vulnerable DEFI

Welcome to the Damn Vulnerable DeFI challenge walkthrough!

Damn Vulnerable DeFi teaches offensive security of DeFi smart contracts. Your skills will be developed through numerous challenges to help you become a bug hunter or security auditor.

Before starting I wanted to give a shoutout to @tinchoabbate which built the awesome Damn Vulnerable Defi challenge.

In the upcoming articles, I will walk you through the challenges and show you the most efficient way to solve them. Let’s get started!

You can also watch this video to see how to solve the “Unstoppable” challenge:

Damn Vulnerable DeFi Setup

In order to get started clone this repository, in your terminal type git checkout v2.2.0 to check out the most recent version, and run yarn install to install dependencies.

Now, we’ve got 2 main important folders: contracts and tests. For each challenge we will have a subfolder in these 2 folders, contracts will include the vulnerable smart contracts of the challenge, and tests will include the Javascript file to deploy the contracts, setup the challenge, and for you to test your exploit.

Challenge 1 — “Unstoppable”

There’s a lending pool UnstoppableLenderwith a million DamnValuableToken (DVT) tokens in balance, offering flash loans for free.
If only there was a way to attack and stop the pool from offering flash loans …You start with 100 DVT tokens in balance.

This is a classic DOS (Denial Of Service) attack, and our goal is to break the pool, so NO ONE will be ever able to use it. Awesome! :)

The first thing I usually do is look in the test files to understand the business logic, while looking in the unstoppable.challlenge.js we can see how the DamnValuableToken and the UnstoppableLender contracts are being deployed, how ETH is being sent to the pool and some sanity checks to make sure everything is working as expected.

To understand how the pool works we jump into the UnstoppableLender.sol smart contract, specifically the flashLoan function which we need to break!

Solving the “Unstoppable” Challenge

Attack Plan

In the flashLoan function, there are some asserts and require opcodes, in case these requirements fail, the transaction will be reverted. We will try to find how we can ALWAYS make one of these assets / require fail. Let’s check everyone and what we can break:

require(borrowAmount > 0, "Must borrow at least one token");
Enter fullscreen mode Exit fullscreen mode

AND

require(balanceBefore >= borrowAmount, "Not enough tokens in pool");
Enter fullscreen mode Exit fullscreen mode

Can’t be broken since the borrowAmount is a param that is sent by the user every transaction.

This assert of integers is interesting:

uint256 balanceBefore = damnValuableToken.balanceOf(address(this));
assert(poolBalance == balanceBefore);
Enter fullscreen mode Exit fullscreen mode

The pool is checking that the current token balance (balanceBefore) is equal to the poolBalance parameter, what is this poolBalance parameter and how it’s calculated?

The poolBalance is a storage variable that keeps track of the contract’s token balance, and it’s being updated in the depositTokens function every time someone deposits tokens.

So in order to break the assets we need to make sure that poolBalance != balanceBefore we can simply do it by sending the ERC20 token DIRECTLY to the contract WITHOUT going through the depositTokens function, so simple right?

Exploitation

We don’t need to create and deploy smart contracts in this challenge, since the exploitation is quite simple, we just need to send some DVD ERC20 tokens directly to the pool without going through the depsitTokens function. Let’s add this line of code to the unstoppable.challenge.js file:

await this.token.connect(attacker).transfer(this.pool.address, 1);
Enter fullscreen mode Exit fullscreen mode

By adding this line of code to the exploit section, we are transferring 1 DVD token to the pool, breaking permanently the assert between poolBalance and the balanceBefore variables.

Now we will run yarn unstoppable in our terminal to check if our exploitation works, and here are the results:
Image description

Congratulation guys, you completed the first Damn Vulnerable DEFI challenge! Next:

Until next time,
JohnnyTime.

Top comments (0)