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.
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.
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
Bob has not interacted yet.
Bob never calls likeUser(Alice).
Bob keeps his profile NFT active and never burns it.
Alice waits indefinitely, but no match is ever created.
Alice attempts to recover her 1 ETH.
There is no function that allows Alice to:
Cancel the like, or
Refund her ETH, as long as Bob’s profile still exists.
refundUnmatchedLikesFromBurnedProfiles cannot be used because:
*profileNFT.profileToToken(Bob) != 0.
Alice’s 1 ETH remains permanently locked in
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.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.