DatingDapp

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

Overpayment Without Refund in LikeRegistry

Summary

The likeUser function in the LikeRegistry contract allows users to send ETH to "like" another user but does not refund excess ETH if the sent amount exceeds the required 1 ETH. But as per the rrequirement of the protocol the user needs to send only 1 ETH to like another user. This results in permanent loss of overpaid funds for users who mistakenly send more than 1 ETH.


Vulnerability Details

Location

  • Contract: LikeRegistry.sol

  • Function: likeUser

Root Cause

  1. Inflexible ETH Handling:

    • The likeUser function requires msg.value >= 1 ether, allowing users to send more than 1 ETH. However, the contract does not refund the excess amount.

    • This violates the principle of least astonishment, as users expect unused ETH to be returned automatically.

Code Snippet

function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH"); // Allows overpayment
// ... rest of the code ...
}

Impact

Severity: Medium

  • Financial Loss: Users who send more than 1 ETH (e.g., 1.5 ETH) lose the excess amount (0.5 ETH) permanently.

  • User Experience: Accidental overpayments due to UI issues or miscalculations lead to frustration and distrust.

  • Reputation Risk: The protocol may be perceived as predatory or buggy.


Proof of Concept (PoC)

Steps to Reproduce

  1. Deploy the LikeRegistry and SoulboundProfileNFT contracts.

  2. User1 mints a profile NFT.

  3. User1 calls likeUser with msg.value = 1.5 ether.

  4. Observe that:

    • The transaction succeeds (since msg.value >= 1 ether).

    • The contract retains the full 1.5 ETH, and no refund is issued.

Expected vs Actual Behavior

  • Expected: Excess ETH should be refunded, or the transaction should revert if the amount is not exact.

  • Actual: The contract retains all ETH sent, leading to financial loss.


Recommended Mitigation

Option 1: Require Exact ETH Amount

Enforce that users send exactly 1 ETH:

require(msg.value == 1 ether, "Must send exactly 1 ETH");

Option 2: Refund Excess ETH

Calculate and refund the excess amount:

function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
// Refund excess ETH
uint256 excess = msg.value - 1 ether;
if (excess > 0) {
(bool success,) = payable(msg.sender).call{value: excess}("");
require(success, "Refund failed");
}
// Track 1 ETH (not the full msg.value)
userBalances[msg.sender] += 1 ether;
// ... rest of the code ...
}

Additional Recommendations

  1. Input Validation: Use msg.value == 1 ether unless variable payments are explicitly allowed.

  2. Gas Limits: Ensure refunds use call{gas: ...} to mitigate reentrancy risks (though not critical here).

  3. Documentation: Clearly state the required ETH amount in the UI/UX to prevent user errors.

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.