Christmas Dinner

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

Sending eth does not make you a participant

Summary

Attendees of the event which provided some sort of funding should bocome participants. However, sending ETH to a contract does not make msg.sender a participant.

Vulnerability Details & Impact

Sending ETH to the contract calls the receive() function, which updates the sender's balance and emits the ChristmasDinner::NewSignup event. Unfortunately, the ETH sender does not become a participant, and sending eth a second time does not generate the ChristmasDinner::GenerousAdditionalContribution event.

Tools Used

See the testSendETHToBecomeParticipant() function in the foundry 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 {
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();
}
function testSendETHToBecomeParticipant() public {
//setup
deal(user1, 1 ether);
//assertions before sending eth
assert(!cd.getParticipationStatus(user1)); //not a participant
assert(address(cd).balance == 0);
assert(user1.balance == 1 ether);
//user1 sends ETH to become participant
vm.prank(user1);
(bool success,) = address(cd).call{value: 1 ether}("");
require(success);
//assertions after sending eth
assert(!cd.getParticipationStatus(user1)); //still not a participant
assert(address(cd).balance == 1 ether);
assert(user1.balance == 0);
}
}

Recommendations

In the receive() function, apply the same logic as in the deposit() function:

  1. A sender who is not a participant becomes a participant

  2. the already participating sender is Generour Donor (i.e. the ChristmasDinner::GenerousAdditionalContribution event is emitted)

Updates

Lead Judging Commences

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

receive does not update participation status

Support

FAQs

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