Normally, cancelParticipation() should let users withdraw their staked assets once before the event starts, and then clear all related state to prevent further withdrawals.
In the current implementation, the function only resets stakedAsset[msg.sender] to 0, but does not clear or guard against multiple calls using the same state conditions. A user can repeatedly call cancelParticipation() before the event starts, receiving multiple refunds and causing the vault balance to deplete.
Likelihood:
Occurs whenever a user calls cancelParticipation() multiple times before the event start timestamp, since there is no flag or secondary guard preventing repeated execution.
The function can also be abused in automated scripts to loop withdrawals before eventStartDate is reached.
Impact:
Impact 1: Users can withdraw more tokens than they deposited, draining the vault’s ERC20 balance and preventing correct payouts later.
Impact 2: Causes accounting inconsistencies between stakedAsset, totalParticipantShares, and actual vault balance, possibly making the contract insolvent before the event begins.
Observed Effect:
Multiple cancelParticipation() calls keep transferring tokens to the same user until vault balance is exhausted, despite stakedAsset[msg.sender] already being cleared.
**Explanation: **Adding require(refundAmount > 0) ensures users cannot execute multiple cancellations once their stake is cleared. This prevents double withdrawals and preserves vault integrity before the event.
CancelParticipation burns shares but leaves the address inside usersAddress and keeps userSharesToCountry populated.
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.