Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secretary Program #347

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
939392f
init
Doordashcon May 9, 2024
acd23f2
imp Doc comm 1
Doordashcon May 13, 2024
7d03cac
remove unreachable pattern
Doordashcon May 13, 2024
1c4659b
location
Doordashcon May 14, 2024
188759e
nit
Doordashcon May 14, 2024
154efb5
update origin, secretary submit fellowship ref
Doordashcon May 17, 2024
bea78a3
changelog include
Doordashcon May 18, 2024
c203940
update imports
Doordashcon May 20, 2024
334c35c
Merge branch 'main' into ddc-secretary-collective
Doordashcon May 20, 2024
482d0be
cargo +nightly fmt
Doordashcon May 20, 2024
d7d4b87
getting weights..
Doordashcon May 21, 2024
2e0968a
nit parameter types
Doordashcon May 21, 2024
572d398
origin update
Doordashcon Jun 1, 2024
09d317c
reset head
Doordashcon Jun 10, 2024
4e5116b
improve documentation
Doordashcon Jun 13, 2024
365d3c5
fmt
Doordashcon Jun 15, 2024
600d2c2
clippy nit
Doordashcon Jun 16, 2024
e884c30
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jun 18, 2024
bcd0a17
Fellowship Admin
Doordashcon Jun 23, 2024
47ed39e
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jul 7, 2024
7b0064a
confl-main
Doordashcon Jul 16, 2024
bdbc39b
conflict fix in progress
Doordashcon Jul 16, 2024
ef75bf7
same Cargo.toml
Doordashcon Jul 16, 2024
86d489f
Cargo.lock
Doordashcon Jul 16, 2024
313bb8c
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jul 16, 2024
d34fcb2
adjust salary periods
Doordashcon Jul 17, 2024
5722c25
doc nit
Doordashcon Jul 22, 2024
b3a82cf
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jul 23, 2024
daca216
no-op poll + nit
Doordashcon Jul 27, 2024
f8ab6a1
secretary on fellow ref submission removal
Doordashcon Jul 27, 2024
95a2cfb
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jul 27, 2024
c32eb13
nit max_ongoing
Doordashcon Jul 27, 2024
51b94ef
remove M: GetMaxVoters
Doordashcon Jul 29, 2024
eaaab37
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Jul 31, 2024
ec53bb8
changelog update
Doordashcon Jul 31, 2024
906bc10
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Aug 3, 2024
1b1e81f
rm origins && secrt
Doordashcon Aug 13, 2024
d4dac6f
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Aug 13, 2024
02f8a49
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Aug 15, 2024
a80a668
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Aug 17, 2024
1962aef
cllective
Doordashcon Aug 30, 2024
fe184d9
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Aug 30, 2024
53e60a6
Merge branch 'main' into ddc-secretary-collective2
Doordashcon Sep 4, 2024
fd82ec2
nit time crate + fmt
Doordashcon Sep 6, 2024
b34d4b1
remove {} AHP
Doordashcon Sep 6, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Kusama: Relay General Admin Origin mapping to xcm Location ([polkadot-fellows/runtimes#383](https://github.com/polkadot-fellows/runtimes/pull/383))
- Encointer, PeopleKusama, PeoplePolkadot: Configure delivery fees for UMP ([polkadot-fellows/runtimes#390](https://github.com/polkadot-fellows/runtimes/pull/390))
- The Secretary Program ([polkadot-fellows/runtimes#306](https://github.com/polkadot-fellows/runtimes/pull/306))

### Changed

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,8 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
RuntimeCall::Assets { .. } |
RuntimeCall::Utility { .. } |
RuntimeCall::Multisig { .. } |
RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. }
RuntimeCall::Nfts { .. } |
RuntimeCall::Uniques { .. }
)
},
ProxyType::AssetOwner => matches!(
Expand Down
26 changes: 26 additions & 0 deletions system-parachains/asset-hubs/asset-hub-polkadot/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ parameter_types! {
pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
}

/// Location type to determine the Technical Fellowship related
/// pallets for use in XCM.
pub struct FellowshipEntities;
impl Contains<Location> for FellowshipEntities {
fn contains(location: &Location) -> bool {
Expand Down Expand Up @@ -259,6 +261,8 @@ impl Contains<Location> for FellowshipEntities {
}
}

/// Location type to determine the Ambassador Collective
/// pallets for use in XCM.
pub struct AmbassadorEntities;
impl Contains<Location> for AmbassadorEntities {
fn contains(location: &Location) -> bool {
Expand All @@ -285,6 +289,26 @@ impl Contains<Location> for AmbassadorEntities {
}
}

/// Location type to determine the Secretary Collective related
/// pallets for use in XCM.
pub struct SecretaryEntities;
impl Contains<Location> for SecretaryEntities {
fn contains(location: &Location) -> bool {
matches!(
location.unpack(),
(
1,
[
Parachain(system_parachain::COLLECTIVES_ID),
PalletInstance(
collectives_polkadot_runtime_constants::SECRETARY_SALARY_PALLET_INDEX
)
]
)
)
}
}

pub struct ParentOrParentsPlurality;
impl Contains<Location> for ParentOrParentsPlurality {
fn contains(location: &Location) -> bool {
Expand Down Expand Up @@ -314,6 +338,7 @@ pub type Barrier = TrailingSetTopicAsId<
Equals<RelayTreasuryLocation>,
Equals<bridging::SiblingBridgeHub>,
AmbassadorEntities,
SecretaryEntities,
)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
Expand All @@ -340,6 +365,7 @@ pub type WaivedLocations = (
Equals<RelayTreasuryLocation>,
FellowshipEntities,
AmbassadorEntities,
SecretaryEntities,
);

/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ pub const AMBASSADOR_SALARY_PALLET_INDEX: u8 = 74;

/// Polkadot Ambassador Treasury pallet instance.
pub const AMBASSADOR_TREASURY_PALLET_INDEX: u8 = 75;

/// Polkadot Secretary Salary pallet instance.
pub const SECRETARY_SALARY_PALLET_INDEX: u8 = 82;
22 changes: 22 additions & 0 deletions system-parachains/collectives/collectives-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,15 @@ pub mod xcm_config;
pub mod fellowship;
pub use ambassador::pallet_ambassador_origins;

// Secretary Configuration
pub mod secretary;

use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use fellowship::{pallet_fellowship_origins, Fellows};
use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp, ToParentTreasury};
use polkadot_runtime_common::impls::VersionedLocatableAsset;
use secretary::pallet_secretary_origins;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
Expand Down Expand Up @@ -310,6 +314,8 @@ pub enum ProxyType {
Fellowship,
/// Ambassador proxy. Allows calls related to the Ambassador Program.
Ambassador,
/// Secretary proxy. Allows calls related to the Secretary collective
Secretary,
}
impl Default for ProxyType {
fn default() -> Self {
Expand Down Expand Up @@ -356,6 +362,13 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
RuntimeCall::Utility { .. } |
RuntimeCall::Multisig { .. }
),
ProxyType::Secretary => matches!(
c,
RuntimeCall::SecretaryCollective { .. } |
RuntimeCall::SecretarySalary { .. } |
RuntimeCall::Utility { .. } |
RuntimeCall::Multisig { .. }
),
}
}
fn is_superset(&self, o: &Self) -> bool {
Expand Down Expand Up @@ -723,6 +736,13 @@ construct_runtime!(
AmbassadorCore: pallet_core_fellowship::<Instance2> = 73,
AmbassadorSalary: pallet_salary::<Instance2> = 74,
AmbassadorTreasury: pallet_treasury::<Instance2> = 75,

// The Secretary Collective
// pub type SecretaryCollectiveInstance = pallet_ranked_cllective::instance3;
SecretaryCollective: pallet_ranked_collective::<Instance3> = 80,
SecretaryOrigins: pallet_secretary_origins = 81,
// pub type SecretarySalaryInstance = pallet_salary::Instance3;
SecretarySalary: pallet_salary::<Instance3> = 82,
}
);

Expand Down Expand Up @@ -807,6 +827,8 @@ mod benches {
[pallet_core_fellowship, AmbassadorCore]
[pallet_salary, AmbassadorSalary]
[pallet_treasury, AmbassadorTreasury]
[pallet_ranked_cllective, SecretaryCollective]
[pallet_salary, SecretarySalary]
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Copyright (C) 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/>.

//! The Polkadot Secretary Collective.

mod origins;
use core::marker::PhantomData;

use crate::{fellowship::FellowshipAdminBodyId, *};
use frame_support::{
parameter_types,
traits::{tokens::GetSalary, EitherOf, MapSuccess, PalletInfoAccess, PollStatus, Polling},
};
use frame_system::{pallet_prelude::BlockNumberFor, EnsureRootWithSuccess};
pub use origins::{pallet_origins as pallet_secretary_origins, Secretary};
use pallet_ranked_collective::{GetMaxVoters, MemberIndex, TallyOf, Votes};
use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
use polkadot_runtime_constants::time::HOURS;
use sp_core::{ConstU128, ConstU32};
use sp_runtime::{
traits::{ConstU16, ConvertToValue, Identity, Replace},
DispatchError,
};

use xcm::prelude::*;
use xcm_builder::{AliasesIntoAccountId32, PayOverXcm};

use self::xcm_config::AssetHubUsdt;

/// The Secretary members' ranks.
pub mod ranks {
use pallet_ranked_collective::Rank;

pub const SECRETARY_CANDIDATE: Rank = 0;
pub const SECRETARY: Rank = 1;
}

/// Origins of:
/// - Root;
/// - FellowshipAdmin (i.e. token holder referendum);
/// - Plurality vote from Fellows can promote, demote, remove and approve rank retention
/// of members of the Secretary Collective (rank `2`).
type ApproveOrigin = EitherOf<
EnsureRootWithSuccess<AccountId, ConstU16<65535>>,
EitherOf<
MapSuccess<
EnsureXcm<IsVoiceOfBody<GovernanceLocation, FellowshipAdminBodyId>>,
Replace<ConstU16<65535>>,
>,
MapSuccess<Fellows, Replace<ConstU16<65535>>>,
>,
>;

impl pallet_secretary_origins::Config for Runtime {}

pub struct NoopGetMaxVoters;

impl GetMaxVoters for NoopGetMaxVoters {
type Class = u16;

fn get_max_voters(_c: Self::Class) -> MemberIndex {
0 // No-op implementation always returns 0
}
}

pub struct SecretaryPolling<T: pallet_ranked_collective::Config<I>, I: 'static, M: GetMaxVoters>(
PhantomData<(T, I, M)>,
);

impl<T: pallet_ranked_collective::Config<I>, I: 'static, M: GetMaxVoters> Polling<TallyOf<T, I>>
Doordashcon marked this conversation as resolved.
Show resolved Hide resolved
for SecretaryPolling<T, I, M>
{
type Index = MemberIndex;
type Votes = Votes;
type Class = u16;
type Moment = BlockNumberFor<T>;

fn classes() -> Vec<Self::Class> {
vec![]
}

fn as_ongoing(_index: Self::Index) -> Option<(TallyOf<T, I>, Self::Class)> {
None
}

fn access_poll<R>(
_index: Self::Index,
f: impl FnOnce(PollStatus<&mut TallyOf<T, I>, Self::Moment, Self::Class>) -> R,
) -> R {
f(PollStatus::None)
}

fn try_access_poll<R>(
_index: Self::Index,
f: impl FnOnce(
PollStatus<&mut TallyOf<T, I>, Self::Moment, Self::Class>,
) -> Result<R, DispatchError>,
) -> Result<R, DispatchError> {
f(PollStatus::None)
}

#[cfg(feature = "runtime-benchmarks")]
fn create_ongoing(_class: Self::Class) -> Result<Self::Index, ()> {
Err(())
}

#[cfg(feature = "runtime-benchmarks")]
fn end_ongoing(_index: Self::Index, _approved: bool) -> Result<(), ()> {
Err(())
}

#[cfg(feature = "runtime-benchmarks")]
fn max_ongoing() -> (Self::Class, u32) {
(0, 0)
}
}

pub type SecretaryCollectiveInstance = pallet_ranked_collective::Instance3;

impl pallet_ranked_collective::Config<SecretaryCollectiveInstance> for Runtime {
type WeightInfo = (); // TODO weights::pallet_ranked_collective_secretary_collective::WeightInfo<Runtime>;
type RuntimeEvent = RuntimeEvent;
type AddOrigin = ApproveOrigin;
type RemoveOrigin = ApproveOrigin;
type PromoteOrigin = ApproveOrigin;
type DemoteOrigin = ApproveOrigin;
type ExchangeOrigin = ApproveOrigin;
type Polls = SecretaryPolling<Runtime, SecretaryCollectiveInstance, NoopGetMaxVoters>;
type MinRankOfClass = Identity;
type MemberSwappedHandler = crate::SecretarySalary;
type VoteWeight = pallet_ranked_collective::Geometric;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkSetup = crate::SecretarySalary;
}

pub type SecretarySalaryInstance = pallet_salary::Instance3;

parameter_types! {
// The interior location on AssetHub for the paying account. This is the Secretary Salary
// pallet instance. This sovereign account will need funding.
pub SecretarySalaryInteriorLocation: InteriorLocation = PalletInstance(<crate::SecretarySalary as PalletInfoAccess>::index() as u8).into();
}

const USDT_UNITS: u128 = 1_000_000;
Doordashcon marked this conversation as resolved.
Show resolved Hide resolved

/// [`PayOverXcm`] setup to pay the Secretary salary on the AssetHub in USDT.
pub type SecretarySalaryPaymaster = PayOverXcm<
SecretarySalaryInteriorLocation,
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be the fellowship interior account, because the secretary should be paid by the same account. Or we move some funds.

@joepetrowski @muharem WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe better separate account for a separate accounting. But can be funded from the fellowship sub treasury. No strong opinion. Let's hear Joe opinion.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we control the account using a fellowship proposal?

Copy link
Contributor

Choose a reason for hiding this comment

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

Are the secretaries only for the Fellowship? I thought the program was meant to include secretaries for other collectives as well. If it's just for the Fellowship, then yeah we should just pay them from the Fellowship salary account. But if it's meant to serve others, then I think they can have their own sub-treasury and make proposals for funding to the collectives that they provide secretary services for.

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 the current idea is to enable the secretary collective for the technical fellowship for now until more ideas and participants are clearer, rather than having a tresury implementation for just one member. The salary payout account can be changed to the technical fellowship interior account IMO.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Doordashcon what do you mean?

Copy link
Contributor Author

@Doordashcon Doordashcon Aug 9, 2024

Choose a reason for hiding this comment

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

@joepetrowski highlighted that using the Fellowship Salary account would be a wrong direction because of needing migration later on.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not the "wrong" direction, it's a choice. I see two solutions:

  1. Special rank of Secretary within Ranked Collective (it doesn't need to be called that in the pallet, could even be a rank 10 for example and the origins are configured to treat that as special);
  2. Separate Secretary collective with its own sub-treasury.

In the case of (1), it would naturally just use the specific collective's sub-treasury. In the case of (2), each collective that the Secretary collective serves would have to chip in funds to pay for the Secretary collective's services.

The only thing that is wrong IMO is to make one Secretary collective for every other collective (effectively halving the total number of collectives that the chain can support).

Copy link
Contributor Author

@Doordashcon Doordashcon Aug 9, 2024

Choose a reason for hiding this comment

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

Thank you for the clarification, @muharem suggested we don't need the Tresury implementation, the Secretary Salary account can be funded using the Technical fellowship sub-treasury.

When more members join who perform operations for other collectives, those collectives can also fund the Salary account using their respective sub-tresuries, a blocker to this might be the refusal of those collectives to comply.

But a need for another Secretary member would have to arise before considering adding another member to the collective.

We won't have a Secretary collective for every other collective, just the one and add more member through the demand for another that serves a seperate collective.

I hope I have been able to understand the suggestions clearly so far 🙏.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we do not need a sub treasury to pay salaries or fund the Secretary salary account. The whole Secretary can be setup as ranked collective pallet and salary pallet and can serve later secretaries for all collectives. We can even have a different salary accounts for different secretary ranks if needed later. They can be funded by other collective's sub treasuries or the Polkadot Treasury. We do not need referenda and origins because in all cases right now we just need to check if the account belongs to a certain rank of the collective, no plurality voice needed.

crate::xcm_config::XcmRouter,
crate::PolkadotXcm,
ConstU32<{ 6 * HOURS }>,
AccountId,
(),
ConvertToValue<AssetHubUsdt>,
AliasesIntoAccountId32<(), AccountId>,
>;

pub struct SalaryForRank;
impl GetSalary<u16, AccountId, Balance> for SalaryForRank {
fn get_salary(rank: u16, _who: &AccountId) -> Balance {
if rank == 1 {
6666 * USDT_UNITS
} else {
0
}
}
}

impl pallet_salary::Config<SecretarySalaryInstance> for Runtime {
type WeightInfo = (); // TODO weights::pallet_salary_secretary_salary::WeightInfo<Runtime>;
type RuntimeEvent = RuntimeEvent;

#[cfg(not(feature = "runtime-benchmarks"))]
type Paymaster = SecretarySalaryPaymaster;
#[cfg(feature = "runtime-benchmarks")]
type Paymaster = crate::impls::benchmarks::PayWithEnsure<
SecretarySalaryPaymaster,
crate::impls::benchmarks::OpenHrmpChannel<ConstU32<1000>>,
>;
type Members = pallet_ranked_collective::Pallet<Runtime, SecretaryCollectiveInstance>;

#[cfg(not(feature = "runtime-benchmarks"))]
type Salary = SalaryForRank;
#[cfg(feature = "runtime-benchmarks")]
type Salary = frame_support::traits::tokens::ConvertRank<
crate::impls::benchmarks::RankToSalary<Balances>,
>;
// 15 days to register for a salary payment.
type RegistrationPeriod = ConstU32<{ 15 * DAYS }>;
// 15 days to claim the salary payment.
type PayoutPeriod = ConstU32<{ 15 * DAYS }>;
// Total monthly salary budget.
type Budget = ConstU128<{ 6666 * USDT_UNITS }>;
}
Loading
Loading