Skip to content

Commit

Permalink
Write migration to release bonds to proposers
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidK committed Oct 2, 2024
1 parent 547fc0d commit c27a3d7
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 84 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,8 @@ type Migrations = (
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, FellowshipCoreInstance>,
// unreleased
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, AmbassadorCoreInstance>,
// unreleased
pallet_treasury::migration::MigrateV0ToV1<Runtime, FellowshipCoreInstance>,
);

/// Executive: handles dispatch to the various modules.
Expand Down
16 changes: 16 additions & 0 deletions prdoc/pr_5892.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json

title: Add migration to clear unapproved proposals treasury from pallet

doc:
- audience:
- Runtime Dev
description: |
It is no longer possible to create Proposals in this pallet but there
are some Proposals whose bonds are stuck. Purpose of this migration is to
clear those and return bonds to the proposers.

crates:
- name: pallet-treasury
bump: patch
1 change: 1 addition & 0 deletions substrate/frame/treasury/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ frame-system = { workspace = true }
pallet-balances = { workspace = true }
sp-runtime = { workspace = true }
sp-core = { optional = true, workspace = true }
log = { workspace = true }

[dev-dependencies]
sp-io = { workspace = true, default-features = true }
Expand Down
15 changes: 0 additions & 15 deletions substrate/frame/treasury/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,21 +348,6 @@ mod benchmarks {
Ok(())
}

#[benchmark]
fn release_proposal_bonds() -> Result<(), BenchmarkError> {
let (_, _value, _beneficiary_lookup) = setup_proposal::<T, _>(SEED);
let origin =
T::RejectOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;

#[block]
{
let _ = Treasury::<T, _>::release_proposal_bonds(origin as T::RuntimeOrigin);
}

assert!(Spends::<T, I>::get(0).is_none());
Ok(())
}

impl_benchmark_test_suite!(
Treasury,
crate::tests::ExtBuilder::default().build(),
Expand Down
64 changes: 10 additions & 54 deletions substrate/frame/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#![cfg_attr(not(feature = "std"), no_std)]

mod benchmarking;
pub mod migration;
#[cfg(test)]
mod tests;
pub mod weights;
Expand All @@ -86,10 +87,7 @@ extern crate alloc;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

use alloc::{
boxed::Box,
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
};
use alloc::{boxed::Box, collections::btree_map::BTreeMap};
use sp_runtime::{
traits::{AccountIdConversion, CheckedAdd, Saturating, StaticLookup, Zero},
Permill, RuntimeDebug,
Expand Down Expand Up @@ -202,7 +200,10 @@ pub mod pallet {
};
use frame_system::pallet_prelude::*;

const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);

#[pallet::config]
Expand Down Expand Up @@ -382,12 +383,6 @@ pub mod pallet {
/// A spend was processed and removed from the storage. It might have been successfully
/// paid or it may have expired.
SpendProcessed { index: SpendIndex },
/// An approved spend was voided.
ProposalBondReleased {
proposal_index: ProposalIndex,
amount: BalanceOf<T, I>,
account: T::AccountId,
},
}

/// Error for the treasury pallet.
Expand Down Expand Up @@ -416,8 +411,6 @@ pub mod pallet {
NotAttempted,
/// The payment has neither failed nor succeeded yet.
Inconclusive,
/// No proposals were released
NoProposalsReleased,
}

#[pallet::hooks]
Expand Down Expand Up @@ -788,48 +781,6 @@ pub mod pallet {
Self::deposit_event(Event::<T, I>::AssetSpendVoided { index });
Ok(())
}

/// ## Dispatch Origin
///
/// Any user with account
///
/// ## Details
///
/// Releases any proposals that didn't make it into Approval yet
///
/// ## Events
///
/// Emits [`Event::ProposalBondReleased`] if successful.
#[pallet::call_index(9)]
#[pallet::weight(T::WeightInfo::release_proposal_bonds())]
pub fn release_proposal_bonds(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _who = ensure_signed(origin)?;

let mut approval_index = BTreeSet::new();
for approval in Approvals::<T, I>::get().iter() {
approval_index.insert(*approval);
}

let mut proposals_released = 0;
for (proposal_index, p) in Proposals::<T, I>::iter() {
if !approval_index.contains(&proposal_index) {
let err_amount = T::Currency::unreserve(&p.proposer, p.bond);
debug_assert!(err_amount.is_zero());
Proposals::<T, I>::remove(proposal_index);
proposals_released += 1;
Self::deposit_event(Event::<T, I>::ProposalBondReleased {
proposal_index,
amount: p.bond,
account: p.proposer,
});
}
}

// we don't want people spamming this function if it doesn't do any work
ensure!(proposals_released > 0, Error::<T, I>::NoProposalsReleased);

Ok(frame_support::dispatch::Pays::No.into())
}
}
}

Expand All @@ -849,6 +800,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
ProposalCount::<T, I>::get()
}

/// Public function to proposals storage.
pub fn proposals(index: ProposalIndex) -> Option<Proposal<T::AccountId, BalanceOf<T, I>>> {
Proposals::<T, I>::get(index)
}

/// Public function to approvals storage.
pub fn approvals() -> BoundedVec<ProposalIndex, T::MaxApprovals> {
Approvals::<T, I>::get()
Expand Down
74 changes: 74 additions & 0 deletions substrate/frame/treasury/src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use super::*;
use alloc::collections::BTreeSet;
use core::marker::PhantomData;
use frame_support::traits::UncheckedOnRuntimeUpgrade;

/// The log target for this pallet.
const LOG_TARGET: &str = "runtime::treasury";

mod v1 {
use super::*;
pub struct MigrateToV1Impl<T, I>(PhantomData<(T, I)>);

impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for MigrateToV1Impl<T, I> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let mut approval_index = BTreeSet::new();
for approval in Approvals::<T, I>::get().iter() {
approval_index.insert(*approval);
}

let mut proposals_released = 0;
for (proposal_index, p) in Proposals::<T, I>::iter() {
if !approval_index.contains(&proposal_index) {
let err_amount = T::Currency::unreserve(&p.proposer, p.bond);
debug_assert!(err_amount.is_zero());
Proposals::<T, I>::remove(proposal_index);
log::info!(
target: LOG_TARGET,
"Released bond amount of {:?} to proposer {:?}",
p.bond,
p.proposer,
);
proposals_released += 1;
}
}

log::info!(
target: LOG_TARGET,
"Storage migration v1 for pallet-treasury finished, released {} proposal bonds.",
proposals_released,
);

// calculate and return migration weights
let approvals_read = 1;
T::DbWeight::get()
.reads_writes(proposals_released as u64 + approvals_read, proposals_released as u64)
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
Ok((Proposals::<T, I>::count() as u32).encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let old_count = u32::decode(&mut &state[..]).expect("Known good");
let new_count = Regions::<T>::iter_values().count() as u32;

ensure!(
old_count <= new_count,
"Proposals after migration should be less or equal to old proposals"
);
Ok(())
}
}
}

/// Migrate the pallet storage from `0` to `1`.
pub type MigrateV0ToV1<T, I> = frame_support::migrations::VersionedMigration<
0,
1,
v1::MigrateToV1Impl<T, I>,
Pallet<T, I>,
<T as frame_system::Config>::DbWeight,
>;
15 changes: 0 additions & 15 deletions substrate/frame/treasury/src/weights.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c27a3d7

Please sign in to comment.