DatingDapp

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

Unmatched Likes Can Permanently Lock User Funds

[M-3] Unmatched Likes Can Permanently Lock User Funds

Note: Please resolve [M-2] before addressing [M-3], as [M-3] relies on the refund mechanism introduced in [M-2] to safely handle unmatched likes and prevent permanent fund locking

Description

  • When a user sends ETH through likeUser, the funds remain locked in the contract until one of the following occurs:

  • The liked user reciprocates and a match is created, or The liked user burns their profile and the sender calls refundUnmatchedLikesFromBurnedProfiles.

  • If the liked user never reciprocates and never burns their profile, the sender has no available mechanism to withdraw or cancel their locked funds.

=> This creates a scenario where user funds can remain permanently locked in the contract with no recovery path.

Risk:

Impact: Medium

  • This issue does not allow direct theft of funds, but it can cause permanent loss of user liquidity and significantly degrade user experience.

  • In practice, a malicious or inactive user can grief others by indefinitely locking their ETH.

  • Over time, this can accumulate into a large amount of trapped funds inside the protocol

Likelihood: High

  • Any user can simply ignore incoming likes.

  • No malicious behavior or advanced attack is required.

  • Inactive or abandoned accounts naturally cause this condition.

=> Therefore, this situation is very likely to occur in production.

Proof of concept:

  1. Alice has a valid profile NFT and calls likeUser(Bob) while sending 1 ETH.

    The contract records:

    • likes[Alice][Bob].status = Liked

    • likes[Alice][Bob].totalSent = 1 ETH

  2. Bob has not interacted yet.

  3. Bob never calls likeUser(Alice).

  4. Bob keeps his profile NFT active and never burns it.

  5. Alice waits indefinitely, but no match is ever created.

  6. Alice attempts to recover her 1 ETH.

  7. There is no function that allows Alice to:

    • Cancel the like, or

    • Refund her ETH, as long as Bob’s profile still exists.

  8. refundUnmatchedLikesFromBurnedProfiles cannot be used because:

    *profileNFT.profileToToken(Bob) != 0.

  9. Alice’s 1 ETH remains permanently locked in

Recommended Mitigation:

  • Put this following mitigation in conntract LikeRegistry:

    • The cancelLike function allows users to recover funds from an unmatched like, preventing permanent fund locking.

    • The check require(likes[liked][msg.sender].status == None) ensures that cancellation is only possible before the other party reciprocates, preventing front-running and race-condition abuse.

    • By resetting state before transferring ETH, the function follows the CEI pattern and avoids reentrancy risks.

+ function cancelLike(address liked) external {
+ Like storage l = likes[msg.sender][liked];
+ require(l.status == LikeStatus.Liked, "No active like");
+ require(likes[liked][msg.sender].status == LikeStatus.None, "Already reciprocated");
+
+ uint256 amount = l.totalSent;
+ l.totalSent = 0;
+ l.status = LikeStatus.None;
+
+ payable(msg.sender).transfer(amount);
+ }
+
Updates

Lead Judging Commences

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