The ChoosingRam::increaseValuesOfParticipants() function is intended to increase the attributes of the user's RamNFT. When a RamNFT is minted, it stores the address of the minter (RamNFT::CharacteristicsOfRam.ram) and defaults 5 characteristics to false:
When all of these characteristics are set to true, RamNFT::CharacteristicsOfRam.ram becomes the ChoosingRam::selectedRam. The ChoosingRam::selectedRam has access to the Dussehra::withdraw() function. Dussehra::withdraw() allows the ChoosingRam::selectedRam to have a share of the funds derived from each entry into the protocol (Dussehra::totalAmountGivenToRam)
The ChoosingRam::increaseValuesOfParticipants() requires two uint256 arguments
The function uses this formula to create a random number:
uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender))) % 2;
If the random number is 0, then a characteristic of tokenIdOfChallenger's (msg.sender) RamNFT will be flipped to true. If a user is able to do this 5 times, then their address will be chosen as ChoosingRam::selectedRam.
If the random number is not 0, then the RamNFT for the second argument provided (presumably a user chosen at random) will have a characteristic switched to true
The user chosen as ChoosingRam::selectedRam will have access to the Dussehra::withdraw() function which will give 50% of the total mint funds to the user.
This is an example attack contract:
The attack function will take two uint256 parameters that will be passed to ChoosingRam::increaseValuesOfParticipants()
A while loop is utilized to continuously run the random calculation until random = 0.
When random = 0, the contract calls ChoosingRam::increaseValuesOfParticipants
The contract should be able to receive ether (so it can enter the protocol and claim the reward)
The contract should be able to receive NFTs
A withdraw function for the attacker to withdraw the funds
This foundry test shows that the attacker can call the function 5 times and become ChoosingRam::selectedRam:
This is a high risk vulnerability that allows a user to manipulate the "randomness" mechanic employed by the protocol.
Due to weak randomness, a user can easily manipulate ChoosingRam::increaseValuesOfParticipants() to quickly become ChoosingRam::selectedRam. The ChoosingRam::selectedRam status allows the user to withdraw 50% of the minting funds through the Dussehra::withdraw() function.
The system is meant to be random, and the funds are meant to be rewarded to a user through luck based mechanics.
A user can create an attack contract that manipulates the randomness used in the protocol rendering the randomness useless. Anyone that deploys a simple attack contract will gain 50% of the funds raised with ease.
Manual Review
Foundry
Don't allow contracts to enter the protocol.
When a user tries to enter the protocol through Dussehra::enterPeopleWhoLikeRam, we can prevent contracts from entering:
Dussehra::enterPeopleWhoLikeRam()
This would mitigate users from entering contracts that exploit weak randomness, but this is still something that may be exploited by validators.
The best solution would be to use off-chain methods such as ChainlinkVRF to create randomness.
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.