DatingDapp

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

There is no way for users or the owner to get money out if someone deletes their profile without any matches

Summary

The protocol lacks a withdrawal/refund mechanism for users who delete their profiles before getting matches, resulting in permanently locked ETH in the contract. Neither users nor the contract owner can recover these funds, creating a potential accumulation of inaccessible ETH.

Vulnerability Details

Imagine a scenario where a user creates a profile, likes someone and transfers eth to the contract. Then if they don't get a match for a long time or circumstances change otherwise (e.g. find a partner outside of the app) they may decide to leave the app, delete their profile and want to receive their money back. Currently, there is no way for users to get their ETH back if they delete their profile without getting any matches. This could lead to locked funds in the contract.

The vulnerability exists in the interaction between SoulboundProfileNFT.sol and LikeRegistry.sol. When users like someone, they send 1 ETH:

function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
// ...existing code...
}

Currently, this money is transferred out of the contract in two ways only: either through fees or by transferring the funds to the multi sig couples' walets. SoulboundProfileNFT.sol contract allows users to delete their profiles and cleans up associated data. However, there is no refund functionality if the user who wants to delete their profile has already transferred some eth to the contract.

Impact

This will cause funds to get locked in the contract when a user who liked someone on the patform (hence already transferred money) without any match decides to delete their profile. This could be by design, i.e. for making the stakes of liking somebody high. As a result users are forced to keep unwanted profiles to avoid losing funds until they get matched. Even if they abondon their funds, these are still locked in the contract forever without even the possibility for the owner to collect those extra eth.

Tools Used

Manual inspection, copilot and foundry.

Recommendations

Depending on the design purpose, a refund function can be added to the contract or the withdraw function can be augmented to collect the unclaimed eth. All existing likes of the leaving user needs to be cleaned up and their balance can be refunded after deleting their profile, perhaps with an exit fee cut.

Option 1: Add Refund Functionality

function refundLikeBalance() external {
require(profileNFT.profileToToken(msg.sender) == 0, "Must delete profile first");
uint256 refundAmount = userBalances[msg.sender];
require(refundAmount > 0, "No balance to refund");
// Apply exit fee
uint256 exitFee = (refundAmount * 20) / 100; // 20% exit fee
uint256 finalRefund = refundAmount - exitFee;
userBalances[msg.sender] = 0;
totalFees += exitFee;
(bool success,) = payable(msg.sender).call{value: finalRefund}("");
require(success, "Refund failed");
}

Option 2: Enable Owner Recovery

function recoverAbandonedFunds(address[] calldata deletedProfiles) external onlyOwner {
for (uint i = 0; i < deletedProfiles.length; i++) {
if (profileNFT.profileToToken(deletedProfiles[i]) == 0 &&
userBalances[deletedProfiles[i]] > 0) {
totalFees += userBalances[deletedProfiles[i]];
userBalances[deletedProfiles[i]] = 0;
}
}
}
Updates

Appeal created

n0kto Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_blocking_or_burning_no_refund_balances_or_multisig

Likelihood: Low, burning with money in it would be a user mistake, and being blocked is Low. Impact: High, loss of funds

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.