pallet_collective_proxy/lib.rs
1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19#![cfg_attr(not(feature = "std"), no_std)]
20
21use frame_support::{
22 dispatch::GetDispatchInfo,
23 pallet_prelude::*,
24 traits::{InstanceFilter, IsType, OriginTrait},
25};
26use frame_system::pallet_prelude::*;
27use sp_runtime::traits::Dispatchable;
28use sp_std::prelude::*;
29
30pub use pallet::*;
31
32#[cfg(test)]
33mod mock;
34#[cfg(test)]
35mod tests;
36
37#[cfg(feature = "runtime-benchmarks")]
38mod benchmarking;
39
40pub mod weights;
41pub use weights::WeightInfo;
42
43#[frame_support::pallet]
44pub mod pallet {
45 use super::*;
46
47 #[pallet::pallet]
48 pub struct Pallet<T>(_);
49
50 // TODO: The pallet is intentionally very basic. It could be improved to handle more origins, more aliases, etc.
51 // There could also be different instances, if such approach was needed.
52 // However, it's supposed to be the simplest solution possible to cover a specific scenario.
53 // Pallet is stateless and can easily be upgraded in the future.
54
55 /// Configuration trait.
56 #[pallet::config]
57 pub trait Config: frame_system::Config {
58 /// The overarching call type.
59 type RuntimeCall: Parameter
60 + Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
61 + GetDispatchInfo
62 + From<frame_system::Call<Self>>
63 + IsType<<Self as frame_system::Config>::RuntimeCall>;
64
65 /// Origin that can act on behalf of the collective.
66 type CollectiveProxy: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
67
68 /// Account representing the collective treasury.
69 type ProxyAccountId: Get<Self::AccountId>;
70
71 /// Filter to determine whether a call can be executed or not.
72 type CallFilter: InstanceFilter<<Self as Config>::RuntimeCall> + Default;
73
74 /// Weight info
75 type WeightInfo: WeightInfo;
76 }
77
78 #[pallet::event]
79 #[pallet::generate_deposit(pub(super) fn deposit_event)]
80 pub enum Event<T: Config> {
81 /// Community proxy call executed successfully.
82 CollectiveProxyExecuted { result: DispatchResult },
83 }
84
85 #[pallet::call]
86 impl<T: Config> Pallet<T> {
87 /// Executes the call on a behalf of an aliased account.
88 ///
89 /// The `origin` of the call is supposed to be a _collective_ (but can be anything) which can dispatch `call` on behalf of the aliased account.
90 /// It's essentially a proxy call that can be made by arbitrary origin type.
91 #[pallet::call_index(0)]
92 #[pallet::weight({
93 let di = call.get_dispatch_info();
94 (T::WeightInfo::execute_call().saturating_add(di.total_weight()), di.class)
95 })]
96 pub fn execute_call(
97 origin: OriginFor<T>,
98 call: Box<<T as Config>::RuntimeCall>,
99 ) -> DispatchResult {
100 // Ensure origin is valid.
101 T::CollectiveProxy::ensure_origin(origin)?;
102
103 // Account authentication is ensured by the `CollectiveProxy` origin check.
104 let mut origin: T::RuntimeOrigin =
105 frame_system::RawOrigin::Signed(T::ProxyAccountId::get()).into();
106
107 // Ensure custom filter is applied.
108 origin.add_filter(move |c: &<T as frame_system::Config>::RuntimeCall| {
109 let c = <T as Config>::RuntimeCall::from_ref(c);
110 T::CallFilter::default().filter(c)
111 });
112
113 // Dispatch the call.
114 let e = call.dispatch(origin);
115 Self::deposit_event(Event::CollectiveProxyExecuted {
116 result: e.map(|_| ()).map_err(|e| e.error),
117 });
118
119 Ok(())
120 }
121 }
122}