# NestedFactory does not track operators properly

NestedFactory's addOperator/removeOperator don't rebuild the operator cache, so create() and swapTokenForTokens() can use stale or missing operators.

- Payout: Audit contest
- Severity: medium
- Program: Nested Finance
- Found by: IllIllI
- Disclosed: 2022-04-27
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-02-nested#m-02
- Library page: http://bugbountylibrary.com/r/c4%3A2022-02-nested%3AM-02
- Tags: area:web3 domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:incomplete-fix technique:source-review vuln:access-control vuln:business-logic

**Target:** NestedFactory / MixinOperatorResolver operator cache
**Root cause:** addOperator() and removeOperator() mutate the operators array without calling rebuildCache(), and rebuildCache()/isResolverCached() only iterate resolverOperatorsRequired() so removed operators are never purged from operatorCache.
**Steps:**
1. Call `NestedFactory.removeOperator(operator)` (no rebuildCache triggered).
2. Call `NestedFactory.create()` using that operator — still succeeds because operatorCache retains it.
3. Alternatively call `addOperator(operator)` then `create()` — fails since operator absent from operatorCache until rebuildCache().
4. `isResolverCached()` returns true despite the desync, so owner is unaware rebuildCache() is needed.
**How found:** Traced the synthetix MixinResolver invariant (isResolverCached false until rebuildCache) and noticed the prior contest's atomicity fix was applied only to importOperators, not to addOperator/removeOperator; then checked rebuildCache's loop over resolverOperatorsRequired() and saw removed entries are never deleted from operatorCache.
**Exploitation:** Owner-level operator add/remove leaves operatorCache stale; core functions create() and swapTokenForTokens() rely on the cache being synced, allowing use of a removed operator or blocking a newly added one.
**Insight:** When a resolver/cache pattern is patched for one mutation path, audit every other mutator of the same state and the cache-invalidation predicate itself — a loop over 'required' items can never detect deletions.

