BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Users can join multiple times, inflating totalParticipantShares

Root + Impact

Description

  • Normal behavior:
    Each user should join once per event, and their shares for a selected team should reflect their deposit.


  • Specific issue:
    The joinEvent() function allows a user to call it multiple times, each time overwriting userToCountry and adding their shares again to userSharesToCountry and totalParticipantShares:

// Root cause in the codebase with @> marks to highlight the relevant section
@> function joinEvent(uint256 countryId) public {
@> if (stakedAsset[msg.sender] == 0) { revert noDeposit(); }
@> ...
@> userToCountry[msg.sender] = teams[countryId];
@> userSharesToCountry[msg.sender][countryId] = participantShares;
@> usersAddress.push(msg.sender);
@> numberOfParticipants++;
@> totalParticipantShares += participantShares;
}

Risk

Likelihood:

  • This occurs whenever a user calls joinEvent() multiple times before the event starts.

This occurs because there is no check preventing duplicate entries in usersAddress or multiple selections for userSharesToCountry.

Impact:

  • Users can artificially inflate totalParticipantShares, reducing payouts to genuine winners.

Users could game the system to increase the denominator in _getWinnerShares() calculations, stealing or diluting rewards.

Proof of Concept

Explanation:
Repeated calls increase totalParticipantShares without increasing actual deposits, diluting rewards for honest participants.

contract VaultJoinAttack {
function exploit(BriVault vault, uint256 countryId, uint256 times) external {
for (uint256 i = 0; i < times; i++) {
vault.joinEvent(countryId); // increment totalParticipantShares multiple times
}
}
}

Recommended Mitigation

Brief explanation:

  • Add a check to ensure a user can only join once per event.

  • Use a mapping to track participation status instead of pushing addresses blindly to usersAddress.

- remove this code
+ add this code
+ require(bytes(userToCountry[msg.sender]).length == 0, "Already joined");
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Duplicate registration through `joinEvent`

Support

FAQs

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

Give us feedback!