Git Hash d5160c1d567cc73c7df6c816d41e21aa3adb188d
Made with Substrate, for Polkadot.
The Treasury pallet provides a “pot” of funds that can be managed by stakeholders in the system and a structure for making spending proposals from this pot.
The Treasury Pallet itself provides the pot to store funds, and a means for stakeholders to propose and claim expenditures (aka spends). The chain will need to provide a method to approve spends (e.g. public referendum) and a method for collecting funds (e.g. inflation, fees).
By way of example, stakeholders could vote to fund the Treasury with a portion of the block reward and use the funds to pay developers.
#[test]
fn spend_local_origin_works() {
ExtBuilder::default().build().execute_with(|| {
// Check that accumulate works when we have Some value in Dummy already.
Balances::make_free_balance_be(&Treasury::account_id(), 101);
// approve spend of some amount to beneficiary `6`.
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(10), 5, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(10), 5, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(10), 5, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(10), 5, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(11), 10, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(12), 20, 6));
assert_ok!(Treasury::spend_local(RuntimeOrigin::signed(13), 50, 6));
// free balance of `6` is zero, spend period has not passed.
<Treasury as OnInitialize<u64>>::on_initialize(1);
assert_eq!(Balances::free_balance(6), 0);
// free balance of `6` is `100`, spend period has passed.
<Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Balances::free_balance(6), 100);
// `100` spent, `1` burned.
assert_eq!(Treasury::pot(), 0);
});
}
#[test]
fn spend_payout_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
// approve a `2` coins spend of asset `1` to beneficiary `6`, the spend valid from now.
assert_ok!(Treasury::spend(RuntimeOrigin::signed(10), Box::new(1), 2, Box::new(6), None));
// payout the spend.
assert_ok!(Treasury::payout(RuntimeOrigin::signed(1), 0));
// beneficiary received `2` coins of asset `1`.
assert_eq!(paid(6, 1), 2);
assert_eq!(SpendCount::<Test, _>::get(), 1);
let payment_id = get_payment_id(0).expect("no payment attempt");
System::assert_last_event(Event::<Test, _>::Paid { index: 0, payment_id }.into());
set_status(payment_id, PaymentStatus::Success);
// the payment succeed.
assert_ok!(Treasury::check_status(RuntimeOrigin::signed(1), 0));
System::assert_last_event(Event::<Test, _>::SpendProcessed { index: 0 }.into());
// cannot payout the same spend twice.
assert_noop!(Treasury::payout(RuntimeOrigin::signed(1), 0), Error::<Test, _>::InvalidIndex);
});
}
See the pallet
module for more information about the interfaces this pallet exposes,
including its configuration trait, dispatchables, storage items, events and errors.
Spends can be initiated using either the spend_local
or spend
dispatchable. The
spend_local
dispatchable enables the creation of spends using the native currency of the
chain, utilizing the funds stored in the pot. These spends are automatically paid out every
pallet::Config::SpendPeriod
. On the other hand, the spend
dispatchable allows spending of
any asset kind managed by the treasury, with payment facilitated by a designated
pallet::Config::Paymaster
. To claim these spends, the payout
dispatchable should be called
within some temporal bounds, starting from the moment they become valid and within one
pallet::Config::PayoutPeriod
.
pub use weights::WeightInfo;
pub use pallet::*;
pallet
module in each FRAME pallet hosts the most important items needed
to construct this pallet.pallet_treasury
u32
.