Summary
When a user signs up using Ether, it does not register the user as a participant in ChristmasDinner::participant.
Vulnerability Details
The receive() function records the Ether receive and emits the NewSignup event. However, it does not record the user as a participant in ChristmasDinner::participant.
receive() external payable {
etherBalance[msg.sender] += msg.value;
emit NewSignup(msg.sender, msg.value, true);
}
Impact
Deposit ether by calling ChristmasDinner and transferring 5 ether
Check user's participation status and assert that it is false
function testDepositEtherNotParticipant() public {
vm.deal(user1, 5 ether);
vm.startPrank(user1);
(bool success1, ) = address(cd).call{value: 5 ether}("");
require(success1, "Deposit ether failed for user 1");
bool participated = cd.getParticipationStatus(user1);
assertEq(participated, false, "User is participated");
}
Results
[PASS] testDepositEtherNotParticipant() (gas: 45663)
Traces:
[45663] ChristmasDinnerTest::testDepositEtherNotParticipant()
├─ [0] VM::deal(user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF], 5000000000000000000 [5e18])
│ └─ ← [Return]
├─ [0] VM::startPrank(user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF])
│ └─ ← [Return]
├─ [24234] ChristmasDinner::receive{value: 5000000000000000000}()
│ ├─ emit NewSignup(: user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF], : 5000000000000000000 [5e18], : true)
│ └─ ← [Stop]
├─ [2571] ChristmasDinner::getParticipationStatus(user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF]) [staticcall]
│ └─ ← [Return] false
├─ [0] VM::assertEq(false, false, "User is participated") [staticcall]
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.97s (305.87ms CPU time)
Tools Used
Foundry
Recommendations
Register the user as a participant if Ether is used to deposit.
receive() external payable {
etherBalance[msg.sender] += msg.value;
+ participant[msg.sender] = true;
emit NewSignup(msg.sender, msg.value, true);
}