DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Users Cannot Recover excess Eth sent or their ETH If the Person They Like Likes Another Person, Leading to excess Loss of Funds Over Time if They Like Many People

Summary

The LikeRegistry contract allows users to express interest in others by sending ETH along with their "like." However, if a user likes multiple people and those likes are not reciprocated, the ETH they send remains locked in the contract indefinitely. There is no mechanism for users to recover funds if they are not matched. Over time, this results in a significant loss of funds for users who engage with the platform frequently but do not receive mutual likes. Also, there is no refund mechanism for excess eth sent to the contract

Vulnerability Details

When a user submits a "like," they must send at least 1 ETH. However, if the recipient of the like does not like them back, there is no mechanism for the sender to withdraw their ETH. This results in funds becoming permanently locked in the contract. The users who were not reciprocated lose their ETH permanently to the contract unless an admin function allows withdrawals or refunds which does not exist. The contract accumulates stuck ETH over time, which can lead to centralization risks or funds being trapped indefinitely. secondly, If a user sends more than 1 ETH, only the minimum requirement is checked. Extra ETH is not credited or tracked in userBalances. The user permanently loses any extra ETH sent.

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");
likes[msg.sender][liked] = true;
emit Liked(msg.sender, liked);
// Check if mutual like
if (likes[liked][msg.sender]) {
matches[msg.sender].push(liked);
matches[liked].push(msg.sender);
emit Matched(msg.sender, liked);
matchRewards(liked, msg.sender);
}
}

Proof of concept

This poc shows that excess eth cannot be refunded and there is no mechanism to recover eth if users are not liked back as users balance shows zero, meaning that the eth they sent is in stucked in the contract

function testExcessETHCannotBeRefunded() public {
// Fund user1 with 10 ETH before interaction
vm.deal(user1, 10 ether);
// User1 sends 3 ETH instead of just 1 ETH
vm.prank(user1);
likeRegistry.likeUser{value: 3 ether}(user2);
// Ensure contract balance increased
assertEq(address(likeRegistry).balance, 3 ether, "ETH should be in LikeRegistry");
// Check that user1's balance is still 0
assertEq(likeRegistry.userBalances(user1), 0, "User1 balance should NOT be updated");
// Try to withdraw the excess ETH (assuming there's no withdrawal function)
vm.prank(user1);
(bool success, ) = address(likeRegistry).call(abi.encodeWithSignature("withdraw()"));
// The call should fail since withdraw() does not exist
assertFalse(success, "User1 should NOT be able to withdraw excess ETH");
}

Impact

This issue leads to long-term loss of funds for users who frequently use the protocol but do not receive mutual likes. Since there is no mechanism to refund ETH for unreciprocated likes, the contract accumulates funds. Users who engage more frequently will be affected, as their ETH contributions will continue to be locked without any means of retrieval.

This discourages engagement with the protocol. Users who realize their funds are irrecoverable may stop participating, leading to a decline in user activity and trust in the platform.

Tools Used

Manual review

Recommendations

To address this issue, the contract should implement a withdrawal function that allows users to recover ETH if their like is not reciprocated. This can be achieved by modifying the likeUser function to only transfer ETH upon a confirmed match, rather than requiring an upfront payment that may never be refunded.

Updates

Appeal created

n0kto Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.