# Flash loans allow borrowing from frozen pools, bypassing security controls

Blend's flash loan path skipped pool/reserve status checks, letting users borrow from frozen or on-ice pools despite the circuit breaker.

- Payout: Contest reward
- Severity: medium
- Program: Blend
- Credited: Testerbot
- Disclosed: 2025-08-13
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-02-blend-v2-audit-certora-formal-verification#m-01
- Library page: https://bugbountylibrary.com/r/c4%3A2025-02-blend-v2-audit-certora-formal-verification%3AM-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:access-control vuln:business-logic vuln:flash-loan

**Target:** Soroban lending pool flash_loan entrypoint
**Root cause:** flash_loan() does not call pool.require_action_allowed() or reserve.require_action_allowed(), unlike build_actions_from_request()/apply_borrow(), so frozen/on-ice status is never enforced on that path.
**Steps:**
1. Freeze pool via set_status(4) (or permissionless backstop-withdrawal threshold).
2. Confirm normal borrow via submit() panics with InvalidPoolStatus.
3. Call pool.flash_loan(&user, &FlashLoan{contract: receiver, asset, amount}, &[]) with empty actions_request.
4. Flash loan succeeds and funds can be retained as a borrow if position stays healthy.
**How found:** Code-reading: noticed flash_loan implementation lacks the require_action_allowed() checks present in build_actions_from_request() and apply_borrow(), then wrote a test freezing the pool and confirming flash_loan still succeeds.
**Exploitation:** Attacker with healthy collateral calls flash_loan with an empty actions request; since repayment isn't enforced when the resulting position is healthy, the loan becomes a plain borrow, extracting liquidity from a pool the owner froze to stop risk accumulation.
**Insight:** When a protocol gates operations via a central require_action_allowed() helper, enumerate every entrypoint (flash loans, liquidations, auctions) and check each calls it—alternate borrow paths often skip the circuit breaker.
