# Failed external call handling errors

Panics, swallowed reverts, or empty-revert misreads on external calls that burn gas or wedge state

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2024-10-03. Updated 2026-10-25._

## How it works
A contract makes an external call and then handles failure wrongly. Three shapes appear in the evidence: (1) a failure path that panics the caller instead of reverting with a reason, consuming all forwarded gas; (2) a state flag set before a try/catch external call, where an out-of-gas revert is swallowed by the catch (Solidity keeps 1/64 gas), leaving state desynced; (3) a try/catch that treats empty revert data as out-of-gas, when real token calls also revert empty. In each case the assumption "this failure mode is distinguishable and safe to handle this way" is false.

## Where to show up
- `nearCallPanic` vs `revertWithReason` branches around operator- or user-controllable calls [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-08.md)
- State flags written before a `try`/`catch` external call [E2](https://bugbountylibrary.com/r/c4%3A2023-03-wenwin%3AM-02.md)
- `catch` blocks that branch on empty revert data as an OOG signal [E3](https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md)
- External token calls (`approve`, `balanceOf`, `refPerTok`) inside a guarded block [E3](https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md)
- Chained calls where one failure aborts a larger settlement [E3](https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md)

## How to review
For every external call, ask: can the callee fail in a way the handler misclassifies? The invariant: a failure must either revert the whole transaction with a reason, or be caught without leaving persistent state inconsistent. Check that panic paths are not reachable from untrusted input; that flags are set only after the call succeeds or are reset in the catch; and that empty-revert handling does not assume OOG. Confirm the caller retains enough gas for the catch to run meaningfully.

## Variants seen
- Operator-controllable revert in Compressor panics the bootloader near call, burning all L2 gas [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-08.md)
- Insufficient-gas VRF request reverts inside try/catch, leaving lottery stuck in drawing state [E2](https://bugbountylibrary.com/r/c4%3A2023-03-wenwin%3AM-02.md)
- Empty revert from a collateral token's `approve()` aborts Dutch auction settlement [E3](https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md)

## Impact and severity
Led to full gas burn and forced transaction failure [E1](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-08.md), protocol stuck in a drawing state for the delay window [E2](https://bugbountylibrary.com/r/c4%3A2023-03-wenwin%3AM-02.md), and failed settlement of auctions [E3](https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md). Severity rises when the trigger is cheap or attacker-controllable and the stuck state blocks other users or funds.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-08.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-03-wenwin%3AM-02.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-07-reserve%3AM-04.md
