DatingDapp

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

Direct ETH sent to LikeRegistry is also stuck

Root + Impact

Description

  • The LikeRegistry contract has a payable receive() function, but direct ETH is not assigned to any user balance or to totalFees

  • That ETH cannot be withdrawn by users or the owner.

  • The ETH is stuck in LikeRegistry contract

/// @notice Allows the contract to receive ETH
receive() external payable {}

Risk

Likelihood:

  • Any user can mistakenly send ETH directly to LikeRegistry contract and not receive the funds back , so likelihood is Medium


Impact:

  • The impact is Medium since user isn't able to withdraw or use the funds/ETH in any meaningful way.


Proof of Concept

It proves issue where user, alice sends 1 eth directly to LikeRegistry contract . After the transfer

  • LikeRegistry still holds 1 ether

  • Alice userBalances is 0

  • withdrawFees() reverts with "No fees to withdraw"

  • Alice isn't able to recover or withdraw the funds

contract LikeRegistryStuckFundsPoC is Test {
SoulboundProfileNFT profileNFT;
LikeRegistry likeRegistry;
address alice = address(0xA11CE);
address bob = address(0xB0B);
function setUp() public {
profileNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(profileNFT));
vm.deal(alice, 1 ether);
vm.deal(bob, 1 ether);
vm.prank(alice);
profileNFT.mintProfile("Alice", 25, "ipfs://alice");
vm.prank(bob);
profileNFT.mintProfile("Bob", 26, "ipfs://bob");
}
function testPoC_ReceivedEthRemainsStuckInRegistry() public {
vm.prank(alice);
assertEq(address(likeRegistry).balance, 0 ether);
(bool success,) = address(likeRegistry).call{value: 1 ether}("");
assertEq(likeRegistry.userBalances(alice), 0);
assertEq(address(alice).balance, 0 ether);
vm.expectRevert("No fees to withdraw");
likeRegistry.withdrawFees();
}
}

Recommended Mitigation

either remove receive() so accidental transfers revert, or account direct transfers under a defined recoverable balance. A conservative fix is:

receive() external payable {
revert("Use likeUser");
}

the second option is accounting direct transfer into defined recoverable balances

receive() external payable {
userBalances[msg.sender]+=msg.value
}
Updates

Lead Judging Commences

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