From c62a28831564e390c0710d0ba93c4672912a52fd Mon Sep 17 00:00:00 2001 From: wangjj9219 <183318287@qq.com> Date: Wed, 11 Sep 2024 12:53:35 +0800 Subject: [PATCH] Limit process redeem requests (#2806) * limit process redeem requests * fix benchmarks * update --- modules/homa/src/lib.rs | 35 ++++++---- modules/homa/src/mock.rs | 3 +- modules/homa/src/tests.rs | 79 ++++++++++++++++++++-- modules/homa/src/weights.rs | 10 ++- runtime/acala/src/lib.rs | 1 + runtime/acala/src/weights/module_homa.rs | 4 +- runtime/common/src/precompile/mock.rs | 1 + runtime/karura/src/lib.rs | 1 + runtime/karura/src/weights/module_homa.rs | 4 +- runtime/mandala/src/benchmarking/homa.rs | 24 +++++-- runtime/mandala/src/lib.rs | 1 + runtime/mandala/src/weights/module_homa.rs | 4 +- 12 files changed, 138 insertions(+), 29 deletions(-) diff --git a/modules/homa/src/lib.rs b/modules/homa/src/lib.rs index ccba0cb274..42694fc29b 100644 --- a/modules/homa/src/lib.rs +++ b/modules/homa/src/lib.rs @@ -156,6 +156,10 @@ pub mod module { /// The XcmInterface to manage the staking of sub-account on relaychain. type XcmInterface: HomaSubAccountXcm; + /// The limit for process redeem requests when bump era. + #[pallet::constant] + type ProcessRedeemRequestsLimit: Get; + /// Weight information for the extrinsics in this module. type WeightInfo: WeightInfo; @@ -383,14 +387,14 @@ pub mod module { fn on_initialize(_: BlockNumberFor) -> Weight { let bump_era_number = Self::era_amount_should_to_bump(T::RelayChainBlockNumber::current_block_number()); if !bump_era_number.is_zero() { - let _ = Self::bump_current_era(bump_era_number); + let res = Self::bump_current_era(bump_era_number); debug_assert_eq!( TotalStakingBonded::::get(), StakingLedgers::::iter().fold(Zero::zero(), |total_bonded: Balance, (_, ledger)| { total_bonded.saturating_add(ledger.bonded) }) ); - ::WeightInfo::on_initialize_with_bump_era() + ::WeightInfo::on_initialize_with_bump_era(res.unwrap_or_default()) } else { ::WeightInfo::on_initialize() } @@ -659,10 +663,12 @@ pub mod module { } #[pallet::call_index(8)] - #[pallet::weight(< T as Config >::WeightInfo::on_initialize_with_bump_era())] - pub fn force_bump_current_era(origin: OriginFor, bump_amount: EraIndex) -> DispatchResult { + #[pallet::weight(< T as Config >::WeightInfo::on_initialize_with_bump_era(T::ProcessRedeemRequestsLimit::get()))] + pub fn force_bump_current_era(origin: OriginFor, bump_amount: EraIndex) -> DispatchResultWithPostInfo { T::GovernanceOrigin::ensure_origin(origin)?; - Self::bump_current_era(bump_amount) + + let res = Self::bump_current_era(bump_amount); + Ok(Some(T::WeightInfo::on_initialize_with_bump_era(res.unwrap_or_default())).into()) } /// Execute fast match for specific redeem requests, require completely matched. @@ -1067,17 +1073,18 @@ pub mod module { /// Process redeem requests and subaccounts do unbond on relaychain by XCM message. #[transactional] - pub fn process_redeem_requests(new_era: EraIndex) -> DispatchResult { + pub fn process_redeem_requests(new_era: EraIndex) -> Result { let era_index_to_expire = new_era + T::BondingDuration::get(); let total_bonded = TotalStakingBonded::::get(); let mut total_redeem_amount: Balance = Zero::zero(); let mut remain_total_bonded = total_bonded; + let mut handled_requests: u32 = 0; // iter RedeemRequests and insert to Unbondings if remain_total_bonded is enough. for (redeemer, (redeem_amount, _)) in RedeemRequests::::iter() { let redemption_amount = Self::convert_liquid_to_staking(redeem_amount)?; - if remain_total_bonded >= redemption_amount { + if remain_total_bonded >= redemption_amount && handled_requests < T::ProcessRedeemRequestsLimit::get() { total_redeem_amount = total_redeem_amount.saturating_add(redeem_amount); remain_total_bonded = remain_total_bonded.saturating_sub(redemption_amount); RedeemRequests::::remove(&redeemer); @@ -1090,6 +1097,8 @@ pub mod module { liquid_amount: redeem_amount, unbonding_staking_amount: redemption_amount, }); + + handled_requests += 1; } else { break; } @@ -1126,7 +1135,9 @@ pub mod module { } // burn total_redeem_amount. - Self::burn_liquid_currency(&Self::account_id(), total_redeem_amount) + Self::burn_liquid_currency(&Self::account_id(), total_redeem_amount)?; + + Ok(handled_requests) } /// Process nominate validators for subaccounts on relaychain. @@ -1163,7 +1174,7 @@ pub mod module { /// The rebalance will send XCM messages to relaychain. Once the XCM message is sent, /// the execution result cannot be obtained and cannot be rolled back. So the process /// of rebalance is not atomic. - pub fn bump_current_era(amount: EraIndex) -> DispatchResult { + pub fn bump_current_era(amount: EraIndex) -> Result { let previous_era = Self::relay_chain_current_era(); let new_era = previous_era.saturating_add(amount); RelayChainCurrentEra::::put(new_era); @@ -1171,14 +1182,14 @@ pub mod module { Self::deposit_event(Event::::CurrentEraBumped { new_era_index: new_era }); // Rebalance: - let res = || -> DispatchResult { + let res = || -> Result { TotalVoidLiquid::::put(0); Self::process_staking_rewards(new_era, previous_era)?; Self::process_scheduled_unbond(new_era)?; Self::process_to_bond_pool()?; - Self::process_redeem_requests(new_era)?; + let count = Self::process_redeem_requests(new_era)?; Self::process_nominate(new_era)?; - Ok(()) + Ok(count) }(); log::debug!( diff --git a/modules/homa/src/mock.rs b/modules/homa/src/mock.rs index d34c9f070a..51864f0cdb 100644 --- a/modules/homa/src/mock.rs +++ b/modules/homa/src/mock.rs @@ -23,7 +23,7 @@ use super::*; use frame_support::{ derive_impl, ord_parameter_types, parameter_types, - traits::{ConstU128, Nothing}, + traits::{ConstU128, ConstU32, Nothing}, }; use frame_system::{EnsureRoot, EnsureSignedBy}; use module_support::mocks::MockAddressMapping; @@ -216,6 +216,7 @@ impl Config for Runtime { type XcmInterface = MockHomaSubAccountXcm; type WeightInfo = (); type NominationsProvider = MockNominationsProvider; + type ProcessRedeemRequestsLimit = ConstU32<3>; } type Block = frame_system::mocking::MockBlock; diff --git a/modules/homa/src/tests.rs b/modules/homa/src/tests.rs index d09b969527..ef6f7fab31 100644 --- a/modules/homa/src/tests.rs +++ b/modules/homa/src/tests.rs @@ -1057,7 +1057,7 @@ fn process_redeem_requests_works() { ); // total_bonded is enough to process all redeem requests - assert_ok!(Homa::process_redeem_requests(1)); + assert_eq!(Homa::process_redeem_requests(1), Ok(1)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { redeemer: ALICE, era_index_when_unbond: 1, @@ -1106,7 +1106,7 @@ fn process_redeem_requests_works() { ); // total_bonded is not enough to process all redeem requests - assert_ok!(Homa::process_redeem_requests(2)); + assert_eq!(Homa::process_redeem_requests(2), Ok(2)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { redeemer: BOB, era_index_when_unbond: 2, @@ -1276,7 +1276,7 @@ fn bump_current_era_works() { // bump era to #1, // will process to_bond_pool. MockRelayBlockNumberProvider::set(100); - assert_ok!(Homa::bump_current_era(1)); + assert_eq!(Homa::bump_current_era(1), Ok(0)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::CurrentEraBumped { new_era_index: 1 })); assert_eq!(Homa::last_era_bumped_block(), 100); assert_eq!(Homa::relay_chain_current_era(), 1); @@ -1307,7 +1307,7 @@ fn bump_current_era_works() { // bump era to #2, // accumulate staking reward and draw commission MockRelayBlockNumberProvider::set(200); - assert_ok!(Homa::bump_current_era(1)); + assert_eq!(Homa::bump_current_era(1), Ok(0)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::CurrentEraBumped { new_era_index: 2 })); assert_eq!(Homa::last_era_bumped_block(), 200); assert_eq!(Homa::relay_chain_current_era(), 2); @@ -1358,7 +1358,7 @@ fn bump_current_era_works() { // bump era to #3, // will process redeem requests MockRelayBlockNumberProvider::set(300); - assert_ok!(Homa::bump_current_era(1)); + assert_eq!(Homa::bump_current_era(1), Ok(1)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::CurrentEraBumped { new_era_index: 3 })); System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { redeemer: ALICE, @@ -1404,7 +1404,7 @@ fn bump_current_era_works() { // bump era to #31, // will process scheduled unbonded MockRelayBlockNumberProvider::set(3100); - assert_ok!(Homa::bump_current_era(28)); + assert_eq!(Homa::bump_current_era(28), Ok(0)); System::assert_has_event(RuntimeEvent::Homa(crate::Event::CurrentEraBumped { new_era_index: 31 })); assert_eq!(Homa::last_era_bumped_block(), 3100); assert_eq!(Homa::relay_chain_current_era(), 31); @@ -1483,3 +1483,70 @@ fn last_era_bumped_block_config_check_works() { assert_eq!(MockRelayBlockNumberProvider::current_block_number(), 100); }); } + +#[test] +fn process_redeem_requests_under_limit_works() { + ExtBuilder::default() + .balances(vec![ + (ALICE, LIQUID_CURRENCY_ID, 10_000_000), + (BOB, LIQUID_CURRENCY_ID, 10_000_000), + (CHARLIE, LIQUID_CURRENCY_ID, 10_000_000), + (DAVE, LIQUID_CURRENCY_ID, 10_000_000), + ]) + .build() + .execute_with(|| { + assert_ok!(Homa::reset_ledgers( + RuntimeOrigin::signed(HomaAdmin::get()), + vec![(0, Some(4_000_000), None)] + )); + ToBondPool::::put(4_000_000); + + assert_ok!(Homa::request_redeem(RuntimeOrigin::signed(ALICE), 5_000_000, false)); + assert_ok!(Homa::request_redeem(RuntimeOrigin::signed(BOB), 5_000_000, false)); + assert_ok!(Homa::request_redeem(RuntimeOrigin::signed(CHARLIE), 5_000_000, false)); + assert_ok!(Homa::request_redeem(RuntimeOrigin::signed(DAVE), 5_000_000, false)); + assert_eq!(Homa::redeem_requests(&ALICE), Some((5_000_000, false))); + assert_eq!(Homa::redeem_requests(&BOB), Some((5_000_000, false))); + assert_eq!(Homa::redeem_requests(&CHARLIE), Some((5_000_000, false))); + assert_eq!(Homa::redeem_requests(&DAVE), Some((5_000_000, false))); + assert_eq!(Homa::unbondings(&ALICE, 1 + BondingDuration::get()), 0); + assert_eq!(Homa::unbondings(&BOB, 1 + BondingDuration::get()), 0); + assert_eq!(Homa::unbondings(&CHARLIE, 1 + BondingDuration::get()), 0); + assert_eq!(Homa::unbondings(&DAVE, 1 + BondingDuration::get()), 0); + assert_eq!(Homa::get_total_bonded(), 4_000_000); + assert_eq!(Currencies::total_issuance(LIQUID_CURRENCY_ID), 40_000_000); + + // total_bonded is enough to process all redeem requests, but excceed limit + assert_eq!(Homa::process_redeem_requests(1), Ok(3)); + System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { + redeemer: ALICE, + era_index_when_unbond: 1, + liquid_amount: 5_000_000, + unbonding_staking_amount: 1_000_000, + })); + System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { + redeemer: BOB, + era_index_when_unbond: 1, + liquid_amount: 5_000_000, + unbonding_staking_amount: 1_000_000, + })); + System::assert_has_event(RuntimeEvent::Homa(crate::Event::RedeemedByUnbond { + redeemer: CHARLIE, + era_index_when_unbond: 1, + liquid_amount: 5_000_000, + unbonding_staking_amount: 1_000_000, + })); + System::assert_has_event(RuntimeEvent::Homa(crate::Event::HomaUnbond { + sub_account_index: 0, + amount: 3_000_000, + })); + assert_eq!(Homa::redeem_requests(&ALICE), None); + assert_eq!(Homa::redeem_requests(&BOB), None); + assert_eq!(Homa::redeem_requests(&CHARLIE), None); + assert_eq!(Homa::redeem_requests(&DAVE), Some((5_000_000, false))); + assert_eq!(Homa::unbondings(&ALICE, 1 + BondingDuration::get()), 1_000_000); + assert_eq!(Homa::unbondings(&BOB, 1 + BondingDuration::get()), 1_000_000); + assert_eq!(Homa::unbondings(&CHARLIE, 1 + BondingDuration::get()), 1_000_000); + assert_eq!(Homa::unbondings(&DAVE, 1 + BondingDuration::get()), 0); + }); +} diff --git a/modules/homa/src/weights.rs b/modules/homa/src/weights.rs index 2d34c64745..ca603bceee 100644 --- a/modules/homa/src/weights.rs +++ b/modules/homa/src/weights.rs @@ -48,7 +48,7 @@ use sp_std::marker::PhantomData; /// Weight functions needed for module_homa. pub trait WeightInfo { fn on_initialize() -> Weight; - fn on_initialize_with_bump_era() -> Weight; + fn on_initialize_with_bump_era(n: u32,) -> Weight; fn mint() -> Weight; fn request_redeem() -> Weight; fn fast_match_redeems(n: u32, ) -> Weight; @@ -92,10 +92,12 @@ impl WeightInfo for AcalaWeight { // Storage: Homa RedeemRequests (r:2 w:1) // Storage: Homa Unbondings (r:1 w:1) // Storage: Homa TotalVoidLiquid (r:0 w:1) - fn on_initialize_with_bump_era() -> Weight { + fn on_initialize_with_bump_era(n: u32,) -> Weight { Weight::from_parts(253_506_000, 0) .saturating_add(T::DbWeight::get().reads(31 as u64)) + .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(n as u64))) .saturating_add(T::DbWeight::get().writes(18 as u64)) + .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(n as u64))) } // Storage: unknown [0x3a7472616e73616374696f6e5f6c6576656c3a] (r:1 w:1) // Storage: Homa TotalStakingBonded (r:1 w:0) @@ -195,10 +197,12 @@ impl WeightInfo for () { Weight::from_parts(5_281_000, 0) .saturating_add(RocksDbWeight::get().reads(3 as u64)) } - fn on_initialize_with_bump_era() -> Weight { + fn on_initialize_with_bump_era(n: u32,) -> Weight { Weight::from_parts(253_506_000, 0) .saturating_add(RocksDbWeight::get().reads(31 as u64)) + .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(n as u64))) .saturating_add(RocksDbWeight::get().writes(18 as u64)) + .saturating_add(RocksDbWeight::get().writes((2 as u64).saturating_mul(n as u64))) } fn mint() -> Weight { Weight::from_parts(88_950_000, 0) diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 95f40e3286..8a2bd047c2 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1592,6 +1592,7 @@ impl module_homa::Config for Runtime { type XcmInterface = XcmInterface; type WeightInfo = weights::module_homa::WeightInfo; type NominationsProvider = NomineesElection; + type ProcessRedeemRequestsLimit = ConstU32<2_000>; } parameter_types! { diff --git a/runtime/acala/src/weights/module_homa.rs b/runtime/acala/src/weights/module_homa.rs index 59d3143e06..a01452e04c 100644 --- a/runtime/acala/src/weights/module_homa.rs +++ b/runtime/acala/src/weights/module_homa.rs @@ -111,14 +111,16 @@ impl module_homa::WeightInfo for WeightInfo { // Proof: `Homa::Unbondings` (`max_values`: None, `max_size`: None, mode: `Measured`) // Storage: `Homa::TotalVoidLiquid` (r:0 w:1) // Proof: `Homa::TotalVoidLiquid` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn on_initialize_with_bump_era() -> Weight { + fn on_initialize_with_bump_era(n: u32,) -> Weight { // Proof Size summary in bytes: // Measured: `2961` // Estimated: `13851` // Minimum execution time: 298_418 nanoseconds. Weight::from_parts(305_164_000, 13851) .saturating_add(T::DbWeight::get().reads(32)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(18)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } // Storage: `Homa::TotalStakingBonded` (r:1 w:0) // Proof: `Homa::TotalStakingBonded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) diff --git a/runtime/common/src/precompile/mock.rs b/runtime/common/src/precompile/mock.rs index 5aa130e1fa..b48b37ef9c 100644 --- a/runtime/common/src/precompile/mock.rs +++ b/runtime/common/src/precompile/mock.rs @@ -743,6 +743,7 @@ impl module_homa::Config for Test { type XcmInterface = MockHomaSubAccountXcm; type WeightInfo = (); type NominationsProvider = (); + type ProcessRedeemRequestsLimit = ConstU32<2_000>; } parameter_type_with_key! { diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index 53b71786c9..7dab295c97 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -1617,6 +1617,7 @@ impl module_homa::Config for Runtime { type XcmInterface = XcmInterface; type WeightInfo = weights::module_homa::WeightInfo; type NominationsProvider = NomineesElection; + type ProcessRedeemRequestsLimit = ConstU32<2_000>; } parameter_types! { diff --git a/runtime/karura/src/weights/module_homa.rs b/runtime/karura/src/weights/module_homa.rs index 5e4a953179..498676d412 100644 --- a/runtime/karura/src/weights/module_homa.rs +++ b/runtime/karura/src/weights/module_homa.rs @@ -111,14 +111,16 @@ impl module_homa::WeightInfo for WeightInfo { // Proof: `Homa::Unbondings` (`max_values`: None, `max_size`: None, mode: `Measured`) // Storage: `Homa::TotalVoidLiquid` (r:0 w:1) // Proof: `Homa::TotalVoidLiquid` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn on_initialize_with_bump_era() -> Weight { + fn on_initialize_with_bump_era(n: u32,) -> Weight { // Proof Size summary in bytes: // Measured: `2962` // Estimated: `13852` // Minimum execution time: 314_492 nanoseconds. Weight::from_parts(320_994_000, 13852) .saturating_add(T::DbWeight::get().reads(34)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(19)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } // Storage: `Homa::TotalStakingBonded` (r:1 w:0) // Proof: `Homa::TotalStakingBonded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) diff --git a/runtime/mandala/src/benchmarking/homa.rs b/runtime/mandala/src/benchmarking/homa.rs index 64b02c3e8d..e5ee43f6f8 100644 --- a/runtime/mandala/src/benchmarking/homa.rs +++ b/runtime/mandala/src/benchmarking/homa.rs @@ -16,7 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{AccountId, ActiveSubAccountsIndexList, Balance, Currencies, Homa, Rate, RelaychainDataProvider, Runtime}; +use crate::{ + AccountId, ActiveSubAccountsIndexList, Balance, Currencies, Homa, Rate, RedeemThreshold, RelaychainDataProvider, + Runtime, +}; use super::utils::{set_balance, LIQUID, STAKING}; use frame_benchmarking::{account, whitelisted_caller}; @@ -39,17 +42,24 @@ runtime_benchmarks! { } on_initialize_with_bump_era { + let n in 1 .. 50; let minter: AccountId = account("minter", 0, SEED); - let redeemer: AccountId = account("redeemer", 0, SEED); let sub_account_index = ActiveSubAccountsIndexList::get().first().unwrap().clone(); set_balance(STAKING, &minter, 1_000_000_000_000_000); - set_balance(LIQUID, &redeemer, 1_000_000_000_000_000 * 10); + + for i in 0 .. n { + let redeemer = account("redeemer", i, SEED); + set_balance(LIQUID, &redeemer, 1_000_000_000_000_000); + } + + // need to process unlocking Homa::reset_ledgers( RawOrigin::Root.into(), vec![(sub_account_index, Some(1_000_000_000_000_000), Some(vec![UnlockChunk{value: 1_000_000_000_000, era: 10}]))] )?; Homa::reset_current_era(RawOrigin::Root.into(), 9)?; + Homa::update_homa_params( RawOrigin::Root.into(), Some(10_000_000_000_000_000), @@ -61,8 +71,14 @@ runtime_benchmarks! { RelaychainDataProvider::::set_block_number(10); Homa::update_bump_era_params(RawOrigin::Root.into(), None, Some(1))?; + // need to process to bond Homa::mint(RawOrigin::Signed(minter).into(), 100_000_000_000_000)?; - Homa::request_redeem(RawOrigin::Signed(redeemer).into(), 5_000_000_000_000_000, true)?; + + // need to process redeem request + for i in 0 .. n { + let redeemer = account("redeemer", i, SEED); + Homa::request_redeem(RawOrigin::Signed(redeemer).into(), 100_000_000_000_000, false)?; + } }: { Homa::on_initialize(1) } diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs index 0cffcae17c..058acb33ad 100644 --- a/runtime/mandala/src/lib.rs +++ b/runtime/mandala/src/lib.rs @@ -1452,6 +1452,7 @@ impl module_homa::Config for Runtime { type XcmInterface = XcmInterface; type WeightInfo = weights::module_homa::WeightInfo; type NominationsProvider = NomineesElection; + type ProcessRedeemRequestsLimit = ConstU32<2_000>; } parameter_types! { diff --git a/runtime/mandala/src/weights/module_homa.rs b/runtime/mandala/src/weights/module_homa.rs index 813bd2fd32..cd48d1deca 100644 --- a/runtime/mandala/src/weights/module_homa.rs +++ b/runtime/mandala/src/weights/module_homa.rs @@ -109,14 +109,16 @@ impl module_homa::WeightInfo for WeightInfo { // Proof: `Homa::Unbondings` (`max_values`: None, `max_size`: None, mode: `Measured`) // Storage: `Homa::TotalVoidLiquid` (r:0 w:1) // Proof: `Homa::TotalVoidLiquid` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn on_initialize_with_bump_era() -> Weight { + fn on_initialize_with_bump_era(n: u32,) -> Weight { // Proof Size summary in bytes: // Measured: `4057` // Estimated: `14947` // Minimum execution time: 207_924 nanoseconds. Weight::from_parts(215_712_000, 14947) .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(18)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } // Storage: `Homa::TotalStakingBonded` (r:1 w:0) // Proof: `Homa::TotalStakingBonded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)