DatingDapp

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

App owner can lock users' funds by blocking them: `blockProfile` strands outstanding like deposits

Description


The app owner can block any user via blockProfile, which burns their profile NFT. Because having a profile NFT is a prerequisite for matching, blocking a user who has outstanding paid likes permanently strands their funds:


function blockProfile(address blockAddress) external onlyOwner {
uint256 tokenId = profileToToken[blockAddress];
require(tokenId != 0, "No profile found");
_burn(tokenId); // @> owner destroys the user's profile
delete profileToToken[blockAddress];
...
}
```
​
`LikeRegistry::likeUser` requires both parties to have a profile (`profileToToken(...) != 0`), and there is no refund/withdraw path for a user's paid likes. Once the owner blocks a user, that user can never complete a match (no profile), and the ETH they already paid for pending likes is locked with no way to recover it. The owner can do this unilaterally to any user.
​
## Risk
​
**Likelihood: Medium**
​
- `blockProfile` is `onlyOwner` and unrestricted; the owner can block any user at any time, including users with funds in flight.
​
**Impact: Medium**
​
- A blocked user's outstanding like deposits are permanently locked (no match possible, no refund). The owner can weaponize `blockProfile` to grief specific users and strand their funds — a centralization risk that directly causes loss of user funds.
​
## Proof of Concept
​
```solidity
// Alice mints a profile and likeUser(Bob){value: 1 ether}; Bob hasn't liked back yet.
// owner.blockProfile(Alice) -> Alice's profile burned; profileToToken[Alice] = 0.
// -> Alice can no longer match, and has no way to withdraw the 1 ETH -> funds locked by the owner.
```
​
## Recommended Mitigation
​
Refund (or make withdrawable) a user's outstanding deposits when they are blocked, and constrain the owner's unilateral power over user funds:
​
```solidity
// on block: settle/refund the user's likeRegistry balance before burning,
// or let users withdraw their funds independently of profile/block state.
```
}
Updates

Lead Judging Commences

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