53063 sc low maxvalidatorpercentage can be used to dos protocol staking
Submitted on Aug 14th 2025 at 18:41:03 UTC by @heeze for Attackathon | Plume Network
- Report ID: #53063
- Report Type: Smart Contract
- Report severity: Low
- Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/StakingFacet.sol
- Impacts:
- Protocol insolvency
Description
Brief/Intro
The StakingFacet contract enforces a maximum validator percentage limit to prevent any single validator from controlling too much of the total stake. However, if the first staker deposits only the minimum stake amount, and the protocol is configured with more than three validators and a maxValidatorPercentage such that the sum of all validator percentages equals 100% (e.g., 3 validators at 33% each), then after the first stake, no further staking can occur to any validator. This results in a protocol-wide denial-of-service (DoS), freezing all staking activity and preventing any further participation.
Vulnerability Details
The _validateValidatorPercentage function checks that a validator's delegated amount does not exceed a set percentage of the total staked amount:
if (previousTotalStaked > 0 && $.maxValidatorPercentage > 0) {
uint256 newDelegatedAmount = $.validators[validatorId].delegatedAmount;
uint256 validatorPercentage = (newDelegatedAmount * 10_000) / $.totalStaked;
if (validatorPercentage > $.maxValidatorPercentage) {
revert ValidatorPercentageExceeded();
}
}
When the first user stakes to a validator, previousTotalStaked is zero, so the check is skipped. After the first stake, the validator's delegated amount equals the total staked, making their percentage 100%.
Example calculations following the first stake:
- After first stake of 1 ETH to Validator1:
totalStaked = 1 ETH,validator1.delegatedAmount = 1 ETH(100%)
- Second stake of 1 ETH to Validator1:
- validator's delegated amount becomes 2 ETH, totalStaked becomes 2 ETH → percentage = 100% → reverts if
maxValidatorPercentage = 33%
- validator's delegated amount becomes 2 ETH, totalStaked becomes 2 ETH → percentage = 100% → reverts if
- Stake of 1 ETH to Validator2 after first stake:
- validatorPercentage = (1 ETH * 10,000) / 2 ETH = 5,000 (50%) → reverts if
maxValidatorPercentage = 33%
- validatorPercentage = (1 ETH * 10,000) / 2 ETH = 5,000 (50%) → reverts if
- Stake of 1 ETH to Validator3 after first stake:
- same as Validator2 → reverts
Any further staking attempt to any validator will revert, as the validator percentage for any new deposit will exceed the per-validator limit.
Impact Details
- If the first staker deposits only the minimum stake to any validator, no other user can stake to any validator, freezing the growth of the entire protocol.
- The rate of growth for the entire protocol is determined by the size of the first deposit to each validator, which is neither intuitive nor fair.
- Validators and users can be permanently locked out of further participation, halting protocol growth and decentralization.
References
Proof of Concept
Setup
Deploy the protocol and set:
minStakeAmountto 1 ethermaxValidatorPercentageto 33% (3300 basis points)
Step: First stake
User A stakes 1 ether (the minimum) to Validator1.
previousTotalStakedis 0, so the percentage check is skipped.- After staking:
delegatedAmount = 1 ether,totalStaked = 1 etherfor Validator1.
Step: Second stake to same validator
User B attempts to stake 1 ether to Validator1.
- Validator percentage = (2 ether * 10,000) / 2 ether = 10,000 (100%), which exceeds 33%, so the transaction reverts.
Step: Stake to another validator
User C attempts to stake 1 ether to Validator2.
- Validator percentage = (1 ether * 10,000) / 2 ether = 5,000 (50%), which exceeds 33%, so the transaction reverts.
Step: Stake to yet another validator
User D attempts to stake 1 ether to Validator3.
- Validator percentage = (1 ether * 10,000) / 2 ether = 5,000 (50%), which exceeds 33%, so the transaction reverts.
Outcome
The protocol is now globally frozen: no additional staking can occur to any validator, and the staking system is effectively DoS'ed.