DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

ETH Payments Not Tracked in userBalances, Causing loss of funds

Summary

LikeRegistry does not track user balances, leading to locked ETH

The LikeRegistry fails to credit users' userBalances when ETH is sent during likeUser, resulting in zero rewards for matched pairs and permanent ETH loss.

Vulnerability Details

The LikeUserfunction accepts ETH but fails to update the user balance mapping userBalances, causing all rewards to default to 0 during matches.
The ETH goes into the contract but the sender's balance in userBalanacesremain 0

When matches occur, matchRewards pools from userBalances (always zero), sending 90% of zero ETH to the multisig while retaining all user ETH in the contract.

This means all ETH sent with likes gets trapped in the contract

Impact

ETH is being permanently locked in the contract, rendering the core matching functionality non-functional and causing direct financial loss to users.

POC

// User A (0xAA) sends 1 ETH to like User B (0xBB)
vm.deal(address(0xAA), 1 ether);
vm.prank(0xAA);
likeRegistry.likeUser{value: 1 ether}(0xBB);
//User B reciprocates
vm.prank(0xBB);
likeRegistry.likeUser{value: 1 ether}(0xAA);
//MatchRewards calculates totalRewards = 0 + 0 = 0 ETH
// All 2 ETH remain stuck in LikeRegistry

Tools Used

Manual review, Foundry test simulations.

Recommendations

Track ETH per user

In the likeUserfunction implement updating the userBalancesmapping with the value being 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");
userBalances[msg.sender] += msg.value; // add this line here
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);
}
}
Updates

Appeal created

n0kto Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_likeUser_no_userBalances_updated

Likelihood: High, always. Impact: High, loss of funds

Support

FAQs

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