Christmas Dinner

First Flight #31
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Reentrancy vulnerability due to weak 'nonReentrant' modifier

Summary

There is a re-entrancy vulnerability in the nonReentrant modifier used by the contract. The modifier never sets locked = true before executing the function body, which renders the re-entrancy check ineffective. This can allow malicious contracts to repeatedly call functions like refund() and drain user balances.

Vulnerability Details

modifier nonReentrant() {
require(!locked, "No re-entrancy");
_;
locked = false;
}

Because locked is never set to true before _;, re-entrant calls are never blocked.
A malicious contract can deposit funds, then call refund(). When receiving Ether (or a token transfer), the contract’s fallback can re-enter refund() again, bypassing the guard check. The contract’s internal balances are only set to zero at the end of the transaction, letting multiple refunds happen in the same transaction.

Impact

An attacker can drain funds by exploiting the vulnerability. This includes ETH and any whitelisted ERC20 tokens.
Other participants’ deposits could also be at risk if the logic allows attackers to claim more than their fair share, creating a significant financial loss.

Tools Used

Manual code review

Recommendations

1. Fix the Non-Reentrant Modifier:

modifier nonReentrant() {
require(!locked, "No re-entrancy");
++ locked = true;
_;
locked = false;
}

2. Use existing battle-tested libraries
OpenZeppelin offers ReentrancyGuard's that can be imported and be used instead of writing code that has not been battle-tested in production.

Updates

Lead Judging Commences

0xtimefliez Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

mutex lock incomplete

0xtimefliez Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

mutex lock incomplete

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.