Vulnerability: Optimization issue
Severity: medium

Description:
The codebase is huge, and there are still a lot of places where these complications and gas efficiency can be improved.\\n`_updateTopUsers`, `_updateGroupLeaders`, `_updateLeaderboard` are having a similar mechanism of adding users to a sorted set which makes more storage operations than needed:\\n```\\nuint256 \\_tmpIndex = \\_currentIndex - 1;\\nuint256 \\_currentUserAmount = usersTeamInfo[msg.sender].stakedAmount;\\n \\nwhile (\\_currentUserAmount > usersTeamInfo[topUsers[\\_tmpIndex]].stakedAmount) {\\n    address \\_tmpAddr = topUsers[\\_tmpIndex];\\n    topUsers[\\_tmpIndex] = msg.sender;\\n    topUsers[\\_tmpIndex + 1] = \\_tmpAddr;\\n \\n    if (\\_tmpIndex == 0) {\\n        break;\\n    }\\n \\n    \\_tmpIndex--;\\n}\\n```\\n\\nInstead of doing 2 operations per item that is lower than the new_item, same can be done with one operation: while `topUsers[_tmpIndex]` is lower than the new itemtopUsers[_tmpIndex + 1] = `topUsers[_tmpIndex]`.\\ncreating the Queue library looks like overkill `for` the intended task. It is only used `for` the withdrawal queue in the PolicyBook. The structure stores and processes extra data, which is unnecessary and more expensive. A larger codebase also has a higher chance of introducing a bug (and it happened here https://github.com/ConsenSys/bridge-mutual-audit-2021-03/issues/25). It's usually better to have a simpler and optimized version like described here issue 5.14.\\nThere are a few `for` loops that are using `uint8` iterators. It's unnecessary and can be even more expensive because, under the hood, it's additionally converted to `uint256` all the time. In general, shrinking data to `uint8` makes sense to optimize storage slots, but that's not the case here.\\nThe value that is calculated in a loop can be obtained simpler by just having a 1-line formula:\\n```\\nfunction \\_getAvailableMonthForReward(address \\_userAddr) internal view returns (uint256) {\\n    uint256 \\_oneMonth = 30 days;\\n    uint256 \\_startRewardTime = getEndLMTime();\\n \\n    uint256 \\_countOfRewardedMonth = countsOfRewardedMonth[usersTeamInfo[\\_userAddr].teamAddr][\\_userAddr];\\n    uint256 \\_numberOfMonthForReward;\\n \\n    for (uint256 i = \\_countOfRewardedMonth; i < MAX\\_MONTH\\_TO\\_GET\\_REWARD; i++) {\\n        if (block.timestamp > \\_startRewardTime.add(\\_oneMonth.mul(i))) {\\n        \\_numberOfMonthForReward++;\\n        } else {\\n            break;\\n        }\\n    }\\n \\n    return \\_numberOfMonthForReward;\\n}\\n```\\n\\nThe mapping is using 2 keys, but the first key is strictly defined by the second one, so there's no need for it:\\n```\\n// Referral link => Address => count of rewarded month\\nmapping (address => mapping (address => uint256)) public countsOfRewardedMonth;\\n```\\n\\nThere are a lot of structures in the code with duplicated and unnecessary data, for example:\\n```\\nstruct UserTeamInfo {\\n    string teamName;\\n    address teamAddr;\\n \\n    uint256 stakedAmount;\\n    bool isNFTDistributed;\\n}\\n```\\n\\nHere the structure is created for every team member, duplicating the team name for each member.

Impact:

Recommended mitigation:
Optimize and simplify the code.