stakedAsset[receiver] = stakeAsset; overwrites the value instead of accumulating it. If a user deposits multiple times, only the last deposit is tracked, but shares are minted additively. This causes incorrect refunds in cancelParticipation.
Likelihood:
Users deposit multiple times before the event starts to increase their bet size or correct earlier amounts, triggering the overwrite of stakedAsset on every subsequent deposit.
Impact:
Users who cancel participation after multiple deposits lose all but the last deposited stake, with the difference (e.g., 98.5 ETH in the POC) becoming permanently stuck in the vault and donated to winners.
The vault accumulates unclaimed funds with zero shares outstanding, creating accounting inconsistencies and enabling unfair windfalls for winning participants.
Assume fee = 0 for simplicity, minimumAmount = 0.
User A deposits 100: stakedAsset[UserA] = 100, shares minted = 100.
User A deposits 200: stakedAsset[UserA] = 200 (overwrites), additional shares minted = 200 (total shares = 300). Vault balance = 300.
User A calls cancelParticipation: refundAmount = 200, burns 300 shares, transfers 200 back.
Result: Vault has 300 - 200 = 100 left, but no shares outstanding. The extra 100 is stuck/donated to the pool.
Change stakedAsset[receiver] = stakeAsset; to stakedAsset[receiver] += stakeAsset; to correctly track total user stake across multiple deposits. This ensures cancelParticipation() refunds the full deposited amount, preventing permanent fund loss.
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.