DatingDapp

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

burnProfile() can orphan pending like funds with no recovery or refund path

Root + Impact

Description

  • Users are allowed to delete their profile by calling burnProfile().

  • The registry separately stores persistent like state, match state, and user balance state, but there is no cleanup, refund, or settlement hook when a profile is burned.

  • Once a user burns their profile, they can lose eligibility for future matching while any ETH already committed through the registry remains trapped in LikeRegistry.

  • The system therefore allows state in SoulboundProfileNFT and LikeRegistry to diverge, leaving pending user funds with no recovery mechanism

function burnProfile() external {
uint256 tokenId = profileToToken[msg.sender];
require(tokenId != 0, "No profile found");
require(ownerOf(tokenId) == msg.sender, "Not profile owner");
@> _burn(tokenId);
@> delete profileToToken[msg.sender];
@> delete _profiles[tokenId];
emit ProfileBurned(msg.sender, tokenId);
}
// LikeRegistry has no corresponding refund, cleanup, or withdrawal path
mapping(address => uint256) public userBalances;
mapping(address => mapping(address => bool)) public likes;
mapping(address => address[]) public matches;

Risk

Likelihood:

  • Any user can trigger this by deleting their own profile after funding likes.

  • The issue can occur during normal use, especially when users leave the app before a mutual match is formed.

Impact:

  • ETH associated with pending likes can become permanently stranded.

  • Protocol state becomes inconsistent because profile existence and escrowed funds are no longer synchronized

Proof of Concept

// 1. Alice mints a profile and likes Bob with ETH
// 2. Bob has not yet liked Alice back
// 3. Alice calls burnProfile()
// 4. Alice no longer has a profile NFT, but her like-related balance remains in LikeRegistry
// 5. There is no function that lets Alice reclaim or settle the pending funds

Recommended Mitigation

The safer design is to either refund and clear registry state before burning, or block profile deletion until the registry state is fully resolved.

// Option 1: prevent profile deletion while funds or pending likes exist
function burnProfile() external {
+ require(!likeRegistry.hasPendingExposure(msg.sender), "Pending likes or funds exist");
uint256 tokenId = profileToToken[msg.sender];
require(tokenId != 0, "No profile found");
require(ownerOf(tokenId) == msg.sender, "Not profile owner");
_burn(tokenId);
delete profileToToken[msg.sender];
delete _profiles[tokenId];
emit ProfileBurned(msg.sender, tokenId);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 6 days 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!