LikeRegistry.likeUser() collects 1 ETH from each caller and, when a mutual like is detected, calls matchRewards() to split the pooled payments between the matched couple via a newly deployed MultiSigWallet.
likeUser never writes userBalances[msg.sender] += msg.value, so matchRewards reads zero for both participants every time it fires. All ETH paid accumulates permanently in the contract with no recovery path.
Likelihood:
Every call to likeUser skips the balance write — the bug triggers on 100% of likes without exception.
The missing line is structural, not conditional; there is no code path in the current implementation that credits userBalances.
Impact:
All ETH paid by liking users (minimum 1 ETH each, 2 ETH per match) is permanently locked in LikeRegistry with no recovery path.
Every matched couple receives an empty multisig wallet, completely breaking the protocol's core value proposition of pooling payments for matched users.
withdrawFees only drains totalFees, which is also always zero due to the same root cause, so the owner cannot recover the locked ETH either.
Place this test in test/ and run forge test --match-test test_matchRewardsAlwaysZero. The test demonstrates that matched users always receive zero ETH from the MultiSig because likeUser() never credits userBalances[msg.sender] with the deposited ETH.
Add userBalances[msg.sender] += msg.value immediately after likes[msg.sender][liked] = true so every liker's balance reflects their deposited ETH before the mutual-like check fires.
## Description User A calls `likeUser` and sends `value > 1` ETH. According to the design of DatingDapp, the amount for user A should be accumulated by `userBalances`. Otherwise, in the subsequent calculations, the balance for each user will be 0. ## Vulnerability Details When User A calls `likeUser`, the accumulation of `userBalances` is not performed. ```solidity 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); } } ``` This will result in `totalRewards` always being 0, affecting all subsequent calculations: ```solidity uint256 totalRewards = matchUserOne + matchUserTwo; uint256 matchingFees = (totalRewards * FIXEDFEE ) / 100; uint256 rewards = totalRewards - matchingFees; totalFees += matchingFees; ``` ## POC ```solidity function testUserBalanceshouldIncreaseAfterLike() public { vm.prank(user1); likeRegistry.likeUser{value: 20 ether}(user2); assertEq(likeRegistry.userBalances(user1), 20 ether, "User1 balance should be 20 ether"); } ``` Then we will get an error: ```shell [FAIL: User1 balance should be 20 ether: 0 != 20000000000000000000] ``` ## Impact - Users will be unable to receive rewards. - The contract owner will also be unable to withdraw ETH from the contract. ## Recommendations Add processing for `userBalances` in the `likeUser` function: ```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[msg.sender] += msg.value; emit Liked(msg.sender, liked); [...] } ```
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.