# Flashloan end result isn't controlled

Ajna flashLoan never verifies returned balance, so a token that reports successful transferFrom without moving funds lets an attacker drain the pool.

- Payout: Contest reward
- Severity: medium
- Program: Ajna
- Credited: hyh
- Disclosed: 2022-12-21
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-01-ajna-judging/issues/101
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-01-ajna%3AM-13
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** ERC20Pool / FlashloanablePool flashLoan functions
**Root cause:** Flash loan repayment relies solely on safeTransferFrom success and never compares pool token balance before/after the callback, so tokens that report success without accounting updates leave the loan unreturned.
**Steps:**
1. Call `flashLoan(receiver, token, amount, data)` on an Ajna pool for quote or collateral token.
2. Pool transfers `amount` to receiver via `_transferQuoteToken`/`_transferCollateral`.
3. Receiver's `onFlashLoan` returns the ERC3156 magic value without returning funds.
4. Pool calls `_transferQuoteTokenFrom`/`_transferCollateralFrom`; a token that reports success but withholds accounting update leaves pool balance reduced.
5. Repeat to drain up to full pool balance of that token.
**How found:** Code review of flashLoan flow: noticed no balance invariant check after callback, reasoned about exotic ERC20 behaviors (upgradable tokens like USDC/USDT introducing blacklist/freeze) that report successful safeTransfer without updating accounting.
**Exploitation:** Attacker deploys a receiver implementing onFlashLoan returning the magic value; if the pool's token exhibits report-success-without-accounting behavior (e.g. after an upgrade introducing blacklist/freeze logic), the repayment transferFrom is a no-op and the borrowed amount is never returned, draining the pool.
**Insight:** When auditing flash loans, check whether repayment is verified by balance delta rather than transfer return value; upgradable tokens can later introduce freeze/blacklist semantics that turn a benign transferFrom into a silent no-op.
