1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Polkadot is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Polkadot is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Elements of governance concerning the Starlight Fellowship.
18

            
19
use {
20
    frame_support::traits::{MapSuccess, TryMapSuccess},
21
    sp_runtime::str_array as s,
22
    sp_runtime::traits::{CheckedReduceBy, ConstU16, Replace, ReplaceWithDefault},
23
};
24

            
25
use {
26
    super::*,
27
    crate::{CENTS, DAYS},
28
};
29

            
30
parameter_types! {
31
    pub const AlarmInterval: BlockNumber = 1;
32
    pub const SubmissionDeposit: Balance = 0;
33
    pub const UndecidingTimeout: BlockNumber = 7 * DAYS;
34
}
35

            
36
pub struct TracksInfo;
37
impl pallet_referenda::TracksInfo<Balance, BlockNumber> for TracksInfo {
38
    type Id = u16;
39
    type RuntimeOrigin = <RuntimeOrigin as frame_support::traits::OriginTrait>::PalletsOrigin;
40
1
    fn tracks(
41
1
    ) -> impl Iterator<Item = Cow<'static, pallet_referenda::Track<Self::Id, Balance, BlockNumber>>>
42
1
    {
43
        static DATA: [pallet_referenda::Track<u16, Balance, BlockNumber>; 10] = [
44
            pallet_referenda::Track {
45
                id: 0,
46
                info: pallet_referenda::TrackInfo {
47
                    name: s("candidates"),
48
                    max_deciding: 10,
49
                    decision_deposit: 100 * 3 * CENTS,
50
                    prepare_period: 30 * MINUTES,
51
                    decision_period: 7 * DAYS,
52
                    confirm_period: 30 * MINUTES,
53
                    min_enactment_period: 1 * MINUTES,
54
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
55
                        length: Perbill::from_percent(100),
56
                        floor: Perbill::from_percent(50),
57
                        ceil: Perbill::from_percent(100),
58
                    },
59
                    min_support: pallet_referenda::Curve::LinearDecreasing {
60
                        length: Perbill::from_percent(100),
61
                        floor: Perbill::from_percent(0),
62
                        ceil: Perbill::from_percent(50),
63
                    },
64
                },
65
            },
66
            pallet_referenda::Track {
67
                id: 1,
68
                info: pallet_referenda::TrackInfo {
69
                    name: s("members"),
70
                    max_deciding: 10,
71
                    decision_deposit: 10 * 3 * CENTS,
72
                    prepare_period: 30 * MINUTES,
73
                    decision_period: 7 * DAYS,
74
                    confirm_period: 30 * MINUTES,
75
                    min_enactment_period: 1 * MINUTES,
76
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
77
                        length: Perbill::from_percent(100),
78
                        floor: Perbill::from_percent(50),
79
                        ceil: Perbill::from_percent(100),
80
                    },
81
                    min_support: pallet_referenda::Curve::LinearDecreasing {
82
                        length: Perbill::from_percent(100),
83
                        floor: Perbill::from_percent(0),
84
                        ceil: Perbill::from_percent(50),
85
                    },
86
                },
87
            },
88
            pallet_referenda::Track {
89
                id: 2,
90
                info: pallet_referenda::TrackInfo {
91
                    name: s("proficients"),
92
                    max_deciding: 10,
93
                    decision_deposit: 10 * 3 * CENTS,
94
                    prepare_period: 30 * MINUTES,
95
                    decision_period: 7 * DAYS,
96
                    confirm_period: 30 * MINUTES,
97
                    min_enactment_period: 1 * MINUTES,
98
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
99
                        length: Perbill::from_percent(100),
100
                        floor: Perbill::from_percent(50),
101
                        ceil: Perbill::from_percent(100),
102
                    },
103
                    min_support: pallet_referenda::Curve::LinearDecreasing {
104
                        length: Perbill::from_percent(100),
105
                        floor: Perbill::from_percent(0),
106
                        ceil: Perbill::from_percent(50),
107
                    },
108
                },
109
            },
110
            pallet_referenda::Track {
111
                id: 3,
112
                info: pallet_referenda::TrackInfo {
113
                    name: s("fellows"),
114
                    max_deciding: 10,
115
                    decision_deposit: 10 * 3 * CENTS,
116
                    prepare_period: 30 * MINUTES,
117
                    decision_period: 7 * DAYS,
118
                    confirm_period: 30 * MINUTES,
119
                    min_enactment_period: 1 * MINUTES,
120
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
121
                        length: Perbill::from_percent(100),
122
                        floor: Perbill::from_percent(50),
123
                        ceil: Perbill::from_percent(100),
124
                    },
125
                    min_support: pallet_referenda::Curve::LinearDecreasing {
126
                        length: Perbill::from_percent(100),
127
                        floor: Perbill::from_percent(0),
128
                        ceil: Perbill::from_percent(50),
129
                    },
130
                },
131
            },
132
            pallet_referenda::Track {
133
                id: 4,
134
                info: pallet_referenda::TrackInfo {
135
                    name: s("senior fellows"),
136
                    max_deciding: 10,
137
                    decision_deposit: 10 * 3 * CENTS,
138
                    prepare_period: 30 * MINUTES,
139
                    decision_period: 7 * DAYS,
140
                    confirm_period: 30 * MINUTES,
141
                    min_enactment_period: 1 * MINUTES,
142
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
143
                        length: Perbill::from_percent(100),
144
                        floor: Perbill::from_percent(50),
145
                        ceil: Perbill::from_percent(100),
146
                    },
147
                    min_support: pallet_referenda::Curve::LinearDecreasing {
148
                        length: Perbill::from_percent(100),
149
                        floor: Perbill::from_percent(0),
150
                        ceil: Perbill::from_percent(50),
151
                    },
152
                },
153
            },
154
            pallet_referenda::Track {
155
                id: 5,
156
                info: pallet_referenda::TrackInfo {
157
                    name: s("experts"),
158
                    max_deciding: 10,
159
                    decision_deposit: 1 * 3 * CENTS,
160
                    prepare_period: 30 * MINUTES,
161
                    decision_period: 7 * DAYS,
162
                    confirm_period: 30 * MINUTES,
163
                    min_enactment_period: 1 * MINUTES,
164
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
165
                        length: Perbill::from_percent(100),
166
                        floor: Perbill::from_percent(50),
167
                        ceil: Perbill::from_percent(100),
168
                    },
169
                    min_support: pallet_referenda::Curve::LinearDecreasing {
170
                        length: Perbill::from_percent(100),
171
                        floor: Perbill::from_percent(0),
172
                        ceil: Perbill::from_percent(50),
173
                    },
174
                },
175
            },
176
            pallet_referenda::Track {
177
                id: 6,
178
                info: pallet_referenda::TrackInfo {
179
                    name: s("senior experts"),
180
                    max_deciding: 10,
181
                    decision_deposit: 1 * 3 * CENTS,
182
                    prepare_period: 30 * MINUTES,
183
                    decision_period: 7 * DAYS,
184
                    confirm_period: 30 * MINUTES,
185
                    min_enactment_period: 1 * MINUTES,
186
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
187
                        length: Perbill::from_percent(100),
188
                        floor: Perbill::from_percent(50),
189
                        ceil: Perbill::from_percent(100),
190
                    },
191
                    min_support: pallet_referenda::Curve::LinearDecreasing {
192
                        length: Perbill::from_percent(100),
193
                        floor: Perbill::from_percent(0),
194
                        ceil: Perbill::from_percent(50),
195
                    },
196
                },
197
            },
198
            pallet_referenda::Track {
199
                id: 7,
200
                info: pallet_referenda::TrackInfo {
201
                    name: s("masters"),
202
                    max_deciding: 10,
203
                    decision_deposit: 1 * 3 * CENTS,
204
                    prepare_period: 30 * MINUTES,
205
                    decision_period: 7 * DAYS,
206
                    confirm_period: 30 * MINUTES,
207
                    min_enactment_period: 1 * MINUTES,
208
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
209
                        length: Perbill::from_percent(100),
210
                        floor: Perbill::from_percent(50),
211
                        ceil: Perbill::from_percent(100),
212
                    },
213
                    min_support: pallet_referenda::Curve::LinearDecreasing {
214
                        length: Perbill::from_percent(100),
215
                        floor: Perbill::from_percent(0),
216
                        ceil: Perbill::from_percent(50),
217
                    },
218
                },
219
            },
220
            pallet_referenda::Track {
221
                id: 8,
222
                info: pallet_referenda::TrackInfo {
223
                    name: s("senior masters"),
224
                    max_deciding: 10,
225
                    decision_deposit: 1 * 3 * CENTS,
226
                    prepare_period: 30 * MINUTES,
227
                    decision_period: 7 * DAYS,
228
                    confirm_period: 30 * MINUTES,
229
                    min_enactment_period: 1 * MINUTES,
230
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
231
                        length: Perbill::from_percent(100),
232
                        floor: Perbill::from_percent(50),
233
                        ceil: Perbill::from_percent(100),
234
                    },
235
                    min_support: pallet_referenda::Curve::LinearDecreasing {
236
                        length: Perbill::from_percent(100),
237
                        floor: Perbill::from_percent(0),
238
                        ceil: Perbill::from_percent(50),
239
                    },
240
                },
241
            },
242
            pallet_referenda::Track {
243
                id: 9,
244
                info: pallet_referenda::TrackInfo {
245
                    name: s("grand masters"),
246
                    max_deciding: 10,
247
                    decision_deposit: 1 * 3 * CENTS,
248
                    prepare_period: 30 * MINUTES,
249
                    decision_period: 7 * DAYS,
250
                    confirm_period: 30 * MINUTES,
251
                    min_enactment_period: 1 * MINUTES,
252
                    min_approval: pallet_referenda::Curve::LinearDecreasing {
253
                        length: Perbill::from_percent(100),
254
                        floor: Perbill::from_percent(50),
255
                        ceil: Perbill::from_percent(100),
256
                    },
257
                    min_support: pallet_referenda::Curve::LinearDecreasing {
258
                        length: Perbill::from_percent(100),
259
                        floor: Perbill::from_percent(0),
260
                        ceil: Perbill::from_percent(50),
261
                    },
262
                },
263
            },
264
        ];
265
1
        DATA.iter().map(Cow::Borrowed)
266
1
    }
267
    fn track_for(id: &Self::RuntimeOrigin) -> Result<Self::Id, ()> {
268
        use super::origins::Origin;
269

            
270
        #[cfg(feature = "runtime-benchmarks")]
271
        {
272
            // For benchmarks, we enable a root origin.
273
            // It is important that this is not available in production!
274
            let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into();
275
            if &root == id {
276
                return Ok(9);
277
            }
278
        }
279

            
280
        match Origin::try_from(id.clone()) {
281
            Ok(Origin::FellowshipInitiates) => Ok(0),
282
            Ok(Origin::Fellowship1Dan) => Ok(1),
283
            Ok(Origin::Fellowship2Dan) => Ok(2),
284
            Ok(Origin::Fellowship3Dan) | Ok(Origin::Fellows) => Ok(3),
285
            Ok(Origin::Fellowship4Dan) => Ok(4),
286
            Ok(Origin::Fellowship5Dan) | Ok(Origin::FellowshipExperts) => Ok(5),
287
            Ok(Origin::Fellowship6Dan) => Ok(6),
288
            Ok(Origin::Fellowship7Dan | Origin::FellowshipMasters) => Ok(7),
289
            Ok(Origin::Fellowship8Dan) => Ok(8),
290
            Ok(Origin::Fellowship9Dan) => Ok(9),
291
            _ => Err(()),
292
        }
293
    }
294
}
295

            
296
pub type FellowshipReferendaInstance = pallet_referenda::Instance2;
297

            
298
impl pallet_referenda::Config<FellowshipReferendaInstance> for Runtime {
299
    type WeightInfo = weights::pallet_referenda::SubstrateWeight<Runtime>;
300
    type RuntimeCall = RuntimeCall;
301
    type RuntimeEvent = RuntimeEvent;
302
    type Scheduler = Scheduler;
303
    type Currency = Balances;
304
    type SubmitOrigin =
305
        pallet_ranked_collective::EnsureMember<Runtime, FellowshipCollectiveInstance, 1>;
306
    type CancelOrigin = FellowshipExperts;
307
    type KillOrigin = FellowshipMasters;
308
    type Slash = Treasury;
309
    type Votes = pallet_ranked_collective::Votes;
310
    type Tally = pallet_ranked_collective::TallyOf<Runtime, FellowshipCollectiveInstance>;
311
    type SubmissionDeposit = SubmissionDeposit;
312
    type MaxQueued = ConstU32<100>;
313
    type UndecidingTimeout = UndecidingTimeout;
314
    type AlarmInterval = AlarmInterval;
315
    type Tracks = TracksInfo;
316
    type Preimages = Preimage;
317
    type BlockNumberProvider = System;
318
}
319

            
320
pub type FellowshipCollectiveInstance = pallet_ranked_collective::Instance1;
321

            
322
impl pallet_ranked_collective::Config<FellowshipCollectiveInstance> for Runtime {
323
    type WeightInfo = weights::pallet_ranked_collective::SubstrateWeight<Runtime>;
324
    type RuntimeEvent = RuntimeEvent;
325
    // Adding is by any of:
326
    // - Root.
327
    // - the FellowshipAdmin origin.
328
    // - a Fellowship origin.
329
    type AddOrigin = MapSuccess<Self::PromoteOrigin, ReplaceWithDefault<()>>;
330
    // Promotion is by any of:
331
    // - Root can demote arbitrarily.
332
    // - the FellowshipAdmin origin (i.e. token holder referendum);
333
    // - a vote by the rank *above* the new rank.
334
    type PromoteOrigin = EitherOf<
335
        frame_system::EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
336
        EitherOf<
337
            MapSuccess<FellowshipAdmin, Replace<ConstU16<9>>>,
338
            TryMapSuccess<origins::EnsureFellowship, CheckedReduceBy<ConstU16<1>>>,
339
        >,
340
    >;
341
    // Removing is by any of:
342
    // - Root can remove arbitrarily.
343
    // - the FellowshipAdmin origin (i.e. token holder referendum);
344
    // - a vote by the rank two above the current rank.
345
    type RemoveOrigin = Self::DemoteOrigin;
346
    // Demotion is by any of:
347
    // - Root can demote arbitrarily.
348
    // - the FellowshipAdmin origin (i.e. token holder referendum);
349
    // - a vote by the rank two above the current rank.
350
    type DemoteOrigin = EitherOf<
351
        frame_system::EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
352
        EitherOf<
353
            MapSuccess<FellowshipAdmin, Replace<ConstU16<9>>>,
354
            TryMapSuccess<origins::EnsureFellowship, CheckedReduceBy<ConstU16<2>>>,
355
        >,
356
    >;
357
    // Exchange is by any of:
358
    // - Root can exchange arbitrarily.
359
    // - the Fellows origin;
360
    type ExchangeOrigin =
361
        EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Fellows>;
362
    type Polls = FellowshipReferenda;
363
    type MinRankOfClass = sp_runtime::traits::Identity;
364
    type MemberSwappedHandler = ();
365
    type VoteWeight = pallet_ranked_collective::Geometric;
366
    type MaxMemberCount = ();
367
    #[cfg(feature = "runtime-benchmarks")]
368
    type BenchmarkSetup = ();
369
}