Updating of protocol fee via `V3FactoryOwner.sol#setFeeProtocol()` function can cause unfair rewards distributation for stakers in `UniStaker.sol` contract (the changing of protocol fees will apply to pending for claiming fees)
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L142-L149
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L204


# Vulnerability details

## Impact and Proof of Concept

The `V3FactoryOwner.sol` contract serves as the owner of the Uniswap V3 factory, with the capability to manage protocol fees on individual Uniswap V3 pools. It is designed to enable the setting of protocol fees through the `setFeeProtocol()` function and the collection of these fees via the [`V3FactoryOwner.sol#claimFees()`](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L204) function. The collected fees are intended to be transferred to the `UniStaker.sol` contract, where they are distributed as rewards to stakers.

- **Setting Protocol Fees**: The `setFeeProtocol()` function allows the admin of the `V3FactoryOwner.sol` contract to set protocol fees on individual Uniswap V3 pools. This function is critical for adjusting the fees that contribute to the rewards pool for stakers in the `UniStaker.sol` contract.
- **Claiming Fees**: The `claimFees()` function facilitates the collection of accrued protocol fees from a specified Uniswap V3 pool. These fees are then forwarded to the `UniStaker.sol` contract's reward pool, to be distributed among stakers.
- **Reward Distribution**: The `UniStaker.sol` contract manages the distribution of these collected fees as rewards to stakers, based on their share of the total staked UNI tokens.

- [`V3FactoryOwner.sol#setFeeProtocol()`](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L142-L149) function:

```solidity
  function setFeeProtocol(
    IUniswapV3PoolOwnerActions _pool,
    uint8 _feeProtocol0,
    uint8 _feeProtocol1
  ) external {
    _revertIfNotAdmin();
    _pool.setFeeProtocol(_feeProtocol0, _feeProtocol1);
  }
```

- [`V3FactoryOwner.sol#claimFees()`](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L204) function:

```solidity
  function claimFees(
    IUniswapV3PoolOwnerActions _pool,
    address _recipient,
    uint128 _amount0Requested,
    uint128 _amount1Requested
  ) external returns (uint128, uint128) {
    PAYOUT_TOKEN.safeTransferFrom(msg.sender, address(REWARD_RECEIVER), payoutAmount);
    REWARD_RECEIVER.notifyRewardAmount(payoutAmount);
    (uint128 _amount0, uint128 _amount1) =
      _pool.collectProtocol(_recipient, _amount0Requested, _amount1Requested);

    // Protect the caller from receiving less than requested. See `collectProtocol` for context.
    if (_amount0 < _amount0Requested || _amount1 < _amount1Requested) {
      revert V3FactoryOwner__InsufficientFeesCollected();
    }
    emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1);
    return (_amount0, _amount1);
  }

  /// @notice Ensures the msg.sender is the contract admin and reverts otherwi