DatingDapp

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

Untracked MultiSig Wallets Vulnerability in LikeRegistry Contract

Description

The LikeRegistry contract creates MultiSig wallets for matched users but fails to track or record these wallet addresses. This leads to potential loss of access to funds, difficulty in contract management, and inability to use the wallet.

In the matchRewards function, MultiSig wallets are created but not tracked:

function matchRewards(address from, address to) internal {
// ... reward calculations ...
// Deploy MultiSig but address is not stored
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
// Send ETH but no record of which wallet holds it
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}

Impact:

  • Lost access to MultiSig wallets and funds

  • No way to verify correct wallet for match

  • No audit trail of deployments (no event emitted)

  • No way to lookup MultiSig wallet for a match

  • Lost access if frontend doesn't capture deployment

Proof of Concept:

function testUntrackedWallet() public {
vm.deal(user, 2 ether);
vm.deal(user2, 2 ether);
// Create profiles and match
vm.startPrank(user2);
soulboundNFT.mintProfile("Bob", 28, "ipfs://bob");
vm.stopPrank();
vm.startPrank(user);
soulboundNFT.mintProfile("Alice", 25, "ipfs://alice");
likeRegistry.likeUser{value: 1 ether}(user2);
vm.stopPrank();
vm.startPrank(user2);
likeRegistry.likeUser{value: 1 ether}(user);
vm.stopPrank();
// MultiSig created and funds transferred
// But
// 1. Address is not returned to user
// 2. event is not emitted
// 3. Address is not stored in contract
}

Recommended Mitigation Steps

  • Add created MultiSig wallet tracking:

struct MatchWallet {
address multiSigAddress;
uint256 createdAt;
uint256 fundingAmount;
bool isActive;
}
// Track MultiSig wallets by user pairs
mapping(address => mapping(address => MatchWallet)) public matchWallets;
function matchRewards(address from, address to) internal {
// ... reward calculations ...
// Deploy and track MultiSig
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
// Store wallet info
matchWallets[from][to] = MatchWallet({
multiSigAddress: address(multiSigWallet),
createdAt: block.timestamp,
fundingAmount: rewards,
isActive: true
});
matchWallets[to][from] = matchWallets[from][to];
emit MultiSigCreated(from, to, address(multiSigWallet), rewards);
// Transfer funds
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}
  • Add lookup function:

function getMatchMultiSig(address user1, address user2)
external
view
returns (
address multiSigAddress,
uint256 createdAt,
uint256 fundingAmount,
bool isActive
)
{
MatchWallet memory wallet = matchWallets[user1][user2];
require(wallet.multiSigAddress != address(0), "No MultiSig found");
return (
wallet.multiSigAddress,
wallet.createdAt,
wallet.fundingAmount,
wallet.isActive
);
}

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:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood 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.