Migrate pallet-proxy to pallet attribute macro (#8365)

* Migrate pallet-proxy to pallet attribute macro

Part of #7882.

Converts the `Proxy` pallet to the new pallet attribute macro introduced in #6877.

[Upgrade guidelines used](https://substrate.dev/rustdocs/v3.0.0/frame_support/attr.pallet.html#upgrade-guidelines).

## ⚠️ Breaking Change  ⚠️ 

From [checking upgrade guidelines](https://crates.parity.io/frame_support/attr.pallet.html#checking-upgrade-guidelines)

> storages now use PalletInfo for module_prefix instead of the one given to `decl_storage`: use of this pallet in `construct_runtime!` needs careful updating of the name in order to not break storage or to upgrade storage (moreover for instantiable pallet). If pallet is published, make sure to warn about this breaking change.

So users of the `Assets` pallet must be careful about the name they used in `construct_runtime!`. Hence the `runtime-migration` label, which might not be needed depending on the configuration of the `Assets` pallet.

### Notes

There are some changes to the docs in metadata for the constants. The docs in the metadata for constants are now more complete.
This commit is contained in:
Zeke Mostov
2021-03-17 01:52:42 -07:00
committed by GitHub
parent 23b32e7543
commit 62abc784a4
3 changed files with 249 additions and 191 deletions
+4 -4
View File
@@ -90,7 +90,7 @@ benchmarks! {
let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
}: _(RawOrigin::Signed(caller), real, Some(T::ProxyType::default()), Box::new(call))
verify {
assert_last_event::<T>(RawEvent::ProxyExecuted(Ok(())).into())
assert_last_event::<T>(Event::ProxyExecuted(Ok(())).into())
}
proxy_announced {
@@ -111,7 +111,7 @@ benchmarks! {
add_announcements::<T>(a, Some(delegate.clone()), None)?;
}: _(RawOrigin::Signed(caller), delegate, real, Some(T::ProxyType::default()), Box::new(call))
verify {
assert_last_event::<T>(RawEvent::ProxyExecuted(Ok(())).into())
assert_last_event::<T>(Event::ProxyExecuted(Ok(())).into())
}
remove_announcement {
@@ -169,7 +169,7 @@ benchmarks! {
let call_hash = T::CallHasher::hash_of(&call);
}: _(RawOrigin::Signed(caller.clone()), real.clone(), call_hash)
verify {
assert_last_event::<T>(RawEvent::Announced(real, caller, call_hash).into());
assert_last_event::<T>(Event::Announced(real, caller, call_hash).into());
}
add_proxy {
@@ -220,7 +220,7 @@ benchmarks! {
)
verify {
let anon_account = Module::<T>::anonymous_account(&caller, &T::ProxyType::default(), 0, None);
assert_last_event::<T>(RawEvent::AnonymousCreated(
assert_last_event::<T>(Event::AnonymousCreated(
anon_account,
caller,
T::ProxyType::default(),
+222 -165
View File
@@ -15,11 +15,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! # Proxy Module
//! A module allowing accounts to give permission to other accounts to dispatch types of calls from
//! # Proxy Pallet
//! A pallet allowing accounts to give permission to other accounts to dispatch types of calls from
//! their signed origin.
//!
//! The accounts to which permission is delegated may be requied to announce the action that they
//! The accounts to which permission is delegated may be required to announce the action that they
//! wish to execute some duration prior to execution happens. In this case, the target account may
//! reject the announcement and in doing so, veto the execution.
//!
@@ -45,74 +45,26 @@ pub mod weights;
use sp_std::prelude::*;
use codec::{Encode, Decode};
use sp_io::hashing::blake2_256;
use sp_runtime::{DispatchResult, traits::{Dispatchable, Zero, Hash, Member, Saturating}};
use frame_support::{
decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug, traits::{
Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, IsType, IsSubType,
}, weights::{Weight, GetDispatchInfo}, dispatch::PostDispatchInfo, storage::IterableStorageMap,
use sp_runtime::{
DispatchResult,
traits::{Dispatchable, Zero, Hash, Saturating}
};
use frame_system::{self as system, ensure_signed};
use frame_support::{
RuntimeDebug, ensure,
dispatch::{DispatchResultWithPostInfo, PostDispatchInfo},
traits::{Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, IsType, IsSubType},
weights::{Weight, GetDispatchInfo}
};
use frame_system::{self as system};
use frame_support::dispatch::DispatchError;
pub use weights::WeightInfo;
pub use pallet::*;
type CallHashOf<T> = <<T as Config>::CallHasher as Hash>::Output;
type BalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
/// Configuration trait.
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
/// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>> + IsSubType<Call<Self>>
+ IsType<<Self as frame_system::Config>::Call>;
/// The currency mechanism.
type Currency: ReservableCurrency<Self::AccountId>;
/// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler.
/// The instance filter determines whether a given call may be proxied under this type.
///
/// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value.
type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<<Self as Config>::Call>
+ Default;
/// The base amount of currency needed to reserve for creating a proxy.
///
/// This is held for an additional storage item whose value size is
/// `sizeof(Balance)` bytes and whose key size is `sizeof(AccountId)` bytes.
type ProxyDepositBase: Get<BalanceOf<Self>>;
/// The amount of currency needed per proxy added.
///
/// This is held for adding 32 bytes plus an instance of `ProxyType` more into a pre-existing
/// storage value.
type ProxyDepositFactor: Get<BalanceOf<Self>>;
/// The maximum amount of proxies allowed for a single account.
type MaxProxies: Get<u16>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
/// The maximum amount of time-delayed announcements that are allowed to be pending.
type MaxPending: Get<u32>;
/// The type of hash used for hashing the call.
type CallHasher: Hash;
/// The base amount of currency needed to reserve for creating an announcement.
///
/// This is held when a new storage item holding a `Balance` is created (typically 16 bytes).
type AnnouncementDepositBase: Get<BalanceOf<Self>>;
/// The amount of currency needed per announcement made.
///
/// This is held for adding an `AccountId`, `Hash` and `BlockNumber` (typically 68 bytes)
/// into a pre-existing storage value.
type AnnouncementDepositFactor: Get<BalanceOf<Self>>;
}
/// The parameters under which a particular account has a proxy relationship with some other
/// account.
#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)]
@@ -137,84 +89,85 @@ pub struct Announcement<AccountId, Hash, BlockNumber> {
height: BlockNumber,
}
type CallHashOf<T> = <<T as Config>::CallHasher as Hash>::Output;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::{*, DispatchResult};
decl_storage! {
trait Store for Module<T: Config> as Proxy {
/// The set of account proxies. Maps the account which has delegated to the accounts
/// which are being delegated to, together with the amount held on deposit.
pub Proxies get(fn proxies): map hasher(twox_64_concat) T::AccountId
=> (Vec<ProxyDefinition<T::AccountId, T::ProxyType, T::BlockNumber>>, BalanceOf<T>);
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
/// The announcements made by the proxy (key).
pub Announcements get(fn announcements): map hasher(twox_64_concat) T::AccountId
=> (Vec<Announcement<T::AccountId, CallHashOf<T>, T::BlockNumber>>, BalanceOf<T>);
}
}
/// Configuration trait.
#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
decl_error! {
pub enum Error for Module<T: Config> {
/// There are too many proxies registered or too many announcements pending.
TooMany,
/// Proxy registration not found.
NotFound,
/// Sender is not a proxy of the account to be proxied.
NotProxy,
/// A call which is incompatible with the proxy type's filter was attempted.
Unproxyable,
/// Account is already a proxy.
Duplicate,
/// Call may not be made by proxy because it may escalate its privileges.
NoPermission,
/// Announcement, if made at all, was made too recently.
Unannounced,
/// Cannot add self as proxy.
NoSelfProxy,
}
}
/// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>> + IsSubType<Call<Self>>
+ IsType<<Self as frame_system::Config>::Call>;
decl_event! {
/// Events type.
pub enum Event<T> where
AccountId = <T as frame_system::Config>::AccountId,
ProxyType = <T as Config>::ProxyType,
Hash = CallHashOf<T>,
{
/// A proxy was executed correctly, with the given \[result\].
ProxyExecuted(DispatchResult),
/// Anonymous account has been created by new proxy with given
/// disambiguation index and proxy type. \[anonymous, who, proxy_type, disambiguation_index\]
AnonymousCreated(AccountId, AccountId, ProxyType, u16),
/// An announcement was placed to make a call in the future. \[real, proxy, call_hash\]
Announced(AccountId, AccountId, Hash),
}
}
/// The currency mechanism.
type Currency: ReservableCurrency<Self::AccountId>;
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
type Error = Error<T>;
/// Deposit one of this module's events by using the default implementation.
fn deposit_event() = default;
/// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler.
/// The instance filter determines whether a given call may be proxied under this type.
///
/// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value.
type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<<Self as Config>::Call>
+ Default;
/// The base amount of currency needed to reserve for creating a proxy.
const ProxyDepositBase: BalanceOf<T> = T::ProxyDepositBase::get();
///
/// This is held for an additional storage item whose value size is
/// `sizeof(Balance)` bytes and whose key size is `sizeof(AccountId)` bytes.
#[pallet::constant]
type ProxyDepositBase: Get<BalanceOf<Self>>;
/// The amount of currency needed per proxy added.
const ProxyDepositFactor: BalanceOf<T> = T::ProxyDepositFactor::get();
///
/// This is held for adding 32 bytes plus an instance of `ProxyType` more into a pre-existing
/// storage value. Thus, when configuring `ProxyDepositFactor` one should take into account
/// `32 + proxy_type.encode().len()` bytes of data.
#[pallet::constant]
type ProxyDepositFactor: Get<BalanceOf<Self>>;
/// The maximum amount of proxies allowed for a single account.
const MaxProxies: u16 = T::MaxProxies::get();
#[pallet::constant]
type MaxProxies: Get<u16>;
/// `MaxPending` metadata shadow.
const MaxPending: u32 = T::MaxPending::get();
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
/// `AnnouncementDepositBase` metadata shadow.
const AnnouncementDepositBase: BalanceOf<T> = T::AnnouncementDepositBase::get();
/// The maximum amount of time-delayed announcements that are allowed to be pending.
#[pallet::constant]
type MaxPending: Get<u32>;
/// `AnnouncementDepositFactor` metadata shadow.
const AnnouncementDepositFactor: BalanceOf<T> = T::AnnouncementDepositFactor::get();
/// The type of hash used for hashing the call.
type CallHasher: Hash;
/// The base amount of currency needed to reserve for creating an announcement.
///
/// This is held when a new storage item holding a `Balance` is created (typically 16 bytes).
#[pallet::constant]
type AnnouncementDepositBase: Get<BalanceOf<Self>>;
/// The amount of currency needed per announcement made.
///
/// This is held for adding an `AccountId`, `Hash` and `BlockNumber` (typically 68 bytes)
/// into a pre-existing storage value.
#[pallet::constant]
type AnnouncementDepositFactor: Get<BalanceOf<Self>>;
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Dispatch the given `call` from an account that the sender is authorised for through
/// `add_proxy`.
///
@@ -230,24 +183,27 @@ decl_module! {
/// # <weight>
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
#[weight = {
#[pallet::weight({
let di = call.get_dispatch_info();
(T::WeightInfo::proxy(T::MaxProxies::get().into())
.saturating_add(di.weight)
// AccountData for inner call origin accountdata.
.saturating_add(T::DbWeight::get().reads_writes(1, 1)),
di.class)
}]
fn proxy(origin,
})]
pub(super) fn proxy(
origin: OriginFor<T>,
real: T::AccountId,
force_proxy_type: Option<T::ProxyType>,
call: Box<<T as Config>::Call>,
) {
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let def = Self::find_proxy(&real, &who, force_proxy_type)?;
ensure!(def.delay.is_zero(), Error::<T>::Unannounced);
Self::do_proxy(def, real, *call);
Ok(().into())
}
/// Register a proxy account for the sender that is able to make calls on its behalf.
@@ -263,12 +219,13 @@ decl_module! {
/// # <weight>
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
#[weight = T::WeightInfo::add_proxy(T::MaxProxies::get().into())]
fn add_proxy(origin,
#[pallet::weight(T::WeightInfo::add_proxy(T::MaxProxies::get().into()))]
pub(super) fn add_proxy(
origin: OriginFor<T>,
delegate: T::AccountId,
proxy_type: T::ProxyType,
delay: T::BlockNumber,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
Self::add_proxy_delegate(&who, delegate, proxy_type, delay)
}
@@ -284,12 +241,13 @@ decl_module! {
/// # <weight>
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
#[weight = T::WeightInfo::remove_proxy(T::MaxProxies::get().into())]
fn remove_proxy(origin,
#[pallet::weight(T::WeightInfo::remove_proxy(T::MaxProxies::get().into()))]
pub(super) fn remove_proxy(
origin: OriginFor<T>,
delegate: T::AccountId,
proxy_type: T::ProxyType,
delay: T::BlockNumber,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
Self::remove_proxy_delegate(&who, delegate, proxy_type, delay)
}
@@ -304,11 +262,13 @@ decl_module! {
/// # <weight>
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
#[weight = T::WeightInfo::remove_proxies(T::MaxProxies::get().into())]
fn remove_proxies(origin) {
#[pallet::weight(T::WeightInfo::remove_proxies(T::MaxProxies::get().into()))]
pub(super) fn remove_proxies(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let (_, old_deposit) = Proxies::<T>::take(&who);
T::Currency::unreserve(&who, old_deposit);
Ok(().into())
}
/// Spawn a fresh new account that is guaranteed to be otherwise inaccessible, and
@@ -334,8 +294,13 @@ decl_module! {
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
/// TODO: Might be over counting 1 read
#[weight = T::WeightInfo::anonymous(T::MaxProxies::get().into())]
fn anonymous(origin, proxy_type: T::ProxyType, delay: T::BlockNumber, index: u16) {
#[pallet::weight(T::WeightInfo::anonymous(T::MaxProxies::get().into()))]
pub(super) fn anonymous(
origin: OriginFor<T>,
proxy_type: T::ProxyType,
delay: T::BlockNumber,
index: u16
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let anonymous = Self::anonymous_account(&who, &proxy_type, index, None);
@@ -348,7 +313,9 @@ decl_module! {
delay,
};
Proxies::<T>::insert(&anonymous, (vec![proxy_def], deposit));
Self::deposit_event(RawEvent::AnonymousCreated(anonymous, who, proxy_type, index));
Self::deposit_event(Event::AnonymousCreated(anonymous, who, proxy_type, index));
Ok(().into())
}
/// Removes a previously spawned anonymous proxy.
@@ -371,14 +338,15 @@ decl_module! {
/// # <weight>
/// Weight is a function of the number of proxies the user has (P).
/// # </weight>
#[weight = T::WeightInfo::kill_anonymous(T::MaxProxies::get().into())]
fn kill_anonymous(origin,
#[pallet::weight(T::WeightInfo::kill_anonymous(T::MaxProxies::get().into()))]
pub(super) fn kill_anonymous(
origin: OriginFor<T>,
spawner: T::AccountId,
proxy_type: T::ProxyType,
index: u16,
#[compact] height: T::BlockNumber,
#[compact] ext_index: u32,
) {
#[pallet::compact] height: T::BlockNumber,
#[pallet::compact] ext_index: u32,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let when = (height, ext_index);
@@ -387,6 +355,8 @@ decl_module! {
let (_, deposit) = Proxies::<T>::take(&who);
T::Currency::unreserve(&spawner, deposit);
Ok(().into())
}
/// Publish the hash of a proxy-call that will be made in the future.
@@ -410,8 +380,12 @@ decl_module! {
/// - A: the number of announcements made.
/// - P: the number of proxies the user has.
/// # </weight>
#[weight = T::WeightInfo::announce(T::MaxPending::get(), T::MaxProxies::get().into())]
fn announce(origin, real: T::AccountId, call_hash: CallHashOf<T>) {
#[pallet::weight(T::WeightInfo::announce(T::MaxPending::get(), T::MaxProxies::get().into()))]
pub(super) fn announce(
origin: OriginFor<T>,
real: T::AccountId,
call_hash: CallHashOf<T>
) -> DispatchResultWithPostInfo{
let who = ensure_signed(origin)?;
Proxies::<T>::get(&real).0.into_iter()
.find(|x| &x.delegate == &who)
@@ -435,7 +409,9 @@ decl_module! {
).map(|d| d.expect("Just pushed; pending.len() > 0; rejig_deposit returns Some; qed"))
.map(|d| *deposit = d)
})?;
Self::deposit_event(RawEvent::Announced(real, who, call_hash));
Self::deposit_event(Event::Announced(real, who, call_hash));
Ok(().into())
}
/// Remove a given announcement.
@@ -454,10 +430,18 @@ decl_module! {
/// - A: the number of announcements made.
/// - P: the number of proxies the user has.
/// # </weight>
#[weight = T::WeightInfo::remove_announcement(T::MaxPending::get(), T::MaxProxies::get().into())]
fn remove_announcement(origin, real: T::AccountId, call_hash: CallHashOf<T>) {
#[pallet::weight(
T::WeightInfo::remove_announcement(T::MaxPending::get(), T::MaxProxies::get().into())
)]
pub(super) fn remove_announcement(
origin: OriginFor<T>,
real: T::AccountId,
call_hash: CallHashOf<T>
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
Self::edit_announcements(&who, |ann| ann.real != real || ann.call_hash != call_hash)?;
Ok(().into())
}
/// Remove the given announcement of a delegate.
@@ -476,13 +460,21 @@ decl_module! {
/// - A: the number of announcements made.
/// - P: the number of proxies the user has.
/// # </weight>
#[weight = T::WeightInfo::reject_announcement(T::MaxPending::get(), T::MaxProxies::get().into())]
fn reject_announcement(origin, delegate: T::AccountId, call_hash: CallHashOf<T>) {
#[pallet::weight(
T::WeightInfo::reject_announcement(T::MaxPending::get(), T::MaxProxies::get().into())
)]
pub(super) fn reject_announcement(
origin: OriginFor<T>,
delegate: T::AccountId,
call_hash: CallHashOf<T>
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
Self::edit_announcements(&delegate, |ann| ann.real != who || ann.call_hash != call_hash)?;
Ok(().into())
}
/// Dispatch the given `call` from an account that the sender is authorised for through
/// Dispatch the given `call` from an account that the sender is authorized for through
/// `add_proxy`.
///
/// Removes any corresponding announcement(s).
@@ -499,20 +491,21 @@ decl_module! {
/// - A: the number of announcements made.
/// - P: the number of proxies the user has.
/// # </weight>
#[weight = {
#[pallet::weight({
let di = call.get_dispatch_info();
(T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get().into())
.saturating_add(di.weight)
// AccountData for inner call origin accountdata.
.saturating_add(T::DbWeight::get().reads_writes(1, 1)),
di.class)
}]
fn proxy_announced(origin,
})]
pub(super) fn proxy_announced(
origin: OriginFor<T>,
delegate: T::AccountId,
real: T::AccountId,
force_proxy_type: Option<T::ProxyType>,
call: Box<<T as Config>::Call>,
) {
) -> DispatchResultWithPostInfo {
ensure_signed(origin)?;
let def = Self::find_proxy(&real, &delegate, force_proxy_type)?;
@@ -523,8 +516,72 @@ decl_module! {
).map_err(|_| Error::<T>::Unannounced)?;
Self::do_proxy(def, real, *call);
Ok(().into())
}
}
#[pallet::event]
#[pallet::metadata(T::AccountId = "AccountId", T::ProxyType = "ProxyType", CallHashOf<T> = "Hash")]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config>
{
/// A proxy was executed correctly, with the given \[result\].
ProxyExecuted(DispatchResult),
/// Anonymous account has been created by new proxy with given
/// disambiguation index and proxy type. \[anonymous, who, proxy_type, disambiguation_index\]
AnonymousCreated(T::AccountId, T::AccountId, T::ProxyType, u16),
/// An announcement was placed to make a call in the future. \[real, proxy, call_hash\]
Announced(T::AccountId, T::AccountId, CallHashOf<T>),
}
/// Old name generated by `decl_event`.
#[deprecated(note="use `Event` instead")]
pub type RawEvent<T> = Event<T>;
#[pallet::error]
pub enum Error<T> {
/// There are too many proxies registered or too many announcements pending.
TooMany,
/// Proxy registration not found.
NotFound,
/// Sender is not a proxy of the account to be proxied.
NotProxy,
/// A call which is incompatible with the proxy type's filter was attempted.
Unproxyable,
/// Account is already a proxy.
Duplicate,
/// Call may not be made by proxy because it may escalate its privileges.
NoPermission,
/// Announcement, if made at all, was made too recently.
Unannounced,
/// Cannot add self as proxy.
NoSelfProxy,
}
/// The set of account proxies. Maps the account which has delegated to the accounts
/// which are being delegated to, together with the amount held on deposit.
#[pallet::storage]
#[pallet::getter(fn proxies)]
pub type Proxies<T: Config> = StorageMap<
_,
Twox64Concat,
T::AccountId,
(Vec<ProxyDefinition<T::AccountId, T::ProxyType, T::BlockNumber>>, BalanceOf<T>),
ValueQuery
>;
/// The announcements made by the proxy (key).
#[pallet::storage]
#[pallet::getter(fn announcements)]
pub type Announcements<T: Config> = StorageMap<
_,
Twox64Concat,
T::AccountId,
(Vec<Announcement<T::AccountId, CallHashOf<T>, T::BlockNumber>>, BalanceOf<T>),
ValueQuery
>;
}
impl<T: Config> Module<T> {
@@ -568,7 +625,7 @@ impl<T: Config> Module<T> {
delegatee: T::AccountId,
proxy_type: T::ProxyType,
delay: T::BlockNumber,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
ensure!(delegator != &delegatee, Error::<T>::NoSelfProxy);
Proxies::<T>::try_mutate(delegator, |(ref mut proxies, ref mut deposit)| {
ensure!(proxies.len() < T::MaxProxies::get() as usize, Error::<T>::TooMany);
@@ -582,7 +639,7 @@ impl<T: Config> Module<T> {
T::Currency::unreserve(delegator, *deposit - new_deposit);
}
*deposit = new_deposit;
Ok(())
Ok(().into())
})
}
@@ -599,7 +656,7 @@ impl<T: Config> Module<T> {
delegatee: T::AccountId,
proxy_type: T::ProxyType,
delay: T::BlockNumber,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
Proxies::<T>::try_mutate_exists(delegator, |x| {
let (mut proxies, old_deposit) = x.take().ok_or(Error::<T>::NotFound)?;
let proxy_def = ProxyDefinition { delegate: delegatee, proxy_type, delay };
@@ -614,7 +671,7 @@ impl<T: Config> Module<T> {
if !proxies.is_empty() {
*x = Some((proxies, new_deposit))
}
Ok(())
Ok(().into())
})
}
@@ -701,7 +758,7 @@ impl<T: Config> Module<T> {
}
});
let e = call.dispatch(origin);
Self::deposit_event(RawEvent::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error)));
Self::deposit_event(Event::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error)));
}
}
+23 -22
View File
@@ -150,6 +150,7 @@ use pallet_balances::Error as BalancesError;
use pallet_balances::Event as BalancesEvent;
use pallet_utility::Call as UtilityCall;
use pallet_utility::Event as UtilityEvent;
use super::Event as ProxyEvent;
use super::Call as ProxyCall;
pub fn new_test_ext() -> sp_io::TestExternalities {
@@ -309,11 +310,11 @@ fn filtering_works() {
let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
let derivative_id = Utility::derivative_account_id(1, 0);
assert!(Balances::mutate_account(&derivative_id, |a| a.free = 1000).is_ok());
@@ -321,42 +322,42 @@ fn filtering_works() {
let call = Box::new(Call::Utility(UtilityCall::as_derivative(0, inner.clone())));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]);
expect_events(vec![UtilityEvent::BatchCompleted.into(), ProxyEvent::ProxyExecuted(Ok(())).into()]);
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_events(vec![
UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(),
RawEvent::ProxyExecuted(Ok(())).into(),
ProxyEvent::ProxyExecuted(Ok(())).into(),
]);
let inner = Box::new(Call::Proxy(ProxyCall::add_proxy(5, ProxyType::Any, 0)));
let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]);
expect_events(vec![UtilityEvent::BatchCompleted.into(), ProxyEvent::ProxyExecuted(Ok(())).into()]);
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_events(vec![
UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(),
RawEvent::ProxyExecuted(Ok(())).into(),
ProxyEvent::ProxyExecuted(Ok(())).into(),
]);
let call = Box::new(Call::Proxy(ProxyCall::remove_proxies()));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_events(vec![BalancesEvent::<Test>::Unreserved(1, 5).into(), RawEvent::ProxyExecuted(Ok(())).into()]);
expect_events(vec![BalancesEvent::<Test>::Unreserved(1, 5).into(), ProxyEvent::ProxyExecuted(Ok(())).into()]);
});
}
@@ -411,18 +412,18 @@ fn proxying_works() {
Error::<Test>::NotProxy
);
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_eq!(Balances::free_balance(6), 1);
let call = Box::new(Call::System(SystemCall::set_code(vec![])));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive(6, 1)));
assert_ok!(Call::Proxy(super::Call::proxy(1, None, call.clone())).dispatch(Origin::signed(2)));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_eq!(Balances::free_balance(6), 2);
});
}
@@ -432,7 +433,7 @@ fn anonymous_works() {
new_test_ext().execute_with(|| {
assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0, 0));
let anon = Proxy::anonymous_account(&1, &ProxyType::Any, 0, None);
expect_event(RawEvent::AnonymousCreated(anon.clone(), 1, ProxyType::Any, 0));
expect_event(ProxyEvent::AnonymousCreated(anon.clone(), 1, ProxyType::Any, 0));
// other calls to anonymous allowed as long as they're not exactly the same.
assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::JustTransfer, 0, 0));
@@ -449,13 +450,13 @@ fn anonymous_works() {
let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
assert_ok!(Balances::transfer(Origin::signed(3), anon, 5));
assert_ok!(Proxy::proxy(Origin::signed(1), anon, None, call));
expect_event(RawEvent::ProxyExecuted(Ok(())));
expect_event(ProxyEvent::ProxyExecuted(Ok(())));
assert_eq!(Balances::free_balance(6), 1);
let call = Box::new(Call::Proxy(ProxyCall::kill_anonymous(1, ProxyType::Any, 0, 1, 0)));
assert_ok!(Proxy::proxy(Origin::signed(2), anon2, None, call.clone()));
let de = DispatchError::from(Error::<Test>::NoPermission).stripped();
expect_event(RawEvent::ProxyExecuted(Err(de)));
expect_event(ProxyEvent::ProxyExecuted(Err(de)));
assert_noop!(
Proxy::kill_anonymous(Origin::signed(1), 1, ProxyType::Any, 0, 1, 0),
Error::<Test>::NoPermission