Each call to deposit overwrites stakedAsset[receiver] with the latest net contribution (src/briVault.sol:222-223). When a participant cancels, cancelParticipation refunds only stakedAsset[msg.sender], burns all shares, and transfers that amount back (src/briVault.sol:280-288). Earlier deposits remain stranded in the vault with no shares outstanding.
Likelihood: Medium – users often top up positions before committing.
Cancelling after multiple deposits refunds only the last contribution; earlier funds are permanently lost.
Stranded assets inflate the vault balance, skewing future share issuance.
User deposits 5 ether (net ≈4.925 ether).
User deposits 2 ether (net ≈1.97 ether) before the event starts.
User calls cancelParticipation().
Refund equals ≈1.97 ether; the earlier ≈4.925 ether stays in the vault with no shares.
(Demonstrated in test/BriVaultAttack.t.sol:160 through testCancelOnlyRefundsLastStake.)
Accumulate stakes (stakedAsset[receiver] += stakeAsset) or track per-deposit receipts.
When cancelling, return the full outstanding principal and reconcile share accounting accordingly.
Add regression tests covering multi-deposit then cancel flows.
Proposed patch (Solidity-like pseudocode):
Vault tracks only a single deposit slot per user and overwrites it on every call instead of accumulating the total.
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.