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");
AND
require(balanceBefore >= borrowAmount, "Not enough tokens in pool");
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);
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);
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:
Congratulation guys, you completed the first Damn Vulnerable DEFI challenge! Next:
- Damn Vulnerable DeFI Challenge 2 (“Naive Receiver”) Solution
- Master Smart Contract Hacking & Auditing
- Request a Smart Contract Audit
Until next time, JohnnyTime.