BriVault

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

Overwriting User Country and Share Attribution on Repeated joinEvent


Description

  • The joinEvent functionshould assign a user's shares to a single chosen country irrevocably before the event starts, updating mappings once per user.

Repeated calls overwrite the country assignment and re-attribute the full share balance to the new country, allowing retroactive changes without adjusting prior allocations.

function joinEvent(uint256 countryId) public {
// ...
userToCountry[msg.sender] = teams[countryId]; // @> Overwrites previous
uint256 participantShares = balanceOf(msg.sender);
userSharesToCountry[msg.sender][countryId] = participantShares; // @> Sets full to new, ignores old
// ...
}

Risk

Likelihood:

  • Pre-event start when users change their mind or exploit information asymmetry about likely winners.

In repeated transactions where front-running bots switch to the predicted winning country.

  • Or being aware of the issue they opt fr each and every country so that if any country wins they get the prize.

Impact:

  • Late switchers steal proportional shares from original country backers during winner payouts.

Distorts _getWinnerShares totals, underpaying early joiners and enabling unfair profit extraction.

  • allowing malicious user to steal money in any country's win

Proof of Concept

function testOverwriteJoin() public {
vault.deposit(100e18, user);
vm.prank(user); vault.joinEvent(0); // userToCountry=0, shares[0]=100
vm.prank(user); vault.joinEvent(1); // Overwrites: userToCountry=1, shares[1]=100 (shares[0] unchanged but ignored)
// setWinner(1); totalWinnerShares includes user's 100 from [1]
// withdraw succeeds via userToCountry check, user claims as "country 1" backer
// Original country 0 backers diluted, even though user initially supported 0
}

Recommended Mitigation

+mapping(address => bool) public hasJoined;
function joinEvent(uint256 countryId) public {
// ...
+ require(!hasJoined[msg.sender], "Already joined; cannot switch");
userToCountry[msg.sender] = teams[countryId];
// ...
+ hasJoined[msg.sender] = true;
}
+// If multi-country intended, add prorated allocation logic instead
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!