When a user calls likeUser(), they send 1 ETH as a "stake" representing genuine interest. If the like is mutual, matchRewards() is called, which reads both users' balances from userBalances, zeroes them out, takes a 10% fee, and forwards the remaining ETH to a newly deployed MultiSigWallet that both matched users control.
likeUser() accepts msg.value and stores the like flag, but never writes msg.value into userBalances[msg.sender]. As a result, every call to matchRewards() reads userBalances[from] == 0 and userBalances[to] == 0. The total rewards computed is 0 wei. The MultiSig is deployed and funded with nothing. Both users' ETH remains trapped in LikeRegistry forever, with no user-facing withdrawal function to recover it.
Likelihood:
Every single likeUser() call is affected — this is the core user flow, not an edge case. Any user who sends ETH and gets matched will lose their funds.
No special conditions are required. The bug triggers on every mutual match, 100% of the time.
Impact:
All ETH sent via likeUser() accumulates in the LikeRegistry contract balance with zero accounting, making it unrecoverable by users.
Matched couples receive a 0-wei MultiSig wallet instead of their pooled date fund.
The withdrawFees() function only withdraws totalFees, which is also 0 — so even the owner cannot rescue the locked ETH.
Protocol is economically non-functional from block 1 of deployment.
Add userBalances[msg.sender] += msg.value; immediately after the validation checks in likeUser(), before the mutual-like check:
## 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.