DatingDapp

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

ETH Overpayment Vulnerability in LikeRegistry Contract

Overview

The LikeRegistry contract's likeUser function improperly handles ETH payments by accepting more than the required 1 ETH fee without providing refunds. This leads to permanent loss of user funds through locked overpayments.

Description

According to the protocol documentation, users should pay exactly 1 ETH to like another profile. However, the likeUser function only validates that the payment is >= 1 ETH without refunding excess amounts:

function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
// No refund of excess payment
// Rest of function...
}

Impact:

  • Permanent loss of user funds through overpayment

  • Users cannot recover excess ETH

Proof of Concept:

// // SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../src/SoulboundProfileNFT.sol";
import "../src/LikeRegistry.sol";
contract SoulboundProfileNFTTest is Test {
SoulboundProfileNFT soulboundNFT;
LikeRegistry likeRegistry;
address user = address(0x123);
address user2 = address(0x456);
address user3 = address(0x789);
address owner = address(this); // Test contract acts as the owner
function setUp() public {
soulboundNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(soulboundNFT));
}
function testLikeOverpayment() public {
vm.deal(user, 5 ether);
// Create profiles
vm.startPrank(user);
soulboundNFT.mintProfile("Alice", 25, "ipfs://alice");
vm.stopPrank();
vm.startPrank(user2);
soulboundNFT.mintProfile("Bob", 28, "ipfs://bob");
vm.stopPrank();
// user overpays for like
uint256 userBalanceBefore = user.balance;
vm.prank(user);
likeRegistry.likeUser{value: 2 ether}(user2);
uint256 userBalanceAfter = user.balance;
// Verify overpayment was taken but not refunded
assertEq(userBalanceBefore - userBalanceAfter, 2 ether);
// Verify no way to recover excess payment
// Contract balance includes the extra 1 ETH
assertEq(address(likeRegistry).balance, 2 ether);
}
}

Recommended Mitigation Steps

  • Enforce exact payment of 1 ETH:

function likeUser(address liked) external payable {
require(msg.value == 1 ether, "Must send exactly 1 ETH");
// Rest of function...
}

OR

  • Add refund for overpayments:

function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
// Process the like
// ... existing like logic ...
// Refund excess payment
uint256 excess = msg.value - 1 ether;
if (excess > 0) {
(bool success,) = payable(msg.sender).call{value: excess}("");
require(success, "Refund failed");
}
}

Tools Used

  • Foundry Testing Framework

  • Manual Review

Updates

Appeal created

n0kto Lead Judge 5 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.