Puppy Raffle

AI First Flight #1
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

# M-01 Forced ETH can permanently block `withdrawFees()`

M-01 Forced ETH can permanently block withdrawFees()

Description

  • Normal behavior: protocol fees should remain withdrawable whenever business logic allows withdrawals.

  • Issue: withdrawFees() requires strict equality between raw contract balance and totalFees. Forced ETH (e.g., via selfdestruct) breaks this invariant permanently and can lock fee withdrawals.

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");
}

Risk

Likelihood:

  • Any external actor can deploy a helper contract and force-send ETH using selfdestruct.

  • The strict equality condition remains brittle under unavoidable balance perturbations.

Impact:

  • Fee withdrawal can be indefinitely DoSed.

  • Operational revenue flow is interrupted and may require contract migration or privileged recovery.

Proof of Concept

contract ForceSend {
constructor() payable {}
function boom(address payable target) external {
selfdestruct(target);
}
}
// Steps:
// 1) Deploy ForceSend with 1 wei.
// 2) Call boom(payable(address(raffle))).
// 3) Call raffle.withdrawFees(); strict equality check fails and reverts.

Recommended Mitigation

- require(address(this).balance == uint256(totalFees), "PuppyRaffle: There are currently players active!");
+ require(address(this).balance >= uint256(totalFees), "Insufficient fees");
+ // maintain dedicated accounting for active pot vs fees; do not rely on exact raw balance equality
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!