DatingDapp

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

Blocked Users Can Recreate Profiles and Retain Likes (Bypassing Moderation & System Integrity Violation)

Description

The blockProfile function allows the contract owner to remove a user's profile by burning their NFT and deleting associated metadata. However, this function does not actually prevent the blocked user from minting a new profile with the same address. Since blockProfile only deletes profileToToken[blockAddress] and _profiles[tokenId], the user can simply call mintProfile again and receive a new soulbound NFT.

Additionally, the function does not remove the user's interactions from the likes mapping, meaning that blocked users retain all previous likes and matches, effectively bypassing the ban.

This violates the integrity of the contract, as users who were removed can continue participating in the system as if nothing happened, potentially allowing abuse and spam.

Impact

  • Bypassing Moderation: The contract fails to enforce a true ban, allowing blocked users to create new profiles instantly.

  • Retaining Previous Interactions: A banned user retains all previous likes and matches, maintaining their influence in the system.

  • This could allow malicious actors to exploit the system by continuously creating new profiles after being blocked.

Tools Used

manual

Proof of Concept

Add this function to SoulboundProfileNFT.sol

function testBlockedUserCanRecreateProfile() public {
likeRegistry = new LikeRegistry(address(soulboundNFT));
vm.prank(user);
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
vm.prank(user2);
soulboundNFT.mintProfile("Pablo", 25, "ipfs://profileImage");
hoax(user, 1 ether);
likeRegistry.likeUser{value: 1 ether}(user2);
bool beforeBlock = likeRegistry.likes(user, user2); //just to confirm
console.log("Like: ", beforeBlock);
uint256 tokenId = soulboundNFT.profileToToken(user);
assertEq(tokenId, 1, "Token should exist before blocking");
vm.prank(owner);
soulboundNFT.blockProfile(user);
uint256 newTokenId = soulboundNFT.profileToToken(user);
assertEq(newTokenId, 0, "Token should be removed after blocking");
vm.prank(user);
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
bool afterBlock = likeRegistry.likes(user, user2);
assertEq(beforeBlock, afterBlock);
}

Recommendations

Implement a blockedUsers mapping to prevent blocked users from creating new profiles:

mapping(address => bool) public blockedUsers;
function blockProfile(address blockAddress) external onlyOwner {
uint256 tokenId = profileToToken[blockAddress];
require(tokenId != 0, "No profile found");
_burn(tokenId);
delete profileToToken[blockAddress];
delete _profiles[tokenId];
blockedUsers[blockAddress] = true; // ✅ Mark user as blocked
emit ProfileBurned(blockAddress, tokenId);
}
function mintProfile(string memory name, uint8 age, string memory profileImage) external {
require(!blockedUsers[msg.sender], "User is blocked"); // ✅ Prevents blocked users from minting
require(profileToToken[msg.sender] == 0, "Profile already exists");
uint256 tokenId = ++_nextTokenId;
_profiles[tokenId] = Profile(name, age, profileImage);
profileToToken[msg.sender] = tokenId;
_safeMint(msg.sender, tokenId);
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}
Updates

Appeal created

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

finding_blocked_user_can_recreate_a_profil

Likelihood: Low, any blocked users. Impact: High, not really blocked.

Support

FAQs

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