DatingDapp

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

Missing ETH Refund When Admin Blocks Dating Profiles

Summary

In this dating platform, users invest 1 ETH to "like" other profiles, but when an admin blocks a profile using blockProfile(), all ETH invested in relation to that profile becomes permanently locked in the contract. This includes both the ETH spent by others liking the blocked profile and the ETH the blocked user spent liking others.

Vulnerability Details

contract SoulboundProfileNFT {
mapping(address => uint256) public profileToToken;
function blockProfile(address blockAddress) external onlyOwner {
uint256 tokenId = profileToToken[blockAddress];
require(tokenId != 0, "No profile found");
// Burns NFT without any fund consideration
_burn(tokenId);
delete profileToToken[blockAddress];
delete _profiles[tokenId];
emit ProfileBurned(blockAddress, tokenId);
// No mechanism to:
// 1. Notify LikeRegistry of profile removal
// 2. Handle pending matches
// 3. Refund likes
// 4. Clear like history
}
}

Impact

  • Multiple users could be affected per blocked profile

  • Users who liked blocked profile lose 1 ETH per like

  • UserBalances remain unchanged but inaccessible

  • Users lose funds through no fault of their own

  • Admin could block profiles to deliberately lock funds

Recommendations

When a user is blocked there should be a mechanism to refund users who liked the blocked profile and another mechnism to refund the user that was blocked.

contract LikeRegistry {
function handleProfileBlocked(address blockedUser) external onlyProfileNFT {
// Refund users who liked the blocked profile
for (uint i = 0; i < likersList[blockedUser].length; i++) {
address liker = likersList[blockedUser][i];
if (likes[liker][blockedUser]) {
payable(liker).transfer(1 ether);
likes[liker][blockedUser] = false;
emit LikeRefunded(liker, blockedUser, 1 ether);
}
}
// Refund blocked user's likes
uint256 userRefund = userBalances[blockedUser];
if (userRefund > 0) {
userBalances[blockedUser] = 0;
payable(blockedUser).transfer(userRefund);
emit BlockedUserRefunded(blockedUser, userRefund);
}
}
}
contract SoulboundProfileNFT {
function blockProfile(address blockAddress) external onlyOwner {
// First handle funds in LikeRegistry
+ likeRegistry.handleProfileBlocked(blockAddress);
// Then proceed with profile removal
uint256 tokenId = profileToToken[blockAddress];
_burn(tokenId);
delete profileToToken[blockAddress];
delete _profiles[tokenId];
emit ProfileBurned(blockAddress, tokenId);
}
}
Updates

Appeal created

n0kto Lead Judge 3 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.