Skip to content

Commit ae4a15e

Browse files
committed
bring in proxy pallet code & skip pays::No
1 parent 53154e4 commit ae4a15e

File tree

8 files changed

+2624
-3
lines changed

8 files changed

+2624
-3
lines changed

Cargo.lock

Lines changed: 18 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pallet-insecure-randomness-collective-flip = { git = "https://github.com/parityt
104104
pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
105105
pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
106106
pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
107-
pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
107+
pallet-proxy = { path = "pallets/proxy", default-features = false }
108108
pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
109109
pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }
110110
pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409", default-features = false }

pallets/proxy/Cargo.toml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[package]
2+
name = "pallet-proxy"
3+
version = "38.0.0"
4+
authors = ["Bittensor Nucleus Team"]
5+
edition = "2021"
6+
license = "Apache-2.0"
7+
homepage = "https://bittensor.com"
8+
description = "FRAME proxying pallet"
9+
readme = "README.md"
10+
11+
[lints]
12+
workspace = true
13+
14+
[package.metadata.docs.rs]
15+
targets = ["x86_64-unknown-linux-gnu"]
16+
17+
[dependencies]
18+
codec = { features = ["max-encoded-len"], workspace = true }
19+
scale-info = { features = ["derive"], workspace = true }
20+
frame-benchmarking = { optional = true, workspace = true }
21+
frame-support.workspace = true
22+
frame-system.workspace = true
23+
sp-io.workspace = true
24+
sp-runtime.workspace = true
25+
26+
[dev-dependencies]
27+
pallet-balances = { default-features = true, workspace = true }
28+
pallet-utility = { default-features = true, workspace = true }
29+
sp-core = { default-features = true, workspace = true }
30+
31+
[features]
32+
default = ["std"]
33+
std = [
34+
"codec/std",
35+
"frame-benchmarking?/std",
36+
"frame-support/std",
37+
"frame-system/std",
38+
"scale-info/std",
39+
"sp-io/std",
40+
"sp-runtime/std",
41+
]
42+
runtime-benchmarks = [
43+
"frame-benchmarking/runtime-benchmarks",
44+
"frame-support/runtime-benchmarks",
45+
"frame-system/runtime-benchmarks",
46+
"sp-runtime/runtime-benchmarks",
47+
"pallet-balances/runtime-benchmarks",
48+
"pallet-utility/runtime-benchmarks"
49+
]
50+
try-runtime = [
51+
"frame-support/try-runtime",
52+
"frame-system/try-runtime",
53+
"sp-runtime/try-runtime",
54+
"pallet-balances/try-runtime",
55+
"pallet-utility/try-runtime"
56+
]

pallets/proxy/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Proxy Module
2+
A module allowing accounts to give permission to other accounts to dispatch types of calls from
3+
their signed origin.
4+
5+
The accounts to which permission is delegated may be required to announce the action that they
6+
wish to execute some duration prior to execution happens. In this case, the target account may
7+
reject the announcement and in doing so, veto the execution.
8+
9+
- [`Config`](https://docs.rs/pallet-proxy/latest/pallet_proxy/pallet/trait.Config.html)
10+
- [`Call`](https://docs.rs/pallet-proxy/latest/pallet_proxy/pallet/enum.Call.html)
11+
12+
## Overview
13+
14+
## Interface
15+
16+
### Dispatchable Functions
17+
18+
[`Call`]: ./enum.Call.html
19+
[`Config`]: ./trait.Config.html
20+
21+
License: Apache-2.0
22+
23+
24+
## Release
25+
26+
Polkadot SDK stable2409

pallets/proxy/src/benchmarking.rs

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
// Benchmarks for Proxy Pallet
19+
20+
#![cfg(feature = "runtime-benchmarks")]
21+
22+
use super::*;
23+
use crate::Pallet as Proxy;
24+
use alloc::{boxed::Box, vec};
25+
use frame_benchmarking::v1::{account, benchmarks, whitelisted_caller};
26+
use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
27+
use sp_runtime::traits::Bounded;
28+
29+
const SEED: u32 = 0;
30+
31+
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
32+
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
33+
}
34+
35+
fn add_proxies<T: Config>(n: u32, maybe_who: Option<T::AccountId>) -> Result<(), &'static str> {
36+
let caller = maybe_who.unwrap_or_else(whitelisted_caller);
37+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
38+
for i in 0..n {
39+
let real = T::Lookup::unlookup(account("target", i, SEED));
40+
41+
Proxy::<T>::add_proxy(
42+
RawOrigin::Signed(caller.clone()).into(),
43+
real,
44+
T::ProxyType::default(),
45+
BlockNumberFor::<T>::zero(),
46+
)?;
47+
}
48+
Ok(())
49+
}
50+
51+
fn add_announcements<T: Config>(
52+
n: u32,
53+
maybe_who: Option<T::AccountId>,
54+
maybe_real: Option<T::AccountId>,
55+
) -> Result<(), &'static str> {
56+
let caller = maybe_who.unwrap_or_else(|| account("caller", 0, SEED));
57+
let caller_lookup = T::Lookup::unlookup(caller.clone());
58+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
59+
let real = if let Some(real) = maybe_real {
60+
real
61+
} else {
62+
let real = account("real", 0, SEED);
63+
T::Currency::make_free_balance_be(&real, BalanceOf::<T>::max_value() / 2u32.into());
64+
Proxy::<T>::add_proxy(
65+
RawOrigin::Signed(real.clone()).into(),
66+
caller_lookup,
67+
T::ProxyType::default(),
68+
BlockNumberFor::<T>::zero(),
69+
)?;
70+
real
71+
};
72+
let real_lookup = T::Lookup::unlookup(real);
73+
for _ in 0..n {
74+
Proxy::<T>::announce(
75+
RawOrigin::Signed(caller.clone()).into(),
76+
real_lookup.clone(),
77+
T::CallHasher::hash_of(&("add_announcement", n)),
78+
)?;
79+
}
80+
Ok(())
81+
}
82+
83+
benchmarks! {
84+
proxy {
85+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
86+
// In this case the caller is the "target" proxy
87+
let caller: T::AccountId = account("target", p - 1, SEED);
88+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
89+
// ... and "real" is the traditional caller. This is not a typo.
90+
let real: T::AccountId = whitelisted_caller();
91+
let real_lookup = T::Lookup::unlookup(real);
92+
let call: <T as Config>::RuntimeCall = frame_system::Call::<T>::remark { remark: vec![] }.into();
93+
}: _(RawOrigin::Signed(caller), real_lookup, Some(T::ProxyType::default()), Box::new(call))
94+
verify {
95+
assert_last_event::<T>(Event::ProxyExecuted { result: Ok(()) }.into())
96+
}
97+
98+
proxy_announced {
99+
let a in 0 .. T::MaxPending::get() - 1;
100+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
101+
// In this case the caller is the "target" proxy
102+
let caller: T::AccountId = account("pure", 0, SEED);
103+
let delegate: T::AccountId = account("target", p - 1, SEED);
104+
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
105+
T::Currency::make_free_balance_be(&delegate, BalanceOf::<T>::max_value() / 2u32.into());
106+
// ... and "real" is the traditional caller. This is not a typo.
107+
let real: T::AccountId = whitelisted_caller();
108+
let real_lookup = T::Lookup::unlookup(real);
109+
let call: <T as Config>::RuntimeCall = frame_system::Call::<T>::remark { remark: vec![] }.into();
110+
Proxy::<T>::announce(
111+
RawOrigin::Signed(delegate.clone()).into(),
112+
real_lookup.clone(),
113+
T::CallHasher::hash_of(&call),
114+
)?;
115+
add_announcements::<T>(a, Some(delegate.clone()), None)?;
116+
}: _(RawOrigin::Signed(caller), delegate_lookup, real_lookup, Some(T::ProxyType::default()), Box::new(call))
117+
verify {
118+
assert_last_event::<T>(Event::ProxyExecuted { result: Ok(()) }.into())
119+
}
120+
121+
remove_announcement {
122+
let a in 0 .. T::MaxPending::get() - 1;
123+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
124+
// In this case the caller is the "target" proxy
125+
let caller: T::AccountId = account("target", p - 1, SEED);
126+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
127+
// ... and "real" is the traditional caller. This is not a typo.
128+
let real: T::AccountId = whitelisted_caller();
129+
let real_lookup = T::Lookup::unlookup(real);
130+
let call: <T as Config>::RuntimeCall = frame_system::Call::<T>::remark { remark: vec![] }.into();
131+
Proxy::<T>::announce(
132+
RawOrigin::Signed(caller.clone()).into(),
133+
real_lookup.clone(),
134+
T::CallHasher::hash_of(&call),
135+
)?;
136+
add_announcements::<T>(a, Some(caller.clone()), None)?;
137+
}: _(RawOrigin::Signed(caller.clone()), real_lookup, T::CallHasher::hash_of(&call))
138+
verify {
139+
let (announcements, _) = Announcements::<T>::get(&caller);
140+
assert_eq!(announcements.len() as u32, a);
141+
}
142+
143+
reject_announcement {
144+
let a in 0 .. T::MaxPending::get() - 1;
145+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
146+
// In this case the caller is the "target" proxy
147+
let caller: T::AccountId = account("target", p - 1, SEED);
148+
let caller_lookup = T::Lookup::unlookup(caller.clone());
149+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
150+
// ... and "real" is the traditional caller. This is not a typo.
151+
let real: T::AccountId = whitelisted_caller();
152+
let real_lookup = T::Lookup::unlookup(real.clone());
153+
let call: <T as Config>::RuntimeCall = frame_system::Call::<T>::remark { remark: vec![] }.into();
154+
Proxy::<T>::announce(
155+
RawOrigin::Signed(caller.clone()).into(),
156+
real_lookup,
157+
T::CallHasher::hash_of(&call),
158+
)?;
159+
add_announcements::<T>(a, Some(caller.clone()), None)?;
160+
}: _(RawOrigin::Signed(real), caller_lookup, T::CallHasher::hash_of(&call))
161+
verify {
162+
let (announcements, _) = Announcements::<T>::get(&caller);
163+
assert_eq!(announcements.len() as u32, a);
164+
}
165+
166+
announce {
167+
let a in 0 .. T::MaxPending::get() - 1;
168+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
169+
// In this case the caller is the "target" proxy
170+
let caller: T::AccountId = account("target", p - 1, SEED);
171+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
172+
// ... and "real" is the traditional caller. This is not a typo.
173+
let real: T::AccountId = whitelisted_caller();
174+
let real_lookup = T::Lookup::unlookup(real.clone());
175+
add_announcements::<T>(a, Some(caller.clone()), None)?;
176+
let call: <T as Config>::RuntimeCall = frame_system::Call::<T>::remark { remark: vec![] }.into();
177+
let call_hash = T::CallHasher::hash_of(&call);
178+
}: _(RawOrigin::Signed(caller.clone()), real_lookup, call_hash)
179+
verify {
180+
assert_last_event::<T>(Event::Announced { real, proxy: caller, call_hash }.into());
181+
}
182+
183+
add_proxy {
184+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
185+
let caller: T::AccountId = whitelisted_caller();
186+
let real = T::Lookup::unlookup(account("target", T::MaxProxies::get(), SEED));
187+
}: _(
188+
RawOrigin::Signed(caller.clone()),
189+
real,
190+
T::ProxyType::default(),
191+
BlockNumberFor::<T>::zero()
192+
)
193+
verify {
194+
let (proxies, _) = Proxies::<T>::get(caller);
195+
assert_eq!(proxies.len() as u32, p + 1);
196+
}
197+
198+
remove_proxy {
199+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
200+
let caller: T::AccountId = whitelisted_caller();
201+
let delegate = T::Lookup::unlookup(account("target", 0, SEED));
202+
}: _(
203+
RawOrigin::Signed(caller.clone()),
204+
delegate,
205+
T::ProxyType::default(),
206+
BlockNumberFor::<T>::zero()
207+
)
208+
verify {
209+
let (proxies, _) = Proxies::<T>::get(caller);
210+
assert_eq!(proxies.len() as u32, p - 1);
211+
}
212+
213+
remove_proxies {
214+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
215+
let caller: T::AccountId = whitelisted_caller();
216+
}: _(RawOrigin::Signed(caller.clone()))
217+
verify {
218+
let (proxies, _) = Proxies::<T>::get(caller);
219+
assert_eq!(proxies.len() as u32, 0);
220+
}
221+
222+
create_pure {
223+
let p in 1 .. (T::MaxProxies::get() - 1) => add_proxies::<T>(p, None)?;
224+
let caller: T::AccountId = whitelisted_caller();
225+
}: _(
226+
RawOrigin::Signed(caller.clone()),
227+
T::ProxyType::default(),
228+
BlockNumberFor::<T>::zero(),
229+
0
230+
)
231+
verify {
232+
let pure_account = Pallet::<T>::pure_account(&caller, &T::ProxyType::default(), 0, None);
233+
assert_last_event::<T>(Event::PureCreated {
234+
pure: pure_account,
235+
who: caller,
236+
proxy_type: T::ProxyType::default(),
237+
disambiguation_index: 0,
238+
}.into());
239+
}
240+
241+
kill_pure {
242+
let p in 0 .. (T::MaxProxies::get() - 2);
243+
244+
let caller: T::AccountId = whitelisted_caller();
245+
let caller_lookup = T::Lookup::unlookup(caller.clone());
246+
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
247+
Pallet::<T>::create_pure(
248+
RawOrigin::Signed(whitelisted_caller()).into(),
249+
T::ProxyType::default(),
250+
BlockNumberFor::<T>::zero(),
251+
0
252+
)?;
253+
let height = system::Pallet::<T>::block_number();
254+
let ext_index = system::Pallet::<T>::extrinsic_index().unwrap_or(0);
255+
let pure_account = Pallet::<T>::pure_account(&caller, &T::ProxyType::default(), 0, None);
256+
257+
add_proxies::<T>(p, Some(pure_account.clone()))?;
258+
ensure!(Proxies::<T>::contains_key(&pure_account), "pure proxy not created");
259+
}: _(RawOrigin::Signed(pure_account.clone()), caller_lookup, T::ProxyType::default(), 0, height, ext_index)
260+
verify {
261+
assert!(!Proxies::<T>::contains_key(&pure_account));
262+
}
263+
264+
impl_benchmark_test_suite!(Proxy, crate::tests::new_test_ext(), crate::tests::Test);
265+
}

0 commit comments

Comments
 (0)