frequency icon indicating copy to clipboard operation
frequency copied to clipboard

[Capacity] `MinimumStakingAmount` is not enforced if a stake already exists for a different provider

Open wilwade opened this issue 6 months ago • 0 comments

Summary

A user can stake to multiple providers, but the minimum staking amount is enforced only for the first staking action that the user submits.

Issue details

During the staking process, both for the stake and provider_boost extrinsics, a minimum staking amount should be enforced by the Runtime::MinimumStakingAmount parameter.

The current implementation of ensure_can_stake verifies if the amount that the account is staking in total (the current active staking and the new staking amount) is greater than the MinimumStakingAmount:

let new_active_staking_amount = staking_details
	.active
	.checked_add(&stakable_amount)
	.ok_or(ArithmeticError::Overflow)?;

ensure!(
	new_active_staking_amount >= T::MinimumStakingAmount::get(),
	Error::<T>::StakingAmountBelowMinimum
);

This implies that the user has to stake the MinimumStakingAmount only when they first submit a stake for a provider, all the subsequent staking requests being accepted even with the amount of 1.

Risk

The current implementation does not follow the intended use-case, as described in the design documentation.
An attacker could stake the minimum required amount to a provider, and then stake 1 token to each of the other available providers, underpaying for the storage that they use. This can cause a storage bloating, slowing down the network in the long run.

Mitigation

The ensure_can_stake function should verify that the stakable_amount is greater than MinimumStakingAmount, instead of verifying the new_active_staking_amount.

wilwade avatar Aug 20 '24 15:08 wilwade