DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Unhandled ETH Locked in LikeRegistry Contract

Summary

The LikeRegistry contract accumulates ETH sent via the likeUser function but lacks a mechanism to access or distribute it. The withdrawFees function relies on the totalFees state variable, which remains zero due to incorrect fee tracking. As a result, all ETH sent by users becomes permanently locked in the contract, rendering it unusable and causing financial loss.


Vulnerability Details

Location

  • Contract: LikeRegistry.sol

  • Functions: likeUser, matchRewards, and withdrawFees

Root Cause

  1. ETH Tracking Failure:

    • The likeUser function does not update userBalances (as identified in Critical: Incorrect ETH Accounting), so the matchRewards function cannot calculate valid rewards or fees.

    • The totalFees variable remains zero because matchingFees (derived from userBalances) is always zero.

  2. No Recovery Mechanism:

    • The contract has no function to recover stuck ETH (e.g., an emergency withdrawal for the owner).

Code Snippets

Incorrect Fee Tracking in matchRewards

function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances[from]; // Always zero
uint256 matchUserTwo = userBalances[to]; // Always zero
// ...
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100; // Always zero
totalFees += matchingFees; // No fees accumulated
}

Useless withdrawFees Function

function withdrawFees() external onlyOwner {
require(totalFees > 0, "No fees to withdraw"); // Always reverts
// ...
}

Impact

Severity: High

  • Permanent Fund Locking: All ETH sent by users is stuck in the contract indefinitely.

  • Protocol Failure: The core reward/fee mechanism is non-functional, making the contract unusable.

  • Reputation Damage: Users lose trust in the protocol due to unresponsive funds.


Proof of Concept (PoC)

Expected vs Actual Behavior

  • Expected: ETH should be tracked as fees/rewards and accessible via withdrawFees or other functions.

  • Actual: ETH is permanently locked, and withdrawFees reverts due to zero totalFees.


Recommended Mitigation

Step 1: Fix ETH Tracking

Resolve the root cause by properly updating userBalances in likeUser (as detailed in Critical: Incorrect ETH Accounting).

Step 2: Add Emergency ETH Recovery

Implement a function to recover stuck ETH (e.g., for the owner):

function recoverStuckETH() external onlyOwner {
(bool success,) = payable(owner()).call{value: address(this).balance}("");
require(success, "Transfer failed");
}

Step 3: Validate Fee Logic

Ensure totalFees is correctly incremented in matchRewards:

function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances[from]; // Now tracks real ETH
uint256 matchUserTwo = userBalances[to]; // Now tracks real ETH
// ...
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100;
totalFees += matchingFees; // Correctly accumulates fees
}
Updates

Appeal created

n0kto Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Users mistake, only impacting themselves.

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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