Summary
The PuppyRaffle::withdrawFees() function is currently accessible to anyone. However, it's worth noting that the feeAddress is established and controlled by the contract owner. Therefore, it's advisable to limit the withdrawal access to the contract owner exclusively. In this manner, the owner can exercise discretion in determining when to withdraw fees from the system.
Vulnerability Details
@>function withdrawFees() external {
require(address(this).balance == uint256(totalFees), "PuppyRaffle: There are currently players active!");
uint256 feesToWithdraw = totalFees;
totalFees = 0;
(bool success,) = feeAddress.call{value: feesToWithdraw}("");
require(success, "PuppyRaffle: Failed to withdraw fees");
}
Impact
function testNotOwnerCanWithdrawFees() public playersEntered {
vm.warp(block.timestamp + duration + 1);
vm.roll(block.number + 1);
uint256 expectedFeeAmount = ((entranceFee * 4) * 20) / 100;
console.log("The expected fee amount:", expectedFeeAmount);
puppyRaffle.selectWinner();
vm.prank(playerOne);
puppyRaffle.withdrawFees();
assertEq(address(feeAddress).balance, expectedFeeAmount);
console.log("The withdrawed fee:", address(feeAddress).balance);
}
Tools Used
Manual review
Recommendations
Restrict with onlyOwner modifier the PuppyRaffle::withdrawFees() function.
- function withdrawFees() external {
+ function withdrawFees() external onlyOwner{
require(address(this).balance == uint256(totalFees), "PuppyRaffle: There are currently players active!");
uint256 feesToWithdraw = totalFees;
totalFees = 0;
(bool success,) = feeAddress.call{value: feesToWithdraw}("");
require(success, "PuppyRaffle: Failed to withdraw fees");
}