DatingDapp

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

`LikeRegistry::matchRewards` does not emit or store the deployed MultiSig wallet address, making it impossible for users to find their funds

LikeRegistry::matchRewards does not emit or store the deployed MultiSig wallet address, making it impossible for users to find their funds

Description

When two users match in LikeRegistry::matchRewards, a new MultiSigWallet contract is deployed and funded with their pooled rewards. However, the address of this newly deployed multisig is never emitted in an event or stored in contract state. This means matched users have no way to discover the address of their shared wallet through the contract interface - they would need to manually trace the transaction on a block explorer to find it.

Note: Per the README, users should be able to "access" their shared multisig wallet for their first date, but the implementation provides no mechanism for users to discover the wallet address through the contract interface.

function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances[from];
uint256 matchUserTwo = userBalances[to];
userBalances[from] = 0;
userBalances[to] = 0;
uint256 totalRewards = matchUserOne + matchUserTwo;
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100;
uint256 rewards = totalRewards - matchingFees;
totalFees += matchingFees;
// Deploy a MultiSig contract for the matched users
@> MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
@> // Address is not stored or emitted - users can't find their wallet!
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}

Risk

Likelihood:

  • Every time two users match, a MultiSig is deployed without any way for users to retrieve its address

  • This affects 100% of matches on the platform

Impact:

  • Users cannot find their shared MultiSig wallet address through the contract

  • Users must manually trace the match transaction on a block explorer to find their funds

  • Poor user experience and potential confusion about where funds went

  • If users don't know the address, they cannot interact with the MultiSig to withdraw funds

Proof of Concept

  1. User1 and User2 both create profiles

  2. User1 likes User2 (pays 1 ETH)

  3. User2 likes User1 (pays 1 ETH) - this triggers a match

  4. LikeRegistry::matchRewards deploys a new MultiSig with their pooled funds

  5. Neither user has any way to query the contract for their MultiSig address

  6. LikeRegistry::getMatches only returns matched addresses, not the MultiSig wallet

Recommended Mitigation

Add a mapping to store MultiSig addresses and emit an event when deployed:

+ mapping(address => mapping(address => address)) public matchMultiSig;
+ event MultiSigCreated(address indexed user1, address indexed user2, address multiSigWallet);
function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances[from];
uint256 matchUserTwo = userBalances[to];
userBalances[from] = 0;
userBalances[to] = 0;
uint256 totalRewards = matchUserOne + matchUserTwo;
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100;
uint256 rewards = totalRewards - matchingFees;
totalFees += matchingFees;
// Deploy a MultiSig contract for the matched users
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
+ // Store and emit the multisig address
+ matchMultiSig[from][to] = address(multiSigWallet);
+ matchMultiSig[to][from] = address(multiSigWallet);
+ emit MultiSigCreated(from, to, address(multiSigWallet));
// Send ETH to the deployed multisig wallet
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 20 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!