diff --git a/runtime/mainnet/src/config/proxy.rs b/runtime/mainnet/src/config/proxy.rs index 0b8ab9b99..411d6f290 100644 --- a/runtime/mainnet/src/config/proxy.rs +++ b/runtime/mainnet/src/config/proxy.rs @@ -1,11 +1,61 @@ +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::InstanceFilter; -use pop_runtime_common::proxy::{ - AnnouncementDepositBase, AnnouncementDepositFactor, MaxPending, MaxProxies, ProxyDepositBase, - ProxyDepositFactor, ProxyType, +use pop_runtime_common::proxy::{MaxPending, MaxProxies}; +use sp_runtime::RuntimeDebug; + +use crate::{ + deposit, parameter_types, Balance, Balances, BlakeTwo256, Runtime, RuntimeCall, RuntimeEvent, }; -use sp_runtime::traits::BlakeTwo256; -use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; +/// The type used to represent the kinds of proxying allowed. +// Mainnet will use this definition of ProxyType instead of the ones in +// `pop-common` crates until `pallet-assets` is in runtime. +// `ProxyType` in `pop-common` include Assets specific proxies which won't +// make much sense in this runtime. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum ProxyType { + /// Fully permissioned proxy. Can execute any call on behalf of _proxied_. + Any, + /// Can execute any call that does not transfer funds or assets. + NonTransfer, + /// Proxy with the ability to reject time-delay proxy announcements. + CancelProxy, + /// Collator selection proxy. Can execute calls related to collator selection mechanism. + Collator, +} +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +impl ProxyType { + /// Defines proxies permission hierarchy. + // Example: A proxy that is not superset of another one won't be able to remove + // that proxy relationship + // src: https://github.com/paritytech/polkadot-sdk/blob/4cd07c56378291fddb9fceab3b508cf99034126a/substrate/frame/proxy/src/lib.rs#L802 + pub fn is_superset(s: &ProxyType, o: &ProxyType) -> bool { + match (s, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + (ProxyType::NonTransfer, ProxyType::Collator) => true, + _ => false, + } + } +} impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { @@ -18,15 +68,6 @@ impl InstanceFilter for ProxyType { RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), - ProxyType::Assets => { - matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) - }, - ProxyType::AssetOwner => { - matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) - }, - ProxyType::AssetManager => { - matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) - }, ProxyType::Collator => matches!( c, RuntimeCall::CollatorSelection { .. } | @@ -41,6 +82,17 @@ impl InstanceFilter for ProxyType { } } +parameter_types! { + // One storage item; key size 32 + hash size 8. + pub const ProxyDepositBase: Balance = deposit(1, 40); + // Additional storage item size of AccountId 32 bytes + ProxyType 1 byte + BlockNum 4 bytes. + pub const ProxyDepositFactor: Balance = deposit(0, 37); + // One storage item; key size 32, value size 16 + hash size 8. + pub const AnnouncementDepositBase: Balance = deposit(1, 56); + // Additional storage item 32 bytes AccountId + 32 bytes Hash + 4 bytes BlockNum. + pub const AnnouncementDepositFactor: Balance = deposit(0, 68); +} + impl pallet_proxy::Config for Runtime { type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; @@ -55,3 +107,125 @@ impl pallet_proxy::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_proxy::weights::SubstrateWeight; } + +#[cfg(test)] +mod tests { + use std::any::TypeId; + + use frame_support::{traits::Get, StorageHasher, Twox64Concat}; + use pallet_proxy::Config; + use parachains_common::BlockNumber; + use sp_runtime::traits::Hash; + + use super::*; + use crate::AccountId; + + #[test] + fn proxy_type_default_is_any() { + assert_eq!(ProxyType::default(), ProxyType::Any); + } + + #[test] + fn proxy_type_superset_as_defined() { + let all_proxies = vec![ + ProxyType::Any, + ProxyType::NonTransfer, + ProxyType::CancelProxy, + ProxyType::Collator, + ]; + for proxy in all_proxies { + // Every proxy is part of itself. + assert!(ProxyType::is_superset(&proxy, &proxy)); + + // Any contains all others, but is not contained. + if proxy != ProxyType::Any { + assert!(ProxyType::is_superset(&ProxyType::Any, &proxy)); + assert!(!ProxyType::is_superset(&proxy, &ProxyType::Any)); + } + // CancelProxy does not contain any other proxy. + if proxy != ProxyType::CancelProxy { + assert!(!ProxyType::is_superset(&ProxyType::CancelProxy, &proxy)); + } + } + assert!(ProxyType::is_superset(&ProxyType::NonTransfer, &ProxyType::Collator)); + assert!(!ProxyType::is_superset(&ProxyType::Collator, &ProxyType::NonTransfer)); + } + + #[test] + fn proxy_has_announcement_deposit_base() { + // AnnouncementDepositBase #bytes. + let base_bytes = Twox64Concat::max_len::() + Balance::max_encoded_len(); + assert_eq!(base_bytes, 56); + + assert_eq!( + <::AnnouncementDepositBase as Get>::get(), + deposit(1, 56), + ); + } + #[test] + fn proxy_has_announcement_deposit_factor() { + // AnnouncementDepositFactor #bytes. + let factor_bytes = AccountId::max_encoded_len() + + <::CallHasher as Hash>::Output::max_encoded_len() + + BlockNumber::max_encoded_len(); + assert_eq!(factor_bytes, 68); + + assert_eq!( + <::AnnouncementDepositFactor as Get>::get(), + deposit(0, 68), + ); + } + + #[test] + fn proxy_uses_blaketwo256_as_hasher() { + assert_eq!(TypeId::of::<::CallHasher>(), TypeId::of::(),); + } + + #[test] + fn proxy_uses_balances_as_currency() { + assert_eq!(TypeId::of::<::Currency>(), TypeId::of::(),); + } + + #[test] + fn proxy_configures_max_pending() { + assert_eq!(<::MaxPending>::get(), 32,); + } + + #[test] + fn proxy_configures_max_num_of_proxies() { + assert_eq!(<::MaxProxies>::get(), 32,); + } + + #[test] + fn proxy_has_deposit_base() { + // ProxyDepositBase #bytes + let base_bytes = Twox64Concat::max_len::(); + assert_eq!(base_bytes, 40); + + assert_eq!(<::ProxyDepositBase as Get>::get(), deposit(1, 40),); + } + + #[test] + fn proxy_has_deposit_factor() { + // ProxyDepositFactor #bytes + let factor_bytes = AccountId::max_encoded_len() + + ProxyType::max_encoded_len() + + BlockNumber::max_encoded_len(); + assert_eq!(factor_bytes, 37); + + assert_eq!( + <::ProxyDepositFactor as Get>::get(), + deposit(0, 37), + ); + } + + #[test] + fn pallet_proxy_uses_proxy_type() { + assert_eq!(TypeId::of::<::ProxyType>(), TypeId::of::(),); + } + + #[test] + fn proxy_does_not_use_default_weights() { + assert_ne!(TypeId::of::<::WeightInfo>(), TypeId::of::<()>(),); + } +}