pragma solidity ^0.8.24;
import {Test, console} from "forge-std/Test.sol";
import {BriVault} from "../src/briVault.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {MockERC20} from "./MockErc20.t.sol";
contract AuditPoCTest is Test {
uint256 public participationFeeBsp;
uint256 public eventStartDate;
uint256 public eventEndDate;
address public participationFeeAddress;
uint256 public minimumAmount;
BriVault public briVault;
MockERC20 public mockToken;
address owner = makeAddr("owner");
address user1 = makeAddr("user1");
address user2 = makeAddr("user2");
address user3 = makeAddr("user3");
string[48] countries = [
"United States", "Canada", "Mexico", "Argentina", "Brazil", "Ecuador",
"Uruguay", "Colombia", "Peru", "Chile", "Japan", "South Korea",
"Australia", "Iran", "Saudi Arabia", "Qatar", "Uzbekistan", "Jordan",
"France", "Germany", "Spain", "Portugal", "England", "Netherlands",
"Italy", "Croatia", "Belgium", "Switzerland", "Denmark", "Poland",
"Serbia", "Sweden", "Austria", "Morocco", "Senegal", "Nigeria",
"Cameroon", "Egypt", "South Africa", "Ghana", "Algeria", "Tunisia",
"Ivory Coast", "New Zealand", "Costa Rica", "Panama", "United Arab Emirates", "Iraq"
];
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, 100 ether);
mockToken.mint(user1, 100 ether);
mockToken.mint(user2, 100 ether);
mockToken.mint(user3, 100 ether);
vm.startPrank(owner);
briVault = new BriVault(
IERC20(address(mockToken)),
participationFeeBsp,
eventStartDate,
participationFeeAddress,
minimumAmount,
eventEndDate
);
vm.stopPrank();
}
function test_poc5_stale_snapshot_causes_unfair_and_potential_revert() public {
vm.prank(owner);
briVault.setCountry(countries);
uint256 winnerIdx = 10;
vm.startPrank(user1);
mockToken.approve(address(briVault), type(uint256).max);
briVault.deposit(1 ether, user1);
briVault.joinEvent(winnerIdx);
vm.stopPrank();
vm.startPrank(user2);
mockToken.approve(address(briVault), type(uint256).max);
briVault.deposit(1 ether, user2);
briVault.joinEvent(winnerIdx);
vm.stopPrank();
vm.startPrank(user1);
briVault.deposit(9 ether, user1);
vm.stopPrank();
vm.warp(eventEndDate + 1);
vm.prank(owner);
briVault.setWinner(winnerIdx);
uint256 staleTotal = briVault.totalWinnerShares();
uint256 user1SharesNow = briVault.balanceOf(user1);
uint256 user2SharesNow = briVault.balanceOf(user2);
console.log("staleTotal", staleTotal);
console.log("u1 now", user1SharesNow);
console.log("u2 now", user2SharesNow);
assertLt(staleTotal, user1SharesNow + user2SharesNow, "stale snapshot smaller than actual shares");
vm.startPrank(user1);
vm.expectRevert();
briVault.withdraw();
vm.stopPrank();
vm.startPrank(user2);
uint256 before2 = mockToken.balanceOf(user2);
briVault.withdraw();
uint256 paid2 = mockToken.balanceOf(user2) - before2;
vm.stopPrank();
uint256 expectedPaid2 = (user2SharesNow * briVault.finalizedVaultAsset()) / staleTotal;
assertEq(paid2, expectedPaid2, "payout uses stale denominator");
}
}