# Registry.sol fails to deliver expected functionality

MIMOProxy and MIMOProxyRegistry stored ownership separately; transferOwnership on the proxy never updated the registry, desyncing owner state and letting stale owners retain privileged access.

- Payout: Contest reward
- Severity: high
- Program: Mimo DeFi
- Credited: byndooa
- Disclosed: 2022-10-17
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-08-mimo-findings/issues/78
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-mimo%3AH-03
- Tags: domain:web3 impact:funds-loss impact:privesc kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Solidity proxy factory/registry contracts
**Root cause:** Ownership state duplicated in MIMOProxy and MIMOProxyRegistry; MIMOProxy.transferOwnership does not propagate to the registry, so the two stores diverge. deployFor() is callable by anyone without registration checks.
**Steps:**
1. Deploy a proxy via MIMOProxyFactory.deployFor() (callable by anyone, no registration).
2. Call MIMOProxy.transferOwnership(newOwner) directly on the proxy.
3. Observe MIMOProxyRegistry still records the old owner; new owner loses vault access while old owner retains privileged automation config access.
4. Alternatively, multiple owners transferOwnership to one address to accumulate multiple proxies, violating one-proxy-per-owner invariant.
**How found:** Code review of Registry.sol's stated invariant (one proxy per owner) against actual implementation; noticed ownership stored in two places and deployFor() lacking access control.
**Exploitation:** A proxy owner transfers ownership directly on MIMOProxy; the registry is not updated, so the new owner cannot perform owner actions on vault funds while the previous owner retains privileged access to automation configuration. Anyone can also call deployFor() to create unregistered proxies.
**Insight:** When a contract documents an invariant like 'one proxy per owner', verify every state-mutating path (transferOwnership, deployFor) actually enforces it; duplicated ownership state across contracts is a classic desync source.
