Beginner FriendlyFoundryNFT
100 EXP
Ended
View results
Submission Details
Severity: low
Valid

[H-1] Predictable Randomness Logic in `ChoosingRam::selectRamIfNotSelected()`

https://github.com/Cyfrin/2024-06-Dussehra/blob/9c86e1b09ed9516bfbb3851c145929806da75d87/src/ChoosingRam.sol#L83

Description:

The selectRamIfNotSelected() function in the ChoosingRam contract uses a logic that relies on block.timestamp and block.prevrandao to select a random RAM. However, this approach makes the randomness predictable, especially on certain blockchains where block.prevrandao returns constant values, such as Arbitrum and zkSync. This predictability compromises the security and integrity of the selection process.

Impact:

Predictable randomness allows attackers to predict the selected RAM, breaking the randomness logic and potentially manipulating the outcome. This vulnerability can lead to unfair advantages and exploitation within the system.

Proof of Concept:

Run the following code in Dussehra.t.sol :

function test_predictRandomNumber() public participants {
vm.prank(player1);
vm.warp(1728691201); // Set time within the valid range

// Predictable random number using the same logic as in the contract
uint256 predictedRandom =
uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao))) % ramNFT.tokenCounter();
address expectedRam = ramNFT.getCharacteristics(predictedRandom).ram;
// Call the function to select Ram
vm.startPrank(organiser);
choosingRam.selectRamIfNotSelected();
vm.stopPrank();

// Ensure the selected ram matches the predicted ram
assertEq(choosingRam.selectedRam(), expectedRam);
assertTrue(choosingRam.isRamSelected());

console.log("Predicted Ram: ", expectedRam);
console.log("Selected Ram: ", choosingRam.selectedRam());
}

Output :

Logs:
Predicted Ram: 0xEb0A3b7B96C1883858292F0039161abD287E3324
Selected Ram: 0xEb0A3b7B96C1883858292F0039161abD287E3324

To ensure the randomness cannot be predicted or manipulated, use a Verifiable Random Function (VRF) service. VRF services provide secure and verifiable random numbers that are resistant to prediction and manipulation attacks. Some recommended services include:

  • Chainlink VRF (Recommended): Provides cryptographically secure randomness.

  • Gelato: Offers automation and randomness services.

  • Pyth: Delivers reliable and tamper-proof random numbers. By integrating one of these VRF services, the randomness logic in selectRamIfNotSelected() will be significantly more secure, preventing the vulnerabilities associated with the current implementation.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Weak randomness in `ChoosingRam::selectRamIfNotSelected`

The organizer is trusted, but the function `ChoosingRam::selectRamIfNotSelected` uses a way to generate a random number that is not completely random.

Support

FAQs

Can’t find an answer? Join our Discord or follow us on Twitter.

Cyfrin
Updraft
CodeHawks
Solodit
Resources