PuppyRaffle::enterRaffle leads to Protocol Denial of ServiceRoot + Impact
The enterRaffle function uses nested loops to check for duplicate addresses in the players storage array. As the array grows, the gas cost for each new entry increases quadratically ($O(n^2)$). This leads to gas exhaustion where the cost to enter exceeds the Block Gas Limit, resulting in a permanent Denial of Service (DoS) for new participants and "bricking" the raffle.
A scalable raffle contract should maintain a near-constant gas cost for entries. Duplicate checks should be performed using efficient data structures, such as a mapping, to ensure constant-time ($O(1)$) complexity regardless of the number of participants.
The duplicate check is implemented with a nested for loop that iterates over the entire players array for every new player added in the batch.
As players.length increases, the number of required comparison operations grows exponentially. This causes the gas cost to surge rapidly. Once the player count reaches a certain threshold, the gas required for the transaction will exceed the Ethereum Block Gas Limit (30M gas), making it impossible for any further players to join.
Likelihood:
High. This is a fundamental flaw in the duplicate-check logic. Any raffle that successfully attracts a few hundred players will naturally trigger this gas ceiling.
Impact:
High. 1. Total Denial of Service: New users are unable to join the raffle because their transactions will consistently fail with "Out of Gas." 2. Protocol Bricking: If the raffle logic requires a minimum number of players to finish, and the gas cost to reach that number exceeds the block limit, the contract becomes permanently stuck, locking all prize funds and fees inside.
The following test demonstrates that adding 200 players consumes nearly the entire gas capacity of an Ethereum block, proving the growth.
Technical Analysis: At only 200 players, the gas consumption reached 25,556,454. Since the Ethereum Block Gas Limit is 30,000,000, adding even a small additional batch would exceed the limit and cause the transaction to fail permanently.
Replace the nested loop check with a mapping(address => bool) to track active players. This allows for duplicate checks to be performed in constant time.
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.