# Vault.sol: `settle`ing the 0 address will disrupt accounting

Settling address(0) in Perennial Vault aliases global and local context, so processLocal overwrites global accounting with lower keeper fees, inflating global assets/shares.

- Payout: Contest reward
- Severity: high
- Program: Perennial
- Credited: Emmanuel
- Disclosed: 2023-07-17
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-07-perennial-judging/issues/62
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-07-perennial%3AH-5
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Vault.sol settle/_loadContext/_saveContext accounting
**Root cause:** _loadContext(address(0)) sets context.global and context.local to the same account; _settle runs processGlobal then processLocal on the same slot, and _saveContext stores global before local, so the local (toAssetsLocal/toSharesLocal) values overwrite the correct global values.
**Steps:**
1. Call `settle(address(0))` on Vault.
2. _loadContext(0) returns context.global == context.local == _accounts[address(0)].
3. _settle while-loop processes global checkpoints via processGlobal (deducts full globalKeeperFees).
4. _settle if-block then runs processLocal on the same account, recomputing with toAssetsLocal/toSharesLocal (deducts globalKeeperFees/Checkpoint.count).
5. _saveContext stores context.global then context.local, overwriting the correct global data with the wrong local data.
**How found:** Code reading of _loadContext revealed global is _accounts[address(0)]; noticing that settling address(0) makes global and local identical, then tracing _settle and _saveContext ordering to see the local write clobbers the global write.
**Exploitation:** Any user can permissionlessly call settle on address(0); the resulting global assets/shares are recorded higher than correct because lower keeper fees were deducted, corrupting vault accounting for all depositors.
**Insight:** When a contract stores a 'global' singleton at address(0) and also allows per-account operations on address(0), check whether the two contexts alias and whether save ordering lets the local write overwrite the global one.
