Unlinked tophat retains linkedTreeRequests, can be rugged
When a tophat is unlinked from its admin, it is intended to regain its status as a tophat that is fully self-sovereign. However, because the `linkedTreeRequests` value isn't deleted, an independent tophat could still be vulnerable to "takeover" from another admin and could lose its sovereignty.\\nFor a tophat to get linked to a new tree, it calls `requestLinkTopHatToTree()` function:\\n```\\nfunction requestLinkTopHatToTree(uint32 _topHatDomain, uint256 _requestedAdminHat) external {\\n    uint256 fullTopHatId = uint256(_topHatDomain) << 224; // (256 - TOPHAT_ADDRESS_SPACE);\\n\\n    _checkAdmin(fullTopHatId);\\n\\n    linkedTreeRequests[_topHatDomain] = _requestedAdminHat;\\n    emit TopHatLinkRequested(_topHatDomain, _requestedAdminHat);\\n}\\n```\\n\\nThis creates a "request" to link to a given admin, which can later be approved by the admin in question:\\n```\\nfunction approveLinkTopHatToTree(uint32 _topHatDomain, uint256 _newAdminHat) external {\\n    // for everything but the last hat level, check the admin of `_newAdminHat`'s theoretical child hat, since either wearer or admin of `_newAdminHat` can approve\\n    if (getHatLevel(_newAdminHat) < MAX_LEVELS) {\\n        _checkAdmin(buildHatId(_newAdminHat, 1));\\n    } else {\\n        // the above buildHatId trick doesn't work for the last hat level, so we need to explicitly check both admin and wearer in this case\\n        _checkAdminOrWearer(_newAdminHat);\\n    }\\n\\n    // Linkages must be initiated by a request\\n    if (_newAdminHat != linkedTreeRequests[_topHatDomain]) revert LinkageNotRequested();\\n\\n    // remove the request -- ensures all linkages are initialized by unique requests,\\n    // except for relinks (see `relinkTopHatWithinTree`)\\n    delete linkedTreeRequests[_topHatDomain];\\n\\n    // execute the link. Replaces existing link, if any.\\n    _linkTopHatToTree(_topHatDomain, _newAdminHat);\\n}\\n```\\n\\nThis function shows that if there is a pending `linkedTreeRequests`, then the admin can use that to link the tophat into their tree and claim authority over it.\\nWhen a tophat is unlinked, it is expected to regain its sovereignty:\\n```\\nfunction unlinkTopHatFromTree(uint32 _topHatDomain) external {\\n    uint256 fullTopHatId = uint256(_topHatDomain) << 224; // (256 - TOPHAT_ADDRESS_SPACE);\\n    _checkAdmin(fullTopHatId);\\n\\n    delete linkedTreeAdmins[_topHatDomain];\\n    emit TopHatLinked(_topHatDomain, 0);\\n}\\n```\\n\\nHowever, this function does not delete `linkedTreeRequests`.\\nTherefore, the following set of actions is possible:\\nTopHat is linked to Admin A\\nAdmin A agrees to unlink the tophat\\nAdmin A calls `requestLinkTopHatToTree` with any address as the admin\\nThis call succeeds because Admin A is currently an admin for TopHat\\nAdmin A unlinks TopHat as promised\\nIn the future, the address chosen can call `approveLinkTopHatToTree` and take over admin controls for the TopHat without the TopHat's permission
In `unlinkTopHatFromTree()`, the `linkedTreeRequests` should be deleted:\\n```\\nfunction unlinkTopHatFromTree(uint32 _topHatDomain) external {\\n    uint256 fullTopHatId = uint256(_topHatDomain) << 224; // (256 - TOPHAT_ADDRESS_SPACE);\\n    _checkAdmin(fullTopHatId);\\n\\n    delete linkedTreeAdmins[_topHatDomain];\\n// Add the line below\\n   delete linkedTreeRequests[_topHatDomain];\\n    emit TopHatLinked(_topHatDomain, 0);\\n}\\n```\\n
Tophats that expect to be fully self-sovereign and without any oversight can be surprisingly claimed by another admin, because settings from a previous admin remain through unlinking.
```\\nfunction requestLinkTopHatToTree(uint32 _topHatDomain, uint256 _requestedAdminHat) external {\\n    uint256 fullTopHatId = uint256(_topHatDomain) << 224; // (256 - TOPHAT_ADDRESS_SPACE);\\n\\n    _checkAdmin(fullTopHatId);\\n\\n    linkedTreeRequests[_topHatDomain] = _requestedAdminHat;\\n    emit TopHatLinkRequested(_topHatDomain, _requestedAdminHat);\\n}\\n```\\n