DatingDapp

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

Innocent matched users griefed with no rewards due to unused `userBalances` mapping.

Description:

The matchRewards function fetches ETH balances from userBalances[from] and userBalances[to] but these balances are never updated when users send ETH via likeUser.

Impact:

Since userBalances is never updated, the matchRewards function will always consider these values as zero, leading to an incorrect reward distribution. Additionally, ETH accumulates in the contract without being properly accounted for

Proof of Concept:

Created an external function to view the userBalances mapping.

function getUserBalance(address user) external view returns (uint256) {
return userBalances[user];
}

Place this in the testLikeRegistry.t.sol file.

function testMatchedUsersBalancesUpdated() public {
// Supply UserA with ETH.
deal(userA, 2 ether);
// Supply UserB with ETH.
deal(userB, 2 ether);
// UserA mints Nft
vm.startPrank(userA);
profileNft.mintProfile("userA", 25, "ipfs://profileImage");
vm.stopPrank();
// UserB mints Nft
vm.startPrank(userB);
profileNft.mintProfile("userB", 25, "ipfs://profileImage");
vm.stopPrank();
// UserA liking UserB
vm.prank(userA);
likeRegistry.likeUser{value: 1 ether}(userB);
// UserB liking UserA
vm.prank(userB);
likeRegistry.likeUser{value: 1 ether}(userA);
// check to see if the userBalances have been updated...
uint256 userBalanceOfUserA = likeRegistry.getUserBalance(userA);
uint256 userBalanceOfUserB = likeRegistry.getUserBalance(userB);
console2.log("This is the user balance of UserA::", userBalanceOfUserA);
console2.log("This is th user balance of UserB::", userBalanceOfUserB);
}

These were the following logs that were outputted:

534] LikeRegistry::getUserBalance(ECRecover: [0x0000000000000000000000000000000000000001]) [staticcall]
│ └─ ← [Return] 0
├─ [534] LikeRegistry::getUserBalance(SHA-256: [0x0000000000000000000000000000000000000002]) [staticcall]
│ └─ ← [Return] 0
├─ [0] console::log("This is the user balance of UserA::", 0) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("This is th user balance of UserB::", 0) [staticcall]
│ └─ ← [Stop]

Meaning that the userBalances is not updated this making the reward distribution system of the protocol to be null and void.

Recommended Mitigation:

The userBalances mapping should be updated in the likeUser function as shown below.

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;
// event emitted correctly..
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.