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.