DatingDapp

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

matchRewards forwards rewards via a low-level call whose only failure handling is revert, so a non-receiving recipient blocks the entire match

Match path uses a revert-on-failure push payment, making it brittle to future changes

Description

matchRewards forwards rewards to a freshly deployed MultiSigWallet with a low-level call and require(success) (lines 62-66). Because that call sits inside the likeUser execution path, any failure to deliver ETH reverts the entire like/match. The recipient is currently a protocol-controlled wallet with a receive(), so it is safe today, but the push-payment-in-the-hot-path pattern is fragile.

MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}(""); // @> push payment inside like flow
require(success, "Transfer failed");

Risk

Likelihood: Low. The recipient is a new MultiSigWallet whose receive() accepts ETH, so the call succeeds under current code. Risk materializes only if a future change makes the reward recipient able to reject ETH (e.g. a recipient without receive, a gas-griefing fallback, or configurable destinations).

Impact: Low today, but structurally brittle. Should the recipient ever revert on receipt, require(success) would revert the whole likeUser transaction, meaning a single un-receivable reward destination could brick matching for the affected users. Coupling reward delivery to the like transaction concentrates this failure mode in a critical user-facing path.

Proof of Concept

If the deployed reward recipient rejected ETH, the mutual like would revert:

function test_pushPaymentRevertsLike() public {
// Hypothetical: reward recipient with a reverting receive().
// matchRewards' require(success) would bubble up and revert
// the entire likeUser() call that triggered the match.
vm.prank(alice); registry.likeUser{value: 1 ether}(bob);
vm.prank(bob);
// vm.expectRevert("Transfer failed"); // under a non-receiving recipient
registry.likeUser{value: 1 ether}(alice);
}

Recommended Mitigation

Decouple reward delivery from the like transaction using a pull-payment pattern so a failed transfer cannot brick matching.

- (bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
- require(success, "Transfer failed");
+ pendingRewards[address(multiSigWallet)] += rewards; // claimed later via a separate withdraw()
Updates

Lead Judging Commences

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