Puppy Raffle

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

`totalFees` is `uint64` and overflows — Solidity 0.7.6 has no checked math

Author Revealed upon completion

Root + Impact

Description

totalFees is a uint64 (max ≈ 18.45 ETH) and the contract uses Solidity 0.7.6, where arithmetic is unchecked — both the uint64(fee) cast and the + silently wrap instead of reverting.

@> uint64 public totalFees = 0;
...
@> totalFees = totalFees + uint64(fee);

Risk

Likelihood: Medium — it triggers in any raffle whose 20% fee exceeds ~18.45 ETH (e.g. 93+ players at a 1 ETH entrance fee).

Impact: Medium — the fee accounting is corrupted and withdrawFees() can never succeed afterwards, because it requires balance == totalFees. PoC: 100 players × 1 ETH → fee = 20 ETH, but uint64(20 ether) truncates to ≈ 1.55 ETH, so 20 ETH of protocol fees are permanently locked (balance 20 ETH vs totalFees 1.55 ETH).

Proof of Concept

The test enters 100 players at 1 ETH each, runs selectWinner(), and shows the fee was truncated by the uint64 cast and withdrawFees() reverts forever.

function test_M3_TotalFeesUint64Overflow() public {
_bulkEnter(100, 1000); // 100 players x 1 ETH = 100 ETH pot
vm.warp(block.timestamp + duration + 1);
raffle.selectWinner(); // fee = 20 ETH, but totalFees is uint64
​
uint256 expectedTruncated = uint256(uint64(20 ether));
assertEq(uint256(raffle.totalFees()), expectedTruncated, "fee truncated by uint64 cast");
assertTrue(uint256(raffle.totalFees()) != 20 ether, "20 ETH fee does not fit in uint64");
assertEq(address(raffle).balance, 20 ether, "real balance is 20 ETH");
​
vm.expectRevert(bytes("PuppyRaffle: There are currently players active!"));
raffle.withdrawFees(); // 20 ETH != ~1.55 ETH -> 20 ETH of fees stuck
}

Recommended Mitigation

Use uint256 for totalFees (no gas benefit justifies uint64 here), and upgrade to Solidity ≥ 0.8, where arithmetic is checked by default.

- uint64 public totalFees = 0;
+ uint256 public totalFees = 0;
...
- totalFees = totalFees + uint64(fee);
+ totalFees = totalFees + fee;

Support

FAQs

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

Give us feedback!