# Zero address recipient reverts payout

Mapping lookups, sentinel addresses, or unvalidated fee recipients feeding a transfer recipient that can be address(0)

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2023-11-16. Updated 2026-11-01._

## How it works
A transfer or approve is sent to an address that resolves to `address(0)`. Two distinct failure modes follow: either the token call reverts (many ERC20s reject transfers to zero), or the assets are sent to the zero address and effectively burned. The broken assumption is that any address used as a recipient is a real, initialized account. When that address comes from a mapping lookup, a constructor argument, or a sentinel meaning "native asset", it can silently be zero.

## Where it shows up
- A mapping read (`mapping[a][b].field`) used directly as a transfer recipient, where a missing key returns the zero value [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md)
- Constructor or setter parameters for `feeRecipient`, `treasury`, `owner` accepted without a non-zero check [E3](https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md)
- A sentinel `address(0)` meaning "native token", with downstream code still calling ERC20 methods on it [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-46.md)
- `safeTransfer`/`approve` calls where the recipient is a state variable set once and never re-validated [E3](https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md)
- Privileged callers (a contract acting as operator) passing an unvalidated recipient into a withdraw function [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md)

## How to review
For every transfer or approve, trace the recipient back to its source. The invariant: **any address used as a transfer or approve recipient must be provably non-zero on every reachable path, or the path must be explicitly gated.**
- If the recipient is a mapping lookup, confirm the key is validated to exist before use [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md).
- If the recipient is a constructor/setter parameter, confirm a `!= address(0)` check exists [E3](https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md).
- If `address(0)` is a sentinel for native asset, confirm every downstream path branches on it before calling ERC20 methods [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-46.md).
- Confirm the calling contract's privilege (operator/owner) does not let an attacker reach the bad path [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md).

## How finders spotted it
- Read the migration flow and noticed `newVault` came from a mapping without `proposalId` validation; a missing key yields `address(0)`, which is then passed as the transfer recipient [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md).
- Noticed `erc20` can be `address(0)` for native-token wrappers, then traced `sendForLeverage -> leverageDown` to an unconditional `IERC20(erc20).approve` [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-46.md).
- Followed `claimRewards -> _lockToken -> escrow.lock`, saw `feeRecipient` set in the constructor without validation, and that `safeTransfer` to zero reverts [E3](https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md).

## Variants seen
- Uninitialized mapping key becomes a burn recipient for vault assets [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md)
- Sentinel zero address for native asset breaks an ERC20-only code path, reverting and burning user funds/gas [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-46.md)
- Zero fee recipient makes every reward claim revert, a griefing/DoS lever toggled by a privileged creator [E3](https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md)

## Impact and severity
E1 lets anyone burn migrated vault assets (high). E2 permanently burns user TOFT and gas on every `leverageDown` (high). E3 blocks all staking reward claims and lets the creator control claim timing (medium). Impact rises when the bad recipient is reachable by an unprivileged caller [E1](https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md) or when the revert is unconditional on a core user path [E2, E3].

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-09.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-46.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-01.md
