2025-02-datingdapp/audit/H-03.md
han 09ed9015e5
Some checks failed
CI / Foundry project (push) Has been cancelled
add valid finding, ai finding, and retro
2025-03-08 23:24:27 +07:00

2.4 KiB

Fund Sent Directly to LikeRegistry Will Not be Able to Withdraw by Anyone

This is an invalid low finding because its user mistake. Written by myself.

Summary

Due to missing handling of received funds which transferred directly to the contract address, it can lead to the funds unable to withdraw. Both user and the contract owner are unable to withdraw the fund being sent directly to the contract lead to a loss of fund.

Vulnerability Details

When a user send fund directly to LikeRegistry contract, it will do nothing and doen't account the fund to the user who send it.

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

While we see there is a storage variable designed to store and account the user funds called userBalances.

contract LikeRegistry is Ownable {
    [...]

    mapping(address => mapping(address => bool)) public likes;
    mapping(address => address[]) public matches;
    mapping(address => uint256) public userBalances;
    
    [...]

POC

function testSendMoneyToLikeRegistry() public {
    uint256 sendAmount = 1 ether;
    uint256 initialLikeRegistryFund = address(likeRegistry).balance;

    // user send money directly to like registry contract
    vm.prank(user);
    (bool success,) = payable(address(likeRegistry)).call{value: sendAmount}("");
    uint256 likeRegistryFundAfterFunded = address(likeRegistry).balance;

    assertEq(success, true);
    assertEq(initialLikeRegistryFund, 0);
    assertEq(likeRegistryFundAfterFunded, sendAmount);

    // check userBalances
    uint256 userUserBalance = likeRegistry.userBalances(user);
    assertEq(userUserBalance, sendAmount); // sending money directly to contract should adjust userBalance to reflect the address fund

    // owner try to withdraw money
    vm.prank(owner);
    vm.expectRevert();
    likeRegistry.withdrawFees(); // the contract will assume that there is no fees to withdraw

    // try to withdraw money
    vm.prank(user);
    vm.expectRevert();
    likeRegistry.withdrawFees(); // there is no withdraw function for user
}

Impact

  • Loss of fund because no one can withdraw it

Recommendations

Account the fund to address by storing it in the userBalances variable

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