# Predictable address squatting and accounting drift

Approvals or payouts to counterfactual or weakly-seeded addresses; CREATE2 salts that omit mutable constructor args

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2026-10-26. Updated 2026-10-29._

## How it works
An address is treated as an identity, but the code treats it as a destination. Allowances and balances are keyed per-address, not per-caller, so whoever controls code at that address can spend them. When the address is derived from deterministic inputs (CREATE2 salt plus CREATE nonce chain) or a weak seed (block.number, a stored last-recipient), an outsider can compute it in advance and deploy or steer funds to it. The broken assumption: "this address is ours because we computed it." Computation is not ownership.

## Where it shows up
- Unlimited ERC20 approvals whose spender is empty on-chain and derived from CREATE2/CREATE math [E1](https://bugbountylibrary.com/r/dhl%3A20261026-safeapprovalsquat.md)
- Recipient addresses derived from block.number, a stored last address, or pair address [E2](https://bugbountylibrary.com/r/dhl%3A20230720-utopia.md)
- CREATE2 salts covering only some constructor args while mutable args (fees, ticks, scales) feed init_code [E3](https://bugbountylibrary.com/r/c4%3A2022-12-stealth-project%3AM-02.md)
- Integrations that precompute pool or contract addresses and trust them without checking deployed code
- Any payout or skim path where the destination is computed rather than stored and verified

## How to review
For every approval, payout, or precomputed address, ask: can an outsider cause code to exist at that address, or predict it before deployment? The invariant: an address receiving value or allowance must be either already deployed with known code, or derived from a secret the outsider cannot guess. For CREATE2, the salt plus init_code must cover every constructor argument that affects the address; mutable args must be fixed before address computation or excluded from identity [E3](https://bugbountylibrary.com/r/c4%3A2022-12-stealth-project%3AM-02.md). For seeded recipients, the seed must not be attacker-influenceable or block-predictable [E2](https://bugbountylibrary.com/r/dhl%3A20230720-utopia.md).

## Variants seen
- Standing unlimited approval to a counterfactual address, squatted via CREATE2+CREATE chain [E1](https://bugbountylibrary.com/r/dhl%3A20261026-safeapprovalsquat.md)
- Airdrop recipient predicted from block.number and last recipient, then pair reserves skimmed to it [E2](https://bugbountylibrary.com/r/dhl%3A20230720-utopia.md)
- Precomputed pool address diverging from deployed pool because mutable constructor args change init_code [E3](https://bugbountylibrary.com/r/c4%3A2022-12-stealth-project%3AM-02.md)

## Impact and severity
Direct loss of funds: ~$7.45M swept through squatted approvals [E1](https://bugbountylibrary.com/r/dhl%3A20261026-safeapprovalsquat.md), ~$119k drained from pair reserves [E2](https://bugbountylibrary.com/r/dhl%3A20230720-utopia.md). Severity is high when approvals are unlimited or reserves are large. Worse when the address is empty on-chain (no signal of danger) and when the derivation is fully public, so any observer can front-run deployment.

## Why fixes fail
Partial fixes that add a salt but leave mutable constructor args outside the identity still produce mismatched addresses [E3](https://bugbountylibrary.com/r/c4%3A2022-12-stealth-project%3AM-02.md); integrations then trust a wrong address. Verifying only that an address was computed, not that code exists there, leaves the squat window open [E1](https://bugbountylibrary.com/r/dhl%3A20261026-safeapprovalsquat.md).

## Evidence
- E1: https://bugbountylibrary.com/r/dhl%3A20261026-safeapprovalsquat.md
- E2: https://bugbountylibrary.com/r/dhl%3A20230720-utopia.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-12-stealth-project%3AM-02.md
