Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Pallets: Treasury spend() should use Pay trait #13607

Closed
wants to merge 72 commits into from
Closed
Changes from 5 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
a027594
pallet_treasury: implement treasury pallet over the pay trait in pall…
tonyalaribe Mar 15, 2023
29194c3
update the new spend logic to exist parallel to original spend logic
tonyalaribe Mar 15, 2023
11cd988
clean up imports diffs
tonyalaribe Mar 16, 2023
57aacbe
switch to using the pay trait in frame support
tonyalaribe Mar 16, 2023
67b9f7a
remove the changes to the build genesis config method
tonyalaribe Mar 16, 2023
2b20924
fix some type errors
tonyalaribe Mar 16, 2023
3602844
add a test for the new spend workflow
tonyalaribe Mar 16, 2023
dd99d7c
implement initial tests for the new spend workflow
tonyalaribe Mar 16, 2023
5f52015
remove unneeded Balance type from Confg
tonyalaribe Mar 16, 2023
1925806
Update lib.rs
tonyalaribe Mar 22, 2023
f94e20a
introduce a unit implementation for BalanceConversion which behaves a…
tonyalaribe Mar 22, 2023
293552f
Merge branch 'aa/multi-asset-support-in-treasury' of github.com:parit…
tonyalaribe Mar 22, 2023
a88fb24
Merge branch 'master' into aa/multi-asset-support-in-treasury
tonyalaribe Mar 22, 2023
3aaed66
fix rebase introduced error
tonyalaribe Mar 22, 2023
a33d4dc
fix broken tests due to rebase
tonyalaribe Mar 22, 2023
414e8e2
fix tests in tips and bounties
tonyalaribe Mar 22, 2023
2f60a1b
fix lint error for unused fn argument in Pay trait
tonyalaribe Mar 22, 2023
182c733
fix tests in child-bounties pallet
tonyalaribe Mar 22, 2023
0916aff
remove unneeded DummyBalanceConverter
tonyalaribe Mar 22, 2023
fdcd66a
Update frame/bounties/src/tests.rs
tonyalaribe Mar 23, 2023
5673e79
Update frame/bounties/src/tests.rs
tonyalaribe Mar 23, 2023
c6f9c5a
Update frame/treasury/src/lib.rs
tonyalaribe Mar 23, 2023
bb372a2
tiny cleanups
tonyalaribe Mar 27, 2023
a56897d
rename asset_id to asset_kind and proposal
tonyalaribe Mar 27, 2023
69cc489
Merge branch 'aa/multi-asset-support-in-treasury' of github.com:parit…
tonyalaribe Mar 27, 2023
e07ee86
Update frame/treasury/src/lib.rs
tonyalaribe Mar 27, 2023
304f536
implememt PR feedback
tonyalaribe Mar 27, 2023
e7ecdbf
update doc comments
tonyalaribe Mar 27, 2023
e689272
Merge branch 'aa/multi-asset-support-in-treasury' of github.com:parit…
tonyalaribe Mar 27, 2023
3cd5760
include correct weight funchtion
tonyalaribe Mar 27, 2023
d97886d
add spend_local to weight.rs
tonyalaribe Mar 27, 2023
805d595
benchmarking updates
tonyalaribe Mar 27, 2023
bbf83fa
rename Treasury1Account to TreasuryAccount1
tonyalaribe Mar 30, 2023
8aa1c3c
update PendingPayment storage comment
tonyalaribe Mar 30, 2023
aabfadf
update PendingPayment storage comment
tonyalaribe Mar 30, 2023
592b81b
adjust naming of Events to not mix PendingPayment and Proposal concepts
tonyalaribe Mar 30, 2023
b295ea7
adjust tests to check more cases
tonyalaribe Mar 30, 2023
1e85a67
benchmarking update
tonyalaribe Apr 3, 2023
eb4b2fe
make benchmarks pass
tonyalaribe Apr 4, 2023
1fdccb7
Merge remote-tracking branch 'origin/master' into aa/multi-asset-supp…
Apr 4, 2023
310578d
update BalanceConverter to use ConversionFromAssetBalance trait
tonyalaribe Apr 4, 2023
22e43a1
Add BenchmarkHelper to runtimes in dependent pallets
tonyalaribe Apr 4, 2023
d96d541
Update frame/treasury/src/lib.rs
tonyalaribe Apr 4, 2023
dc891cb
Update frame/treasury/src/lib.rs
tonyalaribe Apr 4, 2023
3bd3c8e
add benchmark helper to tips
tonyalaribe Apr 5, 2023
1018464
Merge branch 'aa/multi-asset-support-in-treasury' of github.com:parit…
tonyalaribe Apr 5, 2023
c04955d
add From<u32> for ()
tonyalaribe Apr 5, 2023
b5b5d0e
introduce NilBenchmarkHelper for unit asset ids
tonyalaribe Apr 5, 2023
65c71a0
remove comment
tonyalaribe Apr 5, 2023
62b0901
Merge remote-tracking branch 'origin/master' into aa/multi-asset-supp…
Apr 14, 2023
5750f0b
add debug log for pay errors; Pay trait should support an error type
tonyalaribe Apr 20, 2023
e26dee6
add error associated type to Salary pallet test pay impl
tonyalaribe Apr 20, 2023
0739c29
fix fmt error
tonyalaribe Apr 21, 2023
ac27c84
Merge remote-tracking branch 'origin/master' into aa/multi-asset-supp…
Apr 21, 2023
87b905c
Trigger CI
tonyalaribe Apr 21, 2023
5bc0af9
Trigger CI
tonyalaribe Apr 21, 2023
1fca0e9
add a debug log for when Paymaster::check_payment returns failure
tonyalaribe Apr 28, 2023
7d712e2
add payment_id to events
tonyalaribe Apr 28, 2023
db02823
Merge remote-tracking branch 'origin/master' into aa/multi-asset-supp…
May 5, 2023
415561d
Trigger companion CI
tonyalaribe May 5, 2023
449d484
Trigger companion CI
tonyalaribe May 5, 2023
4741037
Trigger Companion CI
tonyalaribe May 5, 2023
9cad108
Trigger Companion CI
tonyalaribe May 5, 2023
b644329
Trigger Companion CI
tonyalaribe May 5, 2023
8a9903b
Trigger Companion CI
tonyalaribe May 5, 2023
f07e8b0
Trigger Companion CI
tonyalaribe May 5, 2023
34c859b
support vector of assets for treasury spend
tonyalaribe May 30, 2023
9237568
Merge branch 'master' into aa/multi-asset-support-in-treasury
tonyalaribe May 30, 2023
1ecd8cc
Merge branch 'aa/multi-asset-support-in-treasury' of github.com:parit…
tonyalaribe May 30, 2023
c029123
fix types on child-bounties and tips
tonyalaribe May 30, 2023
83a2097
switch node template to use SimpleAsset
tonyalaribe May 30, 2023
d79cab0
Merge branch 'master' into aa/multi-asset-support-in-treasury
gavofyork Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 231 additions & 14 deletions frame/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use frame_support::{
print,
traits::{
Currency, ExistenceRequirement::KeepAlive, Get, Imbalance, OnUnbalanced,
ReservableCurrency, WithdrawReasons,
tokens::{Balance, BalanceConversion, Pay, PaymentStatus},
Currency,
ExistenceRequirement::KeepAlive,
Get, Imbalance, OnUnbalanced, ReservableCurrency, WithdrawReasons,
},
weights::Weight,
PalletId,
Expand All @@ -85,6 +87,7 @@ use frame_support::{
pub use pallet::*;
pub use weights::WeightInfo;

pub type PayBalanceOf<T, I> = <<T as Config<I>>::Paymaster as Pay>::Balance;
pub type BalanceOf<T, I = ()> =
<<T as Config<I>>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
pub type PositiveImbalanceOf<T, I = ()> = <<T as Config<I>>::Currency as Currency<
Expand All @@ -93,6 +96,7 @@ pub type PositiveImbalanceOf<T, I = ()> = <<T as Config<I>>::Currency as Currenc
pub type NegativeImbalanceOf<T, I = ()> = <<T as Config<I>>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;

type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;

/// A trait to allow the Treasury Pallet to spend it's funds for other purposes.
Expand All @@ -107,7 +111,7 @@ type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup
/// * `missed_any`: If there were items that you want to spend on, but there were not enough funds,
/// mark this value as `true`. This will prevent the treasury from burning the excess funds.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait SpendFunds<T: Config<I>, I: 'static = ()> {
pub trait SpendFundsLocal<T: Config<I>, I: 'static = ()> {
fn spend_funds(
budget_remaining: &mut BalanceOf<T, I>,
imbalance: &mut PositiveImbalanceOf<T, I>,
Expand All @@ -116,8 +120,15 @@ pub trait SpendFunds<T: Config<I>, I: 'static = ()> {
);
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait SpendFunds<T: Config<I>, I: 'static = ()> {
fn spend_funds(total_weight: &mut Weight, total_spent: T::Balance, total_missed: u32);
}

/// An index of a proposal. Just a `u32`.
pub type ProposalIndex = u32;
/// A count of proposals. Just a `u32`.
pub type ProposalsCount = u32;

/// A spending proposal.
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
Expand All @@ -133,10 +144,30 @@ pub struct Proposal<AccountId, Balance> {
bond: Balance,
}

/// A spending proposal.
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
#[derive(Encode, Decode, Clone, PartialEq, Eq, MaxEncodedLen, RuntimeDebug, TypeInfo)]
pub struct PendingPayment<AccountId, Balance, AssetKind, AssetBalance, PaymentId> {
/// The account proposing it.
proposer: AccountId,
/// The asset_id of the amount to be paid
asset_id: AssetKind,
/// The (total) amount that should be paid.
value: AssetBalance,
/// The account to whom the payment should be made if the proposal is accepted.
beneficiary: AccountId,
/// The amount to be paid, but normalized to the native asset class
normalized_value: Balance,
// payment_status: PaymentStatus,
payment_id: Option<PaymentId>,
}

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::{dispatch_context::with_context, pallet_prelude::*};
use frame_support::{
dispatch_context::with_context, pallet_prelude::*, traits::tokens::AssetId,
};
use frame_system::pallet_prelude::*;

#[pallet::pallet]
Expand All @@ -153,6 +184,25 @@ pub mod pallet {
/// Origin from which rejections must come.
type RejectOrigin: EnsureOrigin<Self::RuntimeOrigin>;

type Balance: Balance;

/// The identifier for what asset should be spent.
type AssetKind: AssetId;

/// Means by which we can make payments to accounts. This also defines the currency and the
/// balance which we use to denote that currency.
type Paymaster: Pay<
Beneficiary = <Self as frame_system::Config>::AccountId,
AssetKind = Self::AssetKind,
>;

type BalanceConverter: BalanceConversion<
PayBalanceOf<Self, I>,
Self::AssetKind,
Self::Balance,
Error = Error<Self, I>,
>;

/// The overarching event type.
type RuntimeEvent: From<Event<Self, I>>
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
Expand Down Expand Up @@ -194,6 +244,9 @@ pub mod pallet {
/// Runtime hooks to external pallet using treasury to compute spend funds.
type SpendFunds: SpendFunds<Self, I>;

/// Runtime hooks to external pallet using treasury to compute spend funds.
type SpendFundsLocal: SpendFundsLocal<Self, I>;

/// The maximum number of approvals that can wait in the spending queue.
///
/// NOTE: This parameter is also used within the Bounties Pallet extension if enabled.
Expand All @@ -203,7 +256,12 @@ pub mod pallet {
/// The origin required for approving spends from the treasury outside of the proposal
/// process. The `Success` value is the maximum amount that this origin is allowed to
/// spend at a time.
type SpendOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = BalanceOf<Self, I>>;
type SpendOriginLocal: EnsureOrigin<Self::RuntimeOrigin, Success = BalanceOf<Self, I>>;

/// The origin required for approving spends from the treasury outside of the proposal
/// process. The `Success` value is the maximum amount that this origin is allowed to
/// spend at a time.
type SpendOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = PayBalanceOf<Self, I>>;
}

/// Number of proposals that have been made.
Expand All @@ -222,6 +280,23 @@ pub mod pallet {
OptionQuery,
>;

/// Proposals that have been made.
#[pallet::storage]
#[pallet::getter(fn pending_payments)]
pub type PendingPayments<T: Config<I>, I: 'static = ()> = CountedStorageMap<
_,
Twox64Concat,
ProposalIndex,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

legacy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept it as ProposalIndex because of #13607 (comment)
As opposed to introducing a new type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but why the alternative would be ProposalCount?
there are no proposals for new flow, but pending payments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time when that comment was made, the count was used for the Proposals storage map. a027594#diff-21571fa193fececabaa733a8fea9e3c6478e1cdcb86f58e3f325418b2555e81aR237

I could introduce PendingPaymentsCount type, but the type going to be a u32 as well, just like ProposalIndex. But yeah, it's likely a good idea for clarity in the code. Though i'll call it PendingPaymentsIndex for consistency.

PendingPayment<
T::AccountId,
T::Balance,
T::AssetKind,
PayBalanceOf<T, I>,
<T::Paymaster as Pay>::Id,
>,
OptionQuery,
>;

/// The amount which has been reported as inactive to Currency.
#[pallet::storage]
pub type Deactivated<T: Config<I>, I: 'static = ()> =
Expand Down Expand Up @@ -286,14 +361,36 @@ pub mod pallet {
Rollover { rollover_balance: BalanceOf<T, I> },
/// Some funds have been deposited.
Deposit { value: BalanceOf<T, I> },
/// We have ended a spend period and will now allocate funds.
ProcessingProposals { waiting_proposals: ProposalIndex },
/// Spending has finished; this is the number of proposals rolled over till next
/// T::SpendPeriod.
RolloverPayments { rollover_proposals: ProposalsCount, allocated_proposals: ProposalsCount },
/// A new spend proposal has been approved.
SpendApproved {
proposal_index: ProposalIndex,
amount: BalanceOf<T, I>,
beneficiary: T::AccountId,
},
QueuedPayment {
proposal_index: ProposalIndex,
amount: PayBalanceOf<T, I>,
beneficiary: T::AccountId,
},
/// The inactive funds of the pallet have been updated.
UpdatedInactive { reactivated: BalanceOf<T, I>, deactivated: BalanceOf<T, I> },
/// The proposal was paid successfully
ProposalPaymentSuccess {
proposal_index: ProposalIndex,
asset_id: T::AssetKind,
amount: PayBalanceOf<T, I>,
},
// The proposal payment failed. Payment will be retried in next spend period.
ProposalPaymentFailure {
proposal_index: ProposalIndex,
asset_id: T::AssetKind,
amount: PayBalanceOf<T, I>,
},
}

/// Error for the treasury pallet.
Expand All @@ -310,6 +407,8 @@ pub mod pallet {
InsufficientPermission,
/// Proposal has not been approved.
ProposalNotApproved,
/// Unable to convert asset to native balance
BalanceConversionFailed,
}

#[pallet::hooks]
Expand All @@ -328,10 +427,9 @@ pub mod pallet {
deactivated: pot,
});
}

// Check to see if we should spend some funds!
if (n % T::SpendPeriod::get()).is_zero() {
Self::spend_funds()
Self::spend_funds().saturating_add(Self::spend_funds_local())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there might be not enough weight capacity left for spend_funds_local .
and spend period might be quite long, for polkadot it is 24 days.

} else {
Weight::zero()
}
Expand Down Expand Up @@ -431,29 +529,25 @@ pub mod pallet {
/// beneficiary.
#[pallet::call_index(3)]
#[pallet::weight(T::WeightInfo::spend())]
pub fn spend(
pub fn spend_local(
origin: OriginFor<T>,
#[pallet::compact] amount: BalanceOf<T, I>,
beneficiary: AccountIdLookupOf<T>,
) -> DispatchResult {
let max_amount = T::SpendOrigin::ensure_origin(origin)?;
let max_amount = T::SpendOriginLocal::ensure_origin(origin)?;
ensure!(amount <= max_amount, Error::<T, I>::InsufficientPermission);

with_context::<SpendContext<BalanceOf<T, I>>, _>(|v| {
let context = v.or_default();

// We group based on `max_amount`, to dinstinguish between different kind of
// origins. (assumes that all origins have different `max_amount`)
//
// Worst case is that we reject some "valid" request.
let spend = context.spend_in_context.entry(max_amount).or_default();

// Ensure that we don't overflow nor use more than `max_amount`
if spend.checked_add(&amount).map(|s| s > max_amount).unwrap_or(true) {
Err(Error::<T, I>::InsufficientPermission)
} else {
*spend = spend.saturating_add(amount);

Ok(())
}
})
Expand All @@ -476,6 +570,63 @@ pub mod pallet {
Ok(())
}

/// Propose and approve a spend of treasury funds.
///
/// - `origin`: Must be `SpendOrigin` with the `Success` value being at least `amount`.
/// - `amount`: The amount to be transferred from the treasury to the `beneficiary`.
/// - `beneficiary`: The destination account for the transfer.
///
/// NOTE: For record-keeping purposes, the proposer is deemed to be equivalent to the
/// beneficiary.
#[pallet::call_index(5)]
#[pallet::weight(T::WeightInfo::spend())]
pub fn spend(
origin: OriginFor<T>,
asset_id: T::AssetKind,
#[pallet::compact] amount: PayBalanceOf<T, I>,
beneficiary: AccountIdLookupOf<T>,
) -> DispatchResult {
let max_amount = T::SpendOrigin::ensure_origin(origin)?;
ensure!(amount <= max_amount, Error::<T, I>::InsufficientPermission);

with_context::<SpendContext<PayBalanceOf<T, I>>, _>(|v| {
let context = v.or_default();

// We group based on `max_amount`, to dinstinguish between different kind of
// origins. (assumes that all origins have different `max_amount`)
//
// Worst case is that we reject some "valid" request.
let spend = context.spend_in_context.entry(max_amount).or_default();

// Ensure that we don't overflow nor use more than `max_amount`
if spend.checked_add(&amount).map(|s| s > max_amount).unwrap_or(true) {
Err(Error::<T, I>::InsufficientPermission)
} else {
*spend = spend.saturating_add(amount);

Ok(())
}
})
.unwrap_or(Ok(()))?;

let beneficiary = T::Lookup::lookup(beneficiary)?;

let proposal = PendingPayment {
proposer: beneficiary.clone(),
asset_id,
value: amount,
beneficiary: beneficiary.clone(),
normalized_value: T::BalanceConverter::to_asset_balance(amount, asset_id)?,
payment_id: None,
};

let proposal_index = PendingPayments::<T, I>::count();
PendingPayments::<T, I>::insert(proposal_index, proposal);

Self::deposit_event(Event::QueuedPayment { proposal_index, amount, beneficiary });
Ok(())
}

/// Force a previously approved proposal to be removed from the approval queue.
/// The original deposit will no longer be returned.
///
Expand Down Expand Up @@ -534,6 +685,72 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Spend some money! returns number of approvals before spend.
pub fn spend_funds() -> Weight {
let mut total_weight = Weight::zero();
let mut total_spent = T::Balance::zero();
let mut missed_proposals: u32 = 0;
let proposals_len = PendingPayments::<T, I>::count();

Self::deposit_event(Event::ProcessingProposals { waiting_proposals: proposals_len });

for key in PendingPayments::<T, I>::iter_keys() {
if let Some(mut p) = PendingPayments::<T, I>::get(key) {
match p.payment_id {
None =>
if let Ok(id) = T::Paymaster::pay(&p.beneficiary, p.asset_id, p.value) {
total_spent += p.normalized_value;
p.payment_id = Some(id);
PendingPayments::<T, I>::set(key, Some(p));
} else {
missed_proposals = missed_proposals.saturating_add(1);
},
Some(payment_id) => match T::Paymaster::check_payment(payment_id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should be timing out after some timeout

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pallet_xcm does not timeout now. but I think it should be on both sides

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you propose?
With the current implementation, we would simply keep retrying the transaction each spend period until it succeeds, and that seems sufficient to me.

Also, the treasury pallet knows nothing about the XCM timeouts nor does it even know anything about XCM.
Eg lots of parachains will implement their treasuries using the PayFromAccount or PayFungibles implementations which have no timeouts. So i'm not convinced about adding any timeout logic into the substrate treasury implementation, as that is too specific to XCM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the treasury pallet does not need to know about XCM to have a timeout for some async status checks it does.
if for some reason it never gets some of the fail/success statuses, by this design it keeps checking the status forever.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a concept of retries, so we retry a payment a given number of times.
About the timeouts, It would only be useful in the XCM context, and in the case of XCM, when it expires, the check_payment method would return a status unknown, which we now treat as a failure, so it would fail immediately at that point. I think with that workflow, there won't be any extra utility for the timeouts, and if that use-case comes up, then we can include it in a subsequent PR.

PaymentStatus::Failure => {
// try again in the next `T::SpendPeriod`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the payment statuses should be check with a different interval, not SpendPeriod. if we separate the pay job and the check status one, we will be able to have more accurate weights for these jobs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. let me explore this more

missed_proposals = missed_proposals.saturating_add(1);
Self::deposit_event(Event::ProposalPaymentFailure {
proposal_index: key,
asset_id: p.asset_id,
amount: p.value,
});
// Force the payment to none, so a fresh payment is sent during the next
// T::SpendPeriod.
p.payment_id = None;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which means we retry endlessly, looks wrong to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no harm. This gives time for governance to solve the reason for the failure. But what would you propose?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if its not recoverable fail, how governance will solve it?

PendingPayments::<T, I>::set(key, Some(p));
},
PaymentStatus::Success => {
PendingPayments::<T, I>::remove(key);
Self::deposit_event(Event::ProposalPaymentSuccess {
proposal_index: key,
asset_id: p.asset_id,
amount: p.value,
});
},
// PaymentStatus::InProgress and PaymentStatus::Unknown indicate that the
// proposal status is inconclusive, and might still be successful or failed
// in the future.
_ => {},
},
}
} else {
}
}

total_weight += T::WeightInfo::on_initialize_proposals(proposals_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on_initialize_proposals is not relevant here


// Call Runtime hooks to external pallet using treasury to compute spend funds.
// We could trigger burning of funds in the spendFunds hook as well.
T::SpendFunds::spend_funds(&mut total_weight, total_spent, missed_proposals);

Self::deposit_event(Event::RolloverPayments {
rollover_proposals: missed_proposals,
allocated_proposals: proposals_len.saturating_sub(missed_proposals),
});

total_weight
}

/// Spend some money! returns number of approvals before spend.
pub fn spend_funds_local() -> Weight {
let mut total_weight = Weight::zero();

let mut budget_remaining = Self::pot();
Self::deposit_event(Event::Spending { budget_remaining });
Expand Down Expand Up @@ -577,7 +794,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
total_weight += T::WeightInfo::on_initialize_proposals(proposals_len);

// Call Runtime hooks to external pallet using treasury to compute spend funds.
T::SpendFunds::spend_funds(
T::SpendFundsLocal::spend_funds(
&mut budget_remaining,
&mut imbalance,
&mut total_weight,
Expand Down