Description
LikeRegistry::likeUser
function is used to be called when one user likes another and the payment for that shoud be 1 ETH. However if user missclicks and sends more than needed ETH, nothing will be returned to him.
Impact
The function does not handle the scenario where the user sends more ETH (msg.value
) than required for the transaction. If the user sends excess ETH, it is not returned, leading to overpayment. This could result in financial losses for users if they mistakenly send more ETH than needed for the swap.
Proof of Concepts
Create test file called LikeRegistryTest.t.sol
Place the following code :
pragma solidity 0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {LikeRegistry} from "src/LikeRegistry.sol";
import {SoulboundProfileNFT} from "src/SoulboundProfileNFT.sol";
contract LikeRegistryTest is Test {
SoulboundProfileNFT profileNFT;
LikeRegistry likeRegistry;
address owner = makeAddr("owner");
address alice = makeAddr("alice");
address bob = makeAddr("bob");
address george = makeAddr("george");
string constant IPFS_PROFILE_IMAGE = "ipfs://bafybeieoydho7jz6cqberycgzowstnj6lrq6ku2ngc3u7mx22izqzk2q4y/50";
function setUp() public {
vm.startPrank(owner);
profileNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(profileNFT));
vm.stopPrank();
vm.deal(alice, 100 ether);
vm.deal(bob, 100 ether);
vm.deal(george, 100 ether);
}
modifier createProfiles() {
vm.prank(alice);
profileNFT.mintProfile("Alice", 34, IPFS_PROFILE_IMAGE);
vm.prank(bob);
profileNFT.mintProfile("Bob", 42, IPFS_PROFILE_IMAGE);
vm.prank(george);
profileNFT.mintProfile("George", 27, IPFS_PROFILE_IMAGE);
_;
}
function testLikeUserWithMoreFunds() public createProfiles {
uint256 startingBobBalance = bob.balance;
vm.prank(bob);
likeRegistry.likeUser{value: 10 ether}(alice);
assertEq(bob.balance, startingBobBalance - 10 ether);
}
}
Run the command on the terminal forge test --mt testLikeUserWithMoreFunds
Recommended mitigation
Consider adding external call for returning the additional funds.
Example:
function likeUser(address liked) external payable {
require(msg.value >= 1 ether, "Must send at least 1 ETH");
require(!likes[msg.sender][liked], "Already liked");
require(msg.sender != liked, "Cannot like yourself");
require(profileNFT.profileToToken(msg.sender) != 0, "Must have a profile NFT");
require(profileNFT.profileToToken(liked) != 0, "Liked user must have a profile NFT");
likes[msg.sender][liked] = true;
userBalances[msg.sender] += 1 ether;
emit Liked(msg.sender, liked);
+ if(msg.value > 1 ether) {
+ (bool success, ) = msg.sender.call{value: msg.value - 1 ether}("");
+ require(success, "Refund failed");
+ }
if (likes[liked][msg.sender]) {
matches[msg.sender].push(liked);
matches[liked].push(msg.sender);
emit Matched(msg.sender, liked);
matchRewards(liked, msg.sender);
}
}