MEDIUM severity: The vulnerability allows users to lose their staking rewards by exploiting a combination of function. The vulnerability allows users to lose their staking rewards by exploiting a combination of functions in the `UserManager` and `Comptroller` contracts. The issue arises when a user unstakes their funds using the `unstake` function, which updates their staked coin age and reduces their staked amount....

Vulnerable code:
```\ncontracts/user/UserManager.sol\n\nfunction unstake(uint96 amount) external whenNotPaused nonReentrant {\n    Staker storage staker = stakers[msg.sender];\n\n    if (staker.stakedAmount - staker.locked < amount) {\n        revert InsufficientBalance();\n    }\n\n    comptroller.withdrawRewards(msg.sender, stakingToken);\n\n    uint256 remaining = IAssetManager(assetManager).withdraw(stakingToken, msg.sender, amount);\n\n    if (uint96(remaining) > amount) {\n        revert AssetManagerWithdrawFailed();\n    }\n\n    uint96 actualAmount = amount - uint96(remaining);\n\n    _updateStakedCoinAge(msg.sender, staker);\n\n    staker.stakedAmount -= actualAmount;\n    totalStaked -= actualAmount;\n\n    emit LogUnstake(msg.sender, actualAmount);\n}\n```\n```\ncontracts/user/UserManager.sol\n\nfunction _updateStakedCoinAge(address stakerAddress, Staker storage staker) private {\n    uint64 currentBlock = uint64(block.number);\n    uint256 lastWithdrawRewards = getLastWithdrawRewards[stakerAddress];\n    uint256 blocksPast = (uint256(currentBlock) - _max(lastWithdrawRewards, uint256(staker.lastUpdated)));\n    staker.stakedCoinAge += blocksPast * uint256(staker.stakedAmount);\n    staker.lastUpdated = currentBlock;\n}\n```\n```\ncontracts/token/Comptroller.sol\n\nfunction withdrawRewards(address account, address token) external override whenNotPaused returns (uint256) {\n    IUserManager userManager = _getUserManager(token);\n\n    (UserManagerAccountState memory user, Info memory userInfo, uint256 pastBlocks) = _getUserInfo(\n        userManager,\n        account,\n        token,\n        0\n    );\n\n    uint256 globalTotalStaked = userManager.globalTotalStaked();\n\n    uint256 amount = _calculateRewardsByBlocks(\n        account,\n        token,\n        pastBlocks,\n        userInfo,\n        globalTotalStaked,\n        user\n    );\n\n    gInflationIndex = _getInflationIndexNew(\n        globalTotalStaked,\n        block.number - gLastUpdatedBlock\n    );\n\n    gLastUpdatedBlock = block.number;\n    users[account][token].updatedBlock = block.number;\n    users[account][token].inflationIndex = gInflationIndex;\n\n    if (unionToken.balanceOf(address(this)) >= amount && amount > 0) {\n        unionToken.safeTransfer(account, amount);\n        users[account][token].accrued = 0;\n        emit LogWithdrawRewards(account, amount);\n        return amount;\n    } else {\n        users[account][token].accrued = amount;\n        emit LogWithdrawRewards(account, 0);\n        return 0;\n    }\n}\n```\n```\nUserManagerAccountState memory user,\nInfo memory userInfo,\nuint256 pastBlocks) = \n    _getUserInfo(\n        userManager,\n        account,\n        token,\n        0\n    );\n```\n```\nuint256 amount = _calculateRewardsByBlocks(\n    account,\n    token,\n    pastBlocks,\n    userInfo,\n    globalTotalStaked,\n    user\n);\n```\n```\nif (user.effectiveStaked == 0 || \n    totalStaked == 0 || \n    startInflationIndex == 0 || \n    pastBlocks == 0) {\n    return 0;\n}\n```\n```\nif (unionToken.balanceOf(address(this)) >= amount && amount > 0) {\n    unionToken.safeTransfer(account, amount);\n    users[account][token].accrued = 0;\n    emit LogWithdrawRewards(account, amount);\n\n    return amount;\n} else {\n    users[account][token].accrued = amount;\n    emit LogWithdrawRewards(account, 0);\n\n    return 0;\n}\n```