DatingDapp

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

User Payments Are Not Tracked in userBalances (Loss of Funds + Incorrect Reward Distribution)

Description

The likeUser function requires users to send at least 1 ETH when liking another user. However, the contract does not update userBalances[msg.sender] with the received funds, causing an issue where:

Users' payments are not tracked, meaning they are effectively lost within the contract.
The matchRewards function relies on userBalances to calculate rewards, but since the balance is never incremented, users will not receive their rightful rewards upon a match.

likeUser Function:

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);
}
}

Impact

  • Loss of funds: Users send ETH, but their balances are never updated, meaning they can never claim or use it later.

  • Incorrect reward distribution: The reward logic in matchRewards relies on userBalance

Proof of Concept

Add the following to the testSoulboundProfileNFT test file.

function testIncreassesBalance() public {
likeRegistry = new LikeRegistry(address(soulboundNFT));
address alice = makeAddr("alice");
address pablo = makeAddr("pablo");
vm.prank(alice);
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
vm.prank(pablo);
soulboundNFT.mintProfile("Pablo", 25, "ipfs://profileImage1");
hoax(makeAddr("pablo"), 1 ether);
console.log("Pablo balance: ", pablo.balance);
likeRegistry.likeUser{value: 1 ether}(alice);
console.log("Pablo balance: ", likeRegistry.userBalances(pablo));
assertEq(likeRegistry.userBalances(pablo), 0);
}

Tools Used

Manual

Recommendations

Update userBalances[msg.sender] inside likeUser function when ETH is received.
Add the following line in likeUser:

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 N FT");
+ userBalances[msg.sender] += msg.value;
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 5 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.