Christmas Dinner

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

The refund does not result in being removed from the list of participants

Summary

If a participant no longer wishes to participate in the event, they can claim the money by calling the refund() function, which returns all assets to the participant. But the function does not remove the participant from the participants list.

Vulnerability Details & Impact

From the participant's point of view, a refund means not attending the dinner. However, the host will still count them because the address is still marked as a participant

Tools Used

Manual review and see testRefundAndStayParticipant() function from the foundty test below:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.27;
import {Test, console2} from "forge-std/Test.sol";
import {ChristmasDinner} from "../src/ChristmasDinner.sol";
import {ERC20Mock} from "../lib/openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol";
contract XmasDinnerTest is Test {
ChristmasDinner cd;
ERC20Mock wbtc;
ERC20Mock weth;
ERC20Mock usdc;
uint256 constant DEADLINE = 7;
address deployer = makeAddr("deployer");
address user1;
function setUp() public {
vm.stopPrank();
wbtc = new ERC20Mock();
weth = new ERC20Mock();
usdc = new ERC20Mock();
vm.startPrank(deployer);
cd = new ChristmasDinner(address(wbtc), address(weth), address(usdc));
vm.warp(1);
cd.setDeadline(DEADLINE);
vm.stopPrank();
user1 = makeAddr("user1");
usdc.mint(user1, 2e18);
vm.prank(user1);
usdc.approve(address(cd), 2e18);
}
function testRefundAndStayParticipant() public {
//before depositing
assert(!cd.getParticipationStatus(user1)); //not a participant
assert(usdc.balanceOf(user1) == 2e18);
assert(usdc.balanceOf(address(cd)) == 0);
//user1 deposits to the contract
vm.prank(user1);
cd.deposit(address(usdc), 1e18);
//after depositing
assert(cd.getParticipationStatus(user1)); //user1 is a participant
assert(usdc.balanceOf(user1) == 1e18);
assert(usdc.balanceOf(address(cd)) == 1e18);
//refunding
vm.prank(user1);
cd.refund();
//after refunding
assert(cd.getParticipationStatus(user1)); //still a participant
assert(usdc.balanceOf(user1) == 2e18);
assert(usdc.balanceOf(address(cd)) == 0);
}
}

Recommendations

Add the following line to the ChristmasDinner::refund() function:

function refund() external nonReentrant beforeDeadline {
address payable _to = payable(msg.sender);
_refundERC20(_to);
_refundETH(_to);
+ participant[msg.sender] = false;
emit Refunded(msg.sender);
}
Updates

Lead Judging Commences

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

refund does not update participation status

Support

FAQs

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

Give us feedback!