Normal behavior: a matched pair's pooled date funds should be spendable, and each party should retain a way to recover at least their own contribution even if the relationship breaks down — since the two owners are strangers matched by an app, not a pre-existing trusted pair.
Specific issue: MultiSigWallet is a strict 2-of-2 with no recovery of any kind. executeTransaction requires BOTH approvedByOwner1 && approvedByOwner2, and the contract has no owner-change, no timelock fallback, no unilateral or time-delayed withdrawal, and no split-refund. The owners are fixed at construction (set by LikeRegistry.matchRewards to the two matched users) with no setter:
The result is that the pooled ETH is trapped whenever the two parties do not both actively cooperate: if either owner disagrees about the recipient or amount, loses/never had access to their key, abandons the app, or simply never signs, neither party — nor the protocol owner — can ever retrieve the funds, not even the portion they personally contributed. On a dating app, a matched pair going cold or one side ghosting is a normal, expected outcome, so this is not a rare edge case. The rest of the wallet is sound (access control, the 2-of-2 approval logic, checks-effects-interactions ordering with executed set before the external call, and replay protection are all correct) — the gap is purely the absence of any escape hatch for the held funds.
Likelihood:
A matched pair failing to both cooperate (disagreement, ghosting, lost key, abandoned account) is a common lifecycle outcome for strangers matched by an app; it needs no attacker.
Impact:
Permanent lock of the matched pair's entire pooled ETH, with no way for either contributor or the owner to recover even their own share. Bounded to a fund-lock (no attacker profit), hence Medium.
test/MultiSigAudit.t.sol::test_FundsPermanentlyLocked_OnDisagreement and ::test_LostKey_NoUnilateralWithdraw (both PASS): each owner approves only their own tx / one owner never acts; both executeTransaction calls revert "Not enough approvals" and the ETH is stuck.
Add a timelocked unilateral withdrawal, a 50/50 split-refund callable by either owner, or an owner-recovery mechanism.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.