Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

Denial of Service (DoS) Attack due to Inefficient Duplicate Check , Attacker can block the others from entering the ruffle

Summary

The enterRaffle function in the PuppyRaffle contract is vulnerable to a Denial of Service (DoS) attack due to an inefficient check for duplicate addresses.

Vulnerability Details

Scenario 1

The function checks for duplicate addresses by iterating over the entire players array for each new player. This results in a time complexity of O(n^2), which can lead to excessive gas costs when the number of players is large. An attacker could exploit this by entering a large number of unique addresses, causing the function to run out of gas and effectively blocking other users from entering the raffle.

In the enterRaffle function, there is a loop that iterates over the newPlayers array, and within that loop, there is another loop that iterates over the players array. This nested loop structure indicates that for each new player, the function checks for duplicates by iterating over the entire players array.

Here is the relevant code snippet:

for (uint256 i = 0; i < newPlayers.length; i++) {
address player = newPlayers[i];
require(!enteredPlayers[player], "PuppyRaffle: Duplicate player");
enteredPlayers[player] = true;
players.push(player);
}

The outer loop iterates over the newPlayers array, which has a length of n. The inner loop iterates over the players array, which can also have a length of n in the worst case.

Since the inner loop is executed for each iteration of the outer loop, the total number of iterations is n * n, resulting in a time complexity of O(n^2).

PoC

An attacker could call enterRaffle with a large array of unique addresses:

function testDoSAttckOnEnterRaffle() public {
// Enter A bunch of players into the raffle
address[] memory players = new address[](1000000000);
for (uint256 i = 0; i < 1000000000; i++) {
players[i] = address(i + 17);
}
puppyRaffle.enterRaffle{value: entranceFee * 1000000000}(players);
}

Impact

An attacker could prevent other users from entering the raffle by causing the enterRaffle function to run out of gas. This could disrupt the operation of the raffle and potentially lead to a loss of trust in the contract.

Tools Used

  • Foundry
    -match test forge test --match-contract PuppyRaffleTest --match-test testDoSAttckOnEnterRaffle

Recommendations

  • To mitigate this vulnerability, the check for duplicate addresses should be done in a more efficient manner.

  • One solution is to use a mapping to keep track of entered addresses. This would reduce the time complexity of the check to O(1), preventing the potential DoS attack.

mapping(address => bool) private enteredPlayers;
function enterRaffle(address[] memory newPlayers) public payable {
require(msg.value == entranceFee * newPlayers.length, "PuppyRaffle: Must send enough to enter raffle");
for (uint256 i = 0; i < newPlayers.length; i++) {
address player = newPlayers[i];
require(!enteredPlayers[player], "PuppyRaffle: Duplicate player");
enteredPlayers[player] = true;
players.push(player);
}
emit RaffleEnter(newPlayers);
}
Updates

Lead Judging Commences

Hamiltonite Lead Judge about 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

denial-of-service-in-enter-raffle

Support

FAQs

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

Give us feedback!