DatingDapp

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

Mishandling ETH in likeUser Function

Summary

In the LikeRegistry contract, the userBalances mapping is never updated with the funds sent by users during the likeUser function execution. As a result, users' balances remain at 0, and the reward mechanism in the matchRewards function fails to properly distribute funds. This leads to an ineffective contract where ETH is sent to the contract but never tracked or distributed and is locked forever.

Vulnerability Details

The contract defines a userBalances mapping to track user balances:

mapping(address => uint256) public userBalances;

However, in the likeUser function, when a user likes another user, the contract does not update userBalances with the ETH sent. As a result, user balances are never incremented with the funds sent to the contract. The matchRewards function is intended to handle reward distribution but always operates with 0 balances for the users because userBalances was never updated.

Step-by-Step Explanation and Proof
Deploy Contracts:

  1. Setup Users (Alice and Bob):

  2. Alice and Bob each mint a profile NFT from SoulboundProfileNFT and fund both with 1 ETH.

  3. Alice calls likeUser(bobAddress) with 1 ETH.

  4. Bob calls likeUser(aliceAddress) with 1 ETH.

  5. The contract's balance becomes 2 ETH.

  6. Mutual like detected; matchRewards is triggered.

    userBalances[alice] = 0 (never updated after sending ETH).

    userBalances[bob] = 0.

    During matchRewards:

    totalRewards = 0 + 0 = 0.

    matchingFees = 0 (10% of 0).

    rewards = 0; nothing sent to MultiSig.

    After matchRewards:

    userBalances[alice] and userBalances[bob] remain 0.

    Contract balance is still 2 ETH (ETH not distributed).

Conclusion:

The userBalances stay at 0 because the contract fails to credit the sent ETH to userBalances.

The 2 ETH remains in the contract, proving the bug.

function setUp() public {
soulboundNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(soulboundNFT));
}
function testUserBalancesAfterMatch() public {
vm.prank(user);
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
vm.deal(user, 1 ether);
vm.prank(user2);
soulboundNFT.mintProfile("Bob", 26, "ipfs://profileImage");
vm.deal(user2, 1 ether);
vm.prank(user);
likeRegistry.likeUser{value: 1 ether}(user2);
vm.prank(user2);
likeRegistry.likeUser{value: 1 ether}(user);
// Prove that balances are still 0
assertEq(likeRegistry.userBalances(user), 0, "User's balance should be 0");
assertEq(likeRegistry.userBalances(user2), 0, "User2's balance should be 0");
// Prove that matchRewards() received 0 funds
assertEq(address(likeRegistry).balance, 2 ether, "Contract balance should be 2 ETH");
}

Output:

[PASS] testUserBalancesAfterMatch() (gas: 1020227)
Suite result: ok. 1 passed; 0 failed; 0 skipped;

Impact

  • High severity: No funds are tracked for users, preventing the reward mechanism from working.

  • High severity: MultiSigWallet receives no funds, making it useless.

  • Critical severity: Users are unable to withdraw or access the rewards they should have received.

  • High severity: Funds are locked forever in LikeRegistry contract.

Tools Used

  • Manual code review

  • Solidity test framework

Recommendations

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");
//Add this line to properly send the ETH
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 6 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.