BriVault

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

User can run JoinEvent multiple times

Root + Impact

Description

  • One user can run multiple times joinEvent. This causes issues when calculating the totalParticipantShares

function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
// Ensure countryId is a valid index in the `teams` array
if (countryId >= teams.length) {
revert invalidCountry();
}
if (block.timestamp > eventStartDate) {
revert eventStarted();
}
@> there is a missing check to see if the participant has joined already
userToCountry[msg.sender] = teams[countryId];
uint256 participantShares = balanceOf(msg.sender);
userSharesToCountry[msg.sender][countryId] = participantShares;
usersAddress.push(msg.sender);
numberOfParticipants++;
totalParticipantShares += participantShares;
emit joinedEvent(msg.sender, countryId);
}

Risk

Likelihood:

  • User can ran function joinEvent multiple times. The likelihood this happen is quite high.

Impact:

  • This generates issues when calculating the prizes.

Proof of Concept

Please insert below code in briVault.t.sol:

function testOneUserPerEvent() public {
vm.startPrank(owner);
briVault.setCountry(countries);
vm.stopPrank();
vm.startPrank(user1);
mockToken.approve(address(briVault), 5 ether);
uint256 user1shares = briVault.deposit(5 ether, user1);
briVault.joinEvent(10);
briVault.joinEvent(11);
uint256 balanceBeforuser1 = mockToken.balanceOf(user1);
vm.stopPrank();
vm.startPrank(user2);
mockToken.approve(address(briVault), 5 ether);
uint256 user2shares = briVault.deposit(5 ether, user2);
briVault.joinEvent(11);
uint256 balanceBeforuser2 = mockToken.balanceOf(user2);
vm.stopPrank();
vm.warp(eventEndDate + 1);
vm.startPrank(owner);
briVault.setWinner(11);
console.log(briVault.finalizedVaultAsset());
vm.stopPrank();
vm.startPrank(user1);
briVault.withdraw();
vm.stopPrank();
vm.startPrank(user2);
briVault.withdraw();
vm.stopPrank();
console.log("balance before withdraw user1: ", balanceBeforuser1);
console.log("balance after withdraw user1: ", mockToken.balanceOf(user1));
console.log("balance before withdraw user2: ", balanceBeforuser2);
console.log("balance after withdraw user2: ", mockToken.balanceOf(user2));
// Both users earned money and in equal amount.
assert(mockToken.balanceOf(user1) > balanceBeforuser1);
assert(mockToken.balanceOf(user2) > balanceBeforuser2);
assertEq(mockToken.balanceOf(user1), mockToken.balanceOf(user2));
}

Recommended Mitigation

function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
// Ensure countryId is a valid index in the `teams` array
if (countryId >= teams.length) {
revert invalidCountry();
}
// OK timestamp is ok?
if (block.timestamp > eventStartDate) {
revert eventStarted();
}
+ if (bytes(userToCountry[msg.sender]))).length == 0) {
+ revert userHasJoinedAlready();
+ }
userToCountry[msg.sender] = teams[countryId];
uint256 participantShares = balanceOf(msg.sender);
userSharesToCountry[msg.sender][countryId] = participantShares;
usersAddress.push(msg.sender);
numberOfParticipants++;
totalParticipantShares += participantShares;
emit joinedEvent(msg.sender, countryId);
}
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!