Hashing msg.sender, block.timestamp, block.prevrandao together creates a predictable final number. A predictable number is not a good random number. Malicious users can manipulate these values or know them ahead of time to choose the randomness that gives them a favorable NFT characteristics.
There are a few attack vectors here.
Validators can know ahead of time the block.timestamp and block.difficulty and use that knowledge to predict when / how to participate. See the solidity blog on prevrando here. block.difficulty was recently replaced with prevrandao.
Users can manipulate the msg.sender value to result in their index being the winner.
Example proof of code:
Paste below code in Dessehra.t.sol and run command - forge test --mt test__manipulateTimestamp
Using on-chain values as a randomness seed is a well-known attack vector in the blockchain space.
ChoosingRam::selectRamIfNotSelected and ChoosingRam::increaseValuesOfParticipants can be manipulated easily in a way that miner can submit these call transactions that can benifit him by picking his NFT or characteristics that can make him a winner.
Foundry
Consider using an oracle for your randomness like Chainlink VRF.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.