From bef136098fb4ae8297a4a1d5ee8d03c46aba854d Mon Sep 17 00:00:00 2001 From: Martin Hloska Date: Thu, 19 Dec 2024 11:09:22 +0100 Subject: [PATCH 1/2] staking - support legacy votes --- Cargo.lock | 13 +- pallets/staking/Cargo.toml | 5 +- pallets/staking/src/benchmarks.rs | 2 +- pallets/staking/src/integrations.rs | 1 + .../src/integrations/conviction_voting.rs | 18 +-- .../src/integrations/democracy_legacy.rs | 143 ++++++++++++++++++ pallets/staking/src/lib.rs | 42 +++-- pallets/staking/src/migration.rs | 77 ---------- pallets/staking/src/tests/mock.rs | 2 +- pallets/staking/src/tests/tests.rs | 56 +++---- pallets/staking/src/tests/unstake.rs | 6 +- runtime/hydradx/Cargo.toml | 2 +- runtime/hydradx/src/governance/old.rs | 2 +- runtime/hydradx/src/lib.rs | 2 +- 14 files changed, 230 insertions(+), 141 deletions(-) create mode 100644 pallets/staking/src/integrations/democracy_legacy.rs delete mode 100644 pallets/staking/src/migration.rs diff --git a/Cargo.lock b/Cargo.lock index b68e6fe0c..56c08cae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4897,7 +4897,7 @@ dependencies = [ "pallet-referrals", "pallet-route-executor", "pallet-stableswap", - "pallet-staking 4.0.0", + "pallet-staking 4.0.1", "pallet-transaction-multi-payment", "pallet-uniques", "pallet-xyk", @@ -4918,7 +4918,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "275.0.0" +version = "276.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -5009,7 +5009,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-stableswap", - "pallet-staking 4.0.0", + "pallet-staking 4.0.1", "pallet-state-trie-migration", "pallet-timestamp", "pallet-tips", @@ -9166,7 +9166,7 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "4.0.0" +version = "4.0.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -9177,6 +9177,7 @@ dependencies = [ "orml-traits", "pallet-balances", "pallet-conviction-voting", + "pallet-democracy 4.3.2", "pallet-referenda", "pallet-uniques", "parity-scale-codec", @@ -12314,7 +12315,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-stableswap", - "pallet-staking 4.0.0", + "pallet-staking 4.0.1", "pallet-timestamp", "pallet-tips", "pallet-transaction-multi-payment", @@ -12378,7 +12379,7 @@ dependencies = [ "pallet-asset-registry", "pallet-omnipool", "pallet-stableswap", - "pallet-staking 4.0.0", + "pallet-staking 4.0.1", "primitives", "scraper", "serde", diff --git a/pallets/staking/Cargo.toml b/pallets/staking/Cargo.toml index 4d3034e16..cccb4f3f8 100644 --- a/pallets/staking/Cargo.toml +++ b/pallets/staking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-staking" -version = "4.0.0" +version = "4.0.1" authors = ['GalacticCouncil'] edition = "2021" license = "Apache-2.0" @@ -34,6 +34,8 @@ frame-benchmarking = { workspace = true, optional = true } pallet-conviction-voting= { workspace = true } pallet-referenda = { workspace = true } +pallet-democracy = {workspace = true} + [dev-dependencies] pallet-uniques = { workspace = true } orml-tokens = { workspace = true } @@ -58,6 +60,7 @@ std = [ "orml-tokens/std", "pallet-conviction-voting/std", "pallet-referenda/std", + "pallet-democracy/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/pallets/staking/src/benchmarks.rs b/pallets/staking/src/benchmarks.rs index d4a570f9a..765d6e5ca 100644 --- a/pallets/staking/src/benchmarks.rs +++ b/pallets/staking/src/benchmarks.rs @@ -66,7 +66,7 @@ fn generate_votes(position_id: T::PositionItemId, count: u32) { votes: votes.try_into().unwrap(), }; - crate::PositionVotes::::insert(position_id, voting); + crate::Votes::::insert(position_id, voting); } fn run_periods(periods: u32) { diff --git a/pallets/staking/src/integrations.rs b/pallets/staking/src/integrations.rs index 0e2cefb3b..35fa0bef7 100644 --- a/pallets/staking/src/integrations.rs +++ b/pallets/staking/src/integrations.rs @@ -1 +1,2 @@ pub mod conviction_voting; +pub mod democracy_legacy; diff --git a/pallets/staking/src/integrations/conviction_voting.rs b/pallets/staking/src/integrations/conviction_voting.rs index 43d74c3ef..b0e3b8c5f 100644 --- a/pallets/staking/src/integrations/conviction_voting.rs +++ b/pallets/staking/src/integrations/conviction_voting.rs @@ -1,4 +1,4 @@ -use crate::pallet::{PositionVotes, Positions, ProcessedVotes}; +use crate::pallet::{Positions, Votes, VotesRewarded}; use crate::traits::{GetReferendumState, VestingDetails}; use crate::types::{Action, Balance, Conviction, ReferendumIndex, Vote}; use crate::{Config, Error, Pallet}; @@ -68,7 +68,7 @@ where conviction, }; - PositionVotes::::try_mutate(position_id, |voting| -> DispatchResult { + Votes::::try_mutate(position_id, |voting| -> DispatchResult { match voting.votes.binary_search_by_key(&ref_index, |value| value.0) { Ok(idx) => { let _ = sp_std::mem::replace(&mut voting.votes[idx], (ref_index, staking_vote)); @@ -94,7 +94,7 @@ where return; }; - let entry = ProcessedVotes::::take(who, ref_index); + let entry = VotesRewarded::::take(who, ref_index); if entry.is_some() { // this vote was already processed, just remove it return; @@ -104,12 +104,12 @@ where if let Some(position) = maybe_position.as_mut() { let max_position_vote = Conviction::max_multiplier().saturating_mul_int(position.stake); - if let Some(vote_idx) = PositionVotes::::get(position_id) + if let Some(vote_idx) = Votes::::get(position_id) .votes .iter() .position(|(idx, _)| *idx == ref_index) { - let (ref_idx, vote) = PositionVotes::::get(position_id).votes[vote_idx]; + let (ref_idx, vote) = Votes::::get(position_id).votes[vote_idx]; debug_assert_eq!(ref_idx, ref_index, "Referendum index mismatch"); let points = Pallet::::calculate_points_for_action(Action::DemocracyVote, vote, max_position_vote); @@ -119,7 +119,7 @@ where position.action_points = position.action_points.saturating_add(points); } } - PositionVotes::::mutate(position_id, |voting| { + Votes::::mutate(position_id, |voting| { voting.votes.remove(vote_idx); }); } @@ -131,16 +131,16 @@ where fn balance_locked_on_unsuccessful_vote(who: &T::AccountId, ref_index: ReferendumIndex) -> Option { let position_id = Pallet::::get_user_position_id(who).ok()??; - if let Some(vote) = ProcessedVotes::::get(who, ref_index) { + if let Some(vote) = VotesRewarded::::get(who, ref_index) { return Some(vote.amount); } - let vote_idx = PositionVotes::::get(position_id) + let vote_idx = Votes::::get(position_id) .votes .iter() .position(|(idx, _)| *idx == ref_index)?; - let (ref_idx, vote) = PositionVotes::::get(position_id).votes[vote_idx]; + let (ref_idx, vote) = Votes::::get(position_id).votes[vote_idx]; debug_assert_eq!(ref_idx, ref_index, "Referendum index mismatch"); Some(vote.amount) } diff --git a/pallets/staking/src/integrations/democracy_legacy.rs b/pallets/staking/src/integrations/democracy_legacy.rs new file mode 100644 index 000000000..3dcbf112c --- /dev/null +++ b/pallets/staking/src/integrations/democracy_legacy.rs @@ -0,0 +1,143 @@ +use crate::pallet::{PositionVotes, Positions, ProcessedVotes}; +use crate::types::{Action, Balance, Conviction, Vote}; +use crate::{Config, Pallet}; +use frame_support::dispatch::DispatchResult; +use orml_traits::MultiCurrencyExtended; +use pallet_democracy::traits::DemocracyHooks; +use pallet_democracy::{AccountVote, ReferendumIndex}; +use sp_core::Get; +use sp_runtime::FixedPointNumber; + +pub struct LegacyStakingDemocracy(sp_std::marker::PhantomData); + +impl DemocracyHooks for LegacyStakingDemocracy +where + T::Currency: MultiCurrencyExtended, +{ + fn on_vote(_who: &T::AccountId, _ref_index: ReferendumIndex, _vote: AccountVote) -> DispatchResult { + // Do nothing. + Ok(()) + } + + fn on_remove_vote(who: &T::AccountId, ref_index: ReferendumIndex, is_finished: Option) { + let Some(maybe_position_id) = Pallet::::get_user_position_id(who).ok() else { + return; + }; + + let Some(position_id) = maybe_position_id else { + return; + }; + + let entry = ProcessedVotes::::take(who, ref_index); + if entry.is_some() { + // this vote was already processed, just remove it + return; + } + + let _ = Positions::::try_mutate(position_id, |maybe_position| -> DispatchResult { + if let Some(position) = maybe_position.as_mut() { + let max_position_vote = Conviction::max_multiplier().saturating_mul_int(position.stake); + + if let Some(vote_idx) = PositionVotes::::get(position_id) + .votes + .iter() + .position(|(idx, _)| *idx == ref_index) + { + let (ref_idx, vote) = PositionVotes::::get(position_id).votes[vote_idx]; + debug_assert_eq!(ref_idx, ref_index, "Referendum index mismatch"); + let points = + Pallet::::calculate_points_for_action(Action::DemocracyVote, vote, max_position_vote); + // Add points only if referendum is finished + if let Some(is_finished) = is_finished { + if is_finished { + position.action_points = position.action_points.saturating_add(points); + } + } + PositionVotes::::mutate(position_id, |voting| { + voting.votes.remove(vote_idx); + }); + } + } + Ok(()) + }); + } + + fn remove_vote_locks_if_needed(who: &T::AccountId, ref_index: ReferendumIndex) -> Option { + let position_id = Pallet::::get_user_position_id(who).ok()??; + + if let Some(vote) = ProcessedVotes::::get(who, ref_index) { + return Some(vote.amount); + } + + let vote_idx = PositionVotes::::get(position_id) + .votes + .iter() + .position(|(idx, _)| *idx == ref_index)?; + + let (ref_idx, vote) = PositionVotes::::get(position_id).votes[vote_idx]; + debug_assert_eq!(ref_idx, ref_index, "Referendum index mismatch"); + Some(vote.amount) + } + + #[cfg(feature = "runtime-benchmarks")] + fn on_vote_worst_case(who: &T::AccountId) { + use crate::LockIdentifier; + #[cfg(not(feature = "std"))] + use codec::alloc::string::ToString; + use frame_system::Origin; + use orml_traits::MultiLockableCurrency; + + T::Currency::update_balance( + T::NativeAssetId::get(), + &Pallet::::pot_account_id(), + 10_000_000_000_000i128, + ) + .unwrap(); + Pallet::::initialize_staking(Origin::::Root.into()).unwrap(); + T::Currency::update_balance(T::NativeAssetId::get(), who, 1_000_000_000_000_000i128).unwrap(); + Pallet::::stake(Origin::::Signed(who.clone()).into(), 1_000_000_000_000_000u128).unwrap(); + + let position_id = Pallet::::get_user_position_id(&who.clone()).unwrap().unwrap(); + + let mut votes = sp_std::vec::Vec::<(u32, Vote)>::new(); + for i in 0..::MaxVotes::get() { + votes.push(( + i, + Vote { + amount: 20_000_000_000_000_000, + conviction: Conviction::Locked1x, + }, + )); + } + + for i in 0..::MaxLocks::get() - 5 { + let id: LockIdentifier = scale_info::prelude::format!("{:a>8}", i.to_string()) + .as_bytes() + .try_into() + .unwrap(); + + T::Currency::set_lock(id, T::NativeAssetId::get(), who, 10_000_000_000_000_u128).unwrap(); + } + + let voting = crate::types::Voting:: { + votes: votes.try_into().unwrap(), + }; + + crate::PositionVotes::::insert(position_id, voting); + } + + #[cfg(feature = "runtime-benchmarks")] + fn on_remove_vote_worst_case(who: &T::AccountId) { + use frame_system::Origin; + + T::Currency::update_balance( + T::NativeAssetId::get(), + &Pallet::::pot_account_id(), + 10_000_000_000_000i128, + ) + .unwrap(); + Pallet::::initialize_staking(Origin::::Root.into()).unwrap(); + T::Currency::update_balance(T::NativeAssetId::get(), who, 1_000_000_000_000_000i128).unwrap(); + Pallet::::stake(Origin::::Signed(who.clone()).into(), 1_000_000_000_000_000u128).unwrap(); + } +} diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index cc9840629..578e291af 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -45,7 +45,6 @@ mod tests; mod benchmarks; pub mod integrations; -pub mod migration; pub mod traits; pub mod types; pub mod weights; @@ -202,13 +201,32 @@ pub mod pallet { #[pallet::storage] /// List of position votes. - #[pallet::getter(fn position_votes)] - pub(super) type PositionVotes = + pub(super) type Votes = StorageMap<_, Blake2_128Concat, T::PositionItemId, Voting, ValueQuery>; #[pallet::storage] /// List of processed vote. Used to determine if the vote should be locked in case of voting not in favor. - #[pallet::getter(fn processed_votes)] + pub(super) type VotesRewarded = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Blake2_128Concat, + types::ReferendumIndex, + types::Vote, + OptionQuery, + >; + + // The original storage is kept for the following reasons. + // 1. To keep legacy staking votes so users don't loose points + // 2. To keep processed votes so balances are correctly locked after a legacy vote is removed. + + #[pallet::storage] + /// Legacy storage! - Used to handle democracy votes until democracy pallet is fully removed. + pub(super) type PositionVotes = + StorageMap<_, Blake2_128Concat, T::PositionItemId, Voting, ValueQuery>; + + #[pallet::storage] + /// Legacy storage! - Used to handle democracy processed votes until democracy pallet is fully removed. pub(super) type ProcessedVotes = StorageDoubleMap< _, Blake2_128Concat, @@ -448,7 +466,7 @@ pub mod pallet { use frame_support::StorageDoubleMap; ensure!( - !ProcessedVotes::::contains_prefix(&who), + !VotesRewarded::::contains_prefix(&who), Error::::ExistingProcessedVotes ); @@ -562,7 +580,7 @@ pub mod pallet { use frame_support::StorageDoubleMap; ensure!( - !ProcessedVotes::::contains_prefix(&who), + !VotesRewarded::::contains_prefix(&who), Error::::ExistingProcessedVotes ); @@ -673,11 +691,11 @@ pub mod pallet { .as_mut() .defensive_ok_or::>(InconsistentStateError::PositionNotFound.into())?; - let voting = PositionVotes::::get(position_id); + let voting = Votes::::get(position_id); use frame_support::StorageDoubleMap; ensure!( - voting.votes.is_empty() && !ProcessedVotes::::contains_prefix(&who), + voting.votes.is_empty() && !VotesRewarded::::contains_prefix(&who), Error::::ExistingVotes ); @@ -731,7 +749,7 @@ pub mod pallet { unlocked_stake: position.stake, }); - PositionVotes::::remove(position_id); + Votes::::remove(position_id); *maybe_position = None; Ok(()) @@ -960,7 +978,7 @@ impl Pallet { position_id: T::PositionItemId, position: &mut Position>, ) -> DispatchResult { - PositionVotes::::mutate(position_id, |voting| { + Votes::::mutate(position_id, |voting| { let max_position_vote = Conviction::max_multiplier().saturating_mul_int(position.stake); voting.votes.retain(|(ref_idx, vote)| { @@ -968,7 +986,7 @@ impl Pallet { let points = Self::calculate_points_for_action(Action::DemocracyVote, vote, max_position_vote); position.action_points = position.action_points.saturating_add(points); // We need to keep the vote info to determine if the vote should be locked when removed. - ProcessedVotes::::insert(who, *ref_idx, vote); + VotesRewarded::::insert(who, *ref_idx, vote); false } else { true @@ -1004,7 +1022,7 @@ impl Pallet { } pub fn get_position_votes(position_id: T::PositionItemId) -> Voting { - PositionVotes::::get(position_id) + Votes::::get(position_id) } } diff --git a/pallets/staking/src/migration.rs b/pallets/staking/src/migration.rs deleted file mode 100644 index c56a5720d..000000000 --- a/pallets/staking/src/migration.rs +++ /dev/null @@ -1,77 +0,0 @@ -use frame_support::migrations::VersionedMigration; -use frame_support::{traits::Get, weights::Weight}; - -use crate::*; - -pub mod versioned { - use super::*; - - pub type V1ToV2 = VersionedMigration< - 1, - 2, - v2::VersionUncheckedMigrateV1ToV2, - crate::pallet::Pallet, - ::DbWeight, - >; -} - -// This migration clear existing staking votes. -// It is necessary to clear the votes because staking supports opengov from v2.0.0. -pub mod v2 { - use super::*; - use frame_support::traits::OnRuntimeUpgrade; - #[cfg(feature = "try-runtime")] - use sp_runtime::TryRuntimeError; - - const TARGET: &str = "runtime::staking::migration::v2"; - - pub struct VersionUncheckedMigrateV1ToV2(PhantomData); - - impl OnRuntimeUpgrade for VersionUncheckedMigrateV1ToV2 { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let existing_votes = PositionVotes::::iter().count(); - let processed_votes = ProcessedVotes::::iter().count(); - log::info!( - target: TARGET, - "pre-upgrade state contains '{}' existing votes and '{} processed votes.", - existing_votes, - processed_votes - - ); - Ok(Vec::new()) - } - - fn on_runtime_upgrade() -> Weight { - log::info!( - target: TARGET, - "running storage migration from version 1 to version 2." - ); - - let existing_votes = PositionVotes::::iter().count(); - let processed_votes = ProcessedVotes::::iter().count(); - - let mut weight = T::DbWeight::get().reads_writes(1, 1); - let _ = PositionVotes::::clear(existing_votes as u32, None); - let _ = ProcessedVotes::::clear(processed_votes as u32, None); - - weight.saturating_accrue(T::DbWeight::get().reads(existing_votes.saturating_add(processed_votes) as u64)); - weight - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - assert_eq!( - PositionVotes::::iter().count(), - 0, - "PositionVotes storage is not empty" - ); - assert_eq!( - ProcessedVotes::::iter().count(), - 0, - "ProcessedVotes storage is not empty" - ); - Ok(()) - } - } -} diff --git a/pallets/staking/src/tests/mock.rs b/pallets/staking/src/tests/mock.rs index cc8f2cfdc..66a6ceda3 100644 --- a/pallets/staking/src/tests/mock.rs +++ b/pallets/staking/src/tests/mock.rs @@ -381,7 +381,7 @@ impl ExtBuilder { votes: votes.try_into().unwrap(), }; - pallet_staking::PositionVotes::::insert(position_id, v); + pallet_staking::Votes::::insert(position_id, v); } }); diff --git a/pallets/staking/src/tests/tests.rs b/pallets/staking/src/tests/tests.rs index b389d777f..919eb70de 100644 --- a/pallets/staking/src/tests/tests.rs +++ b/pallets/staking/src/tests/tests.rs @@ -58,7 +58,7 @@ fn process_votes_should_work_when_referendum_is_finished() { position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); }); } @@ -100,7 +100,7 @@ fn process_votes_should_do_nothing_when_referendum_is_not_finished() { //Assert assert_eq!(position_before, position); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 1); + assert_eq!(Votes::::get(position_id).votes.len(), 1); }); } @@ -148,7 +148,7 @@ fn process_votes_should_work_when_referendum_is_finished_with_conviction() { }, position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); }); } @@ -233,7 +233,7 @@ fn process_votes_should_work_when_multiple_votes_exists() { }, position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 2); + assert_eq!(Votes::::get(position_id).votes.len(), 2); }); } @@ -358,7 +358,7 @@ fn process_votes_should_work_when_on_vote_is_called() { }, Staking::positions(position_id).unwrap() ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 3); + assert_eq!(Votes::::get(position_id).votes.len(), 3); }); } @@ -559,7 +559,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Vote with max stake + max conviction //NOTE: reset previous test @@ -576,7 +576,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -590,7 +590,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Too small vote to get any action points //NOTE: reset previous test @@ -607,7 +607,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -621,7 +621,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Vote max stake + half convition //NOTE: reset previous test @@ -638,7 +638,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -652,7 +652,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Vote with half stake + max convition //NOTE: reset previous test @@ -669,7 +669,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -683,7 +683,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Vote with random stake + random conviction //NOTE: reset previous test @@ -700,7 +700,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -714,7 +714,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); //Vote with max stake + conviction.none //NOTE: reset previous test @@ -731,7 +731,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini votes: votes.try_into().unwrap(), }; - PositionVotes::::insert(position_id, v); + Votes::::insert(position_id, v); //Act assert_ok!(Staking::process_votes(&BOB, position_id, &mut position)); @@ -745,7 +745,7 @@ fn process_votes_should_calculate_action_points_corectly_when_referendum_is_fini position ); - assert_eq!(PositionVotes::::get(position_id).votes.len(), 0); + assert_eq!(Votes::::get(position_id).votes.len(), 0); }); } @@ -783,32 +783,32 @@ fn conviction_voting_hook_vote_cap_should_work() { balance: 100_000 * ONE, }; - assert_eq!(Staking::position_votes(vested_position_id).votes.len(), 0); + assert_eq!(Staking::get_position_votes(vested_position_id).votes.len(), 0); //Act - happy path, user have enough token for staking and vesting. assert_ok!(StakingConvictionVoting::::on_vote(&VESTED_100K, ref_idx, v)); //Assert - let staking_votes = Staking::position_votes(vested_position_id).votes; + let staking_votes = Staking::get_position_votes(vested_position_id).votes; assert_eq!(staking_votes.len(), 1); assert_eq!(staking_votes[0].1, Vote::new(80_000 * ONE, Conviction::Locked6x)); //Assert 2 - 1 token is missing to fully satisfy both locks - PositionVotes::::remove(vested_position_id); + Votes::::remove(vested_position_id); Tokens::transfer(RuntimeOrigin::signed(VESTED_100K), ALICE, HDX, 1).unwrap(); //Act assert_ok!(StakingConvictionVoting::::on_vote(&VESTED_100K, ref_idx, v)); //Assert - let staking_votes = Staking::position_votes(vested_position_id).votes; + let staking_votes = Staking::get_position_votes(vested_position_id).votes; assert_eq!(staking_votes.len(), 1); assert_eq!(staking_votes[0].1, Vote::new(80_000 * ONE - 1, Conviction::Locked6x)); //Assert 3 - only vesting lock is satisfied - PositionVotes::::remove(vested_position_id); + Votes::::remove(vested_position_id); Tokens::transfer(RuntimeOrigin::signed(VESTED_100K), ALICE, HDX, 80_000 * ONE - 1).unwrap(); assert_eq!(Tokens::free_balance(HDX, &VESTED_100K), 100_000 * ONE); @@ -817,13 +817,13 @@ fn conviction_voting_hook_vote_cap_should_work() { assert_ok!(StakingConvictionVoting::::on_vote(&VESTED_100K, ref_idx, v)); //Assert - let staking_votes = Staking::position_votes(vested_position_id).votes; + let staking_votes = Staking::get_position_votes(vested_position_id).votes; assert_eq!(staking_votes.len(), 1); assert_eq!(staking_votes[0].1, Vote::new(0, Conviction::Locked6x)); //Assert 4 - portion of the lock are locked rewards - PositionVotes::::remove(vested_position_id); + Votes::::remove(vested_position_id); Tokens::transfer(RuntimeOrigin::signed(ALICE), VESTED_100K, HDX, 20_000 * ONE).unwrap(); let p = Staking::positions(vested_position_id).unwrap(); @@ -848,13 +848,13 @@ fn conviction_voting_hook_vote_cap_should_work() { assert_ok!(StakingConvictionVoting::::on_vote(&VESTED_100K, ref_idx, v)); //Assert - let staking_votes = Staking::position_votes(vested_position_id).votes; + let staking_votes = Staking::get_position_votes(vested_position_id).votes; assert_eq!(staking_votes.len(), 1); assert_eq!(staking_votes[0].1, Vote::new(10_000 * ONE, Conviction::Locked6x)); //Assert 5 - sum of vested and locked rewards is bigger than account's balance - PositionVotes::::remove(vested_position_id); + Votes::::remove(vested_position_id); Tokens::transfer(RuntimeOrigin::signed(VESTED_100K), ALICE, HDX, 20_000 * ONE).unwrap(); let p = Staking::positions(vested_position_id).unwrap(); @@ -879,7 +879,7 @@ fn conviction_voting_hook_vote_cap_should_work() { assert_ok!(StakingConvictionVoting::::on_vote(&VESTED_100K, ref_idx, v)); //Assert - let staking_votes = Staking::position_votes(vested_position_id).votes; + let staking_votes = Staking::get_position_votes(vested_position_id).votes; assert_eq!(staking_votes.len(), 1); assert_eq!(staking_votes[0].1, Vote::new(0, Conviction::Locked6x)); diff --git a/pallets/staking/src/tests/unstake.rs b/pallets/staking/src/tests/unstake.rs index 02a787770..a41c80966 100644 --- a/pallets/staking/src/tests/unstake.rs +++ b/pallets/staking/src/tests/unstake.rs @@ -524,7 +524,7 @@ fn unstake_should_fail_when_position_has_existing_votes() { set_block_number(1_700_000); let alice_position_id = 0; - assert!(crate::PositionVotes::::contains_key(alice_position_id)); + assert!(crate::Votes::::contains_key(alice_position_id)); //Act assert_noop!( Staking::unstake(RuntimeOrigin::signed(ALICE), alice_position_id), @@ -557,7 +557,7 @@ fn unstake_should_fail_when_position_has_existing_processed_votes() { set_block_number(1_700_000); let alice_position_id = 0; - assert!(crate::PositionVotes::::contains_key(alice_position_id)); + assert!(crate::Votes::::contains_key(alice_position_id)); assert_ok!(Staking::increase_stake( RuntimeOrigin::signed(ALICE), @@ -565,7 +565,7 @@ fn unstake_should_fail_when_position_has_existing_processed_votes() { 10_000 * ONE )); - let voting = PositionVotes::::get(alice_position_id); + let voting = Votes::::get(alice_position_id); assert!(voting.votes.is_empty()); //Act diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index 0bbe083c4..87644ded0 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "275.0.0" +version = "276.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" diff --git a/runtime/hydradx/src/governance/old.rs b/runtime/hydradx/src/governance/old.rs index a3cf51336..7029c7838 100644 --- a/runtime/hydradx/src/governance/old.rs +++ b/runtime/hydradx/src/governance/old.rs @@ -158,7 +158,7 @@ impl pallet_democracy::Config for Runtime { type VetoOrigin = pallet_collective::EnsureMember; type PalletsOrigin = OriginCaller; type Slash = Treasury; - type DemocracyHooks = (); + type DemocracyHooks = pallet_staking::integrations::democracy_legacy::LegacyStakingDemocracy; // Any single technical committee member may remove a vote. type VoteRemovalOrigin = frame_system::EnsureSignedBy; } diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index a7339a492..185543e7d 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 275, + spec_version: 276, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 2a83b2450db9f9939386a0b27b4af8bd0c908ee7 Mon Sep 17 00:00:00 2001 From: Martin Hloska Date: Thu, 19 Dec 2024 11:42:24 +0100 Subject: [PATCH 2/2] bring back the getters --- pallets/staking/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index 578e291af..26f1f9197 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -201,11 +201,13 @@ pub mod pallet { #[pallet::storage] /// List of position votes. + #[pallet::getter(fn get_position_votes)] pub(super) type Votes = StorageMap<_, Blake2_128Concat, T::PositionItemId, Voting, ValueQuery>; #[pallet::storage] /// List of processed vote. Used to determine if the vote should be locked in case of voting not in favor. + #[pallet::getter(fn processed_votes)] pub(super) type VotesRewarded = StorageDoubleMap< _, Blake2_128Concat, @@ -1020,10 +1022,6 @@ impl Pallet { pub fn get_position(position_id: T::PositionItemId) -> Option>> { Positions::::get(position_id) } - - pub fn get_position_votes(position_id: T::PositionItemId) -> Voting { - Votes::::get(position_id) - } } pub struct SigmoidPercentage(sp_std::marker::PhantomData<(T, B)>);