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 months 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!