Santa's List

AI First Flight #3
Beginner FriendlyFoundry
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

Stale likes persist across profile burns -- matches trigger with wrong profile context

Description

  • When a user burns their profile via burnProfile() or gets blocked via blockProfile(), the protocol deletes their NFT and clears profileToToken. The expectation is that the user's previous interactions are invalidated.

  • The likes and matches mappings in LikeRegistry are not cleared when a profile is burned or blocked. If the user re-mints a profile, stale likes from a previous profile session persist and can trigger matches with the new profile identity, creating inconsistent state.

// SoulboundProfileNFT.sol
function burnProfile() external {
// @> Burns NFT, deletes profileToToken and _profiles
// @> But LikeRegistry.likes[user][...] and matches[user] are NOT cleared
}
// LikeRegistry.sol
function likeUser(address liked) external payable {
// ...
if (likes[liked][msg.sender]) { // @> reads stale like from previous profile session
matches[msg.sender].push(liked);
matches[liked].push(msg.sender);
matchRewards(liked, msg.sender);
}
}

Risk

Likelihood:

  • This occurs when a user burns their profile and re-mints, then someone who was previously liked by the old profile reciprocates

  • Also occurs when a blocked user re-mints (via M-1 bypass) and prior likes are still active

Impact:

  • Matches can trigger based on likes from a deleted profile, associating the new identity with old social graph data

  • Users may get matched with someone whose profile data has completely changed since the original like

Proof of Concept

function testStaleLikesAfterBurn() public {
vm.prank(alice);
profileNFT.mintProfile("Alice V1", 25, "img1");
vm.prank(bob);
profileNFT.mintProfile("Bob", 26, "img");
// Alice likes Bob (profile V1)
vm.prank(alice);
likeRegistry.likeUser{value: 1 ether}(bob);
// Alice burns profile and creates new one
vm.prank(alice);
profileNFT.burnProfile();
vm.prank(alice);
profileNFT.mintProfile("Alice V2", 30, "newimg");
// Bob likes Alice -- match triggers based on stale like from Alice V1
vm.prank(bob);
likeRegistry.likeUser{value: 1 ether}(alice);
// Match triggered despite Alice V1 profile no longer existing
}

Recommended Mitigation

// Option 1: Track likes per tokenId instead of per address
- mapping(address => mapping(address => bool)) public likes;
+ mapping(uint256 => mapping(uint256 => bool)) public likes; // tokenId => tokenId => liked
// Option 2: Add a mechanism to clear likes on profile burn
// This requires LikeRegistry to expose a clearLikes function callable by SoulboundProfileNFT
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 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!