DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Denial of Service via Match Array Bloat

Root + Impact

Description

  • Describe the normal behavior in one or more sentences


  • Explain the specific issue or problem in one or more sentences

  • The matches array grows unbounded without limits. A malicious actor can create multiple fake profiles and repeatedly match with a target user, causing their matches array to bloat.

// Root cause in the codebase with @> marks to highlight the relevant section
mapping(address => address[]) public matches;
function getMatches() external view returns (address[] memory) {
return matches[msg.sender]; // No pagination, returns entire array
}

Risk

Likelihood:

  • Reason 1 // Describe WHEN this will occur (avoid using "if" statements)

  • Reason 2

Impact:

  • Impact 1

  • Users cannot retrieve their match list after array grows large

  • Gas costs become prohibitively expensive

  • DoS on legitimate users through array bloat attack


  • Impact 2

Proof of Concept

// Attacker griefs victim
for (uint i = 0; i < 1000; i++) {
address fakeProfile = createFakeProfile();
likeUser{value: 1 ether}(victim);
vm.prank(victim);
likeUser{value: 1 ether}(fakeProfile); // Creates match
// victim.matches array grows to 1000+ entries
}
// Victim cannot call getMatches() - exceeds gas limit
vm.prank(victim);
vm.expectRevert(); // Out of gas
registry.getMatches();

Recommended Mitigation

- remove this code
+ add this code
function getMatches(uint256 offset, uint256 limit)
external
view
returns (address[] memory, uint256 total)
{
address[] storage allMatches = matches[msg.sender];
uint256 total = allMatches.length;
if (offset >= total) {
return (new address[](0), total);
}
uint256 end = offset + limit;
if (end > total) {
end = total;
}
address[] memory page = new address[](end - offset);
for (uint256 i = 0; i < page.length; i++) {
page[i] = allMatches[offset + i];
}
return (page, total);
}
uint256 constant MAX_MATCHES = 100;
function matchRewards(address from, address to) internal {
require(matches[from].length < MAX_MATCHES, "Max matches reached");
require(matches[to].length < MAX_MATCHES, "Max matches reached");
// ...
}
Updates

Lead Judging Commences

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