DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: high
Invalid

LikeRegistry::matchRewards deploys new MultiSig but emits no event with the wallet address — matched users cannot find their shared wallet

Root + Impact

Description

  • When a mutual like is detected, matchRewards deploys a new MultiSigWallet contract for the matched pair. However, the address of this newly deployed wallet is never emitted in an event, nor is it stored in any mapping. After the transaction completes, neither user has any way to discover the address of their shared multisig wallet without manually parsing the transaction's internal traces.

    The Matched event is emitted in likeUser before matchRewards is called, so it cannot include the wallet address. The matchRewards function itself emits no events.

// Root cause in LikeRegistry.sol lines 50-67
function matchRewards(address from, address to) internal {
// ...
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
// @> multiSigWallet address is never stored or emitted
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
// @> Function ends — wallet address is lost
}

Risk

Likelihood:

  • This affects every single match. The wallet address is created but never communicated.

Impact:

  • Low direct financial impact, but severely impacts usability. Users must use block explorers and trace analysis to find their multisig wallet address.

Proof of Concept

This test shows that after Alice and Bob match, there is no public mapping, getter, or emitted event containing the deployed MultiSig wallet address. The only way to find it is by tracing internal transactions off-chain.

function testL01_NoWalletAddressEmitted() public {
vm.prank(alice);
profileNFT.mintProfile("Alice", 25, "ipfs://alice");
vm.prank(bob);
profileNFT.mintProfile("Bob", 27, "ipfs://bob");
vm.prank(alice);
likeRegistry.likeUser{value: 1 ether}(bob);
vm.prank(bob);
likeRegistry.likeUser{value: 1 ether}(alice); // Triggers match + MultiSig deploy
// No way to retrieve the MultiSig wallet address on-chain
// No mapping stores it, no event emits it
// Users must parse internal tx traces to find their shared wallet
}

Recommended Mitigation

Store the MultiSig address and/or emit it in the match event.


+ mapping(address => mapping(address => address)) public matchedWallets;
+ event MatchedWithWallet(address indexed user1, address indexed user2, address wallet);
function matchRewards(address from, address to) internal {
// ...
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
+ matchedWallets[from][to] = address(multiSigWallet);
+ matchedWallets[to][from] = address(multiSigWallet);
+ emit MatchedWithWallet(from, to, address(multiSigWallet));
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!