staking: avoid proportional slashing leak dust into chunks that should not be slashed (#12058)

* replace slash ratio with remaining ratio

Signed-off-by: linning <linningde25@gmail.com>

* little refactor

Signed-off-by: linning <linningde25@gmail.com>

* fix test

Signed-off-by: linning <linningde25@gmail.com>

* fix typo

Signed-off-by: linning <linningde25@gmail.com>

* revert refactor

Signed-off-by: linning <linningde25@gmail.com>

* rounding up instead of remaining ratio

Signed-off-by: linning <linningde25@gmail.com>

* address comment

Signed-off-by: linning <linningde25@gmail.com>

* Update frame/nomination-pools/test-staking/src/lib.rs

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update frame/nomination-pools/test-staking/src/lib.rs

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Roman Useinov <roman.useinov@gmail.com>

Signed-off-by: linning <linningde25@gmail.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Roman Useinov <roman.useinov@gmail.com>
Co-authored-by: parity-processbot <>
This commit is contained in:
NingLin-P
2022-09-06 20:24:31 +08:00
committed by GitHub
parent 2795b5fd29
commit 56e536f6e8
4 changed files with 33 additions and 15 deletions
+19 -5
View File
@@ -31,7 +31,7 @@ use pallet_balances::Error as BalancesError;
use sp_runtime::{
assert_eq_error_rate,
traits::{BadOrigin, Dispatchable},
Perbill, Percent,
Perbill, Percent, Rounding,
};
use sp_staking::{
offence::{DisableStrategy, OffenceDetails, OnOffenceHandler},
@@ -5125,6 +5125,18 @@ fn proportional_ledger_slash_works() {
assert_eq!(LedgerSlashPerEra::get().0, 0);
assert_eq!(LedgerSlashPerEra::get().1, BTreeMap::from([(6, 30), (7, 30)]));
// Given
ledger.unlocking = bounded_vec![c(4, 100), c(5, 100), c(6, 100), c(7, 100)];
ledger.total = 4 * 100;
ledger.active = 0;
// When the first 2 chunks don't overlap with the affected range of unlock eras.
assert_eq!(ledger.slash(15, 0, 3), 15);
// Then
assert_eq!(ledger.unlocking, vec![c(4, 100), c(5, 100), c(6, 100 - 8), c(7, 100 - 7)]);
assert_eq!(ledger.total, 4 * 100 - 15);
assert_eq!(LedgerSlashPerEra::get().0, 0);
assert_eq!(LedgerSlashPerEra::get().1, BTreeMap::from([(6, 92), (7, 93)]));
// Given
ledger.unlocking = bounded_vec![c(4, 40), c(5, 100), c(6, 10), c(7, 250)];
ledger.active = 500;
@@ -5247,6 +5259,7 @@ fn proportional_ledger_slash_works() {
assert_eq!(LedgerSlashPerEra::get().1, BTreeMap::from([(4, 0), (5, 0), (6, 0), (7, 0)]));
// Given
use sp_runtime::PerThing as _;
let slash = u64::MAX as Balance * 2;
let value = u64::MAX as Balance * 2;
let unit = 100;
@@ -5259,18 +5272,19 @@ fn proportional_ledger_slash_works() {
ledger.active = unit;
ledger.total = unit * 4 + value;
// When
assert_eq!(ledger.slash(slash, 0, 0), slash - 43);
assert_eq!(ledger.slash(slash, 0, 0), slash - 5);
// Then
// The amount slashed out of `unit`
let affected_balance = value + unit * 4;
let ratio = Perquintill::from_rational(slash, affected_balance);
let ratio =
Perquintill::from_rational_with_rounding(slash, affected_balance, Rounding::Up).unwrap();
// `unit` after the slash is applied
let unit_slashed = {
let unit_slash = ratio * unit;
let unit_slash = ratio.mul_ceil(unit);
unit - unit_slash
};
let value_slashed = {
let value_slash = ratio * value;
let value_slash = ratio.mul_ceil(value);
value - value_slash
};
assert_eq!(ledger.active, unit_slashed);