The StakingPool
contract is vulnerable to a share minting issue even though the totalShares
never becomes zero due to the introduction of DEAD_SHARES
. If the first user burns all their tokens, the totalShares
will be set to DEAD_SHARES
, which leads to a situation where future deposits by users fail to mint sufficient shares. This happens because the ratio between totalStaked
and totalShares
becomes distorted, causing the share minting formula to return zero or near-zero shares for new deposits.
totalShares
to DEAD_SHARES
Relevant code in _mintShares
:
Issue: When the first user burns all their tokens, totalShares
is set to DEAD_SHARES
to avoid totalShares being zero. However, this introduces a significant issue in the share calculation for future deposits.
Key Problem: With totalShares
set to DEAD_SHARES
, the calculation for minting shares for future deposits becomes distorted. The minting formula in getSharesByStake()
now returns zero or very few shares because the ratio between totalStaked
and totalShares
becomes unbalanced.
The calculation for minting shares is as follows:
After the first user burns all their tokens and totalShares
is set to DEAD_SHARES
, the ratio between totalShares
and totalStaked
becomes heavily skewed.
Key Issue: When a new user deposits tokens, the formula (_amount * totalShares) / totalStaked
results in zero or a very small number of shares being minted because totalShares = DEAD_SHARES
, which is disproportionately large relative to totalStaked
.
Step 1: The first user deposits tokens into the pool and mints shares. Afterward, they call the burn()
function and burn all their share tokens.
Step 2: When totalShares
becomes zero, the system assigns DEAD_SHARES
to totalShares
, maintaining a non-zero value for totalShares
.
Step 3: A new user deposits tokens. However, the minting logic in getSharesByStake()
calculates the new shares as:
Since DEAD_SHARES
is significantly larger than the actual staked amount, this results in a calculation that rounds down to zero or very few shares.
Result: The new user receives zero or an extremely small number of shares, despite having deposited tokens, rendering the staking system ineffective for future users.
This issue has a severe impact on the usability and fairness of the staking pool:
After the first user burns their tokens, future deposits result in zero or minimal shares being minted due to the disproportionate ratio of totalShares
(set to DEAD_SHARES
) and totalStaked
.
Future participants are essentially locked out of earning any meaningful share allocation, breaking the staking pool for any new users.
getSharesByStake()
to Handle DEAD_SHARES
CorrectlyThe minting formula should account for cases where totalShares
is equal to DEAD_SHARES
to prevent it from distorting future share allocations. For example:
This ensures that if the totalShares
is DEAD_SHARES
, the calculation returns appropriate shares based on the new deposit amount.
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.