HIGH severity: Attacker can corrupt `RewardsDistributor` internal accounting forcing LP token incentive deposits to revert for tokens like `cUSDCv3`. **Description:** Some tokens like [cUSDCv3](https://etherscan.io/address/0x9e4dde024f7ea5cf13d5f09c51a1555305c99f0c#code#F1#L930) contains a special case for `amount == type(uint256).max` in their transfer functions that results in only the user's balance being transferred.

For such tokens in...

Vulnerable code:
function _validateIncentive(
    address token,
    uint256 amount,
    uint256 distributionStart,
    uint256 numDistributionPeriods
) private view {
    // distribution must start on future epoch flip and last for [1, max] periods
    if (
        numDistributionPeriods == 0                  || // Distribution in 0 periods is invalid
        numDistributionPeriods > maxIncentivePeriods || // Distribution over max period is invalid
        distributionStart % EPOCH_DURATION != 0      || // Distribution must start at the beginning of a week
        distributionStart < block.timestamp             // Distribution must start in the future
    ) revert InvalidIncentiveDistributionPeriod();

    // approvedIncentiveAmounts indicates the min amount of
    // tokens to distribute per period for a whitelisted token
    uint256 minAmount = approvedIncentiveAmounts[token] * numDistributionPeriods;

    // @audit validation passes for `amount == type(uint256).max`
    if (minAmount == 0 || amount < minAmount)
        revert InvalidIncentiveAmount();
}

function _depositLPIncentive(
    StoredReward memory reward,
    uint256 amount,
    uint256 periodReceived
) private {
    // @audit does not guarantee that `amount`
    // is transferred if `amount == type(uint256).max`
    IERC20(reward.token).safeTransferFrom(msg.sender, address(this), amount);

    // @audit incorrect `amount` will be stored in this case
    _storeReward(periodReceived, reward, amount);
}

function _validateDistributionPeriod(
    uint256 distributionStart,
    uint256 numDistributionPeriods
) private view {
    // distribution must start on future epoch flip and last for [1, max] periods
    if (
        numDistributionPeriods == 0                  || // Distribution in 0 periods is invalid
        numDistributionPeriods > maxIncentivePeriods || // Distribution over max period is invalid
        distributionStart % EPOCH_DURATION != 0      || // Distribution must start at the beginning of a week
        distributionStart < block.timestamp             // Distribution must start in the future
    ) revert InvalidIncentiveDistributionPeriod();
}

// Before calling this function, _validateDistributionPeriod must be called
function _validateIncentive(
    address token,
    uint256 amount,
    uint256 numDistributionPeriods
) private view {
    uint256 minAmount = approvedIncentiveAmounts[token] * numDistributionPeriods;

    if (minAmount == 0 || amount < minAmount)
        revert InvalidIncentiveAmount();
}

function _depositLPIncentive(
    StoredReward memory reward,
+   uint256 numDistributionPeriods
    uint256 amount,
    uint256 periodReceived
-) private {
+) private returns(uint256 actualDeposited) {
+   uint256 tokenBalanceBeforeTransfer = IERC20(reward.token).balanceOf(address(this));
    IERC20(reward.token).safeTransferFrom(
        msg.sender,
        address(this),
        amount
    );
-   _storeReward(periodReceived, reward, amount);
+   actualDeposited = IERC20(reward.token).balanceOf(address(this)) - tokenBalanceBeforeTransfer;
+   _validateIncentive(reward.token, actualDeposited, numDistributionPeriods);
+   _storeReward(periodReceived, reward, actualDeposited);
}