# token -> vault mapping can be overwritten

Manager.addToken overwrites vaults[token] mapping without cleaning the old vault's tokens array, desyncing state and stranding tokens in the previous vault.

- Payout: Audit contest
- Severity: medium
- Program: yAxis
- Found by: cmichel
- Disclosed: 2021-11-10
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-09-yaxis-findings/issues/126
- Library page: https://bugbountylibrary.com/r/c4%3A2021-09-yaxis%3AM-09
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Manager contract addToken / vault-token mappings
**Root cause:** addToken writes vaults[_token]=_vault without checking or removing an existing entry, and without removing the token from the previous vault's tokens[] array, leaving the two mappings inconsistent.
**Steps:**
1. Vault A has token T registered: vaults[T]=A and tokens[A] contains T.
2. Call `addToken(T, vaultB)` (or equivalent) which sets vaults[T]=B.
3. Observe tokens[A] still contains T while vaults[T]=B, so the two mappings disagree.
4. Controller.getBestStrategyWithdraw and onlyVault now resolve T to B, stranding T's balance in A.
**How found:** Code review of Manager's addToken vs removeToken: noticed addToken lacks the cleanup logic present in removeToken, so overwriting vaults[_token] leaves the old vault's tokens array stale.
**Escalation:** Desynced mappings break onlyVault checks and strategy withdrawal selection, potentially stranding funds in the disassociated vault.
**Insight:** When a contract maintains bidirectional mappings (token->vault and vault->token[]), audit every mutator for symmetric cleanup; addToken missing the removeToken cleanup is a classic desync that breaks onlyVault authorization assumptions.
