LyraPositionHandlerL2 inaccurate modifier onlyAuthorized may lead to funds loss if keeper is compromised
The `LyraPositionHandlerL2` contract is operated either by the L2 keeper or by the L1 `LyraPositionHandler` via the `L2CrossDomainMessenger`. This is implemented through the `onlyAuthorized` modifier:\\n```\\nmodifier onlyAuthorized() {\\n    require(\\n        ((msg.sender == L2CrossDomainMessenger &&\\n            OptimismL2Wrapper.messageSender() == positionHandlerL1) ||\\n            msg.sender == keeper),\\n        "ONLY\\_AUTHORIZED"\\n    );\\n    \\_;\\n}\\n```\\n\\nThis is set on:\\n`withdraw()`\\n`openPosition()`\\n`closePosition()`\\n`setSlippage()`\\n`deposit()`\\n`sweep()`\\n`setSocketRegistry()`\\n`setKeeper()`\\nFunctions 1-3 have a corresponding implementation on the L1 `LyraPositionHandler`, so they could indeed be called by it with the right parameters. However, 4-8 do not have an implemented way to call them from L1, and this modifier creates an unnecessarily expanded list of authorised entities that can call them.\\nAdditionally, even if their implementation is provided, it needs to be done carefully because `msg.sender` in their case is going to end up being the `L2CrossDomainMessenger`. For example, the `sweep()` function sends any specified token to `msg.sender`, with the intention likely being that the recipient is under the team's or the governance's control - yet, it will be `L2CrossDomainMessenger` and the tokens will likely be lost forever instead.\\nOn the other hand, the `setKeeper()` function would need a way to be called by something other than the keeper because it is intended to change the keeper itself. In the event that the access to the L2 keeper is compromised, and the L1 `LyraPositionHandler` has no way to call `setKeeper()` on the `LyraPositionHandlerL2`, the whole contract and its funds will be compromised as well. So, there needs to be some way to at least call the `setKeeper()` by something other than the keeper to ensure security of the funds on L2.\\n```\\nfunction closePosition(bool toSettle) public override onlyAuthorized {\\n    LyraController.\\_closePosition(toSettle);\\n    UniswapV3Controller.\\_estimateAndSwap(\\n        false,\\n        LyraController.sUSD.balanceOf(address(this))\\n    );\\n}\\n\\n/\\*///////////////////////////////////////////////////////////////\\n MAINTAINANCE FUNCTIONS\\n//////////////////////////////////////////////////////////////\\*/\\n\\n/// @notice Sweep tokens\\n/// @param \\_token Address of the token to sweepr\\nfunction sweep(address \\_token) public override onlyAuthorized {\\n    IERC20(\\_token).transfer(\\n        msg.sender,\\n        IERC20(\\_token).balanceOf(address(this))\\n    );\\n}\\n\\n/// @notice socket registry setter\\n/// @param \\_socketRegistry new address of socket registry\\nfunction setSocketRegistry(address \\_socketRegistry) public onlyAuthorized {\\n    socketRegistry = \\_socketRegistry;\\n}\\n\\n/// @notice keeper setter\\n/// @param \\_keeper new keeper address\\nfunction setKeeper(address \\_keeper) public onlyAuthorized {\\n    keeper = \\_keeper;\\n}\\n```\\n
Create an additional modifier for functions intended to be called just by the keeper (onlyKeeper) such as functions 4-7, and create an additional modifier `onlyGovernance` for the `setKeeper()` function. As an example, the L1 `Vault` contract also has a `setKeeper()` function that has a `onlyGovernance()` modifier. Please note that this will likely require implementing a function for the system's governance that can call `LyraPositionHandlerL2.setKeeper()` via the `L2CrossDomainMessenger`.
```\\nmodifier onlyAuthorized() {\\n    require(\\n        ((msg.sender == L2CrossDomainMessenger &&\\n            OptimismL2Wrapper.messageSender() == positionHandlerL1) ||\\n            msg.sender == keeper),\\n        "ONLY\\_AUTHORIZED"\\n    );\\n    \\_;\\n}\\n```\\n