# Direct transfer skips balance sync

Tokens arriving without bookkeeping update, leaving tracked balance below actual holdings

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2026-05-29. Updated 2026-11-01._

## How it works
A contract's accounting assumes its tracked balance (reserves, `_accountedBalance`, pair reserves) equals the tokens it actually holds. That assumption breaks when tokens arrive by a path that moves funds but never runs the bookkeeping update: a direct `transfer` to a pair, a manual reserve injection, or an unauthenticated sync/donate function. The contract then holds more tokens than it accounts for, and the gap is claimable by whoever can trigger the next accounting read.

## Where it shows up
- Token transfer logic that infers add/remove-liquidity by comparing pair balance to reserves [E1](https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md)
- Public or unauthenticated `sync`/`donate` functions that move tokens into a pool [E1](https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md)
- Reserve injection paths (e.g. a vault calling `increaseReserve`) that bypass the main accounting flow [E2](https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md)
- Token `transfer`/`transferFrom` to a pair that does not call the pair's reserve update [E3](https://bugbountylibrary.com/r/dhl%3A20240409-ups.md)
- Any `_accountedBalance`-style getter derived from accumulators rather than actual holdings [E2](https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md)

## How to review
Enumerate every path that moves the token in or out: normal deposit, direct transfer, sync/donate, reserve injection, skim. For each, confirm the tracked balance is updated in the same transaction, or that the accounting formula is insensitive to untracked inflow. The invariant to hold: tracked balance equals actual token balance at all times, or any surplus is unclaimable. Check access control on sync/donate functions and whether pricing logic reads raw pair balances that an outsider can shift.

## Variants seen
- Tax logic spoofed via pair-balance-vs-reserve comparison plus unauthenticated `sync()` donating USDT to the pair [E1](https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md)
- Reserve injection not reflected in `_accountedBalance`, enabling double-count and theft; triggerable permissionlessly by any vault [E2](https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md)
- Direct transfer to pair without reserve update, leaving pair reserves stale and enabling repeated skim/swap [E3](https://bugbountylibrary.com/r/dhl%3A20240409-ups.md)

## Impact and severity
Led to fund drains: ~19.49K USDT [E1](https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md), ~$28K [E3](https://bugbountylibrary.com/r/dhl%3A20240409-ups.md), and reserve theft [E2](https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md). Severity is high where the surplus is directly claimable; worse when a flash loan or public function makes the trigger repeatable and permissionless [E1](https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md)[E2](https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md)[E3](https://bugbountylibrary.com/r/dhl%3A20240409-ups.md).

## Evidence
- E1: https://bugbountylibrary.com/r/dhl%3A20260529-ysdao.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AH-08.md
- E3: https://bugbountylibrary.com/r/dhl%3A20240409-ups.md
