# AnnexFinance: unverified flashLoan callback drains WBNB

AnnexFinance's flashLoan callback was not verified, letting an attacker spoof a DODO flash loan and drain ~$3k of WBNB via a fake token pool.

- Payout: Real-world hack
- Severity: high
- Program: - AnnexFinance
- Analysis by: DeFiHackLabs
- Disclosed: 2022-11-19
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2022-11/Annex_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20221119-annex
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:access-control vuln:business-logic vuln:flash-loan

**Target:** Lending protocol flashLoan callback / DODO flash loan interface
**Root cause:** The protocol's flashLoan callback (DPPFlashLoanCall) trusted the caller and did not verify that the flash loan was actually initiated by the legitimate DODO pool, so an attacker could invoke the callback directly with a fake token and fabricated liquidity.
**Steps:**
1. Deploy a malicious ERC20 (`MyERC20`) and mint 10e18 to self.
2. Call `DVM(dodo).flashLoan(8e18, 0, address(this), data)` to obtain 8 WBNB.
3. In `DPPFlashLoanCall`, approve Router for the fake token and WBNB, then `Router.addLiquidity(Token, WBNB, 8e18, 8e18, 0, 0, this, deadline)` to create a Token/WBNB pair.
4. Get the pair via `Factory.getPair(Token, WBNB)` and read `WBNB.balanceOf(Liquidator)`.
5. Call `Uni_Pair_V2(Pair).swap(WBNBAmount, 0, Liquidator, data1)` (or the token0/token1 variant) to send WBNB to the Liquidator address.
6. Approve the pair and `Router.removeLiquidity(...)` to recover liquidity.
7. `WBNB.transferFrom(Liquidator, this, WBNB.balanceOf(Liquidator))` to pull the swapped WBNB, then repay 8 WBNB to DODO.
**How found:** Researcher (Ancilia) noticed the flashLoan callback lacked caller verification, allowing a spoofed flash loan invocation; reproduced with a Foundry PoC on BSC fork at block 23165446.
**Exploitation:** Attacker takes a real 8 WBNB DODO flash loan, but the core abuse is that AnnexFinance's flashLoan callback can be invoked without verifying the caller/pool. The PoC deploys a fake token, seeds a Token/WBNB Uniswap pair, and uses the unverified callback path to route WBNB to a Liquidator address and pull it back, netting ~$3k.
**Insight:** When auditing flashLoan integrations, check that the callback validates msg.sender equals the expected pool and that the loan parameters match; an unverified callback lets anyone trigger the protocol's post-loan logic with attacker-controlled tokens and amounts.

