DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Severity: medium
Valid

blockProfile() can permanently lock a blocked user's pending like funds

Root + Impact

Description

  • The owner can forcibly burn a user's profile by calling blockProfile().

  • This administrative action removes the NFT identity but does not coordinate with LikeRegistry, where pending likes, balances, and potential future match payouts are still stored.

  • Because the blocked user loses their profile immediately, they can no longer participate normally in the matching flow, yet the contract still holds any previously deposited ETH.

  • The absence of a cleanup or refund path means admin intervention can permanently strand user funds.

function blockProfile(address blockAddress) external onlyOwner {
uint256 tokenId = profileToToken[blockAddress];
require(tokenId != 0, "No profile found");
@> _burn(tokenId);
@> delete profileToToken[blockAddress];
@> delete _profiles[tokenId];
emit ProfileBurned(blockAddress, tokenId);
}
// LikeRegistry keeps separate financial state with no admin-block settlement flow
mapping(address => uint256) public userBalances;

Risk

Likelihood:

  • The owner can trigger this condition whenever moderation or blocking is used.

  • No exceptional exploit chain is needed beyond the existing admin power

Impact:

  • Blocked users can lose access to ETH already committed to pending likes.

  • Administrative moderation can create permanent accounting leftovers in the registry.

Proof of Concept

// 1. Alice funds one or more likes in LikeRegistry
// 2. Before any mutual match settles, the owner calls blockProfile(Alice)
// 3. Alice's profile NFT is burned and removed
// 4. Alice's pending financial state remains in LikeRegistry
// 5. No refund or settlement path exists for the blocked user's pending funds

Recommended Mitigation

If blocked users should not retain protocol funds, that policy should still be made explicit and implemented through a deterministic settlement path rather than leaving ETH stranded in the registry.

function blockProfile(address blockAddress) external onlyOwner {
+ likeRegistry.settleOrRefundBlockedUser(blockAddress);
uint256 tokenId = profileToToken[blockAddress];
require(tokenId != 0, "No profile found");
_burn(tokenId);
delete profileToToken[blockAddress];
delete _profiles[tokenId];
emit ProfileBurned(blockAddress, tokenId);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 6 days ago
Submission Judgement Published
Validated
Assigned finding tags:

[M-03] App owner can have users' funds locked by blocking them

## Description App owner can block users at will, causing users to have their funds locked. ## Vulnerability Details `SoulboundProfileNFT::blockProfile` can block any app's user at will. ```js /// @notice App owner can block users function blockProfile(address blockAddress) external onlyOwner { uint256 tokenId = profileToToken[blockAddress]; require(tokenId != 0, "No profile found"); _burn(tokenId); delete profileToToken[blockAddress]; delete _profiles[tokenId]; emit ProfileBurned(blockAddress, tokenId); } ``` ## Proof of Concept The following code demonstrates the scenario where the app owner blocks `bob` and he is no longer able to call `LikeRegistry::likeUser`. Since the contract gives no posibility of fund withdrawal, `bob`'s funds are now locked. Place `test_blockProfileAbuseCanCauseFundLoss` in `testSoulboundProfileNFT.t.sol`: ```js function test_blockProfileAbuseCanCauseFundLoss() public { vm.deal(bob, 10 ether); vm.deal(alice, 10 ether); // mint a profile NFT for bob vm.prank(bob); soulboundNFT.mintProfile("Bob", 25, "ipfs://profileImage"); // mint a profile NFT for Alice vm.prank(alice); soulboundNFT.mintProfile("Alice", 25, "ipfs://profileImage"); // alice <3 bob vm.prank(alice); likeRegistry.likeUser{value: 1 ether}(bob); vm.startPrank(owner); soulboundNFT.blockProfile(bob); assertEq(soulboundNFT.profileToToken(msg.sender), 0); vm.startPrank(bob); vm.expectRevert("Must have a profile NFT"); // bob is no longer able to like a user, as his profile NFT is deleted // his funds are effectively locked likeRegistry.likeUser{value: 1 ether}(alice); } ``` And run the test: ```bash $ forge test --mt test_blockProfileAbuseCanCauseFundLoss Ran 1 test for test/testSoulboundProfileNFT.t.sol:SoulboundProfileNFTTest [PASS] test_blockProfileAbuseCanCauseFundLoss() (gas: 326392) Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.42ms (219.63µs CPU time) Ran 1 test suite in 140.90ms (1.42ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests) ``` ## Impact App users can have their funds locked, as well as miss out on potential dates. ## Recommendations Add a voting mechanism to prevent abuse and/or centralization of the feature.

Support

FAQs

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

Give us feedback!