# Allowance overwrite and missing spend checks

Approval setters that overwrite live allowances, and overrides that skip allowance checks on third-party calls

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2026-04-28. Updated 2026-10-24._

## How it works
An allowance is a promise that a spender may move at most a set amount of an owner's tokens. Two assumptions break. First, a setter that assigns an absolute new value assumes the old allowance is already spent or irrelevant; in reality a spender watching the mempool can spend the old amount before the reduction lands, then spend the new amount too. Second, any function that moves funds on behalf of a `from`/`owner` address assumes the caller was authorized; if the allowance check is omitted, the only gate is whatever broad approval the victim already granted, and anyone can act as the victim.

## Where it shows up
- Approval/allowance setters that assign (`= amount`) instead of adjusting the delta, especially for permissioned spenders [E3](https://bugbountylibrary.com/r/c4%3A2022-08-olympus%3AH-03.md).
- ERC4626 or token forks that override `withdraw`, `redeem`, or `transferFrom` without calling `_spendAllowance` when `msg.sender != owner` [E1](https://bugbountylibrary.com/r/dhl%3A20260428-rwavault.md).
- Router/helper contracts holding broad operator approvals that accept a caller-supplied `from`/`onBehalfOf` and forward it without checking `msg.sender` [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-38.md).
- Any third-party withdrawal path where the receiver is arbitrary.

## How to review
For every allowance setter, confirm it either adjusts the existing allowance by a delta or requires the current allowance to be zero before overwriting. For every function that moves funds for another address, confirm the invariant: `msg.sender == owner` OR a sufficient allowance is spent in the same call. Diff each overridden transfer/withdraw function against the spec's allowance semantics. For helpers with operator approvals, confirm each helper validates `msg.sender` against the supplied `from`.

## Variants seen
- Missing allowance spend in an ERC4626 `withdraw` override, draining depositors to an arbitrary receiver [E1](https://bugbountylibrary.com/r/dhl%3A20260428-rwavault.md).
- Helper contract trusting caller-supplied `from` under a broad operator approval [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-38.md).
- Absolute allowance overwrite front-run to spend old and new amounts [E3](https://bugbountylibrary.com/r/c4%3A2022-08-olympus%3AH-03.md).

## Impact and severity
E1 drained ~398k USDC across eight depositors; severity is high because a single missing check turns every depositor into a victim and the receiver is attacker-chosen. Broad operator approvals [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-38.md) and mempool-visible reductions [E3](https://bugbountylibrary.com/r/c4%3A2022-08-olympus%3AH-03.md) widen the blast radius. Severity rises with the size of approved balances and the number of affected users.

## Evidence
- E1: https://bugbountylibrary.com/r/dhl%3A20260428-rwavault.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-38.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-08-olympus%3AH-03.md
