The maximum value of a uint64 is 18446744073709551615. Since fee is measured in Wei, 18446744073709551615 WEI is equivalent to 18.45 ETH. This means that if the totalFee that has accumulated in the contract surpasses 18.45 ETH, there will be an overflow error resulting in a very small fee balance.
In PuppyRaffle::selectWinner on line 133-134, fee is initialized as a uint256 and then downcast to a uint64 on the subsequent line.
fee is calculated using the following logic:
If totalAmountCollected surpasses (18.45 ETH * 100) / 20 which equates to 92.23 ETH, then fee will overflow when downcast to uint64 as it will surpass the maximum value of uint64:
Firstly, due to overflow in the fee, the totalFees that can be withdrawn by the feeAddress will be smaller than the true fees.
Secondly, if this happens, the value in the contract will be non-zero even if the winner is paid and the feeRecipient withdraws the totalFees. This will result in a state of DoS when calling withdrawFees() as explained in the following issue: "Unable to withdraw fees if contract balance is not equal to totalFees when no players are active".
Since the value of totalAmountCollected required to cause this overflow is 92.23 ETH, this is likely and therefore a high risk vulnerability.
A new PuppyRaffle contract is initialized with an expensiveEntranceFee of 1e20 to ensure that the maximum value of the uint64 is reached.
The test enters 4 players into the raffle. The test passes if the value of the totalFee calculated without the unsafe downcast is greater than the value returned from the contract.
Running the test yields the following output:
As expected, the test passes, meaning that there has been an overflow of fee due to the unsafe downcast to a uint64.
Do not downcast fee to a uint64 and keep all ether values as uint256, including totalFee to ensure the maximum value is not surpassed.
Use OpenZeppelin's SafeMath as SafeMath is not enabled by default for Solidity versions before 0.8.0.
Forge
Chisel
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.