mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-21 06:21:01 +00:00
add instantiable support for treasury pallet (#7058)
* add instantiable support for treasury pallet * update treasury pallet benchmarking code to support multi-instance * use benchmark_intance! macro; fix hard coded treasury identity string; fix over characters line width limitation error * fix line return style
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use frame_system::RawOrigin;
|
use frame_system::RawOrigin;
|
||||||
use frame_benchmarking::{benchmarks, account, whitelisted_caller};
|
use frame_benchmarking::{benchmarks_instance, account, whitelisted_caller};
|
||||||
use frame_support::traits::OnInitialize;
|
use frame_support::traits::OnInitialize;
|
||||||
|
|
||||||
use crate::Module as Treasury;
|
use crate::Module as Treasury;
|
||||||
@@ -30,13 +30,13 @@ use crate::Module as Treasury;
|
|||||||
const SEED: u32 = 0;
|
const SEED: u32 = 0;
|
||||||
|
|
||||||
// Create the pre-requisite information needed to create a treasury `propose_spend`.
|
// Create the pre-requisite information needed to create a treasury `propose_spend`.
|
||||||
fn setup_proposal<T: Trait>(u: u32) -> (
|
fn setup_proposal<T: Trait<I>, I: Instance>(u: u32) -> (
|
||||||
T::AccountId,
|
T::AccountId,
|
||||||
BalanceOf<T>,
|
BalanceOf<T, I>,
|
||||||
<T::Lookup as StaticLookup>::Source,
|
<T::Lookup as StaticLookup>::Source,
|
||||||
) {
|
) {
|
||||||
let caller = account("caller", u, SEED);
|
let caller = account("caller", u, SEED);
|
||||||
let value: BalanceOf<T> = T::ProposalBondMinimum::get().saturating_mul(100.into());
|
let value: BalanceOf<T, I> = T::ProposalBondMinimum::get().saturating_mul(100.into());
|
||||||
let _ = T::Currency::make_free_balance_be(&caller, value);
|
let _ = T::Currency::make_free_balance_be(&caller, value);
|
||||||
let beneficiary = account("beneficiary", u, SEED);
|
let beneficiary = account("beneficiary", u, SEED);
|
||||||
let beneficiary_lookup = T::Lookup::unlookup(beneficiary);
|
let beneficiary_lookup = T::Lookup::unlookup(beneficiary);
|
||||||
@@ -44,7 +44,7 @@ fn setup_proposal<T: Trait>(u: u32) -> (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the pre-requisite information needed to create a `report_awesome`.
|
// Create the pre-requisite information needed to create a `report_awesome`.
|
||||||
fn setup_awesome<T: Trait>(length: u32) -> (T::AccountId, Vec<u8>, T::AccountId) {
|
fn setup_awesome<T: Trait<I>, I: Instance>(length: u32) -> (T::AccountId, Vec<u8>, T::AccountId) {
|
||||||
let caller = whitelisted_caller();
|
let caller = whitelisted_caller();
|
||||||
let value = T::TipReportDepositBase::get()
|
let value = T::TipReportDepositBase::get()
|
||||||
+ T::TipReportDepositPerByte::get() * length.into()
|
+ T::TipReportDepositPerByte::get() * length.into()
|
||||||
@@ -56,8 +56,8 @@ fn setup_awesome<T: Trait>(length: u32) -> (T::AccountId, Vec<u8>, T::AccountId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the pre-requisite information needed to call `tip_new`.
|
// Create the pre-requisite information needed to call `tip_new`.
|
||||||
fn setup_tip<T: Trait>(r: u32, t: u32) ->
|
fn setup_tip<T: Trait<I>, I: Instance>(r: u32, t: u32) ->
|
||||||
Result<(T::AccountId, Vec<u8>, T::AccountId, BalanceOf<T>), &'static str>
|
Result<(T::AccountId, Vec<u8>, T::AccountId, BalanceOf<T, I>), &'static str>
|
||||||
{
|
{
|
||||||
let tippers_count = T::Tippers::count();
|
let tippers_count = T::Tippers::count();
|
||||||
|
|
||||||
@@ -77,13 +77,15 @@ fn setup_tip<T: Trait>(r: u32, t: u32) ->
|
|||||||
|
|
||||||
// Create `t` new tips for the tip proposal with `hash`.
|
// Create `t` new tips for the tip proposal with `hash`.
|
||||||
// This function automatically makes the tip able to close.
|
// This function automatically makes the tip able to close.
|
||||||
fn create_tips<T: Trait>(t: u32, hash: T::Hash, value: BalanceOf<T>) -> Result<(), &'static str> {
|
fn create_tips<T: Trait<I>, I: Instance>(t: u32, hash: T::Hash, value: BalanceOf<T, I>) ->
|
||||||
|
Result<(), &'static str>
|
||||||
|
{
|
||||||
for i in 0 .. t {
|
for i in 0 .. t {
|
||||||
let caller = account("member", i, SEED);
|
let caller = account("member", i, SEED);
|
||||||
ensure!(T::Tippers::contains(&caller), "caller is not a tipper");
|
ensure!(T::Tippers::contains(&caller), "caller is not a tipper");
|
||||||
Treasury::<T>::tip(RawOrigin::Signed(caller).into(), hash, value)?;
|
Treasury::<T, I>::tip(RawOrigin::Signed(caller).into(), hash, value)?;
|
||||||
}
|
}
|
||||||
Tips::<T>::mutate(hash, |maybe_tip| {
|
Tips::<T, I>::mutate(hash, |maybe_tip| {
|
||||||
if let Some(open_tip) = maybe_tip {
|
if let Some(open_tip) = maybe_tip {
|
||||||
open_tip.closes = Some(T::BlockNumber::zero());
|
open_tip.closes = Some(T::BlockNumber::zero());
|
||||||
}
|
}
|
||||||
@@ -92,30 +94,30 @@ fn create_tips<T: Trait>(t: u32, hash: T::Hash, value: BalanceOf<T>) -> Result<(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create proposals that are approved for use in `on_initialize`.
|
// Create proposals that are approved for use in `on_initialize`.
|
||||||
fn create_approved_proposals<T: Trait>(n: u32) -> Result<(), &'static str> {
|
fn create_approved_proposals<T: Trait<I>, I: Instance>(n: u32) -> Result<(), &'static str> {
|
||||||
for i in 0 .. n {
|
for i in 0 .. n {
|
||||||
let (caller, value, lookup) = setup_proposal::<T>(i);
|
let (caller, value, lookup) = setup_proposal::<T, I>(i);
|
||||||
Treasury::<T>::propose_spend(
|
Treasury::<T, I>::propose_spend(
|
||||||
RawOrigin::Signed(caller).into(),
|
RawOrigin::Signed(caller).into(),
|
||||||
value,
|
value,
|
||||||
lookup
|
lookup
|
||||||
)?;
|
)?;
|
||||||
let proposal_id = ProposalCount::get() - 1;
|
let proposal_id = <ProposalCount<I>>::get() - 1;
|
||||||
Treasury::<T>::approve_proposal(RawOrigin::Root.into(), proposal_id)?;
|
Treasury::<T, I>::approve_proposal(RawOrigin::Root.into(), proposal_id)?;
|
||||||
}
|
}
|
||||||
ensure!(Approvals::get().len() == n as usize, "Not all approved");
|
ensure!(<Approvals<I>>::get().len() == n as usize, "Not all approved");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_BYTES: u32 = 16384;
|
const MAX_BYTES: u32 = 16384;
|
||||||
const MAX_TIPPERS: u32 = 100;
|
const MAX_TIPPERS: u32 = 100;
|
||||||
|
|
||||||
benchmarks! {
|
benchmarks_instance! {
|
||||||
_ { }
|
_ { }
|
||||||
|
|
||||||
propose_spend {
|
propose_spend {
|
||||||
let u in 0 .. 1000;
|
let u in 0 .. 1000;
|
||||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T>(u);
|
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||||
// Whitelist caller account from further DB operations.
|
// Whitelist caller account from further DB operations.
|
||||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||||
@@ -123,29 +125,29 @@ benchmarks! {
|
|||||||
|
|
||||||
reject_proposal {
|
reject_proposal {
|
||||||
let u in 0 .. 1000;
|
let u in 0 .. 1000;
|
||||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T>(u);
|
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||||
Treasury::<T>::propose_spend(
|
Treasury::<T, _>::propose_spend(
|
||||||
RawOrigin::Signed(caller).into(),
|
RawOrigin::Signed(caller).into(),
|
||||||
value,
|
value,
|
||||||
beneficiary_lookup
|
beneficiary_lookup
|
||||||
)?;
|
)?;
|
||||||
let proposal_id = ProposalCount::get() - 1;
|
let proposal_id = Treasury::<T, _>::proposal_count() - 1;
|
||||||
}: _(RawOrigin::Root, proposal_id)
|
}: _(RawOrigin::Root, proposal_id)
|
||||||
|
|
||||||
approve_proposal {
|
approve_proposal {
|
||||||
let u in 0 .. 1000;
|
let u in 0 .. 1000;
|
||||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T>(u);
|
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||||
Treasury::<T>::propose_spend(
|
Treasury::<T, _>::propose_spend(
|
||||||
RawOrigin::Signed(caller).into(),
|
RawOrigin::Signed(caller).into(),
|
||||||
value,
|
value,
|
||||||
beneficiary_lookup
|
beneficiary_lookup
|
||||||
)?;
|
)?;
|
||||||
let proposal_id = ProposalCount::get() - 1;
|
let proposal_id = Treasury::<T, _>::proposal_count() - 1;
|
||||||
}: _(RawOrigin::Root, proposal_id)
|
}: _(RawOrigin::Root, proposal_id)
|
||||||
|
|
||||||
report_awesome {
|
report_awesome {
|
||||||
let r in 0 .. MAX_BYTES;
|
let r in 0 .. MAX_BYTES;
|
||||||
let (caller, reason, awesome_person) = setup_awesome::<T>(r);
|
let (caller, reason, awesome_person) = setup_awesome::<T, _>(r);
|
||||||
// Whitelist caller account from further DB operations.
|
// Whitelist caller account from further DB operations.
|
||||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||||
@@ -153,8 +155,8 @@ benchmarks! {
|
|||||||
|
|
||||||
retract_tip {
|
retract_tip {
|
||||||
let r in 0 .. MAX_BYTES;
|
let r in 0 .. MAX_BYTES;
|
||||||
let (caller, reason, awesome_person) = setup_awesome::<T>(r);
|
let (caller, reason, awesome_person) = setup_awesome::<T, _>(r);
|
||||||
Treasury::<T>::report_awesome(
|
Treasury::<T, _>::report_awesome(
|
||||||
RawOrigin::Signed(caller.clone()).into(),
|
RawOrigin::Signed(caller.clone()).into(),
|
||||||
reason.clone(),
|
reason.clone(),
|
||||||
awesome_person.clone()
|
awesome_person.clone()
|
||||||
@@ -170,7 +172,7 @@ benchmarks! {
|
|||||||
let r in 0 .. MAX_BYTES;
|
let r in 0 .. MAX_BYTES;
|
||||||
let t in 1 .. MAX_TIPPERS;
|
let t in 1 .. MAX_TIPPERS;
|
||||||
|
|
||||||
let (caller, reason, beneficiary, value) = setup_tip::<T>(r, t)?;
|
let (caller, reason, beneficiary, value) = setup_tip::<T, _>(r, t)?;
|
||||||
// Whitelist caller account from further DB operations.
|
// Whitelist caller account from further DB operations.
|
||||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||||
@@ -178,9 +180,9 @@ benchmarks! {
|
|||||||
|
|
||||||
tip {
|
tip {
|
||||||
let t in 1 .. MAX_TIPPERS;
|
let t in 1 .. MAX_TIPPERS;
|
||||||
let (member, reason, beneficiary, value) = setup_tip::<T>(0, t)?;
|
let (member, reason, beneficiary, value) = setup_tip::<T, _>(0, t)?;
|
||||||
let value = T::Currency::minimum_balance().saturating_mul(100.into());
|
let value = T::Currency::minimum_balance().saturating_mul(100.into());
|
||||||
Treasury::<T>::tip_new(
|
Treasury::<T, _>::tip_new(
|
||||||
RawOrigin::Signed(member).into(),
|
RawOrigin::Signed(member).into(),
|
||||||
reason.clone(),
|
reason.clone(),
|
||||||
beneficiary.clone(),
|
beneficiary.clone(),
|
||||||
@@ -188,8 +190,8 @@ benchmarks! {
|
|||||||
)?;
|
)?;
|
||||||
let reason_hash = T::Hashing::hash(&reason[..]);
|
let reason_hash = T::Hashing::hash(&reason[..]);
|
||||||
let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
|
let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
|
||||||
ensure!(Tips::<T>::contains_key(hash), "tip does not exist");
|
ensure!(Tips::<T, _>::contains_key(hash), "tip does not exist");
|
||||||
create_tips::<T>(t - 1, hash.clone(), value)?;
|
create_tips::<T, _>(t - 1, hash.clone(), value)?;
|
||||||
let caller = account("member", t - 1, SEED);
|
let caller = account("member", t - 1, SEED);
|
||||||
// Whitelist caller account from further DB operations.
|
// Whitelist caller account from further DB operations.
|
||||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||||
@@ -200,14 +202,14 @@ benchmarks! {
|
|||||||
let t in 1 .. MAX_TIPPERS;
|
let t in 1 .. MAX_TIPPERS;
|
||||||
|
|
||||||
// Make sure pot is funded
|
// Make sure pot is funded
|
||||||
let pot_account = Treasury::<T>::account_id();
|
let pot_account = Treasury::<T, _>::account_id();
|
||||||
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
||||||
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
||||||
|
|
||||||
// Set up a new tip proposal
|
// Set up a new tip proposal
|
||||||
let (member, reason, beneficiary, value) = setup_tip::<T>(0, t)?;
|
let (member, reason, beneficiary, value) = setup_tip::<T, _>(0, t)?;
|
||||||
let value = T::Currency::minimum_balance().saturating_mul(100.into());
|
let value = T::Currency::minimum_balance().saturating_mul(100.into());
|
||||||
Treasury::<T>::tip_new(
|
Treasury::<T, _>::tip_new(
|
||||||
RawOrigin::Signed(member).into(),
|
RawOrigin::Signed(member).into(),
|
||||||
reason.clone(),
|
reason.clone(),
|
||||||
beneficiary.clone(),
|
beneficiary.clone(),
|
||||||
@@ -217,8 +219,8 @@ benchmarks! {
|
|||||||
// Create a bunch of tips
|
// Create a bunch of tips
|
||||||
let reason_hash = T::Hashing::hash(&reason[..]);
|
let reason_hash = T::Hashing::hash(&reason[..]);
|
||||||
let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
|
let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
|
||||||
ensure!(Tips::<T>::contains_key(hash), "tip does not exist");
|
ensure!(Tips::<T, _>::contains_key(hash), "tip does not exist");
|
||||||
create_tips::<T>(t, hash.clone(), value)?;
|
create_tips::<T, _>(t, hash.clone(), value)?;
|
||||||
|
|
||||||
let caller = account("caller", t, SEED);
|
let caller = account("caller", t, SEED);
|
||||||
// Whitelist caller account from further DB operations.
|
// Whitelist caller account from further DB operations.
|
||||||
@@ -228,12 +230,12 @@ benchmarks! {
|
|||||||
|
|
||||||
on_initialize {
|
on_initialize {
|
||||||
let p in 0 .. 100;
|
let p in 0 .. 100;
|
||||||
let pot_account = Treasury::<T>::account_id();
|
let pot_account = Treasury::<T, _>::account_id();
|
||||||
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
||||||
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
||||||
create_approved_proposals::<T>(p)?;
|
create_approved_proposals::<T, _>(p)?;
|
||||||
}: {
|
}: {
|
||||||
Treasury::<T>::on_initialize(T::BlockNumber::zero());
|
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,9 +107,12 @@ use frame_system::{self as system, ensure_signed};
|
|||||||
mod tests;
|
mod tests;
|
||||||
mod benchmarking;
|
mod benchmarking;
|
||||||
|
|
||||||
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
|
type BalanceOf<T, I> =
|
||||||
type PositiveImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::PositiveImbalance;
|
<<T as Trait<I>>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
|
||||||
type NegativeImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
|
type PositiveImbalanceOf<T, I> =
|
||||||
|
<<T as Trait<I>>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::PositiveImbalance;
|
||||||
|
type NegativeImbalanceOf<T, I> =
|
||||||
|
<<T as Trait<I>>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
|
||||||
|
|
||||||
pub trait WeightInfo {
|
pub trait WeightInfo {
|
||||||
fn propose_spend(u: u32, ) -> Weight;
|
fn propose_spend(u: u32, ) -> Weight;
|
||||||
@@ -135,7 +138,7 @@ impl WeightInfo for () {
|
|||||||
fn on_initialize(_p: u32, ) -> Weight { 1_000_000_000 }
|
fn on_initialize(_p: u32, ) -> Weight { 1_000_000_000 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Trait: frame_system::Trait {
|
pub trait Trait<I=DefaultInstance>: frame_system::Trait {
|
||||||
/// The treasury's module id, used for deriving its sovereign account ID.
|
/// The treasury's module id, used for deriving its sovereign account ID.
|
||||||
type ModuleId: Get<ModuleId>;
|
type ModuleId: Get<ModuleId>;
|
||||||
|
|
||||||
@@ -160,23 +163,23 @@ pub trait Trait: frame_system::Trait {
|
|||||||
type TipFindersFee: Get<Percent>;
|
type TipFindersFee: Get<Percent>;
|
||||||
|
|
||||||
/// The amount held on deposit for placing a tip report.
|
/// The amount held on deposit for placing a tip report.
|
||||||
type TipReportDepositBase: Get<BalanceOf<Self>>;
|
type TipReportDepositBase: Get<BalanceOf<Self, I>>;
|
||||||
|
|
||||||
/// The amount held on deposit per byte within the tip report reason.
|
/// The amount held on deposit per byte within the tip report reason.
|
||||||
type TipReportDepositPerByte: Get<BalanceOf<Self>>;
|
type TipReportDepositPerByte: Get<BalanceOf<Self, I>>;
|
||||||
|
|
||||||
/// The overarching event type.
|
/// The overarching event type.
|
||||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
|
type Event: From<Event<Self, I>> + Into<<Self as frame_system::Trait>::Event>;
|
||||||
|
|
||||||
/// Handler for the unbalanced decrease when slashing for a rejected proposal.
|
/// Handler for the unbalanced decrease when slashing for a rejected proposal.
|
||||||
type ProposalRejection: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
type ProposalRejection: OnUnbalanced<NegativeImbalanceOf<Self, I>>;
|
||||||
|
|
||||||
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
||||||
/// An accepted proposal gets these back. A rejected proposal does not.
|
/// An accepted proposal gets these back. A rejected proposal does not.
|
||||||
type ProposalBond: Get<Permill>;
|
type ProposalBond: Get<Permill>;
|
||||||
|
|
||||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||||
type ProposalBondMinimum: Get<BalanceOf<Self>>;
|
type ProposalBondMinimum: Get<BalanceOf<Self, I>>;
|
||||||
|
|
||||||
/// Period between successive spends.
|
/// Period between successive spends.
|
||||||
type SpendPeriod: Get<Self::BlockNumber>;
|
type SpendPeriod: Get<Self::BlockNumber>;
|
||||||
@@ -185,7 +188,7 @@ pub trait Trait: frame_system::Trait {
|
|||||||
type Burn: Get<Permill>;
|
type Burn: Get<Permill>;
|
||||||
|
|
||||||
/// Handler for the unbalanced decrease when treasury funds are burned.
|
/// Handler for the unbalanced decrease when treasury funds are burned.
|
||||||
type BurnDestination: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
type BurnDestination: OnUnbalanced<NegativeImbalanceOf<Self, I>>;
|
||||||
|
|
||||||
/// Weight information for extrinsics in this pallet.
|
/// Weight information for extrinsics in this pallet.
|
||||||
type WeightInfo: WeightInfo;
|
type WeightInfo: WeightInfo;
|
||||||
@@ -236,14 +239,14 @@ pub struct OpenTip<
|
|||||||
}
|
}
|
||||||
|
|
||||||
decl_storage! {
|
decl_storage! {
|
||||||
trait Store for Module<T: Trait> as Treasury {
|
trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Treasury {
|
||||||
/// Number of proposals that have been made.
|
/// Number of proposals that have been made.
|
||||||
ProposalCount get(fn proposal_count): ProposalIndex;
|
ProposalCount get(fn proposal_count): ProposalIndex;
|
||||||
|
|
||||||
/// Proposals that have been made.
|
/// Proposals that have been made.
|
||||||
Proposals get(fn proposals):
|
Proposals get(fn proposals):
|
||||||
map hasher(twox_64_concat) ProposalIndex
|
map hasher(twox_64_concat) ProposalIndex
|
||||||
=> Option<Proposal<T::AccountId, BalanceOf<T>>>;
|
=> Option<Proposal<T::AccountId, BalanceOf<T, I>>>;
|
||||||
|
|
||||||
/// Proposal indices that have been approved but not yet awarded.
|
/// Proposal indices that have been approved but not yet awarded.
|
||||||
Approvals get(fn approvals): Vec<ProposalIndex>;
|
Approvals get(fn approvals): Vec<ProposalIndex>;
|
||||||
@@ -253,7 +256,7 @@ decl_storage! {
|
|||||||
/// guaranteed to be a secure hash.
|
/// guaranteed to be a secure hash.
|
||||||
pub Tips get(fn tips):
|
pub Tips get(fn tips):
|
||||||
map hasher(twox_64_concat) T::Hash
|
map hasher(twox_64_concat) T::Hash
|
||||||
=> Option<OpenTip<T::AccountId, BalanceOf<T>, T::BlockNumber, T::Hash>>;
|
=> Option<OpenTip<T::AccountId, BalanceOf<T, I>, T::BlockNumber, T::Hash>>;
|
||||||
|
|
||||||
/// Simple preimage lookup from the reason's hash to the original data. Again, has an
|
/// Simple preimage lookup from the reason's hash to the original data. Again, has an
|
||||||
/// insecure enumerable hash since the key is guaranteed to be the result of a secure hash.
|
/// insecure enumerable hash since the key is guaranteed to be the result of a secure hash.
|
||||||
@@ -263,7 +266,7 @@ decl_storage! {
|
|||||||
build(|_config| {
|
build(|_config| {
|
||||||
// Create Treasury account
|
// Create Treasury account
|
||||||
let _ = T::Currency::make_free_balance_be(
|
let _ = T::Currency::make_free_balance_be(
|
||||||
&<Module<T>>::account_id(),
|
&<Module<T, I>>::account_id(),
|
||||||
T::Currency::minimum_balance(),
|
T::Currency::minimum_balance(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -271,9 +274,9 @@ decl_storage! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decl_event!(
|
decl_event!(
|
||||||
pub enum Event<T>
|
pub enum Event<T, I=DefaultInstance>
|
||||||
where
|
where
|
||||||
Balance = BalanceOf<T>,
|
Balance = BalanceOf<T, I>,
|
||||||
<T as frame_system::Trait>::AccountId,
|
<T as frame_system::Trait>::AccountId,
|
||||||
<T as frame_system::Trait>::Hash,
|
<T as frame_system::Trait>::Hash,
|
||||||
{
|
{
|
||||||
@@ -305,7 +308,7 @@ decl_event!(
|
|||||||
|
|
||||||
decl_error! {
|
decl_error! {
|
||||||
/// Error for the treasury module.
|
/// Error for the treasury module.
|
||||||
pub enum Error for Module<T: Trait> {
|
pub enum Error for Module<T: Trait<I>, I: Instance> {
|
||||||
/// Proposer's balance is too low.
|
/// Proposer's balance is too low.
|
||||||
InsufficientProposersBalance,
|
InsufficientProposersBalance,
|
||||||
/// No proposal at that index.
|
/// No proposal at that index.
|
||||||
@@ -326,13 +329,16 @@ decl_error! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decl_module! {
|
decl_module! {
|
||||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
pub struct Module<T: Trait<I>, I: Instance=DefaultInstance>
|
||||||
|
for enum Call
|
||||||
|
where origin: T::Origin
|
||||||
|
{
|
||||||
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
||||||
/// An accepted proposal gets these back. A rejected proposal does not.
|
/// An accepted proposal gets these back. A rejected proposal does not.
|
||||||
const ProposalBond: Permill = T::ProposalBond::get();
|
const ProposalBond: Permill = T::ProposalBond::get();
|
||||||
|
|
||||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||||
const ProposalBondMinimum: BalanceOf<T> = T::ProposalBondMinimum::get();
|
const ProposalBondMinimum: BalanceOf<T, I> = T::ProposalBondMinimum::get();
|
||||||
|
|
||||||
/// Period between successive spends.
|
/// Period between successive spends.
|
||||||
const SpendPeriod: T::BlockNumber = T::SpendPeriod::get();
|
const SpendPeriod: T::BlockNumber = T::SpendPeriod::get();
|
||||||
@@ -347,15 +353,15 @@ decl_module! {
|
|||||||
const TipFindersFee: Percent = T::TipFindersFee::get();
|
const TipFindersFee: Percent = T::TipFindersFee::get();
|
||||||
|
|
||||||
/// The amount held on deposit for placing a tip report.
|
/// The amount held on deposit for placing a tip report.
|
||||||
const TipReportDepositBase: BalanceOf<T> = T::TipReportDepositBase::get();
|
const TipReportDepositBase: BalanceOf<T, I> = T::TipReportDepositBase::get();
|
||||||
|
|
||||||
/// The amount held on deposit per byte within the tip report reason.
|
/// The amount held on deposit per byte within the tip report reason.
|
||||||
const TipReportDepositPerByte: BalanceOf<T> = T::TipReportDepositPerByte::get();
|
const TipReportDepositPerByte: BalanceOf<T, I> = T::TipReportDepositPerByte::get();
|
||||||
|
|
||||||
/// The treasury's module id, used for deriving its sovereign account ID.
|
/// The treasury's module id, used for deriving its sovereign account ID.
|
||||||
const ModuleId: ModuleId = T::ModuleId::get();
|
const ModuleId: ModuleId = T::ModuleId::get();
|
||||||
|
|
||||||
type Error = Error<T>;
|
type Error = Error<T, I>;
|
||||||
|
|
||||||
fn deposit_event() = default;
|
fn deposit_event() = default;
|
||||||
|
|
||||||
@@ -371,7 +377,7 @@ decl_module! {
|
|||||||
#[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)]
|
#[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)]
|
||||||
fn propose_spend(
|
fn propose_spend(
|
||||||
origin,
|
origin,
|
||||||
#[compact] value: BalanceOf<T>,
|
#[compact] value: BalanceOf<T, I>,
|
||||||
beneficiary: <T::Lookup as StaticLookup>::Source
|
beneficiary: <T::Lookup as StaticLookup>::Source
|
||||||
) {
|
) {
|
||||||
let proposer = ensure_signed(origin)?;
|
let proposer = ensure_signed(origin)?;
|
||||||
@@ -379,11 +385,11 @@ decl_module! {
|
|||||||
|
|
||||||
let bond = Self::calculate_bond(value);
|
let bond = Self::calculate_bond(value);
|
||||||
T::Currency::reserve(&proposer, bond)
|
T::Currency::reserve(&proposer, bond)
|
||||||
.map_err(|_| Error::<T>::InsufficientProposersBalance)?;
|
.map_err(|_| Error::<T, I>::InsufficientProposersBalance)?;
|
||||||
|
|
||||||
let c = Self::proposal_count();
|
let c = Self::proposal_count();
|
||||||
ProposalCount::put(c + 1);
|
<ProposalCount<I>>::put(c + 1);
|
||||||
<Proposals<T>>::insert(c, Proposal { proposer, value, beneficiary, bond });
|
<Proposals<T, I>>::insert(c, Proposal { proposer, value, beneficiary, bond });
|
||||||
|
|
||||||
Self::deposit_event(RawEvent::Proposed(c));
|
Self::deposit_event(RawEvent::Proposed(c));
|
||||||
}
|
}
|
||||||
@@ -401,12 +407,12 @@ decl_module! {
|
|||||||
fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) {
|
fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) {
|
||||||
T::RejectOrigin::ensure_origin(origin)?;
|
T::RejectOrigin::ensure_origin(origin)?;
|
||||||
|
|
||||||
let proposal = <Proposals<T>>::take(&proposal_id).ok_or(Error::<T>::InvalidProposalIndex)?;
|
let proposal = <Proposals<T, I>>::take(&proposal_id).ok_or(Error::<T, I>::InvalidProposalIndex)?;
|
||||||
let value = proposal.bond;
|
let value = proposal.bond;
|
||||||
let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0;
|
let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0;
|
||||||
T::ProposalRejection::on_unbalanced(imbalance);
|
T::ProposalRejection::on_unbalanced(imbalance);
|
||||||
|
|
||||||
Self::deposit_event(Event::<T>::Rejected(proposal_id, value));
|
Self::deposit_event(Event::<T, I>::Rejected(proposal_id, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary
|
/// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary
|
||||||
@@ -423,8 +429,8 @@ decl_module! {
|
|||||||
fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) {
|
fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) {
|
||||||
T::ApproveOrigin::ensure_origin(origin)?;
|
T::ApproveOrigin::ensure_origin(origin)?;
|
||||||
|
|
||||||
ensure!(<Proposals<T>>::contains_key(proposal_id), Error::<T>::InvalidProposalIndex);
|
ensure!(<Proposals<T, I>>::contains_key(proposal_id), Error::<T, I>::InvalidProposalIndex);
|
||||||
Approvals::mutate(|v| v.push(proposal_id));
|
<Approvals<I>>::mutate(|v| v.push(proposal_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report something `reason` that deserves a tip and claim any eventual the finder's fee.
|
/// Report something `reason` that deserves a tip and claim any eventual the finder's fee.
|
||||||
@@ -451,18 +457,18 @@ decl_module! {
|
|||||||
let finder = ensure_signed(origin)?;
|
let finder = ensure_signed(origin)?;
|
||||||
|
|
||||||
const MAX_SENSIBLE_REASON_LENGTH: usize = 16384;
|
const MAX_SENSIBLE_REASON_LENGTH: usize = 16384;
|
||||||
ensure!(reason.len() <= MAX_SENSIBLE_REASON_LENGTH, Error::<T>::ReasonTooBig);
|
ensure!(reason.len() <= MAX_SENSIBLE_REASON_LENGTH, Error::<T, I>::ReasonTooBig);
|
||||||
|
|
||||||
let reason_hash = T::Hashing::hash(&reason[..]);
|
let reason_hash = T::Hashing::hash(&reason[..]);
|
||||||
ensure!(!Reasons::<T>::contains_key(&reason_hash), Error::<T>::AlreadyKnown);
|
ensure!(!Reasons::<T, I>::contains_key(&reason_hash), Error::<T, I>::AlreadyKnown);
|
||||||
let hash = T::Hashing::hash_of(&(&reason_hash, &who));
|
let hash = T::Hashing::hash_of(&(&reason_hash, &who));
|
||||||
ensure!(!Tips::<T>::contains_key(&hash), Error::<T>::AlreadyKnown);
|
ensure!(!Tips::<T, I>::contains_key(&hash), Error::<T, I>::AlreadyKnown);
|
||||||
|
|
||||||
let deposit = T::TipReportDepositBase::get()
|
let deposit = T::TipReportDepositBase::get()
|
||||||
+ T::TipReportDepositPerByte::get() * (reason.len() as u32).into();
|
+ T::TipReportDepositPerByte::get() * (reason.len() as u32).into();
|
||||||
T::Currency::reserve(&finder, deposit)?;
|
T::Currency::reserve(&finder, deposit)?;
|
||||||
|
|
||||||
Reasons::<T>::insert(&reason_hash, &reason);
|
Reasons::<T, I>::insert(&reason_hash, &reason);
|
||||||
let tip = OpenTip {
|
let tip = OpenTip {
|
||||||
reason: reason_hash,
|
reason: reason_hash,
|
||||||
who,
|
who,
|
||||||
@@ -472,7 +478,7 @@ decl_module! {
|
|||||||
tips: vec![],
|
tips: vec![],
|
||||||
finders_fee: true
|
finders_fee: true
|
||||||
};
|
};
|
||||||
Tips::<T>::insert(&hash, tip);
|
Tips::<T, I>::insert(&hash, tip);
|
||||||
Self::deposit_event(RawEvent::NewTip(hash));
|
Self::deposit_event(RawEvent::NewTip(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,11 +504,11 @@ decl_module! {
|
|||||||
#[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)]
|
#[weight = 120_000_000 + T::DbWeight::get().reads_writes(1, 2)]
|
||||||
fn retract_tip(origin, hash: T::Hash) {
|
fn retract_tip(origin, hash: T::Hash) {
|
||||||
let who = ensure_signed(origin)?;
|
let who = ensure_signed(origin)?;
|
||||||
let tip = Tips::<T>::get(&hash).ok_or(Error::<T>::UnknownTip)?;
|
let tip = Tips::<T, I>::get(&hash).ok_or(Error::<T, I>::UnknownTip)?;
|
||||||
ensure!(tip.finder == who, Error::<T>::NotFinder);
|
ensure!(tip.finder == who, Error::<T, I>::NotFinder);
|
||||||
|
|
||||||
Reasons::<T>::remove(&tip.reason);
|
Reasons::<T, I>::remove(&tip.reason);
|
||||||
Tips::<T>::remove(&hash);
|
Tips::<T, I>::remove(&hash);
|
||||||
if !tip.deposit.is_zero() {
|
if !tip.deposit.is_zero() {
|
||||||
let _ = T::Currency::unreserve(&who, tip.deposit);
|
let _ = T::Currency::unreserve(&who, tip.deposit);
|
||||||
}
|
}
|
||||||
@@ -535,14 +541,14 @@ decl_module! {
|
|||||||
+ 4_000 * reason.len() as Weight
|
+ 4_000 * reason.len() as Weight
|
||||||
+ 480_000 * T::Tippers::max_len() as Weight
|
+ 480_000 * T::Tippers::max_len() as Weight
|
||||||
+ T::DbWeight::get().reads_writes(2, 2)]
|
+ T::DbWeight::get().reads_writes(2, 2)]
|
||||||
fn tip_new(origin, reason: Vec<u8>, who: T::AccountId, tip_value: BalanceOf<T>) {
|
fn tip_new(origin, reason: Vec<u8>, who: T::AccountId, tip_value: BalanceOf<T, I>) {
|
||||||
let tipper = ensure_signed(origin)?;
|
let tipper = ensure_signed(origin)?;
|
||||||
ensure!(T::Tippers::contains(&tipper), BadOrigin);
|
ensure!(T::Tippers::contains(&tipper), BadOrigin);
|
||||||
let reason_hash = T::Hashing::hash(&reason[..]);
|
let reason_hash = T::Hashing::hash(&reason[..]);
|
||||||
ensure!(!Reasons::<T>::contains_key(&reason_hash), Error::<T>::AlreadyKnown);
|
ensure!(!Reasons::<T, I>::contains_key(&reason_hash), Error::<T, I>::AlreadyKnown);
|
||||||
let hash = T::Hashing::hash_of(&(&reason_hash, &who));
|
let hash = T::Hashing::hash_of(&(&reason_hash, &who));
|
||||||
|
|
||||||
Reasons::<T>::insert(&reason_hash, &reason);
|
Reasons::<T, I>::insert(&reason_hash, &reason);
|
||||||
Self::deposit_event(RawEvent::NewTip(hash.clone()));
|
Self::deposit_event(RawEvent::NewTip(hash.clone()));
|
||||||
let tips = vec![(tipper.clone(), tip_value)];
|
let tips = vec![(tipper.clone(), tip_value)];
|
||||||
let tip = OpenTip {
|
let tip = OpenTip {
|
||||||
@@ -554,7 +560,7 @@ decl_module! {
|
|||||||
tips,
|
tips,
|
||||||
finders_fee: false,
|
finders_fee: false,
|
||||||
};
|
};
|
||||||
Tips::<T>::insert(&hash, tip);
|
Tips::<T, I>::insert(&hash, tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declare a tip value for an already-open tip.
|
/// Declare a tip value for an already-open tip.
|
||||||
@@ -584,15 +590,15 @@ decl_module! {
|
|||||||
/// # </weight>
|
/// # </weight>
|
||||||
#[weight = 68_000_000 + 2_000_000 * T::Tippers::max_len() as Weight
|
#[weight = 68_000_000 + 2_000_000 * T::Tippers::max_len() as Weight
|
||||||
+ T::DbWeight::get().reads_writes(2, 1)]
|
+ T::DbWeight::get().reads_writes(2, 1)]
|
||||||
fn tip(origin, hash: T::Hash, tip_value: BalanceOf<T>) {
|
fn tip(origin, hash: T::Hash, tip_value: BalanceOf<T, I>) {
|
||||||
let tipper = ensure_signed(origin)?;
|
let tipper = ensure_signed(origin)?;
|
||||||
ensure!(T::Tippers::contains(&tipper), BadOrigin);
|
ensure!(T::Tippers::contains(&tipper), BadOrigin);
|
||||||
|
|
||||||
let mut tip = Tips::<T>::get(hash).ok_or(Error::<T>::UnknownTip)?;
|
let mut tip = Tips::<T, I>::get(hash).ok_or(Error::<T, I>::UnknownTip)?;
|
||||||
if Self::insert_tip_and_check_closing(&mut tip, tipper, tip_value) {
|
if Self::insert_tip_and_check_closing(&mut tip, tipper, tip_value) {
|
||||||
Self::deposit_event(RawEvent::TipClosing(hash.clone()));
|
Self::deposit_event(RawEvent::TipClosing(hash.clone()));
|
||||||
}
|
}
|
||||||
Tips::<T>::insert(&hash, tip);
|
Tips::<T, I>::insert(&hash, tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close and payout a tip.
|
/// Close and payout a tip.
|
||||||
@@ -617,12 +623,12 @@ decl_module! {
|
|||||||
fn close_tip(origin, hash: T::Hash) {
|
fn close_tip(origin, hash: T::Hash) {
|
||||||
ensure_signed(origin)?;
|
ensure_signed(origin)?;
|
||||||
|
|
||||||
let tip = Tips::<T>::get(hash).ok_or(Error::<T>::UnknownTip)?;
|
let tip = Tips::<T, I>::get(hash).ok_or(Error::<T, I>::UnknownTip)?;
|
||||||
let n = tip.closes.as_ref().ok_or(Error::<T>::StillOpen)?;
|
let n = tip.closes.as_ref().ok_or(Error::<T, I>::StillOpen)?;
|
||||||
ensure!(system::Module::<T>::block_number() >= *n, Error::<T>::Premature);
|
ensure!(system::Module::<T>::block_number() >= *n, Error::<T, I>::Premature);
|
||||||
// closed.
|
// closed.
|
||||||
Reasons::<T>::remove(&tip.reason);
|
Reasons::<T, I>::remove(&tip.reason);
|
||||||
Tips::<T>::remove(hash);
|
Tips::<T, I>::remove(hash);
|
||||||
Self::payout_tip(hash, tip);
|
Self::payout_tip(hash, tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,7 +653,7 @@ decl_module! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Trait> Module<T> {
|
impl<T: Trait<I>, I: Instance> Module<T, I> {
|
||||||
// Add public immutables and private mutables.
|
// Add public immutables and private mutables.
|
||||||
|
|
||||||
/// The account ID of the treasury pot.
|
/// The account ID of the treasury pot.
|
||||||
@@ -659,7 +665,7 @@ impl<T: Trait> Module<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The needed bond for a proposal whose spend is `value`.
|
/// The needed bond for a proposal whose spend is `value`.
|
||||||
fn calculate_bond(value: BalanceOf<T>) -> BalanceOf<T> {
|
fn calculate_bond(value: BalanceOf<T, I>) -> BalanceOf<T, I> {
|
||||||
T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value)
|
T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,9 +674,9 @@ impl<T: Trait> Module<T> {
|
|||||||
///
|
///
|
||||||
/// `O(T)` and one storage access.
|
/// `O(T)` and one storage access.
|
||||||
fn insert_tip_and_check_closing(
|
fn insert_tip_and_check_closing(
|
||||||
tip: &mut OpenTip<T::AccountId, BalanceOf<T>, T::BlockNumber, T::Hash>,
|
tip: &mut OpenTip<T::AccountId, BalanceOf<T, I>, T::BlockNumber, T::Hash>,
|
||||||
tipper: T::AccountId,
|
tipper: T::AccountId,
|
||||||
tip_value: BalanceOf<T>,
|
tip_value: BalanceOf<T, I>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match tip.tips.binary_search_by_key(&&tipper, |x| &x.0) {
|
match tip.tips.binary_search_by_key(&&tipper, |x| &x.0) {
|
||||||
Ok(pos) => tip.tips[pos] = (tipper, tip_value),
|
Ok(pos) => tip.tips[pos] = (tipper, tip_value),
|
||||||
@@ -687,7 +693,7 @@ impl<T: Trait> Module<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove any non-members of `Tippers` from a `tips` vector. `O(T)`.
|
/// Remove any non-members of `Tippers` from a `tips` vector. `O(T)`.
|
||||||
fn retain_active_tips(tips: &mut Vec<(T::AccountId, BalanceOf<T>)>) {
|
fn retain_active_tips(tips: &mut Vec<(T::AccountId, BalanceOf<T, I>)>) {
|
||||||
let members = T::Tippers::sorted_members();
|
let members = T::Tippers::sorted_members();
|
||||||
let mut members_iter = members.iter();
|
let mut members_iter = members.iter();
|
||||||
let mut member = members_iter.next();
|
let mut member = members_iter.next();
|
||||||
@@ -711,7 +717,7 @@ impl<T: Trait> Module<T> {
|
|||||||
///
|
///
|
||||||
/// Up to three balance operations.
|
/// Up to three balance operations.
|
||||||
/// Plus `O(T)` (`T` is Tippers length).
|
/// Plus `O(T)` (`T` is Tippers length).
|
||||||
fn payout_tip(hash: T::Hash, tip: OpenTip<T::AccountId, BalanceOf<T>, T::BlockNumber, T::Hash>) {
|
fn payout_tip(hash: T::Hash, tip: OpenTip<T::AccountId, BalanceOf<T, I>, T::BlockNumber, T::Hash>) {
|
||||||
let mut tips = tip.tips;
|
let mut tips = tip.tips;
|
||||||
Self::retain_active_tips(&mut tips);
|
Self::retain_active_tips(&mut tips);
|
||||||
tips.sort_by_key(|i| i.1);
|
tips.sort_by_key(|i| i.1);
|
||||||
@@ -742,15 +748,15 @@ impl<T: Trait> Module<T> {
|
|||||||
Self::deposit_event(RawEvent::Spending(budget_remaining));
|
Self::deposit_event(RawEvent::Spending(budget_remaining));
|
||||||
|
|
||||||
let mut missed_any = false;
|
let mut missed_any = false;
|
||||||
let mut imbalance = <PositiveImbalanceOf<T>>::zero();
|
let mut imbalance = <PositiveImbalanceOf<T, I>>::zero();
|
||||||
let prior_approvals_len = Approvals::mutate(|v| {
|
let prior_approvals_len = <Approvals<I>>::mutate(|v| {
|
||||||
let prior_approvals_len = v.len() as u64;
|
let prior_approvals_len = v.len() as u64;
|
||||||
v.retain(|&index| {
|
v.retain(|&index| {
|
||||||
// Should always be true, but shouldn't panic if false or we're screwed.
|
// Should always be true, but shouldn't panic if false or we're screwed.
|
||||||
if let Some(p) = Self::proposals(index) {
|
if let Some(p) = Self::proposals(index) {
|
||||||
if p.value <= budget_remaining {
|
if p.value <= budget_remaining {
|
||||||
budget_remaining -= p.value;
|
budget_remaining -= p.value;
|
||||||
<Proposals<T>>::remove(index);
|
<Proposals<T, I>>::remove(index);
|
||||||
|
|
||||||
// return their deposit.
|
// return their deposit.
|
||||||
let _ = T::Currency::unreserve(&p.proposer, p.bond);
|
let _ = T::Currency::unreserve(&p.proposer, p.bond);
|
||||||
@@ -804,7 +810,7 @@ impl<T: Trait> Module<T> {
|
|||||||
|
|
||||||
/// Return the amount of money in the pot.
|
/// Return the amount of money in the pot.
|
||||||
// The existential deposit is not part of the pot so treasury account never gets deleted.
|
// The existential deposit is not part of the pot so treasury account never gets deleted.
|
||||||
fn pot() -> BalanceOf<T> {
|
fn pot() -> BalanceOf<T, I> {
|
||||||
T::Currency::free_balance(&Self::account_id())
|
T::Currency::free_balance(&Self::account_id())
|
||||||
// Must never be less than 0 but better be safe.
|
// Must never be less than 0 but better be safe.
|
||||||
.saturating_sub(T::Currency::minimum_balance())
|
.saturating_sub(T::Currency::minimum_balance())
|
||||||
@@ -838,9 +844,9 @@ impl<T: Trait> Module<T> {
|
|||||||
|
|
||||||
for (hash, old_tip) in StorageKeyIterator::<
|
for (hash, old_tip) in StorageKeyIterator::<
|
||||||
T::Hash,
|
T::Hash,
|
||||||
OldOpenTip<T::AccountId, BalanceOf<T>, T::BlockNumber, T::Hash>,
|
OldOpenTip<T::AccountId, BalanceOf<T, I>, T::BlockNumber, T::Hash>,
|
||||||
Twox64Concat,
|
Twox64Concat,
|
||||||
>::new(b"Treasury", b"Tips").drain()
|
>::new(I::PREFIX.as_bytes(), b"Tips").drain()
|
||||||
{
|
{
|
||||||
let (finder, deposit, finders_fee) = match old_tip.finder {
|
let (finder, deposit, finders_fee) = match old_tip.finder {
|
||||||
Some((finder, deposit)) => (finder, deposit, true),
|
Some((finder, deposit)) => (finder, deposit, true),
|
||||||
@@ -855,13 +861,13 @@ impl<T: Trait> Module<T> {
|
|||||||
tips: old_tip.tips,
|
tips: old_tip.tips,
|
||||||
finders_fee
|
finders_fee
|
||||||
};
|
};
|
||||||
Tips::<T>::insert(hash, new_tip)
|
Tips::<T, I>::insert(hash, new_tip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Trait> OnUnbalanced<NegativeImbalanceOf<T>> for Module<T> {
|
impl<T: Trait<I>, I: Instance> OnUnbalanced<NegativeImbalanceOf<T, I>> for Module<T, I> {
|
||||||
fn on_nonzero_unbalanced(amount: NegativeImbalanceOf<T>) {
|
fn on_nonzero_unbalanced(amount: NegativeImbalanceOf<T, I>) {
|
||||||
let numeric_amount = amount.peek();
|
let numeric_amount = amount.peek();
|
||||||
|
|
||||||
// Must resolve into existing but better to be safe.
|
// Must resolve into existing but better to be safe.
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
|||||||
// Total issuance will be 200 with treasury account initialized at ED.
|
// Total issuance will be 200 with treasury account initialized at ED.
|
||||||
balances: vec![(0, 100), (1, 98), (2, 1)],
|
balances: vec![(0, 100), (1, 98), (2, 1)],
|
||||||
}.assimilate_storage(&mut t).unwrap();
|
}.assimilate_storage(&mut t).unwrap();
|
||||||
GenesisConfig::default().assimilate_storage::<Test>(&mut t).unwrap();
|
GenesisConfig::default().assimilate_storage::<Test, _>(&mut t).unwrap();
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ fn tip_new_cannot_be_used_twice() {
|
|||||||
assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10));
|
assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10));
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Treasury::tip_new(Origin::signed(11), b"awesome.dot".to_vec(), 3, 10),
|
Treasury::tip_new(Origin::signed(11), b"awesome.dot".to_vec(), 3, 10),
|
||||||
Error::<Test>::AlreadyKnown
|
Error::<Test, _>::AlreadyKnown
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ fn report_awesome_and_tip_works() {
|
|||||||
// other reports don't count.
|
// other reports don't count.
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Treasury::report_awesome(Origin::signed(1), b"awesome.dot".to_vec(), 3),
|
Treasury::report_awesome(Origin::signed(1), b"awesome.dot".to_vec(), 3),
|
||||||
Error::<Test>::AlreadyKnown
|
Error::<Test, _>::AlreadyKnown
|
||||||
);
|
);
|
||||||
|
|
||||||
let h = tip_hash();
|
let h = tip_hash();
|
||||||
@@ -259,7 +259,7 @@ fn close_tip_works() {
|
|||||||
|
|
||||||
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
||||||
|
|
||||||
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test>::StillOpen);
|
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test, _>::StillOpen);
|
||||||
|
|
||||||
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ fn close_tip_works() {
|
|||||||
RawEvent::TipClosing(h),
|
RawEvent::TipClosing(h),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test>::Premature);
|
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test, _>::Premature);
|
||||||
|
|
||||||
System::set_block_number(2);
|
System::set_block_number(2);
|
||||||
assert_noop!(Treasury::close_tip(Origin::none(), h.into()), BadOrigin);
|
assert_noop!(Treasury::close_tip(Origin::none(), h.into()), BadOrigin);
|
||||||
@@ -290,7 +290,7 @@ fn close_tip_works() {
|
|||||||
RawEvent::TipClosed(h, 3, 10),
|
RawEvent::TipClosed(h, 3, 10),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_noop!(Treasury::close_tip(Origin::signed(100), h.into()), Error::<Test>::UnknownTip);
|
assert_noop!(Treasury::close_tip(Origin::signed(100), h.into()), Error::<Test, _>::UnknownTip);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,10 +304,10 @@ fn retract_tip_works() {
|
|||||||
assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10));
|
||||||
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
||||||
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
||||||
assert_noop!(Treasury::retract_tip(Origin::signed(10), h.clone()), Error::<Test>::NotFinder);
|
assert_noop!(Treasury::retract_tip(Origin::signed(10), h.clone()), Error::<Test, _>::NotFinder);
|
||||||
assert_ok!(Treasury::retract_tip(Origin::signed(0), h.clone()));
|
assert_ok!(Treasury::retract_tip(Origin::signed(0), h.clone()));
|
||||||
System::set_block_number(2);
|
System::set_block_number(2);
|
||||||
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test>::UnknownTip);
|
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test, _>::UnknownTip);
|
||||||
|
|
||||||
// with tip new
|
// with tip new
|
||||||
Balances::make_free_balance_be(&Treasury::account_id(), 101);
|
Balances::make_free_balance_be(&Treasury::account_id(), 101);
|
||||||
@@ -315,10 +315,10 @@ fn retract_tip_works() {
|
|||||||
let h = tip_hash();
|
let h = tip_hash();
|
||||||
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
||||||
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
||||||
assert_noop!(Treasury::retract_tip(Origin::signed(0), h.clone()), Error::<Test>::NotFinder);
|
assert_noop!(Treasury::retract_tip(Origin::signed(0), h.clone()), Error::<Test, _>::NotFinder);
|
||||||
assert_ok!(Treasury::retract_tip(Origin::signed(10), h.clone()));
|
assert_ok!(Treasury::retract_tip(Origin::signed(10), h.clone()));
|
||||||
System::set_block_number(2);
|
System::set_block_number(2);
|
||||||
assert_noop!(Treasury::close_tip(Origin::signed(10), h.into()), Error::<Test>::UnknownTip);
|
assert_noop!(Treasury::close_tip(Origin::signed(10), h.into()), Error::<Test, _>::UnknownTip);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +387,7 @@ fn spend_proposal_fails_when_proposer_poor() {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Treasury::propose_spend(Origin::signed(2), 100, 3),
|
Treasury::propose_spend(Origin::signed(2), 100, 3),
|
||||||
Error::<Test>::InsufficientProposersBalance,
|
Error::<Test, _>::InsufficientProposersBalance,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -440,21 +440,30 @@ fn reject_already_rejected_spend_proposal_fails() {
|
|||||||
|
|
||||||
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
|
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
|
||||||
assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
|
assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
|
||||||
assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
|
assert_noop!(
|
||||||
|
Treasury::reject_proposal(Origin::root(), 0),
|
||||||
|
Error::<Test, _>::InvalidProposalIndex,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_non_existent_spend_proposal_fails() {
|
fn reject_non_existent_spend_proposal_fails() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
|
assert_noop!(
|
||||||
|
Treasury::reject_proposal(Origin::root(), 0),
|
||||||
|
Error::<Test, _>::InvalidProposalIndex,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accept_non_existent_spend_proposal_fails() {
|
fn accept_non_existent_spend_proposal_fails() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
|
assert_noop!(
|
||||||
|
Treasury::approve_proposal(Origin::root(), 0),
|
||||||
|
Error::<Test, _>::InvalidProposalIndex,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +474,10 @@ fn accept_already_rejected_spend_proposal_fails() {
|
|||||||
|
|
||||||
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
|
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
|
||||||
assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
|
assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
|
||||||
assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
|
assert_noop!(
|
||||||
|
Treasury::approve_proposal(Origin::root(), 0),
|
||||||
|
Error::<Test, _>::InvalidProposalIndex,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user