Christmas Dinner

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

M-1: Lack of Beneficiary Address Validation in Deposit Function

Summary

The protocol documentation suggests that users should be able to register a friend or another participant as a beneficiary. However, the current implementation of both the deposit and receive functions only operates on msg.sender, which limits functionality. Furthermore, the receive function does not allow specifying a beneficiary, creating an inconsistency in the expected behavior.

Vulnerability Details

Root Cause:

  • The deposit function lacks a _beneficiary parameter to specify an external participant's address.

  • The receive function exclusively operates on msg.sender, preventing it from supporting beneficiary registration.

Expected Behavior:

  • Both deposit and ETH-based contributions should allow specifying a beneficiary address, enabling participants to register others.

Current Behavior:

  • The deposit function only registers or adds funds for msg.sender.

  • The receive function adds ETH balance only to msg.sender.

Impact

This inconsistency in implementation and lack of flexibility lead to:

  1. User Confusion: Users cannot register friends or other participants as suggested in the protocol documentation.

  2. Reduced Usability: The inability to register external participants may hinder the protocol's adoption.

  3. Protocol Misalignment: The actual behavior does not align with the protocol’s stated goals.

Tools Used

  • Manual code review

  • Foundry

Recommendations

1 - Introduce a depositWithETH Function:
Replace the receive function with a more explicit function that allows specifying a _beneficiary.

function depositWithETH(address _beneficiary) external payable beforeDeadline {
if (msg.value <= 0) {
revert AmountMustBeGreaterThanZero();
}
if (_beneficiary == address(0)) {
revert InvalidBeneficiaryAddress();
}
etherBalance[_beneficiary] += msg.value;
if (participant[_beneficiary]) {
emit GenerousAdditionalContribution(_beneficiary, msg.value);
} else {
participant[_beneficiary] = true;
emit NewSignup(_beneficiary, msg.value, true);
}
}

2 - Update the deposit Function:
Include a _beneficiary parameter in the deposit function to allow registering other participants.

function deposit(address _token, uint256 _amount, address _beneficiary) external beforeDeadline {
if (!whitelisted[_token]) {
revert NotSupportedToken();
}
if (_amount <= 0) {
revert AmountMustBeGreaterThanZero();
}
if (_beneficiary == address(0)) {
revert InvalidBeneficiaryAddress();
}
if (participant[_beneficiary]) {
balances[_beneficiary][_token] += _amount;
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
emit GenerousAdditionalContribution(_beneficiary, _amount);
} else {
participant[_beneficiary] = true;
balances[_beneficiary][_token] += _amount;
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
emit NewSignup(_beneficiary, _amount, getParticipationStatus(_beneficiary));
}
}

3 - Test the New Functionalities:
Add unit tests to validate beneficiary registration for both token-based and ETH-based contributions.

Implementing these changes ensures consistency with the protocol’s stated goals and improves usability by allowing users to register beneficiaries.

PoC

function testDepositWithETH() public {
vm.deal(user1, 10 ether);
vm.startPrank(user1);
cd.depositWithETH{value: 1 ether}(user2);
assertTrue(cd.getParticipationStatus(user2));
vm.stopPrank();
}
function testSignUpFriend() public {
uint256 amount = 2 ether;
vm.deal(user1, 10 ether);
vm.startPrank(user1);
ERC20Mock(weth).mint(user1, amount);
ERC20Mock(weth).approve(address(cd), amount);
cd.deposit(address(weth), amount, user2);
assertTrue(cd.getParticipationStatus(user2));
vm.stopPrank();
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Deposit function lacks functionality

Support

FAQs

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

Give us feedback!