Westend: Fellowship Treasury (#2532)

Treasury Pallet Instance for the Fellowship in Westend Collectives.

In this update, we present a Treasury Pallet Instance that is under the
control of the Fellowship body, with oversight from the Root and
Treasurer origins. Here's how it is governed:
- the Root origin have the authority to reject or approve spend
proposals, with no amount limit for approvals.
- the Treasurer origin have the authority to reject or approve spend
proposals, with approval limits of up to 10,000,000 DOT.
- Voice of all Fellows ranked at 3 or above can reject or approve spend
proposals, with a maximum approval limit of 10,000 DOT.
- Voice of Fellows ranked at 4 or above can also reject or approve spend
proposals, with a maximum approval limit of 10,000,000 DOT.

Additionally, we introduce the Asset Rate Pallet Instance to establish
conversion rates from asset A to B. This is used to determine if a
proposed spend amount involving a non-native asset is permissible by the
commanding origin. The rates can be set up by the Root, Treasurer
origins, or Voice of all Fellows.

---------

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: joepetrowski <joe@parity.io>
This commit is contained in:
Muharem
2023-12-08 14:02:09 +01:00
committed by GitHub
parent 1bdfb29587
commit da40d97a23
26 changed files with 827 additions and 27 deletions
Generated
+19
View File
@@ -885,6 +885,7 @@ dependencies = [
"asset-test-utils",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"emulated-integration-tests-common",
"frame-support",
"frame-system",
@@ -2613,6 +2614,21 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "collectives-westend-emulated-chain"
version = "0.0.0"
dependencies = [
"collectives-westend-runtime",
"cumulus-primitives-core",
"emulated-integration-tests-common",
"frame-support",
"parachains-common",
"serde_json",
"sp-core",
"sp-runtime",
"westend-emulated-chain",
]
[[package]]
name = "collectives-westend-runtime"
version = "1.0.0"
@@ -2634,6 +2650,7 @@ dependencies = [
"hex-literal",
"log",
"pallet-alliance",
"pallet-asset-rate",
"pallet-aura",
"pallet-authorship",
"pallet-balances",
@@ -2653,6 +2670,7 @@ dependencies = [
"pallet-timestamp",
"pallet-transaction-payment",
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
"pallet-utility",
"pallet-xcm",
"parachains-common",
@@ -21049,6 +21067,7 @@ version = "0.0.0"
dependencies = [
"asset-hub-westend-emulated-chain",
"bridge-hub-westend-emulated-chain",
"collectives-westend-emulated-chain",
"emulated-integration-tests-common",
"penpal-emulated-chain",
"westend-emulated-chain",
+1
View File
@@ -66,6 +66,7 @@ members = [
"cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend",
"cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo",
"cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend",
"cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend",
"cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal",
"cumulus/parachains/integration-tests/emulated/chains/relays/rococo",
"cumulus/parachains/integration-tests/emulated/chains/relays/westend",
@@ -31,6 +31,8 @@ pub mod account {
/// It is used as a temporarily place to deposit a slashed imbalance
/// before the teleport to the Treasury.
pub const AMBASSADOR_REFERENDA_PALLET_ID: PalletId = PalletId(*b"py/amref");
/// Fellowship treasury pallet ID
pub const FELLOWSHIP_TREASURY_PALLET_ID: PalletId = PalletId(*b"py/feltr");
}
/// Consensus-related.
+2
View File
@@ -29,6 +29,8 @@ pub mod account {
/// Ambassador Referenda pallet ID - used as a temporary place to deposit a slashed imbalance
/// before the teleport to the Treasury.
pub const AMBASSADOR_REFERENDA_PALLET_ID: PalletId = PalletId(*b"py/amref");
/// Fellowship treasury pallet ID.
pub const FELLOWSHIP_TREASURY_PALLET_ID: PalletId = PalletId(*b"py/feltr");
}
pub mod currency {
@@ -0,0 +1,25 @@
[package]
name = "collectives-westend-emulated-chain"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Collectives Westend emulated chain"
publish = false
[dependencies]
serde_json = "1.0.104"
# Substrate
sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false }
sp-runtime = { path = "../../../../../../../../substrate/primitives/runtime", default-features = false }
frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false }
# Polakadot
parachains-common = { path = "../../../../../../../parachains/common" }
# Cumulus
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
collectives-westend-runtime = { path = "../../../../../../runtimes/collectives/collectives-westend" }
westend-emulated-chain = { path = "../../../relays/westend" }
@@ -0,0 +1,67 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Substrate
use sp_core::storage::Storage;
// Cumulus
use emulated_integration_tests_common::{
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
};
use parachains_common::Balance;
pub const PARA_ID: u32 = 1001;
pub const ED: Balance = parachains_common::westend::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = collectives_westend_runtime::RuntimeGenesisConfig {
system: collectives_westend_runtime::SystemConfig::default(),
balances: collectives_westend_runtime::BalancesConfig {
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
},
parachain_info: collectives_westend_runtime::ParachainInfoConfig {
parachain_id: PARA_ID.into(),
..Default::default()
},
collator_selection: collectives_westend_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: collectives_westend_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
collectives_westend_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
polkadot_xcm: collectives_westend_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default()
},
..Default::default()
};
build_genesis_storage(
&genesis_config,
collectives_westend_runtime::WASM_BINARY
.expect("WASM binary was not built, please build it!"),
)
}
@@ -0,0 +1,51 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod genesis;
// Substrate
use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impls::Parachain, xcm_emulator::decl_test_parachains,
};
// CollectivesWestend Parachain declaration
decl_test_parachains! {
pub struct CollectivesWestend {
genesis = genesis::genesis(),
on_init = {
collectives_westend_runtime::AuraExt::on_initialize(1);
},
runtime = collectives_westend_runtime,
core = {
XcmpMessageHandler: collectives_westend_runtime::XcmpQueue,
LocationToAccountId: collectives_westend_runtime::xcm_config::LocationToAccountId,
ParachainInfo: collectives_westend_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: collectives_westend_runtime::PolkadotXcm,
Balances: collectives_westend_runtime::Balances,
FellowshipTreasury: collectives_westend_runtime::FellowshipTreasury,
AssetRate: collectives_westend_runtime::AssetRate,
}
},
}
// AssetHubWestend implementation
impl_accounts_helpers_for_parachain!(CollectivesWestend);
impl_assert_events_helpers_for_parachain!(CollectivesWestend);
@@ -13,4 +13,5 @@ emulated-integration-tests-common = { path = "../../common", default-features =
westend-emulated-chain = { path = "../../chains/relays/westend", default-features = false }
asset-hub-westend-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-westend" }
bridge-hub-westend-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-westend" }
collectives-westend-emulated-chain = { path = "../../chains/parachains/collectives/collectives-westend" }
penpal-emulated-chain = { path = "../../chains/parachains/testing/penpal" }
@@ -15,11 +15,13 @@
pub use asset_hub_westend_emulated_chain;
pub use bridge_hub_westend_emulated_chain;
pub use collectives_westend_emulated_chain;
pub use penpal_emulated_chain;
pub use westend_emulated_chain;
use asset_hub_westend_emulated_chain::AssetHubWestend;
use bridge_hub_westend_emulated_chain::BridgeHubWestend;
use collectives_westend_emulated_chain::CollectivesWestend;
use penpal_emulated_chain::{PenpalA, PenpalB};
use westend_emulated_chain::Westend;
@@ -35,6 +37,7 @@ decl_test_networks! {
parachains = vec![
AssetHubWestend,
BridgeHubWestend,
CollectivesWestend,
PenpalA,
PenpalB,
],
@@ -46,6 +49,7 @@ decl_test_sender_receiver_accounts_parameter_types! {
WestendRelay { sender: ALICE, receiver: BOB },
AssetHubWestendPara { sender: ALICE, receiver: BOB },
BridgeHubWestendPara { sender: ALICE, receiver: BOB },
CollectivesWestendPara { sender: ALICE, receiver: BOB },
PenpalAPara { sender: ALICE, receiver: BOB },
PenpalBPara { sender: ALICE, receiver: BOB }
}
@@ -36,6 +36,7 @@ parachains-common = { path = "../../../../../../parachains/common" }
asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
cumulus-pallet-dmp-queue = { default-features = false, path = "../../../../../../pallets/dmp-queue" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" }
emulated-integration-tests-common = { path = "../../../common", default-features = false }
westend-system-emulated-network = { path = "../../../networks/westend-system" }
@@ -47,11 +47,16 @@ pub use westend_system_emulated_network::{
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
collectives_westend_emulated_chain::{
genesis::ED as COLLECTIVES_WESTEND_ED,
CollectivesWestendParaPallet as CollectivesWestendPallet,
},
penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet,
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, PenpalBPara as PenpalB,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver,
CollectivesWestendPara as CollectivesWestend, PenpalBPara as PenpalB,
PenpalBParaReceiver as PenpalBReceiver, PenpalBParaSender as PenpalBSender,
WestendRelay as Westend, WestendRelayReceiver as WestendReceiver,
WestendRelaySender as WestendSender,
@@ -0,0 +1,131 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use emulated_integration_tests_common::accounts::{ALICE, BOB};
use frame_support::traits::fungibles::{Create, Inspect, Mutate};
use polkadot_runtime_common::impls::VersionedLocatableAsset;
use xcm_executor::traits::ConvertLocation;
#[test]
fn create_and_claim_treasury_spend() {
const ASSET_ID: u32 = 1984;
const SPEND_AMOUNT: u128 = 1_000_000;
// treasury location from a sibling parachain.
let treasury_location: MultiLocation = MultiLocation::new(
1,
X2(Parachain(CollectivesWestend::para_id().into()), PalletInstance(65)),
);
// treasury account on a sibling parachain.
let treasury_account =
asset_hub_westend_runtime::xcm_config::LocationToAccountId::convert_location(
&treasury_location,
)
.unwrap();
let asset_hub_location = MultiLocation::new(1, Parachain(AssetHubWestend::para_id().into()));
let root = <CollectivesWestend as Chain>::RuntimeOrigin::root();
// asset kind to be spent from the treasury.
let asset_kind = VersionedLocatableAsset::V3 {
location: asset_hub_location,
asset_id: AssetId::Concrete((PalletInstance(50), GeneralIndex(ASSET_ID.into())).into()),
};
// treasury spend beneficiary.
let alice: AccountId = Westend::account_id_of(ALICE);
let bob: AccountId = CollectivesWestend::account_id_of(BOB);
let bob_signed = <CollectivesWestend as Chain>::RuntimeOrigin::signed(bob.clone());
AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::Assets;
// create an asset class and mint some assets to the treasury account.
assert_ok!(<Assets as Create<_>>::create(
ASSET_ID,
treasury_account.clone(),
true,
SPEND_AMOUNT / 2
));
assert_ok!(<Assets as Mutate<_>>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4));
// beneficiary has zero balance.
assert_eq!(<Assets as Inspect<_>>::balance(ASSET_ID, &alice,), 0u128,);
});
CollectivesWestend::execute_with(|| {
type RuntimeEvent = <CollectivesWestend as Chain>::RuntimeEvent;
type FellowshipTreasury =
<CollectivesWestend as CollectivesWestendPallet>::FellowshipTreasury;
type AssetRate = <CollectivesWestend as CollectivesWestendPallet>::AssetRate;
// create a conversion rate from `asset_kind` to the native currency.
assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
// create and approve a treasury spend.
assert_ok!(FellowshipTreasury::spend(
root,
Box::new(asset_kind),
SPEND_AMOUNT,
Box::new(MultiLocation::new(0, Into::<[u8; 32]>::into(alice.clone())).into()),
None,
));
// claim the spend.
assert_ok!(FellowshipTreasury::payout(bob_signed.clone(), 0));
assert_expected_events!(
CollectivesWestend,
vec![
RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::Paid { .. }) => {},
]
);
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
type Assets = <AssetHubWestend as AssetHubWestendPallet>::Assets;
// assert events triggered by xcm pay program
// 1. treasury asset transferred to spend beneficiary
// 2. response to the Fellowship treasury pallet instance sent back
// 3. XCM program completed
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
id: id == &ASSET_ID,
from: from == &treasury_account,
to: to == &alice,
amount: amount == &SPEND_AMOUNT,
},
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
]
);
// beneficiary received the assets from the treasury.
assert_eq!(<Assets as Inspect<_>>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,);
});
CollectivesWestend::execute_with(|| {
type RuntimeEvent = <CollectivesWestend as Chain>::RuntimeEvent;
type FellowshipTreasury =
<CollectivesWestend as CollectivesWestendPallet>::FellowshipTreasury;
// check the payment status to ensure the response from the AssetHub was received.
assert_ok!(FellowshipTreasury::check_status(bob_signed, 0));
assert_expected_events!(
CollectivesWestend,
vec![
RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::SpendProcessed { .. }) => {},
]
);
});
}
@@ -13,6 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod fellowship_treasury;
mod reserve_transfer;
mod send;
mod set_xcm_versions;
@@ -239,6 +239,18 @@ match_types! {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { .. }) }
};
pub type FellowshipEntities: impl Contains<MultiLocation> = {
// Fellowship Plurality
MultiLocation { parents: 1, interior: X2(Parachain(1001), Plurality { id: BodyId::Technical, ..}) } |
// Fellowship Salary Pallet
MultiLocation { parents: 1, interior: X2(Parachain(1001), PalletInstance(64)) } |
// Fellowship Treasury Pallet
MultiLocation { parents: 1, interior: X2(Parachain(1001), PalletInstance(65)) }
};
pub type AmbassadorEntities: impl Contains<MultiLocation> = {
// Ambassador Salary Pallet
MultiLocation { parents: 1, interior: X2(Parachain(1001), PalletInstance(74)) }
};
}
/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
@@ -487,6 +499,8 @@ pub type Barrier = TrailingSetTopicAsId<
ParentOrParentsPlurality,
Equals<RelayTreasuryLocation>,
Equals<bridging::SiblingBridgeHub>,
FellowshipEntities,
AmbassadorEntities,
)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<Everything>,
@@ -525,6 +539,8 @@ pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger =
pub type WaivedLocations = (
RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
Equals<RelayTreasuryLocation>,
FellowshipEntities,
AmbassadorEntities,
);
/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
@@ -21,6 +21,7 @@ frame-system = { path = "../../../../../substrate/frame/system", default-feature
frame-system-benchmarking = { path = "../../../../../substrate/frame/system/benchmarking", default-features = false, optional = true }
frame-system-rpc-runtime-api = { path = "../../../../../substrate/frame/system/rpc/runtime-api", default-features = false }
frame-try-runtime = { path = "../../../../../substrate/frame/try-runtime", default-features = false, optional = true }
pallet-asset-rate = { path = "../../../../../substrate/frame/asset-rate", default-features = false }
pallet-alliance = { path = "../../../../../substrate/frame/alliance", default-features = false }
pallet-aura = { path = "../../../../../substrate/frame/aura", default-features = false }
pallet-authorship = { path = "../../../../../substrate/frame/authorship", default-features = false }
@@ -34,6 +35,7 @@ pallet-session = { path = "../../../../../substrate/frame/session", default-feat
pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false }
pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false }
pallet-treasury = { path = "../../../../../substrate/frame/treasury", default-features = false }
pallet-utility = { path = "../../../../../substrate/frame/utility", default-features = false }
pallet-referenda = { path = "../../../../../substrate/frame/referenda", default-features = false }
pallet-ranked-collective = { path = "../../../../../substrate/frame/ranked-collective", default-features = false }
@@ -97,6 +99,7 @@ runtime-benchmarks = [
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-alliance/runtime-benchmarks",
"pallet-asset-rate/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-collective-content/runtime-benchmarks",
@@ -111,6 +114,7 @@ runtime-benchmarks = [
"pallet-salary/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-treasury/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"parachains-common/runtime-benchmarks",
@@ -130,6 +134,7 @@ try-runtime = [
"frame-system/try-runtime",
"frame-try-runtime/try-runtime",
"pallet-alliance/try-runtime",
"pallet-asset-rate/try-runtime",
"pallet-aura/try-runtime",
"pallet-authorship/try-runtime",
"pallet-balances/try-runtime",
@@ -148,6 +153,7 @@ try-runtime = [
"pallet-session/try-runtime",
"pallet-timestamp/try-runtime",
"pallet-transaction-payment/try-runtime",
"pallet-treasury/try-runtime",
"pallet-utility/try-runtime",
"pallet-xcm/try-runtime",
"parachain-info/try-runtime",
@@ -172,6 +178,7 @@ std = [
"frame-try-runtime?/std",
"log/std",
"pallet-alliance/std",
"pallet-asset-rate/std",
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
@@ -191,6 +198,7 @@ std = [
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"pallet-treasury/std",
"pallet-utility/std",
"pallet-xcm/std",
"parachain-info/std",
@@ -21,28 +21,41 @@ mod tracks;
use crate::{
impls::ToParentTreasury,
weights,
xcm_config::{FellowshipAdminBodyId, UsdtAssetHub},
AccountId, Balance, Balances, FellowshipReferenda, GovernanceLocation, Preimage, Runtime,
RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, WestendTreasuryAccount, DAYS,
xcm_config::{FellowshipAdminBodyId, TreasurerBodyId, UsdtAssetHub},
AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation, Preimage,
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, WestendTreasuryAccount, DAYS,
};
use frame_support::{
parameter_types,
traits::{EitherOf, EitherOfDiverse, MapSuccess, OriginTrait, TryWithMorphedArg},
traits::{
EitherOf, EitherOfDiverse, MapSuccess, NeverEnsureOrigin, OriginTrait, TryWithMorphedArg,
},
PalletId,
};
use frame_system::EnsureRootWithSuccess;
use frame_system::{EnsureRoot, EnsureRootWithSuccess};
pub use origins::{
pallet_origins as pallet_fellowship_origins, Architects, EnsureCanPromoteTo, EnsureCanRetainAt,
EnsureFellowship, Fellows, Masters, Members, ToVoice,
};
use pallet_ranked_collective::EnsureOfRank;
use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
use parachains_common::{polkadot::account, HOURS};
use parachains_common::westend::{account, currency::GRAND};
use polkadot_runtime_common::impls::{
LocatableAssetConverter, VersionedLocatableAsset, VersionedMultiLocationConverter,
};
use sp_arithmetic::Permill;
use sp_core::{ConstU128, ConstU32};
use sp_runtime::traits::{AccountIdConversion, ConstU16, ConvertToValue, Replace, TakeFirst};
use sp_runtime::traits::{
AccountIdConversion, ConstU16, ConvertToValue, IdentityLookup, Replace, TakeFirst,
};
use westend_runtime_constants::time::HOURS;
use xcm::prelude::*;
use xcm_builder::{AliasesIntoAccountId32, PayOverXcm};
#[cfg(feature = "runtime-benchmarks")]
use crate::impls::benchmarks::{OpenHrmpChannel, PayWithEnsure};
#[cfg(feature = "runtime-benchmarks")]
use parachains_common::westend::currency::DOLLARS;
/// The Fellowship members' ranks.
pub mod ranks {
@@ -191,8 +204,6 @@ impl pallet_core_fellowship::Config<FellowshipCoreInstance> for Runtime {
pub type FellowshipSalaryInstance = pallet_salary::Instance1;
use xcm::prelude::*;
parameter_types! {
// The interior location on AssetHub for the paying account. This is the Fellowship Salary
// pallet instance (which sits at index 64). This sovereign account will need funding.
@@ -236,3 +247,102 @@ impl pallet_salary::Config<FellowshipSalaryInstance> for Runtime {
// Total monthly salary budget.
type Budget = ConstU128<{ 100_000 * USDT_UNITS }>;
}
parameter_types! {
pub const FellowshipTreasuryPalletId: PalletId = account::FELLOWSHIP_TREASURY_PALLET_ID;
pub const HundredPercent: Permill = Permill::from_percent(100);
pub const Burn: Permill = Permill::from_percent(0);
pub const MaxBalance: Balance = Balance::max_value();
// The asset's interior location for the paying account. This is the Fellowship Treasury
// pallet instance (which sits at index 65).
pub FellowshipTreasuryInteriorLocation: InteriorMultiLocation = PalletInstance(65).into();
}
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
// Benchmark bond. Needed to make `propose_spend` work.
pub const TenPercent: Permill = Permill::from_percent(10);
// Benchmark minimum. Needed to make `propose_spend` work.
pub const BenchmarkProposalBondMinimum: Balance = 1 * DOLLARS;
// Benchmark maximum. Needed to make `propose_spend` work.
pub const BenchmarkProposalBondMaximum: Balance = 10 * DOLLARS;
}
/// [`PayOverXcm`] setup to pay the Fellowship Treasury.
pub type FellowshipTreasuryPaymaster = PayOverXcm<
FellowshipTreasuryInteriorLocation,
crate::xcm_config::XcmRouter,
crate::PolkadotXcm,
ConstU32<{ 6 * HOURS }>,
VersionedMultiLocation,
VersionedLocatableAsset,
LocatableAssetConverter,
VersionedMultiLocationConverter,
>;
pub type FellowshipTreasuryInstance = pallet_treasury::Instance1;
impl pallet_treasury::Config<FellowshipTreasuryInstance> for Runtime {
// The creation of proposals via the treasury pallet is deprecated and should not be utilized.
// Instead, public or fellowship referenda should be used to propose and command the treasury
// spend or spend_local dispatchables. The parameters below have been configured accordingly to
// discourage its use.
// TODO: replace with `NeverEnsure` once polkadot-sdk 1.5 is released.
type ApproveOrigin = NeverEnsureOrigin<()>;
type OnSlash = ();
#[cfg(not(feature = "runtime-benchmarks"))]
type ProposalBond = HundredPercent;
#[cfg(not(feature = "runtime-benchmarks"))]
type ProposalBondMinimum = MaxBalance;
#[cfg(not(feature = "runtime-benchmarks"))]
type ProposalBondMaximum = MaxBalance;
#[cfg(feature = "runtime-benchmarks")]
type ProposalBond = TenPercent;
#[cfg(feature = "runtime-benchmarks")]
type ProposalBondMinimum = BenchmarkProposalBondMinimum;
#[cfg(feature = "runtime-benchmarks")]
type ProposalBondMaximum = BenchmarkProposalBondMaximum;
// end.
type WeightInfo = weights::pallet_treasury::WeightInfo<Runtime>;
type PalletId = FellowshipTreasuryPalletId;
type Currency = Balances;
type RejectOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<EnsureXcm<IsVoiceOfBody<GovernanceLocation, TreasurerBodyId>>, Fellows>,
>;
type RuntimeEvent = RuntimeEvent;
type SpendPeriod = ConstU32<{ 7 * DAYS }>;
type Burn = Burn;
type BurnDestination = ();
type SpendFunds = ();
type MaxApprovals = ConstU32<100>;
type SpendOrigin = EitherOf<
EitherOf<
EnsureRootWithSuccess<AccountId, MaxBalance>,
MapSuccess<
EnsureXcm<IsVoiceOfBody<GovernanceLocation, TreasurerBodyId>>,
Replace<ConstU128<{ 10_000 * GRAND }>>,
>,
>,
EitherOf<
MapSuccess<Architects, Replace<ConstU128<{ 10_000 * GRAND }>>>,
MapSuccess<Fellows, Replace<ConstU128<{ 10 * GRAND }>>>,
>,
>;
type AssetKind = VersionedLocatableAsset;
type Beneficiary = VersionedMultiLocation;
type BeneficiaryLookup = IdentityLookup<Self::Beneficiary>;
#[cfg(not(feature = "runtime-benchmarks"))]
type Paymaster = FellowshipTreasuryPaymaster;
#[cfg(feature = "runtime-benchmarks")]
type Paymaster = PayWithEnsure<FellowshipTreasuryPaymaster, OpenHrmpChannel<ConstU32<1000>>>;
type BalanceConverter = AssetRate;
type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments<
sp_core::ConstU8<1>,
ConstU32<1000>,
>;
}
@@ -89,14 +89,16 @@ use parachains_common::{
SLOT_DURATION,
};
use sp_runtime::RuntimeDebug;
use xcm_config::{GovernanceLocation, XcmOriginToTransactDispatchOrigin};
use xcm_config::{GovernanceLocation, TreasurerBodyId, XcmOriginToTransactDispatchOrigin};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
// Polkadot imports
use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate};
use polkadot_runtime_common::{
impls::VersionedLocatableAsset, BlockHashCount, SlowAdjustingFeeUpdate,
};
use xcm::latest::{prelude::*, BodyId};
use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight};
@@ -325,6 +327,7 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
RuntimeCall::FellowshipReferenda { .. } |
RuntimeCall::FellowshipCore { .. } |
RuntimeCall::FellowshipSalary { .. } |
RuntimeCall::FellowshipTreasury { .. } |
RuntimeCall::Utility { .. } |
RuntimeCall::Multisig { .. }
),
@@ -613,6 +616,21 @@ impl pallet_preimage::Config for Runtime {
>;
}
impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo<Runtime>;
type RuntimeEvent = RuntimeEvent;
type CreateOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<EnsureXcm<IsVoiceOfBody<GovernanceLocation, TreasurerBodyId>>, Fellows>,
>;
type RemoveOrigin = Self::CreateOrigin;
type UpdateOrigin = Self::CreateOrigin;
type Currency = Balances;
type AssetKind = VersionedLocatableAsset;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::AssetRateArguments;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime
@@ -648,6 +666,7 @@ construct_runtime!(
Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 42,
Preimage: pallet_preimage::{Pallet, Call, Storage, Event<T>, HoldReason} = 43,
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>} = 44,
AssetRate: pallet_asset_rate::{Pallet, Call, Storage, Event<T>} = 45,
// The main stage.
@@ -665,6 +684,8 @@ construct_runtime!(
FellowshipCore: pallet_core_fellowship::<Instance1>::{Pallet, Call, Storage, Event<T>} = 63,
// pub type FellowshipSalaryInstance = pallet_salary::Instance1;
FellowshipSalary: pallet_salary::<Instance1>::{Pallet, Call, Storage, Event<T>} = 64,
// pub type FellowshipTreasuryInstance = pallet_treasury::Instance1;
FellowshipTreasury: pallet_treasury::<Instance1>::{Pallet, Call, Storage, Event<T>} = 65,
// Ambassador Program.
AmbassadorCollective: pallet_ranked_collective::<Instance2>::{Pallet, Call, Storage, Event<T>} = 70,
@@ -744,6 +765,8 @@ mod benches {
[pallet_collective_content, AmbassadorContent]
[pallet_core_fellowship, AmbassadorCore]
[pallet_salary, AmbassadorSalary]
[pallet_treasury, FellowshipTreasury]
[pallet_asset_rate, AssetRate]
);
}
@@ -19,6 +19,7 @@ pub mod cumulus_pallet_xcmp_queue;
pub mod extrinsic_weights;
pub mod frame_system;
pub mod pallet_alliance;
pub mod pallet_asset_rate;
pub mod pallet_balances;
pub mod pallet_collator_selection;
pub mod pallet_collective;
@@ -38,6 +39,7 @@ pub mod pallet_salary_fellowship_salary;
pub mod pallet_scheduler;
pub mod pallet_session;
pub mod pallet_timestamp;
pub mod pallet_treasury;
pub mod pallet_utility;
pub mod pallet_xcm;
pub mod paritydb_weights;
@@ -0,0 +1,85 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `pallet_asset_rate`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-11-28, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `cob`, CPU: `<UNKNOWN>`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024
// Executed Command:
// ./target/debug/polkadot-parachain
// benchmark
// pallet
// --chain=collectives-westend-dev
// --steps=2
// --repeat=2
// --pallet=pallet-asset-rate
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `pallet_asset_rate`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_asset_rate::WeightInfo for WeightInfo<T> {
/// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1)
/// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`)
fn create() -> Weight {
// Proof Size summary in bytes:
// Measured: `6`
// Estimated: `4703`
// Minimum execution time: 102_000_000 picoseconds.
Weight::from_parts(112_000_000, 0)
.saturating_add(Weight::from_parts(0, 4703))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1)
/// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`)
fn update() -> Weight {
// Proof Size summary in bytes:
// Measured: `74`
// Estimated: `4703`
// Minimum execution time: 101_000_000 picoseconds.
Weight::from_parts(105_000_000, 0)
.saturating_add(Weight::from_parts(0, 4703))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1)
/// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`)
fn remove() -> Weight {
// Proof Size summary in bytes:
// Measured: `74`
// Estimated: `4703`
// Minimum execution time: 112_000_000 picoseconds.
Weight::from_parts(116_000_000, 0)
.saturating_add(Weight::from_parts(0, 4703))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
@@ -0,0 +1,214 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `pallet_treasury`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-11-28, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `cob`, CPU: `<UNKNOWN>`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024
// Executed Command:
// ./target/debug/polkadot-parachain
// benchmark
// pallet
// --chain=collectives-westend-dev
// --steps=2
// --repeat=2
// --pallet=pallet-treasury
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `pallet_treasury`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_treasury::WeightInfo for WeightInfo<T> {
/// Storage: `FellowshipTreasury::ProposalCount` (r:1 w:1)
/// Proof: `FellowshipTreasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Approvals` (r:1 w:1)
/// Proof: `FellowshipTreasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Proposals` (r:0 w:1)
/// Proof: `FellowshipTreasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
fn spend_local() -> Weight {
// Proof Size summary in bytes:
// Measured: `42`
// Estimated: `1887`
// Minimum execution time: 117_000_000 picoseconds.
Weight::from_parts(126_000_000, 0)
.saturating_add(Weight::from_parts(0, 1887))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: `FellowshipTreasury::ProposalCount` (r:1 w:1)
/// Proof: `FellowshipTreasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Proposals` (r:0 w:1)
/// Proof: `FellowshipTreasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
fn propose_spend() -> Weight {
// Proof Size summary in bytes:
// Measured: `143`
// Estimated: `1489`
// Minimum execution time: 264_000_000 picoseconds.
Weight::from_parts(277_000_000, 0)
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `FellowshipTreasury::Proposals` (r:1 w:1)
/// Proof: `FellowshipTreasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn reject_proposal() -> Weight {
// Proof Size summary in bytes:
// Measured: `301`
// Estimated: `3593`
// Minimum execution time: 289_000_000 picoseconds.
Weight::from_parts(312_000_000, 0)
.saturating_add(Weight::from_parts(0, 3593))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// The range of component `p` is `[0, 99]`.
fn approve_proposal(_p: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 0_000 picoseconds.
Weight::from_parts(0, 0)
.saturating_add(Weight::from_parts(0, 0))
}
/// Storage: `FellowshipTreasury::Approvals` (r:1 w:1)
/// Proof: `FellowshipTreasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`)
fn remove_approval() -> Weight {
// Proof Size summary in bytes:
// Measured: `127`
// Estimated: `1887`
// Minimum execution time: 62_000_000 picoseconds.
Weight::from_parts(65_000_000, 0)
.saturating_add(Weight::from_parts(0, 1887))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `System::Account` (r:199 w:199)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Deactivated` (r:1 w:1)
/// Proof: `FellowshipTreasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
/// Storage: `Balances::InactiveIssuance` (r:1 w:1)
/// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Approvals` (r:1 w:1)
/// Proof: `FellowshipTreasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Proposals` (r:99 w:99)
/// Proof: `FellowshipTreasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
/// The range of component `p` is `[0, 99]`.
fn on_initialize_proposals(p: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `145 + p * (250 ±0)`
// Estimated: `256707 + p * (5206 ±0)`
// Minimum execution time: 218_000_000 picoseconds.
Weight::from_parts(221_000_000, 0)
.saturating_add(Weight::from_parts(0, 256707))
// Standard Error: 154_515
.saturating_add(Weight::from_parts(399_232_323, 0).saturating_mul(p.into()))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into())))
.saturating_add(T::DbWeight::get().writes(3))
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into())))
.saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into()))
}
/// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0)
/// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::SpendCount` (r:1 w:1)
/// Proof: `FellowshipTreasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `FellowshipTreasury::Spends` (r:0 w:1)
/// Proof: `FellowshipTreasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`)
fn spend() -> Weight {
// Proof Size summary in bytes:
// Measured: `118`
// Estimated: `4703`
// Minimum execution time: 163_000_000 picoseconds.
Weight::from_parts(171_000_000, 0)
.saturating_add(Weight::from_parts(0, 4703))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `FellowshipTreasury::Spends` (r:1 w:1)
/// Proof: `FellowshipTreasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`)
/// Storage: `ParachainInfo::ParachainId` (r:1 w:0)
/// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1)
/// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0)
/// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0)
/// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1)
/// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1)
/// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `PolkadotXcm::Queries` (r:0 w:1)
/// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn payout() -> Weight {
// Proof Size summary in bytes:
// Measured: `629`
// Estimated: `5318`
// Minimum execution time: 472_000_000 picoseconds.
Weight::from_parts(492_000_000, 0)
.saturating_add(Weight::from_parts(0, 5318))
.saturating_add(T::DbWeight::get().reads(9))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `FellowshipTreasury::Spends` (r:1 w:1)
/// Proof: `FellowshipTreasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`)
/// Storage: `PolkadotXcm::Queries` (r:1 w:1)
/// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn check_status() -> Weight {
// Proof Size summary in bytes:
// Measured: `383`
// Estimated: `5318`
// Minimum execution time: 211_000_000 picoseconds.
Weight::from_parts(215_000_000, 0)
.saturating_add(Weight::from_parts(0, 5318))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `FellowshipTreasury::Spends` (r:1 w:1)
/// Proof: `FellowshipTreasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`)
fn void_spend() -> Weight {
// Proof Size summary in bytes:
// Measured: `179`
// Estimated: `5318`
// Minimum execution time: 124_000_000 picoseconds.
Weight::from_parts(126_000_000, 0)
.saturating_add(Weight::from_parts(0, 5318))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
@@ -33,6 +33,7 @@ use parachains_common::{
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use westend_runtime_constants::xcm as xcm_constants;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
@@ -46,8 +47,6 @@ use xcm_builder::{
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
const FELLOWSHIP_ADMIN_INDEX: u32 = 1;
parameter_types! {
pub const WndLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: Option<NetworkId> = Some(NetworkId::Westend);
@@ -57,7 +56,8 @@ parameter_types! {
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(westend_runtime_constants::TREASURY_PALLET_ID)).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub const GovernanceLocation: MultiLocation = MultiLocation::parent();
pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX);
pub const FellowshipAdminBodyId: BodyId = BodyId::Index(xcm_constants::body::FELLOWSHIP_ADMIN_INDEX);
pub const TreasurerBodyId: BodyId = BodyId::Index(xcm_constants::body::TREASURER_INDEX);
pub AssetHub: MultiLocation = (Parent, Parachain(1000)).into();
pub AssetHubUsdtId: AssetId = (PalletInstance(50), GeneralIndex(1984)).into();
pub UsdtAssetHub: LocatableAssetId = LocatableAssetId {
+17 -4
View File
@@ -149,8 +149,11 @@ impl TryConvert<&VersionedMultiLocation, xcm::latest::MultiLocation>
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarks {
use super::VersionedLocatableAsset;
use core::marker::PhantomData;
use frame_support::traits::Get;
use pallet_asset_rate::AssetKindFactory;
use pallet_treasury::ArgumentsFactory as TreasuryArgumentsFactory;
use sp_core::{ConstU32, ConstU8};
use xcm::prelude::*;
/// Provides a factory method for the [`VersionedLocatableAsset`].
@@ -172,12 +175,22 @@ pub mod benchmarks {
/// Provide factory methods for the [`VersionedLocatableAsset`] and the `Beneficiary` of the
/// [`VersionedMultiLocation`]. The location of the asset is determined as a Parachain with an
/// ID equal to the passed seed.
pub struct TreasuryArguments;
impl TreasuryArgumentsFactory<VersionedLocatableAsset, VersionedMultiLocation>
for TreasuryArguments
pub struct TreasuryArguments<Parents = ConstU8<0>, ParaId = ConstU32<0>>(
PhantomData<(Parents, ParaId)>,
);
impl<Parents: Get<u8>, ParaId: Get<u32>>
TreasuryArgumentsFactory<VersionedLocatableAsset, VersionedMultiLocation>
for TreasuryArguments<Parents, ParaId>
{
fn create_asset_kind(seed: u32) -> VersionedLocatableAsset {
AssetRateArguments::create_asset_kind(seed)
VersionedLocatableAsset::V3 {
location: xcm::v3::MultiLocation::new(Parents::get(), X1(Parachain(ParaId::get()))),
asset_id: xcm::v3::MultiLocation::new(
0,
X2(PalletInstance(seed.try_into().unwrap()), GeneralIndex(seed.into())),
)
.into(),
}
}
fn create_beneficiary(seed: [u8; 32]) -> VersionedMultiLocation {
VersionedMultiLocation::V3(xcm::v3::MultiLocation::new(
@@ -124,6 +124,7 @@ pub mod xcm {
const ROOT_INDEX: u32 = 0;
// The bodies corresponding to the Polkadot OpenGov Origins.
pub const FELLOWSHIP_ADMIN_INDEX: u32 = 1;
pub const TREASURER_INDEX: u32 = 2;
}
}
+11 -2
View File
@@ -21,7 +21,7 @@ use super::{
GeneralAdmin, ParaId, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StakingAdmin,
TransactionByteFee, Treasury, WeightToFee, XcmPallet,
};
use crate::governance::pallet_custom_origins::Treasurer;
use frame_support::{
match_types, parameter_types,
traits::{Everything, Nothing},
@@ -34,7 +34,9 @@ use runtime_common::{
};
use sp_core::ConstU32;
use westend_runtime_constants::{
currency::CENTS, system_parachain::*, xcm::body::FELLOWSHIP_ADMIN_INDEX,
currency::CENTS,
system_parachain::*,
xcm::body::{FELLOWSHIP_ADMIN_INDEX, TREASURER_INDEX},
};
use xcm::latest::prelude::*;
use xcm_builder::{
@@ -198,6 +200,8 @@ parameter_types! {
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
// FellowshipAdmin pluralistic body.
pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX);
// `Treasurer` pluralistic body.
pub const TreasurerBodyId: BodyId = BodyId::Index(TREASURER_INDEX);
}
/// Type to convert the `GeneralAdmin` origin to a Plurality `MultiLocation` value.
@@ -220,6 +224,9 @@ pub type StakingAdminToPlurality =
pub type FellowshipAdminToPlurality =
OriginToPluralityVoice<RuntimeOrigin, FellowshipAdmin, FellowshipAdminBodyId>;
/// Type to convert the `Treasurer` origin to a Plurality `MultiLocation` value.
pub type TreasurerToPlurality = OriginToPluralityVoice<RuntimeOrigin, Treasurer, TreasurerBodyId>;
/// Type to convert a pallet `Origin` type value into a `MultiLocation` value which represents an
/// interior location of this chain for a destination chain.
pub type LocalPalletOriginToLocation = (
@@ -229,6 +236,8 @@ pub type LocalPalletOriginToLocation = (
StakingAdminToPlurality,
// FellowshipAdmin origin to be used in XCM as a corresponding Plurality `MultiLocation` value.
FellowshipAdminToPlurality,
// `Treasurer` origin to be used in XCM as a corresponding Plurality `MultiLocation` value.
TreasurerToPlurality,
);
impl pallet_xcm::Config for Runtime {
+11
View File
@@ -0,0 +1,11 @@
# 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: Westend Fellowship Treasury
doc:
- audience: Runtime User
description: |
Treasury Pallet Instance for the Fellowship in Westend Collectives.
crates: [ ]
+4 -6
View File
@@ -78,8 +78,7 @@ fn create_approved_proposals<T: Config<I>, I: 'static>(n: u32) -> Result<(), &'s
#[allow(deprecated)]
Treasury::<T, I>::propose_spend(RawOrigin::Signed(caller).into(), value, lookup)?;
let proposal_id = <ProposalCount<T, I>>::get() - 1;
#[allow(deprecated)]
Treasury::<T, I>::approve_proposal(RawOrigin::Root.into(), proposal_id)?;
Approvals::<T, I>::try_append(proposal_id).unwrap();
}
ensure!(<Approvals<T, I>>::get().len() == n as usize, "Not all approved");
Ok(())
@@ -163,6 +162,8 @@ mod benchmarks {
fn approve_proposal(
p: Linear<0, { T::MaxApprovals::get() - 1 }>,
) -> Result<(), BenchmarkError> {
let approve_origin =
T::ApproveOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
create_approved_proposals::<T, _>(p)?;
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(SEED);
#[allow(deprecated)]
@@ -172,8 +173,6 @@ mod benchmarks {
beneficiary_lookup,
)?;
let proposal_id = Treasury::<T, _>::proposal_count() - 1;
let approve_origin =
T::ApproveOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
#[extrinsic_call]
_(approve_origin as T::RuntimeOrigin, proposal_id);
@@ -191,8 +190,7 @@ mod benchmarks {
beneficiary_lookup,
)?;
let proposal_id = Treasury::<T, _>::proposal_count() - 1;
#[allow(deprecated)]
Treasury::<T, I>::approve_proposal(RawOrigin::Root.into(), proposal_id)?;
Approvals::<T, _>::try_append(proposal_id).unwrap();
let reject_origin =
T::RejectOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;