DatingDapp

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

Reentrancy Vulnerability in matchRewards Function

Root + Impact

Description

  • The `matchRewards()` function deploys a new multisig wallet contract and immediately sends ETH to it without any reentrancy protection. While the multisig constructor itself may not be malicious, the external call pattern combined with state changes after the call creates a reentrancy risk. Additionally, if the multisig contract or any contract it interacts with during deployment has a malicious fallback function, it could reenter the `LikeRegistry` contract before state is properly updated.

    ```solidity

    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;

    // @> External contract deployment and ETH transfer without reentrancy guard

    MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);

    // @> External call with value transfer

    (bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");

    require(success, "Transfer failed");

    }'''

    ### Root Cause

    The function performs external operations (contract deployment and ETH transfer) after updating state, but there's no reentrancy guard. While the state is updated before the external call, a malicious contract could still exploit this during the multisig deployment or the ETH transfer.


Risk

Likelihood:

  • * The multisig contract is deployed by the protocol, so it's likely not malicious

    * However, if the multisig constructor or any contract it interacts with has a malicious fallback, reentrancy could occur

    * The risk increases if the protocol allows custom multisig implementations in the future

Impact:

  • * If reentrancy occurs, an attacker could drain funds from the contract

    * Multiple matches could be processed for the same pair if reentrancy happens before state updates

    * The `totalFees` accounting could be manipulated

    * User balances could be double-spent or incorrectly zeroed

Proof of Concept

```solidity
// If a malicious contract is deployed that reenters during multisig creation:
contract MaliciousMultisig {
LikeRegistry registry;
constructor(address _owner1, address _owner2) {
// During deployment, reenter the registry
registry.likeUser{value: 1 ether}(attacker);
}
}
// Or if the multisig receive() function calls back:
receive() external payable {
// Reenter LikeRegistry before state is fully updated
registry.likeUser{value: 1 ether}(target);
}
```

Recommended Mitigation

```diff
+import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
-contract LikeRegistry is Ownable {
+contract LikeRegistry is Ownable, ReentrancyGuard {
- function matchRewards(address from, address to) internal {
+ function matchRewards(address from, address to) internal nonReentrant {
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;
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}
```
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 16 days 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!