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 10 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.

Give us feedback!