DatingDapp

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

Duplicate Matches Can Be Created and matchRewards Called Multiple Times

Root + Impact

Description

  • The `likeUser()` function does not check if two users are already matched before processing a mutual like. If a user calls `likeUser()` again after already being matched with someone, the same address will be added to the `matches` array again, and `matchRewards()` will be called again. This creates duplicate entries and could lead to multiple reward distributions if the balance tracking bug is fixed.

    ```solidity

    // Check if mutual like

    if (likes[liked][msg.sender]) {

    matches[msg.sender].push(liked); // @> Can push same address multiple times

    matches[liked].push(msg.sender);

    emit Matched(msg.sender, liked);

    matchRewards(liked, msg.sender); // @> Can be called multiple times for same pair

    }

    ```

    ### Root Cause

    There's no mapping or check to track if two users are already matched. The code only checks if a like exists (`likes[liked][msg.sender]`), but doesn't verify if they've already been matched and processed.


Risk

Likelihood:

  • * Users can call `likeUser()` multiple times with the same address

    * Once mutual likes exist, any subsequent call will trigger match processing again

    * This will occur whenever a user accidentally or intentionally calls `likeUser()` again after matching

Impact:

  • * Duplicate entries in the `matches` array, causing gas waste and data inconsistency

    * `matchRewards()` could be called multiple times for the same pair

    * If the balance tracking bug is fixed, this could lead to double-spending of user balances

    * Multiple multisig wallets could be deployed for the same pair

    * Event emissions will be duplicated, causing off-chain tracking issues

Proof of Concept

```solidity
// User A likes User B
likeRegistry.likeUser{value: 1 ether}(userB);
// User B likes User A - MATCH occurs
likeRegistry.likeUser{value: 1 ether}(userA);
// matchRewards() called, multisig deployed
// User A accidentally calls likeUser again
likeRegistry.likeUser{value: 1 ether}(userB);
// Since likes[userB][userA] is still true, matchRewards() called AGAIN
// Duplicate entry added to matches[userA]
// Another multisig deployed (or attempt to process 0 balances again)
```

Recommended Mitigation

```diff
+ mapping(address => mapping(address => bool)) public isMatched;
function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
require(!likes[msg.sender][liked], "Already liked");
require(msg.sender != liked, "Cannot like yourself");
require(profileNFT.profileToToken(msg.sender) != 0, "Must have a profile NFT");
require(profileNFT.profileToToken(liked) != 0, "Liked user must have a profile NFT");
userBalances[msg.sender] += msg.value;
likes[msg.sender][liked] = true;
emit Liked(msg.sender, liked);
// Check if mutual like
- if (likes[liked][msg.sender]) {
+ if (likes[liked][msg.sender] && !isMatched[msg.sender][liked]) {
+ isMatched[msg.sender][liked] = true;
+ isMatched[liked][msg.sender] = true;
matches[msg.sender].push(liked);
matches[liked].push(msg.sender);
emit Matched(msg.sender, liked);
matchRewards(liked, msg.sender);
}
}
```
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 16 days 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!