-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Pallets: Treasury spend()
should use Pay
trait
#13607
Conversation
41ebd63
to
57aacbe
Compare
…s an identity function or transformation
…ytech/substrate into aa/multi-asset-support-in-treasury
}); | ||
}, | ||
}, | ||
Some(payment_id) => match T::Paymaster::check_payment(payment_id) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
frame/treasury/src/lib.rs
Outdated
"Paymaster::pay failed for PendingPayment with index: {:?}", | ||
key | ||
); | ||
// try again in the next `T::SpendPeriod`. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
frame/treasury/src/lib.rs
Outdated
}); | ||
// Force the payment to none, so a fresh payment is sent during the next | ||
// T::SpendPeriod. | ||
p.payment_id = None; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
frame/treasury/src/lib.rs
Outdated
} | ||
} | ||
|
||
total_weight += T::WeightInfo::on_initialize_pending_payments(proposals_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be checking if there is enough capacity left before executing pay, scheduler is a good example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By scheduler, what do you mean? Maybe point me to a file or code line of what you mean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scheduler pallet, jobs on_initialize
// 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()) |
There was a problem hiding this comment.
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.
create_pending_payments::<T,_>(p)?; | ||
}: { | ||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need some check here that pay was executed
@@ -138,5 +183,12 @@ benchmarks_instance_pallet! { | |||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero()); | |||
} | |||
|
|||
on_initialize_pending_payments { | |||
let p in 0 .. T::MaxApprovals::get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MaxApprovals
limit is not enforced for pending payments
<Treasury as OnInitialize<u64>>::on_initialize(2); | ||
assert_eq!(Assets::reducible_balance(0, &Treasury::account_id(), Expendable, Polite), 0); | ||
assert_eq!(Assets::reducible_balance(0, &6, Expendable, Polite), 100); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like many cases of the new functionality is not covered, would be good to have more tests
I made some larger changes to the spend method, such that it now accepts two main arguments.
The vector of assets can be anything that encodes a way to retrieve a balance from it, but in the kusama/runtimes context, it also allows us to use a type that the PayOverXcm can support. Here's a video demo of the new workflow: Polkadot_Substrate.Portal.-.26.May.2023.mp4 |
Why a vec of assets? This introduces problematic edge cases - e.g. what happens if one asset can be transferred, but another later fails? A pallet/user can always make a batch of spend calls. |
Can you make a separate PR for the alterations to EDIT: Done in #14258 |
This came up on a call where we were discussing the API, and IIRC the idea was that for now we |
Just to add to what Joe said, another reason was to be consistent with some other APIs, eg how the |
…ytech/substrate into aa/multi-asset-support-in-treasury
Why not introduce |
Yeah, I agree with this. I would revert to spends on a single asset for now, except someone has a counterargument. |
spend()
should use Pay
trait
spend()
should use Pay
traitspend()
should use Pay
trait
The CI pipeline was cancelled due to failure one of the required jobs. |
closing in favour of #14434 |
Motivation
To support a more flexible treasury pallet, we need to prevent strongly coupling the treasury implementation to the Currency, fungible or fungibles traits.
Instead, this PR begins an attempt at a treasury pallet which is implemented over a more generic trait, which could then be implemented over fungibles, fungible, or even over pallet_xcm. Opening more possibilities including the ability for the treasury to control and spend assets which are available on remote parachains.
Approach
This PR leverages the new pay trait, as the means of actually implementing spend. The long term goal will be to deprecate the other non-spend extrinsics. Eg
propose_spend()
,reject_proposal
, etc, so that thespend()
extrinsic becomes the de-factor way of using spend().A user story could be that all the proposal management logic happens through a referendum from the respective pallet, and that referendum is able to trigger the spend() action in the treasury pallet, which gets paid out at the next
SpendPeriod
. By doing this, the treasury becomes much simpler in scope, and becomes a pallet which can be used to controlspending
or paying out assets from accounts controlled by an origin.So in practical terms, it could be possible to have many treasury instances for every account which is controlled by a collective. Eg the Governance could control a treasury over funds in statemint and control a treasury over funds on even a remote parachain or on the local chain, via the respective implementations of pay:
PayFromAccount
,PayFungibles
,PayOverXcm
or even a hypotheticalPayNonFungible
polkadot companion: paritytech/polkadot#7058
TODO