Due to the limitations of Solidity/EVM, which lacks floating-point arithmetic, small staking values combined with frequent MP-accruing function calls can result in zero MP generation. This occurs when accruedMP rounds down to zero, depending on the stake size and time interval between calls. The frequency of calls and the amount staked influence this bug.
Therefore, to avoid this bug, the minimal staking value should be 2,628,000 wei. This represents a fraction (0.000000000002628) of an 18-decimal token.
Conclusion:
While the exact impact of this bug is not fully clear, it could disrupt results in specific cases. Setting a minimal stake of 2,628,000 wei should prevent zero MP accruals. This value represents an insignificant fraction (0.000000000002628) of an 18-decimal token and would make no financial difference for users. Token standards typically use 18 decimals precisely to address such cases, ensuring that even very small values can be handled accurately without losing precision.
Additionally, the entire contract should be thoroughly reviewed to ensure similar issues don't occur wherever division operations are used.
[1]: In Ethereum, time is divided into 12-second slots. Each slot selects a validator to propose a block. Under ideal conditions, a block is produced every 12 seconds. Source
Issue:
Due to the limitations of Solidity/EVM, which lacks floating-point arithmetic, small staking values combined with frequent MP-accruing function calls can result in zero MP generation. This occurs when
accruedMP
rounds down to zero, depending on the stake size and time interval between calls. The frequency of calls and the amount staked influence this bug.As defined in:
https://github.com/vacp2p/staking-reward-streamer/blob/74522424e6e2c9ae45cc1fb8150ae33fa123f24a/src/RewardsStreamerMP.sol#L162
The function to calculate MP is:
When the function is called too frequently, especially for small stakes,
accruedMP
may round down to zero.Objective:
To address this, we need to determine the smallest values for which
accruedMP = 1
.If we want to keep the minimal stake as
1
, we can start by isolatingtimeDiff
to calculate the minimal interval between calls:Setting
totalStaked = 1
andaccruedMP = 1
, we get:This result suggests an unrealistic time frame for MP accrual at minimal stake, undermining the "streaming rewards" concept.
Alternative Solution:
A better approach is to calculate the minimal stake required to avoid this issue by isolating
totalStaked
:Using the "minimal block time" of 12 seconds[1] as
timeDiff
and settingaccruedMP = 1
, we find:Therefore, to avoid this bug, the minimal staking value should be
2,628,000 wei
. This represents a fraction (0.000000000002628
) of an 18-decimal token.Conclusion:
While the exact impact of this bug is not fully clear, it could disrupt results in specific cases. Setting a minimal stake of
2,628,000 wei
should prevent zero MP accruals. This value represents an insignificant fraction (0.000000000002628
) of an 18-decimal token and would make no financial difference for users. Token standards typically use 18 decimals precisely to address such cases, ensuring that even very small values can be handled accurately without losing precision.Additionally, the entire contract should be thoroughly reviewed to ensure similar issues don't occur wherever division operations are used.
[1]: In Ethereum, time is divided into 12-second slots. Each slot selects a validator to propose a block. Under ideal conditions, a block is produced every 12 seconds. Source