DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

A user having more than 1 match, might result in MultiSigs with only 1 contributor

Severity

Impact: Medium
Likelihood: High
Severity: Medium

Vulnerability Details

The protocol allows for several matches for a single profile as suggested by the LikeRegistry::matches mapping. However this design introduces a potential issue where a MultiSig wallet may be created with only one contributing party.

Impact

Users who haven't explicitly checked userBalances of the profile they are going to like, will expect a contribution of at least 1 ether to the MultiSig from the other user. This is expected because they got liked by that user and the price of a like is 1 ether. Upon receiving a partial ownership of a MultiSig with less value than they put in on their own, users might feel misled.

Proof of Concept

Prerequisites:

  1. Add the following event in LikeRegistry.sol and emit it after the MultiSig has been created:

+ event MultiSigWalletCreated(address indexed walletAddress, address indexed user1, address indexed user2);
  1. Update the userBalances with this line in LikeRegistry.sol::likeUser

+ userBalances[msg.sender] += msg.value;

Test:

The following test demonstrates:

-Alice ---> liking(Bob)
-Alice ---> liking(Connor)

Whoever likes Alice back second, will end up with 0.9 of their own 1 ether in a MultiSig with Alice, which might be not what they expected.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import {MultiSigWallet} from "../src/MultiSig.sol";
import {LikeRegistry} from "../src/LikeRegistry.sol";
import {SoulboundProfileNFT} from "../src/SoulboundProfileNFT.sol";
contract LikeRegistryTest is Test {
SoulboundProfileNFT profileNFT;
LikeRegistry likeRegistry;
address loveBird1;
address loveBird2;
address thirdWheel;
address owner;
function setUp() public {
owner = makeAddr("owner");
loveBird1 = makeAddr("loveBird1");
loveBird2 = makeAddr("loveBird2");
thirdWheel = makeAddr("thirdWheel");
vm.deal(payable(loveBird1), 10 ether);
vm.deal(payable(loveBird2), 10 ether);
vm.deal(payable(thirdWheel), 10 ether);
}
function test_only1ContributorToMultiSig() public {
vm.startPrank(owner);
profileNFT = new SoulboundProfileNFT();
likeRegistry = new LikeRegistry(address(profileNFT));
vm.stopPrank();
vm.prank(loveBird1);
profileNFT.mintProfile("Alice", 25, "ipfs://profileImageAlice");
vm.prank(loveBird2);
profileNFT.mintProfile("Bob", 25, "ipfs://profileImageBob");
vm.prank(thirdWheel);
profileNFT.mintProfile("Connor", 25, "ipfs://profileThirdWheel");
vm.startPrank(loveBird1);
likeRegistry.likeUser{value: 1 ether}(loveBird2);
likeRegistry.likeUser{value: 1 ether}(thirdWheel);
vm.stopPrank();
vm.recordLogs();
vm.prank(loveBird2);
likeRegistry.likeUser{value: 1 ether}(loveBird1);
vm.prank(thirdWheel);
likeRegistry.likeUser{value: 1 ether}(loveBird1);
Vm.Log[] memory logs = vm.getRecordedLogs();
bytes32 walletAddressBytes = logs[2].topics[1];
address MultiSigWalletAddress = address(uint160(uint256(walletAddressBytes)));
uint256 balance = address(MultiSigWalletAddress).balance;
bytes32 walletAddressBytes2 = logs[5].topics[1];
address MultiSigWalletAddress2 = address(uint160(uint256(walletAddressBytes2)));
uint256 balance2 = address(MultiSigWalletAddress2).balance;
assertEq(balance, 2.7 ether); //The balance of Alice's and Bob's MultiSig
assertEq(balance2, 0.9 ether); //The balance of Alice's and Connor's MultiSig
}

Tools Used

Manual Review

Recommendations

Ensure a userBalance check before matching, that the user which liked first still has a balance of 1 ether.

In LikeRegistry.sol::matchUser add this as this as the first line:

+ require(userBalances[from] >= 1 ether, "Both parties must each have at least 1 ether deposited.");

This will ensure the MultiSig has at least the minimum contribution to be expected from both parties.

Updates

Appeal created

n0kto Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_several_match_lead_to_multisig_with_no_funds

Likelihood: Medium, if anyone has 2 matches or more before reliking. Impact: Medium, the user won't contribute to the wallet.

Support

FAQs

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