Lack of checks for rewarding an epoch that has already been rewarded
To give rewards to the participating stakers, the Forta system utilizes reward epochs for each `shareId`, i.e. a delegated staking share. Each epoch gets their own reward distribution, and then `StakeAllocator` and `RewardsDistributor` contracts along with the Forta staking shares determine how much the users get.\\nTo actually allocate these rewards, a privileged account with the role `REWARDER_ROLE` calls the `RewardsDistributor.reward()` function with appropriate parameters to store the `amount` a `shareId` gets for that specific `epochNumber`, and then adds the `amount` to the `totalRewardsDistributed` contract variable for tracking. However, there is no check that the `shareId` already received rewards for that `epoch`. The new reward `amount` simply replaces the old reward `amount`, and `totalRewardsDistributed` gets the new `amount` added to it anyway. This causes inconsistencies with accounting in the `totalRewardsDistributed` variable.\\nAlthough `totalRewardsDistributed` is essentially isolated to the `sweep()` function to allow transferring out the reward tokens without taking away those tokens reserved for the reward distribution, this still creates an inconsistency, albeit a minor one in the context of the current system.\\nSimilarly, the `sweep()` function deducts the `totalRewardsDistributed` amount instead of the amount of pending rewards only. In other words, either there should be a different variable that tracks only pending rewards, or the `totalRewardsDistributed` should have token amounts deducted from it when users execute the `claimRewards()` function. Otherwise, after a few epochs there will be a really large `totalRewardsDistributed` amount that might not reflect the real amount of pending reward tokens left on the contract, and the `sweep()` function for the reward token is likely to fail for any amount being transferred out.\\n```\\nfunction reward(\\n    uint8 subjectType,\\n    uint256 subjectId,\\n    uint256 amount,\\n    uint256 epochNumber\\n) external onlyRole(REWARDER\\_ROLE) {\\n    if (subjectType != NODE\\_RUNNER\\_SUBJECT) revert InvalidSubjectType(subjectType);\\n    if (!\\_subjectGateway.isRegistered(subjectType, subjectId)) revert RewardingNonRegisteredSubject(subjectType, subjectId);\\n    uint256 shareId = FortaStakingUtils.subjectToActive(getDelegatorSubjectType(subjectType), subjectId);\\n    \\_rewardsPerEpoch[shareId][epochNumber] = amount;\\n    totalRewardsDistributed += amount;\\n    emit Rewarded(subjectType, subjectId, amount, epochNumber);\\n}\\n```\\n
Implement checks as appropriate to the `reward()` function to ensure correct behavior of `totalRewardsDistributed` tracking. Also, implement necessary changes to the tracking of pending rewards, if necessary.
```\\nfunction reward(\\n    uint8 subjectType,\\n    uint256 subjectId,\\n    uint256 amount,\\n    uint256 epochNumber\\n) external onlyRole(REWARDER\\_ROLE) {\\n    if (subjectType != NODE\\_RUNNER\\_SUBJECT) revert InvalidSubjectType(subjectType);\\n    if (!\\_subjectGateway.isRegistered(subjectType, subjectId)) revert RewardingNonRegisteredSubject(subjectType, subjectId);\\n    uint256 shareId = FortaStakingUtils.subjectToActive(getDelegatorSubjectType(subjectType), subjectId);\\n    \\_rewardsPerEpoch[shareId][epochNumber] = amount;\\n    totalRewardsDistributed += amount;\\n    emit Rewarded(subjectType, subjectId, amount, epochNumber);\\n}\\n```\\n