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

Reentrancy attack in `Dussehra::killRavana`, drains the protocol funds to the Organiser.

Summary

Dussehra::killRavana only checks for whether the Ram is selected, meaning that a user can call this function twice, sending half of the total balance to the Organiser twice, draining the entire contract.

Vulnerability Details

@> function killRavana() public RamIsSelected {
if (block.timestamp < 1728691069) {
revert Dussehra__MahuratIsNotStart();
}
if (block.timestamp > 1728777669) {
revert Dussehra__MahuratIsFinished();
}
IsRavanKilled = true;
uint256 totalAmountByThePeople = WantToBeLikeRam.length * entranceFee;
totalAmountGivenToRam = (totalAmountByThePeople * 50) / 100;
(bool success, ) = organiser.call{value: totalAmountGivenToRam}("");
require(success, "Failed to send money to organiser");
}

The function only checks for RamIsSelected meaning that once Ram is selected and the Mahurat starts a user may call this function twice, preventing the Ram from withdrawing.

Add the following code to Dussehra.t.sol:

function testCanKillRavanaTwice() public participants {
vm.warp(1728691200 + 1);
vm.startPrank(organiser);
choosingRam.selectRamIfNotSelected();
vm.stopPrank();
vm.startPrank(player1);
dussehra.killRavana();
vm.stopPrank();
assert(dussehra.IsRavanKilled());
vm.startPrank(player1);
dussehra.killRavana();
vm.stopPrank();
vm.expectRevert();
vm.startPrank(player2);
dussehra.withdraw();
vm.stopPrank();
assertEq(address(organiser).balance, 2 ether);
}

The Test will show the withdraw function reverting due to a EvmError: OutOfFunds, and the 2 Eth of entry funds in the Organiser wallet.

Impact

The Ram is unable to withdraw their funds as all the funds have been sent to the Organiser.

Tools Used

Manual Review,
Foundry,

Recommendations

Add a check for the IsRavanKilled parameter to revert the function, this will prevent re-entry.

function killRavana() public RamIsSelected {
if (block.timestamp < 1728691069) { //written - magic numbers, timestamp for comparison
revert Dussehra__MahuratIsNotStart();
}
if (block.timestamp > 1728777669) { //written - magic numbers, timestamp for comparison
revert Dussehra__MahuratIsFinished();
}
+ require(!IsRavanKilled, "Ravana is already killed!");
IsRavanKilled = true;
uint256 totalAmountByThePeople = WantToBeLikeRam.length * entranceFee;
totalAmountGivenToRam = (totalAmountByThePeople * 50) / 100; //written - magic numbers
(bool success, ) = organiser.call{value: totalAmountGivenToRam}("");
require(success, "Failed to send money to organiser");
}
Updates

Lead Judging Commences

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

isRavanKilled is not checked

Support

FAQs

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