DatingDapp

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

LikeRegistry has no reentrancy guard on the ETH-moving paths; current flow is CEI-safe but defense-in-depth is missing

ETH-moving functions in LikeRegistry lack a reentrancy guard

Description

LikeRegistry makes external low-level ETH calls in matchRewards (line 65) and withdrawFees (line 78) without any nonReentrant guard. The current code follows checks-effects-interactions (state is zeroed before the call), so it is not exploitable today, but the unguarded low-level calls are fragile against future edits.

function withdrawFees() external onlyOwner {
require(totalFees > 0, "No fees to withdraw");
uint256 totalFeesToWithdraw = totalFees;
totalFees = 0;
(bool success,) = payable(owner()).call{value: totalFeesToWithdraw}(""); // @> no reentrancy guard
require(success, "Transfer failed");

Risk

Likelihood: Low. With the present CEI ordering (userBalances/totalFees set to 0 before the external call) there is no live reentrancy path, so exploitation requires a future regression that moves state updates after the call.

Impact: Low (defense-in-depth). If a later change reordered effects after the call, an attacker-controlled recipient could reenter matchRewards/withdrawFees and drain balances. Adding nonReentrant removes that latent risk class entirely at negligible cost.

Proof of Concept

A guard would make a hostile re-entrant receiver revert; today the CEI ordering already prevents the drain, so this is a hardening test:

function test_reentrancyGuardWouldBlockReenter() public {
// A malicious multisig/receiver that calls back into withdrawFees()
// on receive() should be stopped by nonReentrant. Without the guard,
// safety depends solely on CEI ordering being preserved on every edit.
// (Illustrative: assert no nested ETH-moving call succeeds.)
}

Recommended Mitigation

Inherit OpenZeppelin ReentrancyGuard and apply nonReentrant to the ETH-moving functions.

- import "@openzeppelin/contracts/access/Ownable.sol";
+ import "@openzeppelin/contracts/access/Ownable.sol";
+ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
- contract LikeRegistry is Ownable {
+ contract LikeRegistry is Ownable, ReentrancyGuard {
- function withdrawFees() external onlyOwner {
+ function withdrawFees() external onlyOwner nonReentrant {
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!