BriVault

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

Lack of validation in `briVault.sol::joinEvent()` allows users to join as many times as they want increasing `numberOfParticipants` and `totalParticipantShares`

Root + Impact

The root cause is the absence of a validation mechanism to verify whether a user has already joined, allowing repeated participation and incorrect incremention to storage variables.


Description

  • The protocol documentation states that "users should only join once." Even if this restriction is not strictly enforced, additional safeguards should be considered to maintain the protocol’s integrity and accuracy since it will be affected. 1 user joins 10 times, numberofparticipants will be 10 (even though is 1). totalPariticpantShares = 10 * user shares.


//@audit user can enter as many times he want and increase totalPariticpantShares,numberofparticipants
function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
// should have a check if user has joined already
// Ensure countryId is a valid index in the `teams` array
if (countryId >= teams.length) {
revert invalidCountry();
}
if (block.timestamp > eventStartDate) {
revert eventStarted();
}
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:

  • High: Absolutely anyone that has deposited enough

Impact:

  • Multiple joins by the same user can artificially inflate key storage variables such as numberOfParticipants and totalParticipantShares.

Proof of Concept

  1. Random user deposits 0.5 ether, enough to be able to join events

  2. User can now join an event as many times as he wants with no restriction artifically inflating numberOfParticipants and totalParticipantShares

function test_userCanEnterMultipleTimes() public {
vm.startPrank(owner);
briVault.setCountry(countries);
vm.stopPrank();
vm.startPrank(user1);
mockToken.approve(address(briVault), 0.5 ether);
uint256 shares =briVault.deposit(0.5 ether, user1);
briVault.joinEvent(10);
vm.stopPrank();
assertEq(1, briVault.numberOfParticipants());
assertEq(shares, briVault.totalParticipantShares());
vm.startPrank(user1);
for (uint256 i = 0; i < 10; i++) {
briVault.joinEvent(i);
}
vm.stopPrank();
assertEq(11, briVault.numberOfParticipants());
assertEq(shares + (shares * 10), briVault.totalParticipantShares());

Recommended Mitigation

1. Consider adding a mapping(address => bool) usersJoined;
function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
+ if (usersJoined[msg.sender] == true) {
+ revert someCustomError()
}
// should have a check if user has joined already
// Ensure countryId is a valid index in the `teams` array
if (countryId >= teams.length) {
revert invalidCountry();
}
if (block.timestamp > eventStartDate) {
revert eventStarted();
}
+ usersJoined[msg.sender] = true;
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!