The intended behavior is that the feeAddress can withdraw the accumulated protocol fees via withdrawFees.
The specific issue is that withdrawFees requires the contract's ENTIRE ETH balance to be exactly equal to totalFees. Anyone can permanently break this by force-sending even 1 wei to the contract, after which the strict equality can never hold again and the fees are locked forever.
address(this).balance can be increased unconditionally via selfdestruct (force-send), which bypasses any receive/fallback. Once the balance exceeds totalFees, balance == totalFees is never true again, so withdrawFees reverts forever.
Likelihood: Medium
Any address can selfdestruct a tiny contract to force ETH into PuppyRaffle; it is cheap and irreversible.
Impact: Medium
The protocol's fees become permanently un-withdrawable: feeAddress can never collect the fees it is owed. A griefer bricks fee withdrawal for the life of the contract.
Do not tie withdrawal to the whole contract balance. Withdraw the tracked totalFees directly: uint256 amt = totalFees; totalFees = 0; feeAddress.call{value: amt}("");.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.