# Changing hat toggle address can lead to unexpected changes in status

Changing a hat's toggle from a contract to an EOA resets status to stale local storage, reactivating a hat meant to be off.

- Payout: Contest reward
- Severity: medium
- Program: Hats
- Credited: obront
- Disclosed: 2023-02-15
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-hats-judging/issues/34
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-hats%3AM-14
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:medium tech:solidity technique:race-window technique:source-review vuln:access-control vuln:business-logic

**Target:** Hats.sol changeHatToggle / hat status sync
**Root cause:** changeHatToggle() swaps the toggle address without first calling checkHatToggle(), so a contract toggle's unsynced off-state is discarded and the hat reverts to stale local storage (true).
**Steps:**
1. Hat has contract toggle returning false but status never synced to local state (still true).
2. Admin calls `changeHatToggle(_hatId, eoaAddress)` expecting status unchanged.
3. Status now reads stale local storage = true, hat reactivated.
4. Attacker sandwiches a use of the hat between the toggle change and the admin's corrective `setHatStatus()`.
**How found:** Code review of changeHatToggle() noticing it never syncs toggle state before swapping the source of truth, combined with the contract-vs-EOA toggle asymmetry.
**Exploitation:** Admin changes toggle contract->EOA; before admin re-toggles off, a malicious user front-runs/uses the reactivated hat (e.g. multisig signing) while it is wrongly on.
**Insight:** When a contract swaps an external source-of-truth (oracle/module) for a local/EOA one, check whether stale cached state is flushed first; the contract->EOA direction is where cached values resurface.
