# Side Entrance - Damn Vulnerable DeFi #04

## **Objectives**

[A lending pool](https://www.damnvulnerabledefi.xyz/challenges/side-entrance/) allows users to deposit and withdraw ETH. It also offers flash loans for free. The pool has 1000 ETH in balance and we start with 1 ETH. Our objective is to drain the pool.

## **Smart Contract Analysis**

**SideEntranceLenderPool.sol**

%[https://gist.github.com/az0mb13/f2f6a5350fc42fadbc3872bc1b2cea28] 

* function `deposit()` allows users to deposit ETH into the pool which is added to their `balances` mapping.
    
* function `withdraw()` allows users to withdraw their own balance that they have deposited. The `balances` mapping is checked for the amount to withdraw.
    
* function `flashLoan()` is used to request a free flashloan.
    

It's all pretty straightforward, isn't it? So how do we drain the 1000 ETH from the pool?

## **The Exploit**

This contract is vulnerable to the classic Re-entrancy bug. The issue is also on Line 35 `require()` validation. It is only making sure that the balance of the pool after calling the `execute()` is greater than the `balanceBefore` stored on Line 30.

On Line 33, the flow of the contract is in the attacker's control. What this means is that when we receive control inside our own `execute()` function, we can call the `deposit()` function to deposit the loaned amount back to the pool.  
The pool will update its balance and the validation

```solidity
address(this).balance >= balanceBefore
```

will return true because the pool only checks if its total balance is updated. It does not account that the ETH was deposited by the attacker using a different function, and therefore, the attacker will be able to call the `withdraw()` function to take out all the ETH from their balance.

Let's make a contract to exploit the whole thing.

%[https://gist.github.com/az0mb13/cc78a4e51eb0f7338d363b41b7002a96] 

* The function `exploit()` calls the `pool.flashLoan()` to start the attack.
    
* The `flashLoan()` function calls `IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();` which sends the control flow back to our contract's `receive()` function since our contract is `msg.sender` for this transaction, along with the loaned amount.
    
* The function `execute()` calls `pool.deposit()` and deposits the loaned amount back into the pool, but also updates the `balances` mapping so that we can withdraw.
    
* `flashLoan()`'s `require()` validation returns true, the flow is again returned to our contract's `exploit()` function and it calls `pool.withdraw()` to withdraw all the deposited ETH by our `AttackerContract` which is received by the `receive()` function that we have implemented.
    
* It again calls `attacker.transfer()` to transfer all the ETH back into our deployer account, finishing the exploit.
    

Let's write the test case for this:

%[https://gist.github.com/az0mb13/e7c44cd3c5f4439b179655f64ee305ef] 

It just deploys our AttackerContract, connects to it via the attacker account, and calls `exploit()` function with the total ETH owned by the pool as the argument.

Run the script using `yarn run side-entrance` and the test case will pass.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674748713008/adc84aca-ac77-497c-9fe1-7365e5a09d6a.png align="center")

## Key Takeaways

* This could have been easily prevented by using OpenZeppelin's Re-entrancy Guard, or the `nonReentrant` modifier on the `deposit()` function.
    
* When you're handling balances inside multiple functions, make sure that all of them account for the ETH/tokens received via other functions.
    

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