Summary
The code in Dussehra
contract calculates the rewards for the Ram and the Organiser by division of the total amount over 2 and uses the same value for both rewards. It does not consider if the total amount value is even or odd.
Vulnerability Details
The code in Dussehra
contract calculates the the total amount as uint256 totalAmountByThePeople = WantToBeLikeRam.length * entranceFee;
(Line 75, Dussehra.sol). This value might be odd number if the number of participants and the entrance fee are both odd numbers. The calculated rewards in the next line of code will be rounded and 1 wei will remain in the contract.
Proof of Concept
The following test demonstrates the vulnerability.
function test_dustAmountStaysInDussehraContract() public {
Dussehra dussehra;
RamNFT ramNFT;
ChoosingRam choosingRam;
address organiser = makeAddr("organiser");
address player1 = makeAddr("player1");
address player2 = makeAddr("player2");
address player3 = makeAddr("player3");
vm.startPrank(organiser);
ramNFT = new RamNFT();
choosingRam = new ChoosingRam(address(ramNFT));
dussehra = new Dussehra(1 wei, address(choosingRam), address(ramNFT));
ramNFT.setChoosingRamContract(address(choosingRam));
vm.stopPrank();
vm.startPrank(player1);
vm.deal(player1, 1 wei);
dussehra.enterPeopleWhoLikeRam{value: 1 wei}();
vm.stopPrank();
vm.startPrank(player2);
vm.deal(player2, 1 wei);
dussehra.enterPeopleWhoLikeRam{value: 1 wei}();
vm.stopPrank();
vm.startPrank(player3);
vm.deal(player3, 1 wei);
dussehra.enterPeopleWhoLikeRam{value: 1 wei}();
vm.stopPrank();
vm.warp(1728691200 + 1);
vm.startPrank(organiser);
choosingRam.selectRamIfNotSelected();
vm.stopPrank();
vm.startPrank(player2);
dussehra.killRavana();
vm.stopPrank();
vm.startPrank(player3);
dussehra.withdraw();
vm.stopPrank();
assertEq(address(dussehra).balance, 1 wei);
}
Impact
Dust amount of 1 wei will remain in the Dussehra contract if the calculated totalAmountByThePeople
is odd number. This will happen always for odd entrance fee and number of participants but only 1 wei will be lost.
Tools Used
Manual review
Recommendations
Calculate the reward of the Ram by using subtraction. See the code below.
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;
+ uint256 totalAmountGivenToOrganiser = totalAmountByThePeople * 50 / 100;
+ totalAmountGivenToRam = totalAmountByThePeople - totalAmountGivenToOrganiser;
- (bool success, ) = organiser.call{value: totalAmountGivenToRam}("");
+ (bool success, ) = organiser.call{value: totalAmountGivenToOrganiser}("");
require(success, "Failed to send money to organiser");
}