Puppy Raffle

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

feeAddress Is Never Validated Against address(0), Permanently Locking All Protocol Fees

feeAddress Is Never Validated Against address(0), Permanently Locking All Protocol Fees

Severity: Low

Description

  • The constructor and changeFeeAddress both accept any address for feeAddress with no zero-address guard. If address(0) is passed — by accident or
    misconfiguration — all accumulated fees are sent to the burn address and are unrecoverable.

  • withdrawFees transfers the full totalFees balance directly to feeAddress with no fallback or override path, so there is no way to redirect funds after the
    fact.

constructor(uint256 _entranceFee, address _feeAddress, uint256 _raffleDuration) {
@> feeAddress = _feeAddress; // no zero-address check
raffleDuration = _raffleDuration;
entranceFee = _entranceFee;
}
function changeFeeAddress(address newFeeAddress) external onlyOwner {
@> feeAddress = newFeeAddress; // no zero-address check
emit FeeAddressChanged(newFeeAddress);
}

Risk

Likelihood:

  • Deployment mistakes (copy-paste errors, scripting bugs) commonly pass address(0) for address parameters

  • A single changeFeeAddress(address(0)) call by the owner permanently destroys all future fee withdrawals

Impact:

  • All protocol fees sent to address(0) are permanently lost — ETH cannot be recovered from the zero address

  • No financial loss to players, but the protocol operator loses 100% of accumulated revenue

Proof of Concept

Deploying with address(0) as the fee address silently succeeds, and any subsequent withdrawFees call sends ETH to the burn address.

PuppyRaffle broken = new PuppyRaffle(1 ether, address(0), 1 days);
// No revert. withdrawFees will later send all fees to address(0).

Recommended Mitigation

Add a zero-address check wherever feeAddress is assigned.

constructor(uint256 _entranceFee, address _feeAddress, uint256 _raffleDuration) {

  • require(_feeAddress != address(0), "PuppyRaffle: Fee address cannot be zero");
    feeAddress = _feeAddress;

function changeFeeAddress(address newFeeAddress) external onlyOwner {

  • require(newFeeAddress != address(0), "PuppyRaffle: Fee address cannot be zero");
    feeAddress = newFeeAddress;

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 4 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!