Summary
The Dussehra::killRavana() function can be called more than once, because it doesn't have a check for Dussehra::IsRavanKilled or something that prevents this behavior. Also, the function can be called by anyone. A bad organiser could use an anonymous wallet to call this function twice and get all the money in the prize, leaving the chosen Ram without prize to withdraw.
Impact
All the money that this contract is intended to handle is at risk, not to be stolen away, but as a rug pull by the organiser.
Tools Used
Manual review and Foundry test suite
Proof of Code
Include this test in Dussehra.t.sol:
function test_RavanaCanBeKilledTwiceToStealPrize() public participants {
vm.warp(1728691200 + 1);
vm.startPrank(organiser);
choosingRam.selectRamIfNotSelected();
uint256 startingOrganiserBalance = organiser.balance;
vm.stopPrank();
vm.startPrank(player2);
dussehra.killRavana();
uint256 RamwinningAmount = dussehra.totalAmountGivenToRam();
dussehra.killRavana();
vm.stopPrank();
assertEq(organiser.balance, startingOrganiserBalance + (RamwinningAmount * 2));
Recommendations
Include a check for IsRavanKilled in killRavana() to prevent the function being called twice
function killRavana() public RamIsSelected {
+ require(IsRavanKilled == false, "Ravana is already killed!");
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");
}