DatingDapp

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

DoS Through Unbounded Array Growth in Matches

Root + Impact

Description

The matches mapping stores an unbounded array of addresses for each user's matches. Malicious actors can create multiple accounts and repeatedly match with a victim, causing their matches array to grow indefinitely. This makes the getMatches() function increasingly expensive to call and could eventually exceed the block gas limit, effectively DoS-ing the user's ability to retrieve their matches.

mapping(address => address[]) public matches;
function likeUser(address liked) external payable {
// ...
if (likes[liked][msg.sender]) {
matches[msg.sender].push(liked); // Unbounded push
matches[liked].push(msg.sender); // Unbounded push
emit Matched(msg.sender, liked);
matchRewards(liked, msg.sender);
}
}
function getMatches() external view returns (address[] memory) {
return matches[msg.sender]; // Returns entire unbounded array
}

Risk

Impact:
Users with many matches will face increasing gas costs when calling getMatches(). In extreme cases, the function becomes unusable due to block gas limits. Malicious users can grief others by creating fake profiles and matching repeatedly, filling up their matches array.

Proof of Concept

// Attacker creates multiple addresses and profiles
for (uint i = 0; i < 1000; i++) {
address fakeProfile = address(uint160(i));
// Create profile for fakeProfile
// Like victim from fakeProfile
// Like fakeProfile from victim
// This creates a match, adding to victim's array
}
// Victim's matches array now has 1000+ entries
// getMatches() becomes very expensive or fails

Recommended Mitigation

// Solution 1: Implement pagination
mapping(address => address[]) public matches;
mapping(address => uint256) public matchCount;
function getMatches(uint256 offset, uint256 limit)
external view returns (address[] memory) {
uint256 total = matches[msg.sender].length;
if (offset >= total) return new address[](0);
uint256 end = offset + limit;
if (end > total) end = total;
address[] memory result = new address[](end - offset);
for (uint256 i = offset; i < end; i++) {
result[i - offset] = matches[msg.sender][i];
}
return result;
}
// Solution 2: Limit maximum matches per user
uint256 constant MAX_MATCHES = 100;
require(matches[msg.sender].length < MAX_MATCHES, "Match limit reached");
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 1 day 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!