# External call before balance update

State written after an external call or refund, letting a nested call double-count or overwrite accounting

_Area: DeFi accounting and math bugs. Seen in 27 disclosed reports; latest 2026-05-18. Updated 2026-10-22._

## How it works
Accounting code assumes that once it reads or writes a balance, share count, fee, or ID, that value stays put until the function finishes. That assumption breaks when an external call (ETH refund, token transfer, hook, callback) runs before the bookkeeping is committed. The callee re-enters, and the second frame reads stale state or overwrites the first frame's write. The result is double-counted shares, inflated fees, or a balance that no longer matches reality.

## Where it shows up
- ETH refunds or `safeTransfer` to a caller-supplied address before a counter, balance, or share slot is written [E1](https://bugbountylibrary.com/r/c4%3A2024-08-phi%3AH-06.md)[E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md)[E3](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md)[E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md)
- A fee, price, or royalty read once to compute a total and again to execute, with an external call between the reads [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md)
- Temporary "phantom"/virtual balances reconciled by assuming any shortfall was burned [E3](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md)
- Anyone can register a pool/market whose self-reported token list and reward indexes are trusted during harvest [E4](https://bugbountylibrary.com/r/dhl%3A20240903-penpiexyzio.md)
- Push refunds of a blacklistable token (USDC/USDT) inside an eviction/queue path [E5](https://bugbountylibrary.com/r/sherlock%3A2024-12-plaza-finance%3AM-14.md)
- A global accounting variable cached locally and written back after a loop of external transfers [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md)
- A token hook that validates a lock before lazily minting shares in the same transfer [E7](https://bugbountylibrary.com/r/sherlock%3A2025-07-mellow-flexible-vaults%3AM-6.md)
- Cross-chain modes that mutate source state before destination confirmation with no failure callback [E8](https://bugbountylibrary.com/r/c4%3A2024-08-chakra%3AM-07.md)

## How to review
Check the ordering invariant: every state write that a later read depends on must be committed before any external call that can re-enter. For each external call, ask what storage the callee can reach and whether a second frame would see a stale or half-updated value. Confirm a reentrancy guard covers cross-function and cross-contract paths, not just the entry function [E3](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md)[E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md). For fees/prices, verify the value used to transfer equals the value used to compute the total, with no mutation window [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md). For push refunds, confirm a reverting recipient cannot block progress [E5](https://bugbountylibrary.com/r/sherlock%3A2024-12-plaza-finance%3AM-14.md).

## Variants seen
- Reentrant create overwrites the same cred slot before the ID counter increments [E1](https://bugbountylibrary.com/r/c4%3A2024-08-phi%3AH-06.md)
- Fee re-read after refund inflates royalty [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md)
- Phantom shares converted to real shares during liquidation [E3](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md)
- Fake market with reentrant reward claim inflates rewards [E4](https://bugbountylibrary.com/r/dhl%3A20240903-penpiexyzio.md)
- Blacklisted bidder freezes auction eviction [E5](https://bugbountylibrary.com/r/sherlock%3A2024-12-plaza-finance%3AM-14.md)
- Cached global balance overwritten by cross-service reentrancy [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md)
- Lock checked before lazy mint, minted shares escape [E7](https://bugbountylibrary.com/r/sherlock%3A2025-07-mellow-flexible-vaults%3AM-6.md)
- Source burn before destination unlock, no restore path [E8](https://bugbountylibrary.com/r/c4%3A2024-08-chakra%3AM-07.md)

## Impact and severity
Drains ranged from a single pool [E2](https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md) to ~$27M in rewards [E4](https://bugbountylibrary.com/r/dhl%3A20240903-penpiexyzio.md) and ~90% of auction reserves [E5](https://bugbountylibrary.com/r/sherlock%3A2024-12-plaza-finance%3AM-14.md). Severity is high when the external call reaches an attacker-controlled address and the stale value gates a payout; worse when no guard exists and the path is cross-contract [E3](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md)[E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-08-phi%3AH-06.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-01.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AH-02.md
- E4: https://bugbountylibrary.com/r/dhl%3A20240903-penpiexyzio.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2024-12-plaza-finance%3AM-14.md
- E6: https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-05.md
- E7: https://bugbountylibrary.com/r/sherlock%3A2025-07-mellow-flexible-vaults%3AM-6.md
- E8: https://bugbountylibrary.com/r/c4%3A2024-08-chakra%3AM-07.md
