DatingDapp

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

User balances are not updated in `LikeRegistry::userBalances` when we call `LikeRegistry::likeUser`

Summary

In the `LikeRegistry` Contract, there is a mapping of address to uint256, the `LikeRegistry::userBalances`. However, when we call the `LikeRegistry::likeUser`, the `LikeRegistry::userBalances` variable is not updated.

Vulnerability Details

Proof of Concept:

1. Users like other users profile.
2. On call of `LikeRegistry::likeUser` function, the `msg.sender` loses ETH but the `LikeRegistry::userBalances` is not updated. So, the balance of the liked user is still zero.
3. The ETH sent by `msg.sender` is locked in the smartcontract with no way of retrieving it.

Proof of Code:

<details>
<summary>Code</summary>
Add the following code to the `testSoulboundProfileNFT.t.sol` file.
```javascript
function testUserBalanceNotUpdatedWhenUserIsLiked() public {
vm.prank(user); // Simulates user calling the function
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
vm.prank(user2); // Simulates user2 calling the function
soulboundNFT.mintProfile("Ochuko", 24, "ipfs://profileImage");
uint256 TRANSFER_AMOUNT = 1 ether;
// Create LikeRegistry instances with the correct profile NFT address
LikeRegistry userRegistry = new LikeRegistry(address(soulboundNFT));
uint256 userAddressBalanceBefore = address(user).balance;
uint256 user2BalanceBefore = userRegistry.userBalances(user2);
uint256 userRegistryContractBalanceBefore = address(userRegistry).balance;
vm.deal(user, 2 * TRANSFER_AMOUNT);
vm.prank(user);
userRegistry.likeUser{value: TRANSFER_AMOUNT}(user2);
uint256 userAddressBalanceAfter = address(user).balance;
uint256 user2BalanceAfter = userRegistry.userBalances(user2);
uint256 userRegistryContractBalanceAfter = address(userRegistry).balance;
assertEq(user2BalanceBefore, user2BalanceAfter);
assert(userAddressBalanceAfter - userAddressBalanceBefore == TRANSFER_AMOUNT);
assert(userRegistryContractBalanceAfter - userRegistryContractBalanceBefore == TRANSFER_AMOUNT);
}
```
</details>

Impact

The `LikeRegistry::userBalances` variable is not updated. All users' balance will remain zero irrespective of the amount of likes they have. This means that money will be lost in the contract because the `LikeRegistry::totalFees` which is the amount withdrawable by the owner is dependent on `LikeRegistry::userBalances`. The implication is that all users will have zero balances and be unable to withdraw any funds even if they are matched. Also, the owner of the contract will not be able to withdraw any funds because the `LikeRegistry::totalFees` variable is also zero. This means that every ETH sent via the `LikeRegistry::likeUser` function is going to be lost in the smartcontract.

Recommendations

To fix this, we should have the `LikeRegistry::likeUser` function update the `LikeRegistry::userBalances` mapping. The whole issue stems from here [LikeRegistry::likeUser](https://github.com/CodeHawks-Contests/2025-02-datingdapp/blob/878bd34ef6607afe01f280cd5aedf3184fc4ca7b/src/LikeRegistry.sol#L31)

```diff
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;
+ userBalances[liked] += msg.value;
emit Liked(msg.sender, liked);
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.