# Flash callback state mutation before settlement

Callback runs while loan or payment accounting is unsettled, letting caller move, mint, or reuse assets

_Area: DeFi oracles, liquidations and flash loans. Seen in 3 disclosed reports; latest 2024-01-28. Updated 2026-10-24._

## How it works
A flash-style flow hands control to a caller-supplied callback (or a token receive hook) while the protocol's own accounting is still open: assets have moved but payment, burn, or share pricing has not settled. The code assumes the callback is a passive notification, but it is attacker-controlled execution. Anything readable or writable in that window — balances, allowances, share price, ownership — can be manipulated before the protocol finishes its books.

## Where it shows up
- A `flashLoan`/`flash`/`buy` path that calls an external receiver or `onERC721Received`/`onFlashLoan` hook before repayment, burn, or payment completes.
- A caller-supplied `receiver` address used as the target of mint/burn/transfer without checking the caller is authorized by that receiver.
- Allowance checks made against `address(this)` (the token contract) instead of `msg.sender`.
- Asset transfer ordered before payment collection (transfer-then-pay).
- Vaults exposing both a callback-bearing `flash()` and share-minting `bond()`/`debond()` that read share price.

## How to review
Identify every external call that hands control to a caller-chosen address, and list what state is still unsettled at that point. The invariant: when the callback returns, no asset may have been moved, minted, burned, or priced using state the callback could change, and any burn/transfer from a receiver must be authorized by that receiver to `msg.sender`. For transfer-before-pay flows, confirm the round-trip cost is at least the protocol's explicit flash fee. For vaults, confirm share price is not read inside the callback window.

## Variants seen
- Caller picks arbitrary `receiver`; contract burns `amount+fee` from receiver using receiver's allowance, draining victims [E1](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-15.md).
- `buy()` transfers NFT before pulling payment, so buyer uses the NFT in the receive callback and sells back — a cheap flash loan [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AM-01.md).
- `flash()` callback runs before accounting settles; `bond()`/`debond()` pricing manipulated inside it to mint shares from flash-borrowed tokens [E3](https://bugbountylibrary.com/r/dhl%3A20240128-barleyfinance.md).

## Impact and severity
Led to theft of ~10% of BARL supply (~$130K) [E3](https://bugbountylibrary.com/r/dhl%3A20240128-barleyfinance.md), draining of victim receiver balances [E1](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-15.md), and fee bypass enabling cheap leverage [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AM-01.md). Severity rises when the callback window touches share pricing or arbitrary receiver balances, since loss scales with pool or victim holdings rather than a single loan.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-15.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AM-01.md
- E3: https://bugbountylibrary.com/r/dhl%3A20240128-barleyfinance.md
