Integer Overflow Vulnerability in `canaryPrizeCount` Function and Insecure Pseudo-Random Number Generation in `calculatePseudoRandomNumber` Function.
Audit: 2023-07-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/libraries/TierCalculationLib.sol#L52-L64
https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/libraries/TierCalculationLib.sol#L104-L111


# Vulnerability details

## Impact
`calculatePseudoRandomNumber` function computes a pseudo-random number based on user-specific parameters. However, it uses the keccak256 hash function, which may not provide a sufficiently secure and unpredictable random number. It is recommended to use a more robust and secure random number generation algorithm, such as using a cryptographic library or an external oracle, to ensure the randomness and security of the pseudo-random number.

## Proof of Concept
1. Integer Overflow Vuln in `canaryPrizeCount` Function: The `canaryPrizeCount` function contains a potential integer overflow vulnerability when performing large multiplications.

Code block of the `canaryPrizeCount` function: [TierCalculationLib.sol#L52-L63](https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/libraries/TierCalculationLib.sol#L52-L64)
```solidity
function canaryPrizeCount(
  uint8 _numberOfTiers,
  uint8 _canaryShares,
  uint8 _reserveShares,
  uint8 _tierShares
) internal pure returns (UD60x18) {
  uint256 numerator = uint256(_canaryShares) *
    ((_numberOfTiers + 1) * uint256(_tierShares) + _canaryShares + _reserveShares);
  uint256 denominator = uint256(_tierShares) *
    ((_numberOfTiers) * uint256(_tierShares) + _canaryShares + _reserveShares);
  UD60x18 multiplier = toUD60x18(numerator).div(toUD60x18(denominator));
  return multiplier.mul(toUD60x18(prizeCount(_numberOfTiers)));
}
```

In this code block, the `numerator` and `denominator` variables are calculated by multiplying large `uint256` values. If the result of the multiplication exceeds the maximum value representable by a `uint256`, an integer overflow can occur.

The vulnerability arises from the multiplication of the following values:

- `uint256(_canaryShares)`
- `(_numberOfTiers + 1) * uint256(_tierShares)`
- `_canaryShares + _reserveShares`
- `_tierShares * ((_numberOfTiers) * uint256(_tierShares) + _canaryShares + _reserveShares)`

If any of these multiplications result in a value that exceeds the maximum value representable by a `uint256`, an integer overflow occurs, leading to incorrect results or unexpected behavior in the calculation.

To demonstrate the exploitability of this vulnerability, consider the following example:

```solidity
// Set the inputs that trigger the vulnerability
uint8 numberOfTiers = 10;
uint8 canaryShares = 100;
uint8 reserveShares = 200;
uint8 tierShares = 30;

// Calculate the numerator and denominator
uint256 numerator = uint256(canaryShares) *
  ((numberOfTiers + 1) * uint256(tierShares) + canaryShares + reserveShares);
uint256 denominator = uint256(tierShares) *
  (numberOfTiers