# Shared vault list conflicting purposes

One registry or balance formula reused for accounting and routing; check every consumer's required contents and valuation

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2024-06-17. Updated 2026-10-23._

## How it works
A single list, registry, or balance formula is reused for two jobs that need different contents. One consumer needs the list to exclude certain entries (to avoid recursion, double counting, or misrouting); another consumer needs those same entries included to count value. The two requirements cannot both hold, so one path silently returns zero or a wrong number, and tracked value drifts from reality. The broken assumption is that "the vault list" or "the balance" has one meaning shared by all callers.

## Where it shows up
- A registry array (e.g. `vaults`, `isLicensed`) read by more than one contract with different expectations.
- Two contracts each computing "balance" or "price per share" independently for the same asset.
- A wrapper that aggregates many user positions under one on-chain identity or lender address.
- Withdraw/redeem paths that assume the caller owns the entire aggregated balance.
- Valuation code that treats all held tokens as equal value, ignoring non-want tokens.

## How to review
Enumerate every consumer of the shared list or formula and write down what each requires it to contain. The invariant: for each consumer, the list must contain exactly the entries that consumer needs, and no entry may be required-present by one caller and required-absent by another. For balances, diff the two formulas (vault vs controller, wrapper vs underlying) and confirm they agree on which tokens count and at what price. For aggregated identities, confirm every transfer/withdraw path supports partial shares, not just full-balance moves.

## Variants seen
- Vault and Controller value the same vault differently; each `earn()` drops share price ~2% [E1](https://bugbountylibrary.com/r/c4%3A2021-09-yaxis%3AH-06.md).
- KeroseneManager vault list must exclude kerosene vaults for one caller but include them for another, so kerosene collateral is never counted [E2](https://bugbountylibrary.com/r/c4%3A2024-04-dyad%3AM-08.md).
- Two users' LP positions map to one lender address; partial redemption reverts, locking funds [E3](https://bugbountylibrary.com/r/sherlock%3A2023-01-ajna%3AM-22.md).

## Impact and severity
Depositors lose value on every harvest [E1](https://bugbountylibrary.com/r/c4%3A2021-09-yaxis%3AH-06.md); collateral is silently uncounted, breaking solvency accounting [E2](https://bugbountylibrary.com/r/c4%3A2024-04-dyad%3AM-08.md); user funds become unredeemable [E3](https://bugbountylibrary.com/r/sherlock%3A2023-01-ajna%3AM-22.md). Severity rises when the drift is silent and repeats per call, and when the locked or miscounted value is user collateral.

## Why fixes fail
Fixes that patch one consumer's view of the list leave the other consumer still wrong; the contradiction must be resolved at the data-structure level, not per call site [E2](https://bugbountylibrary.com/r/c4%3A2024-04-dyad%3AM-08.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2021-09-yaxis%3AH-06.md
- E2: https://bugbountylibrary.com/r/c4%3A2024-04-dyad%3AM-08.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2023-01-ajna%3AM-22.md
