BriVault

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

Duplicate User Entries in usersAddress Array During Multiple joinEvent Calls

Duplicate User Entries in usersAddress Array During Multiple joinEvent Calls

Description

  • The joinEvent function is intended to register a user once for a specific country, adding their address to the usersAddress array and incrementing participant counters exactly once per unique user.

On repeated calls, it appends duplicates to usersAddress and increments counters multiple times, bloating the array and inflating totals without validation.

function joinEvent(uint256 countryId) public {
// ...
usersAddress.push(msg.sender); // @> Pushed every call, no duplicate check
numberOfParticipants++; // @> Incremented every call
totalParticipantShares += participantShares; // @> Added every call
// ...
}

Risk

Likelihood:

  • After initial join when users accidentally or maliciously call joinEvent again for the same or different country.

In automated scripts or front-runs where multiple transactions target the same user pre-start.

Impact:

  • _getWinnerShares overcounts shares in loops, diluting legitimate winners' withdrawal amounts.

  • Array bloat causes gas exhaustion in setWinner, preventing event finalization for all participants.

Proof of Concept

// Assume user deposited and calls joinEvent twice
function testDuplicateJoins() public {
// User deposits and joins first time
vault.deposit(100e18, user);
vm.prank(user); vault.joinEvent(0); // usersAddress[0] = user, participants=1
vm.prank(user); vault.joinEvent(1); // usersAddress[1] = user (duplicate), participants=2
// Owner sets winner=0
vm.prank(owner); vault.setWinner(0);
// _getWinnerShares loops twice over user, totalWinnerShares = 2 * userShares
uint256 userWithdraw = vault.withdraw(); // User gets 2x share of pot
// Other winners get half due to inflation
}

Recommended Mitigation

+mapping(address => bool) public hasJoined;
function joinEvent(uint256 countryId) public {
// ...
+ require(!hasJoined[msg.sender], "Already joined");
// ...
+ hasJoined[msg.sender] = true;
usersAddress.push(msg.sender);
// ...
}
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!