DatingDapp

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

`LikeRegistry::userBalances` not updated when calling `LikeRegistry::likeUser`

Description:

Every deposit made by the user is tracked via the LikeRegistry::userBalances mapping, which in turn allows for the calculation of the totalRewards in LikeRegistry::matchRewards. However, when the user calls LikeRegistry::likeUser, the mapping is never updated.

Impact:

This bug causes a severe disruption in the protocol functioning, as the LikeRegistry::matchRewards function will not be able to calculate the correct amount of rewards to be pooled in the MultiSig wallet whenever a mutual like happens. Therefore, the funds deposited by the user will be trapped inside the smart contract.

Tools Used:

Manual review

Proof of Concept:

Create a new file in the test folder (e.g. testLikeRegistry) and add the testLikeUserDoesNotUpdateUserBalances test. This test demonstrates how the initial balance stored in the smart contract for a given user doesn't change even after they sent 1 ether to like another user.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../src/SoulboundProfileNFT.sol";
import "../src/LikeRegistry.sol";
contract LikeRegistryTest is Test {
SoulboundProfileNFT soulboundNFT;
LikeRegistry likeRegistry;
address user1 = makeAddr("user1");
address user2 = makeAddr("user2");
address owner = address(this);
function setUp() public {
soulboundNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(soulboundNFT));
vm.prank(user1);
soulboundNFT.mintProfile("Bob", 23, "ipfs://BobProfileImage");
vm.prank(user2);
soulboundNFT.mintProfile("Alice", 25, "ipfs://AliceProfileImage");
deal(user1, 10 ether);
deal(user2, 10 ether);
}
function testLikeUserDoesNotUpdateUserBalances() public {
uint256 user1InitialBalance = likeRegistry.userBalances(user1);
vm.prank(user1);
likeRegistry.likeUser{value: 1 ether}(user2);
uint256 user1FinalBalance = likeRegistry.userBalances(user1);
assertEq(user1InitialBalance, user1FinalBalance);
}
}

Recommended mitigation:

Update the user balance inside the LikeRegistry::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");
+ 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 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.