DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

Reentrancy through _safeMint bypasses the one-profile-per-address invariant

Summary

mintProfile performs the external ERC721 receiver callback in _safeMint before setting profileToToken[msg.sender]. A malicious receiver can re-enter mintProfile from onERC721Received; every nested call still observes a zero mapping and mints another soulbound NFT.

Root cause and evidence

The uniqueness check is at src/SoulboundProfileNFT.sol:31. The external interaction occurs at line 34, but the state that enforces uniqueness is not written until line 38. This violates checks-effects-interactions.

During the callback, the attacker recursively calls mintProfile. Multiple token IDs are minted to the same address. Only the last returned call's token ID remains in profileToToken, leaving the other soulbound tokens owned by the attacker but not addressable through the profile mapping and impossible to transfer.

Impact

An attacker bypasses the protocol's core one-profile-per-address guarantee and can create inconsistent, orphaned profile NFTs.

Minimal patch

Set profileToToken[msg.sender] = tokenId before _safeMint (and store metadata before the callback if callbacks must observe a complete profile). A revert from _safeMint will revert those writes. A nonReentrant guard is an acceptable secondary defense.

Regression test

Use an ERC721Receiver whose callback attempts a second mintProfile. Assert that the nested call reverts with Profile already exists, only one token is minted, and the mapping points to it.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!