The ERC-4626 standard requires that withdraw and redeem functions support a flow where a msg.sender (with an allowance) can act on behalf of an owner. This is the entire purpose of the standard, as it allows other protocols (like yield aggregators, dashboards, or "claim bots") to manage user positions.
The contract's custom withdraw() function (the only way to claim winnings) is hard-coded to msg.sender. It checks userToCountry[msg.sender], gets balanceOf(msg.sender), and pays msg.sender. It is impossible for another contract to call this function on behalf of a winner, even with a full share allowance, completely breaking composability.
Likelihood:
This is a fundamental design flaw, not an edge-case bug. The feature is 100% missing.
Any external protocol (e.g., a "claim-all" dashboard, a re-staking protocol, a yield manager) attempting to integrate with this vault will fail.
It's not a malicious attack but a guaranteed failure of the contract's core promise (being ERC-4626 compliant).
Impact:
The contract is unusable by any other DeFi protocol. Users cannot have their winnings claimed by automated services, moved by yield aggregators, or managed by any third-party contract, which defeats the entire purpose of using the ERC-4626 standard.
A conceptual PoC:
user1 (a winner) has 100 shares.
user1 calls briVault.approve(address(claimBot), 100) to let a bot claim their winnings.
claimBot (as msg.sender) calls briVault.withdraw().
The call reverts at the didNotWin() check, because userToCountry[address(claimBot)] is not set. The claimBot has no way to specify it is acting on behalf of user1.
Remove your custom withdraw() function entirely and replace it with the standard, overridden ERC-4626 withdraw function. Add your custom winner-checking logic inside it.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.