DatingDapp

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

Users can mint multiple profiles after blocking and burning their profiles

Summary

Users can mint new profiles unlimited number of times with `SounboundProfileNFT::mintProfile`.

Vulnerability Details

When a user burns his profile with SounboundProfileNFT::burnProfile, profileToToken[msg.sender] is deleted and the value is again 0. After that they can mint a new profile. Also if the owner of the contract blocks a user with SoundboundProfileNFT::blockProfile, the user with the blocked profile can just create a new one and bypass the block.

Impact

Users can continuously mint, burn and remint new profiles, allowing them to create multiple fake identities on the platform. Also if the contract owner blocks a profile by burning it, the user can simply mint a new one and continue participating.

PoC

Copy this test and paste it in testSoulboundProfileNFT.t.sol

function test_UserCanMintMultipleProfiles() public {
vm.startPrank(user);
// User mints his first profile
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
uint256 firstTokenId = soulboundNFT.profileToToken(user);
// Verifying the first mint was successful
assertEq(soulboundNFT.ownerOf(firstTokenId), user);
// User burns the profile
soulboundNFT.burnProfile();
// User mints a new profile
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
uint256 secondTokenId = soulboundNFT.profileToToken(user);
// Verifying that the user can mint a new profile after burning.
assertEq(soulboundNFT.ownerOf(secondTokenId), user);
vm.stopPrank();
// Also after blocking a profile, users can just create new profiles
vm.startPrank(owner);
// The owner blocks user's profile
soulboundNFT.blockProfile(user);
vm.stopPrank();
vm.startPrank(user);
// User creates a new profile
soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage");
uint256 thirdTokenId = soulboundNFT.profileToToken(user);
// Verifying that the user can mint a new profile after burning.
assertEq(soulboundNFT.ownerOf(thirdTokenId), user);
vm.stopPrank();
}

Tools Used

-foundry

Recommendations

Adding a mapping of blocked users to prevent them from minting new profiles after contract owner calls SoundboundProfileNFT::blockProfile.

+ mapping(address => bool) private _blockedUsers;
/// @notice Mint a soulbound NFT representing the user's profile.
function mintProfile(string memory name, uint8 age, string memory profileImage) external {
require(profileToToken[msg.sender] == 0, "Profile already exists");
+ require(!_blockedUsers[msg.sender], "The user is blocked");
uint256 tokenId = ++_nextTokenId;
_safeMint(msg.sender, tokenId);
// Store metadata on-chain
_profiles[tokenId] = Profile(name, age, profileImage);
profileToToken[msg.sender] = tokenId;
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}
/// @notice App owner can block users
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;
emit ProfileBurned(blockAddress, tokenId);
}
Updates

Appeal created

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