Vulnerability: getReservesByCategory() when useSubmodules =true and submoduleReservesSelector=bytes4(0) will revert
Severity: medium

Description:
in `getReservesByCategory()` Lack of check `data.submoduleReservesSelector!=""` when call `submodule.staticcall(abi.encodeWithSelector(data.submoduleReservesSelector));` will revert\\nwhen `_addCategory()` if `useSubmodules==true`, `submoduleMetricSelector` must not empty and `submoduleReservesSelector` can empty (bytes4(0))\\nlike "protocol-owned-treasury"\\n```\\n        _addCategory(toCategory("protocol-owned-treasury"), true, 0xb600c5e2, 0x00000000); // getProtocolOwnedTreasuryOhm()`\\n```\\n\\nbut when call `getReservesByCategory()` , don't check `submoduleReservesSelector!=bytes4(0)` and direct call `submoduleReservesSelector`\\n```\\n    function getReservesByCategory(\\n        Category category_\\n    ) external view override returns (Reserves[] memory) {\\n// rest of code\\n        // If category requires data from submodules, count all submodules and their sources.\\n        len = (data.useSubmodules) ? submodules.length : 0;\\n\\n// rest of code\\n\\n        for (uint256 i; i < len; ) {\\n            address submodule = address(_getSubmoduleIfInstalled(submodules[i]));\\n            (bool success, bytes memory returnData) = submodule.staticcall(\\n                abi.encodeWithSelector(data.submoduleReservesSelector)\\n            );\\n```\\n\\nthis way , when call like `getReservesByCategory(toCategory("protocol-owned-treasury")` will revert\\nPOC\\nadd to `SUPPLY.v1.t.sol`\\n```\\n    function test_getReservesByCategory_includesSubmodules_treasury() public {\\n        _setUpSubmodules();\\n\\n        // Add OHM/gOHM in the treasury (which will not be included)\\n        ohm.mint(address(treasuryAddress), 100e9);\\n        gohm.mint(address(treasuryAddress), 1e18); // 1 gOHM\\n\\n        // Categories already defined\\n\\n        uint256 expectedBptDai = BPT_BALANCE.mulDiv(\\n            BALANCER_POOL_DAI_BALANCE,\\n            BALANCER_POOL_TOTAL_SUPPLY\\n        );\\n        uint256 expectedBptOhm = BPT_BALANCE.mulDiv(\\n            BALANCER_POOL_OHM_BALANCE,\\n            BALANCER_POOL_TOTAL_SUPPLY\\n        );\\n\\n        // Check reserves\\n        SPPLYv1.Reserves[] memory reserves = moduleSupply.getReservesByCategory(\\n            toCategory("protocol-owned-treasury")\\n        );\\n    }\\n```\\n\\n```\\n forge test -vv --match-test test_getReservesByCategory_includesSubmodules_treasury\\n\\nRunning 1 test for src/test/modules/SPPLY/SPPLY.v1.t.sol:SupplyTest\\n[FAIL. Reason: SPPLY_SubmoduleFailed(0xeb502B1d35e975321B21cCE0E8890d20a7Eb289d, 0x0000000000000000000000000000000000000000000000000000000000000000)] test_getReservesByCategory_includesSubmodules_treasury() (gas: 4774197\\n```\\n

Impact:
some category can't get `Reserves`

Recommended mitigation:
```\\n    function getReservesByCategory(\\n        Category category_\\n    ) external view override returns (Reserves[] memory) {\\n// rest of code\\n\\n\\n        CategoryData memory data = categoryData[category_];\\n        uint256 categorySubmodSources;\\n        // If category requires data from submodules, count all submodules and their sources.\\n// Remove the line below\\n       len = (data.useSubmodules) ? submodules.length : 0;\\n// Add the line below\\n       len = (data.useSubmodules && data.submoduleReservesSelector!=bytes4(0)) ? submodules.length : 0;\\n```\\n