# Truster - Damn Vulnerable DeFi #03

## Objectives

There's a lending pool with a million DVT tokens. This pool offers a flash loan for free. But as it is with all flash loans, the user must pay back the loan in the same transaction.

Our objective is to drain all the funds from the lending pool and empty the contract. Let's get started.

## Smart Contract Analysis

**TrusterLenderPool.sol**

%[https://gist.github.com/az0mb13/7701b7af4a6cf06f78eed8b214c1df41] 

The only function of interest here is the `flashLoan()`. Let's go over the content.

* `balanceBefore` is used to store the current balance of the pool which is then validated again on Line 39 to make sure that the user returns the loaned token.
    
* There's a transfer call on Line 35 in which the loan is offered to the `borrower`.
    
* On line 36, there's an interesting external call - `target.functionCall(data);`. The `functionCall()` is a function coming from OpenZeppelin's [Address.sol](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol). This is calling another internal function called \`[functionCallWithValue()](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L128)\`.
    
    * If you look inside the function definition, you'll notice that it is just a normal `call()` function on the target address, i.e., `target.call{value: value}(data);` . This means that when the user calls the `flashLoan()` function, the lender contract makes an external call to the `target` address with our custom data passed as an argument. This paves the way for exploitation.
        

## The Exploit

Now that we know we can make the lender pool call arbitrary functions on the `target` address, imagine what would happen if we were to pass the `target` as the address of the lender pool's token itself? We don't see any validation happening in the `flashLoan()` function. This would essentially allow us to call any function inside the lender pool and its ERC interfaces in the context of the pool.

Now, to transfer all the tokens from the pool, there's a function called `approve(spender, amount)` in the ERC20 standard. This function is used to allow the spender to spend the `amount` tokens owned by the caller.

Since we can make the lender pool call any function, we will be using the exploit to make it call the `approve()` with our attacker's address and the maximum amount in the lending pool.

Once the tokens are approved by the lender, we can simply withdraw the tokens by calling `transferFrom()`, yet another ERC20 function.

* `borrowAmount` will be 0 since we don't want to pay back anything.
    
* `borrower` will be our attacker's address.
    
* `target` will be the address of the damnValuableToken.
    
* `data` will contain the ABI-encoded data containing the function signature and values to call on the `target` contract. We will be making use of `abi.encodeWithSignature` for this.
    

We'll make an attacker contract so that the exploit happens in a single transaction.

%[https://gist.github.com/az0mb13/9e0a6149b7c76b73bc3e9b3e935117c5] 

This contract code can be placed just below the TrusterLenderPool contract code. In the attacker contract:

* The constructor is handling the pool and token address which we'll pass from inside the test file.
    
* The attack function is storing the total pool balance inside `poolBalance`.
    
* On line 12, `pool.flashLoan` is called with all the parameters specified above. This will make the lender pool approve `poolBalance` tokens for our attacker contract.
    
* On line 22, the approved tokens are transferred back to our contract completing the attack in a single transaction.
    

Here's how the test case will look:

%[https://gist.github.com/az0mb13/34a40d3f3cbf4a307a2bb30c1a1f89b5] 

Lines 4 and 5 are handling our contract deployment and on line 6 we are calling the `attack()` function that we created to exploit the lending pool.

Run the script using `yarn run truster` and the test case will pass.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674409536425/6d55ddb2-a5b0-4de8-ad47-c4c10b1b6eaf.png align="center")

## Key Takeaways

* It's a bad idea to pass user-controlled input directly to function call data without validation.
    
* Do not allow 0 amount in flash loans.
    
* There should have been validations on the `target` address to prevent users from using the token or pool's address.
    

%[https://github.com/az0mb13/damn-vulnerable-defi/blob/master/test/truster/truster.challenge.js]
