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.