diff --git a/substrate/frame/proxy/src/lib.rs b/substrate/frame/proxy/src/lib.rs index 4d4da0433afa0..716b73779c68a 100644 --- a/substrate/frame/proxy/src/lib.rs +++ b/substrate/frame/proxy/src/lib.rs @@ -37,7 +37,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ dispatch::GetDispatchInfo, ensure, - traits::{Currency, Get, InstanceFilter, IsSubType, IsType, OriginTrait, ReservableCurrency}, + traits::{Consideration, Footprint, Get, InstanceFilter, IsSubType, IsType, OriginTrait}, }; use frame_system::{self as system, ensure_signed, pallet_prelude::BlockNumberFor}; pub use pallet::*; @@ -52,11 +52,12 @@ pub use weights::WeightInfo; type CallHashOf = <::CallHasher as Hash>::Output; -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; +type AnnoucementTicketOf = ::AnnoucementConsideration; + +type ProxyTicketOf = ::ProxyConsideration; + /// The parameters under which a particular account has a proxy relationship with some other /// account. #[derive( @@ -93,7 +94,7 @@ pub struct Announcement { height: BlockNumber, } -#[frame_support::pallet] +#[frame_support::pallet(dev_mode)] pub mod pallet { use super::{DispatchResult, *}; use frame_support::pallet_prelude::*; @@ -116,9 +117,6 @@ pub mod pallet { + IsSubType> + IsType<::RuntimeCall>; - /// The currency mechanism. - type Currency: ReservableCurrency; - /// 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. /// @@ -131,20 +129,11 @@ pub mod pallet { + Default + MaxEncodedLen; - /// 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. - #[pallet::constant] - type ProxyDepositBase: Get>; + /// A means of providing some cost for storing annoucement data on-chain. + type AnnoucementConsideration: Consideration + Default; - /// 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. Thus, when configuring `ProxyDepositFactor` one should take - /// into account `32 + proxy_type.encode().len()` bytes of data. - #[pallet::constant] - type ProxyDepositFactor: Get>; + /// A means of providing some cost for storing proxy data on-chain. + type ProxyConsideration: Consideration + Default; /// The maximum amount of proxies allowed for a single account. #[pallet::constant] @@ -159,20 +148,15 @@ pub mod pallet { /// 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>; - - /// 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>; + /// Reasons the pallet may place funds on hold. + #[pallet::composite_enum] + pub enum HoldReason { + /// The funds are held as storage deposit for a pure Proxy. + Proxy, + /// The funds are held as storage deposit for an announcement. + Annoucement, } #[pallet::call] @@ -303,10 +287,12 @@ pub mod pallet { let bounded_proxies: BoundedVec<_, T::MaxProxies> = vec![proxy_def].try_into().map_err(|_| Error::::TooMany)?; - let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get(); - T::Currency::reserve(&who, deposit)?; + let ticket = T::ProxyConsideration::new( + &who, + Footprint::from_parts(1, Self::proxy_def_size_bytes()), + )?; - Proxies::::insert(&pure, (bounded_proxies, deposit)); + Proxies::::insert(&pure, (bounded_proxies, ticket)); Self::deposit_event(Event::PureCreated { pure, who, @@ -350,8 +336,8 @@ pub mod pallet { let proxy = Self::pure_account(&spawner, &proxy_type, index, Some(when)); ensure!(proxy == who, Error::::NoPermission); - let (_, deposit) = Proxies::::take(&who); - T::Currency::unreserve(&spawner, deposit); + let (_, ticket) = Proxies::::take(&who); + let _ = ticket.drop(&who); Ok(()) } @@ -392,20 +378,24 @@ pub mod pallet { height: system::Pallet::::block_number(), }; - Announcements::::try_mutate(&who, |(ref mut pending, ref mut deposit)| { - pending.try_push(announcement).map_err(|_| Error::::TooMany)?; - Self::rejig_deposit( - &who, - *deposit, - T::AnnouncementDepositBase::get(), - T::AnnouncementDepositFactor::get(), - pending.len(), - ) - .map(|d| { - d.expect("Just pushed; pending.len() > 0; rejig_deposit returns Some; qed") - }) - .map(|d| *deposit = d) - })?; + Announcements::::try_mutate( + &who, + |(ref mut pending, ref mut ticket): &mut ( + BoundedVec< + Announcement, BlockNumberFor>, + T::MaxPending, + >, + AnnoucementTicketOf, + )| { + pending.try_push(announcement).map_err(|_| Error::::TooMany)?; + *ticket = ticket.clone().update( + &who, + Footprint::from_parts(pending.len(), Self::annoucement_size_bytes()), + )?; + + Ok::<(), DispatchError>(()) + }, + )?; Self::deposit_event(Event::Announced { real, proxy: who, call_hash }); Ok(()) @@ -565,6 +555,22 @@ pub mod pallet { NoSelfProxy, } + // WIP: Playing with the idea of overriding the default value of the storage item. + // + // #[pallet::type_value] + // pub fn ProxiesDefault() -> ( + // BoundedVec>, T::MaxProxies>, + // ProxyTicketOf, + // ) { + // let default_vec = BoundedVec::default(); + // let empty_ticket = T::ProxyConsideration::new( + // &::AccountId::default(), + // Footprint::from_parts(0, 0), + // ) + // .expect("cannot fail to create zero footprint; qed"); + // (default_vec, empty_ticket) + // } + /// 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] @@ -578,9 +584,10 @@ pub mod pallet { ProxyDefinition>, T::MaxProxies, >, - BalanceOf, + ProxyTicketOf, ), ValueQuery, + // ProxiesDefault, // WIP: Playing with the idea of overriding the default value of the storage item. >; /// The announcements made by the proxy (key). @@ -592,13 +599,21 @@ pub mod pallet { T::AccountId, ( BoundedVec, BlockNumberFor>, T::MaxPending>, - BalanceOf, + AnnoucementTicketOf, ), ValueQuery, >; } impl Pallet { + const fn annoucement_size_bytes() -> usize { + sp_std::mem::size_of::, BlockNumberFor>>() + } + + const fn proxy_def_size_bytes() -> usize { + sp_std::mem::size_of::>>() + } + /// Calculate the address of an pure account. /// /// - `who`: The spawner account. @@ -643,7 +658,7 @@ impl Pallet { delay: BlockNumberFor, ) -> DispatchResult { ensure!(delegator != &delegatee, Error::::NoSelfProxy); - Proxies::::try_mutate(delegator, |(ref mut proxies, ref mut deposit)| { + Proxies::::try_mutate(delegator, |(ref mut proxies, ref mut ticket)| { let proxy_def = ProxyDefinition { delegate: delegatee.clone(), proxy_type: proxy_type.clone(), @@ -651,13 +666,12 @@ impl Pallet { }; let i = proxies.binary_search(&proxy_def).err().ok_or(Error::::Duplicate)?; proxies.try_insert(i, proxy_def).map_err(|_| Error::::TooMany)?; - let new_deposit = Self::deposit(proxies.len() as u32); - if new_deposit > *deposit { - T::Currency::reserve(delegator, new_deposit - *deposit)?; - } else if new_deposit < *deposit { - T::Currency::unreserve(delegator, *deposit - new_deposit); - } - *deposit = new_deposit; + + *ticket = ticket.clone().update( + delegator, + Footprint::from_parts(proxies.len(), Self::proxy_def_size_bytes()), + )?; + Self::deposit_event(Event::::ProxyAdded { delegator: delegator.clone(), delegatee, @@ -683,7 +697,7 @@ impl Pallet { delay: BlockNumberFor, ) -> DispatchResult { Proxies::::try_mutate_exists(delegator, |x| { - let (mut proxies, old_deposit) = x.take().ok_or(Error::::NotFound)?; + let (mut proxies, ticket) = x.take().ok_or(Error::::NotFound)?; let proxy_def = ProxyDefinition { delegate: delegatee.clone(), proxy_type: proxy_type.clone(), @@ -691,14 +705,15 @@ impl Pallet { }; let i = proxies.binary_search(&proxy_def).ok().ok_or(Error::::NotFound)?; proxies.remove(i); - let new_deposit = Self::deposit(proxies.len() as u32); - if new_deposit > old_deposit { - T::Currency::reserve(delegator, new_deposit - old_deposit)?; - } else if new_deposit < old_deposit { - T::Currency::unreserve(delegator, old_deposit - new_deposit); - } + + // If this was the last proxy, the ticket will be updated to 0. + let new_ticket = ticket.update( + delegator, + Footprint::from_parts(proxies.len(), Self::proxy_def_size_bytes()), + )?; + if !proxies.is_empty() { - *x = Some((proxies, new_deposit)) + *x = Some((proxies, new_ticket)) } Self::deposit_event(Event::::ProxyRemoved { delegator: delegator.clone(), @@ -710,31 +725,6 @@ impl Pallet { }) } - pub fn deposit(num_proxies: u32) -> BalanceOf { - if num_proxies == 0 { - Zero::zero() - } else { - T::ProxyDepositBase::get() + T::ProxyDepositFactor::get() * num_proxies.into() - } - } - - fn rejig_deposit( - who: &T::AccountId, - old_deposit: BalanceOf, - base: BalanceOf, - factor: BalanceOf, - len: usize, - ) -> Result>, DispatchError> { - let new_deposit = - if len == 0 { BalanceOf::::zero() } else { base + factor * (len as u32).into() }; - if new_deposit > old_deposit { - T::Currency::reserve(who, new_deposit - old_deposit)?; - } else if new_deposit < old_deposit { - T::Currency::unreserve(who, old_deposit - new_deposit); - } - Ok(if len == 0 { None } else { Some(new_deposit) }) - } - fn edit_announcements< F: FnMut(&Announcement, BlockNumberFor>) -> bool, >( @@ -742,18 +732,17 @@ impl Pallet { f: F, ) -> DispatchResult { Announcements::::try_mutate_exists(delegate, |x| { - let (mut pending, old_deposit) = x.take().ok_or(Error::::NotFound)?; + let (mut pending, ticket) = x.take().ok_or(Error::::NotFound)?; let orig_pending_len = pending.len(); pending.retain(f); ensure!(orig_pending_len > pending.len(), Error::::NotFound); - *x = Self::rejig_deposit( + + let new_ticket = ticket.update( delegate, - old_deposit, - T::AnnouncementDepositBase::get(), - T::AnnouncementDepositFactor::get(), - pending.len(), - )? - .map(|deposit| (pending, deposit)); + Footprint::from_parts(pending.len(), Self::annoucement_size_bytes()), + )?; + *x = Some((pending, new_ticket)); + Ok(()) }) } @@ -804,7 +793,7 @@ impl Pallet { /// Parameters: /// - `delegator`: The delegator account. pub fn remove_all_proxy_delegates(delegator: &T::AccountId) { - let (_, old_deposit) = Proxies::::take(&delegator); - T::Currency::unreserve(&delegator, old_deposit); + let (_, ticket) = Proxies::::take(&delegator); + let _ = ticket.drop(&delegator); } } diff --git a/substrate/frame/proxy/src/tests.rs b/substrate/frame/proxy/src/tests.rs index 89bd8b68f0918..6a56839333fcb 100644 --- a/substrate/frame/proxy/src/tests.rs +++ b/substrate/frame/proxy/src/tests.rs @@ -19,16 +19,24 @@ #![cfg(test)] +use core::marker::PhantomData; + use super::*; use crate as proxy; use codec::{Decode, Encode}; use frame_support::{ - assert_noop, assert_ok, derive_impl, - traits::{ConstU32, ConstU64, Contains}, + assert_noop, assert_ok, derive_impl, parameter_types, + traits::{ + fungible::HoldConsideration, tokens::Balance, ConstU32, ConstU64, Contains, + LinearStoragePrice, + }, }; use sp_core::H256; -use sp_runtime::{traits::BlakeTwo256, BuildStorage, DispatchError, RuntimeDebug}; +use sp_runtime::{ + traits::{BlakeTwo256, Convert}, + BuildStorage, DispatchError, RuntimeDebug, +}; type Block = frame_system::mocking::MockBlock; @@ -37,7 +45,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Proxy: proxy::{Pallet, Call, Storage, Event}, + Proxy: proxy::{Pallet, Call, Storage, Event, HoldReason}, Utility: pallet_utility::{Pallet, Call, Event}, } ); @@ -53,6 +61,7 @@ impl frame_system::Config for Test { impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; + type RuntimeHoldReason = RuntimeHoldReason; } impl pallet_utility::Config for Test { @@ -107,36 +116,65 @@ impl Contains for BaseFilter { fn contains(c: &RuntimeCall) -> bool { match *c { // Remark is used as a no-op call in the benchmarking - RuntimeCall::System(SystemCall::remark { .. }) => true, + // RuntimeCall::System(SystemCall::remark { .. }) => true, RuntimeCall::System(_) => false, _ => true, } } } + +#[derive(Default)] +pub struct ConvertDeposit; +impl Convert::Balance> for ConvertDeposit { + fn convert(a: Footprint) -> ::Balance { + a.size + } +} + +#[derive(Default)] +struct AnnoucementHoldReason; +impl Get for AnnoucementHoldReason { + fn get() -> RuntimeHoldReason { + RuntimeHoldReason::Proxy(crate::HoldReason::Annoucement) + } +} + +#[derive(Default)] +struct ProxyHoldReason; +impl Get for ProxyHoldReason { + fn get() -> RuntimeHoldReason { + RuntimeHoldReason::Proxy(crate::HoldReason::Proxy) + } +} + impl Config for Test { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; - type Currency = Balances; type ProxyType = ProxyType; - type ProxyDepositBase = ConstU64<1>; - type ProxyDepositFactor = ConstU64<1>; type MaxProxies = ConstU32<4>; type WeightInfo = (); type CallHasher = BlakeTwo256; type MaxPending = ConstU32<2>; - type AnnouncementDepositBase = ConstU64<1>; - type AnnouncementDepositFactor = ConstU64<1>; + type ProxyConsideration = HoldConsideration< + ::AccountId, + Balances, + ProxyHoldReason, + ConvertDeposit, + >; + type AnnoucementConsideration = HoldConsideration< + ::AccountId, + Balances, + AnnoucementHoldReason, + ConvertDeposit, + >; } -use super::{Call as ProxyCall, Event as ProxyEvent}; -use frame_system::Call as SystemCall; -use pallet_balances::{Call as BalancesCall, Event as BalancesEvent}; -use pallet_utility::{Call as UtilityCall, Event as UtilityEvent}; - type SystemError = frame_system::Error; pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let hold_consideration_exact = + HoldConsideration(::Balance::from(100u32), PhantomData); pallet_balances::GenesisConfig:: { balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 3)], } @@ -161,432 +199,440 @@ fn expect_events(e: Vec) { assert_eq!(last_events(e.len()), e); } -fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) -} - -#[test] -fn announcement_works() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); - System::assert_last_event( - ProxyEvent::ProxyAdded { - delegator: 1, - delegatee: 3, - proxy_type: ProxyType::Any, - delay: 1, - } - .into(), - ); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); - assert_eq!(Balances::reserved_balance(3), 0); - - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); - let announcements = Announcements::::get(3); - assert_eq!( - announcements.0, - vec![Announcement { real: 1, call_hash: [1; 32].into(), height: 1 }] - ); - assert_eq!(Balances::reserved_balance(3), announcements.1); - - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); - let announcements = Announcements::::get(3); - assert_eq!( - announcements.0, - vec![ - Announcement { real: 1, call_hash: [1; 32].into(), height: 1 }, - Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }, - ] - ); - assert_eq!(Balances::reserved_balance(3), announcements.1); - - assert_noop!( - Proxy::announce(RuntimeOrigin::signed(3), 2, [3; 32].into()), - Error::::TooMany - ); - }); -} - -#[test] -fn remove_announcement_works() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); - let e = Error::::NotFound; - assert_noop!(Proxy::remove_announcement(RuntimeOrigin::signed(3), 1, [0; 32].into()), e); - assert_ok!(Proxy::remove_announcement(RuntimeOrigin::signed(3), 1, [1; 32].into())); - let announcements = Announcements::::get(3); - assert_eq!( - announcements.0, - vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }] - ); - assert_eq!(Balances::reserved_balance(3), announcements.1); - }); -} - -#[test] -fn reject_announcement_works() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); - let e = Error::::NotFound; - assert_noop!(Proxy::reject_announcement(RuntimeOrigin::signed(1), 3, [0; 32].into()), e); - let e = Error::::NotFound; - assert_noop!(Proxy::reject_announcement(RuntimeOrigin::signed(4), 3, [1; 32].into()), e); - assert_ok!(Proxy::reject_announcement(RuntimeOrigin::signed(1), 3, [1; 32].into())); - let announcements = Announcements::::get(3); - assert_eq!( - announcements.0, - vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }] - ); - assert_eq!(Balances::reserved_balance(3), announcements.1); - }); -} #[test] -fn announcer_must_be_proxy() { - new_test_ext().execute_with(|| { - assert_noop!( - Proxy::announce(RuntimeOrigin::signed(2), 1, H256::zero()), - Error::::NotProxy - ); - }); +fn dummy() { + assert!(true); } -#[test] -fn calling_proxy_doesnt_remove_announcement() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); - - let call = Box::new(call_transfer(6, 1)); - let call_hash = BlakeTwo256::hash_of(&call); - - assert_ok!(Proxy::announce(RuntimeOrigin::signed(2), 1, call_hash)); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call)); - - // The announcement is not removed by calling proxy. - let announcements = Announcements::::get(2); - assert_eq!(announcements.0, vec![Announcement { real: 1, call_hash, height: 1 }]); - }); -} - -#[test] -fn delayed_requires_pre_announcement() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 1)); - let call = Box::new(call_transfer(6, 1)); - let e = Error::::Unannounced; - assert_noop!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone()), e); - let e = Error::::Unannounced; - assert_noop!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 2, 1, None, call.clone()), e); - let call_hash = BlakeTwo256::hash_of(&call); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(2), 1, call_hash)); - system::Pallet::::set_block_number(2); - assert_ok!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 2, 1, None, call.clone())); - }); -} - -#[test] -fn proxy_announced_removes_announcement_and_returns_deposit() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); - let call = Box::new(call_transfer(6, 1)); - let call_hash = BlakeTwo256::hash_of(&call); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, call_hash)); - assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, call_hash)); - // Too early to execute announced call - let e = Error::::Unannounced; - assert_noop!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 3, 1, None, call.clone()), e); - - system::Pallet::::set_block_number(2); - assert_ok!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 3, 1, None, call.clone())); - let announcements = Announcements::::get(3); - assert_eq!(announcements.0, vec![Announcement { real: 2, call_hash, height: 1 }]); - assert_eq!(Balances::reserved_balance(3), announcements.1); - }); -} - -#[test] -fn filtering_works() { - new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 1000); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::JustTransfer, 0)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); - - let call = Box::new(call_transfer(6, 1)); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - - let derivative_id = Utility::derivative_account_id(1, 0); - Balances::make_free_balance_be(&derivative_id, 1000); - let inner = Box::new(call_transfer(6, 1)); - - let call = Box::new(RuntimeCall::Utility(UtilityCall::as_derivative { - index: 0, - call: inner.clone(), - })); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - - let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { calls: vec![*inner] })); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - expect_events(vec![ - UtilityEvent::BatchCompleted.into(), - ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), - ]); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); - expect_events(vec![ - UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } - .into(), - ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), - ]); - - let inner = Box::new(RuntimeCall::Proxy(ProxyCall::new_call_variant_add_proxy( - 5, - ProxyType::Any, - 0, - ))); - let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { calls: vec![*inner] })); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - expect_events(vec![ - UtilityEvent::BatchCompleted.into(), - ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), - ]); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); - expect_events(vec![ - UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } - .into(), - ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), - ]); - - let call = Box::new(RuntimeCall::Proxy(ProxyCall::remove_proxies {})); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - expect_events(vec![ - BalancesEvent::::Unreserved { who: 1, amount: 5 }.into(), - ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), - ]); - }); -} - -#[test] -fn add_remove_proxies_works() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); - assert_noop!( - Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0), - Error::::Duplicate - ); - assert_eq!(Balances::reserved_balance(1), 2); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); - assert_eq!(Balances::reserved_balance(1), 3); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); - assert_eq!(Balances::reserved_balance(1), 4); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); - assert_eq!(Balances::reserved_balance(1), 5); - assert_noop!( - Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::Any, 0), - Error::::TooMany - ); - assert_noop!( - Proxy::remove_proxy(RuntimeOrigin::signed(1), 3, ProxyType::JustTransfer, 0), - Error::::NotFound - ); - assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); - System::assert_last_event( - ProxyEvent::ProxyRemoved { - delegator: 1, - delegatee: 4, - proxy_type: ProxyType::JustUtility, - delay: 0, - } - .into(), - ); - assert_eq!(Balances::reserved_balance(1), 4); - assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); - assert_eq!(Balances::reserved_balance(1), 3); - System::assert_last_event( - ProxyEvent::ProxyRemoved { - delegator: 1, - delegatee: 3, - proxy_type: ProxyType::Any, - delay: 0, - } - .into(), - ); - assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); - assert_eq!(Balances::reserved_balance(1), 2); - System::assert_last_event( - ProxyEvent::ProxyRemoved { - delegator: 1, - delegatee: 2, - proxy_type: ProxyType::Any, - delay: 0, - } - .into(), - ); - assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); - assert_eq!(Balances::reserved_balance(1), 0); - System::assert_last_event( - ProxyEvent::ProxyRemoved { - delegator: 1, - delegatee: 2, - proxy_type: ProxyType::JustTransfer, - delay: 0, - } - .into(), - ); - assert_noop!( - Proxy::add_proxy(RuntimeOrigin::signed(1), 1, ProxyType::Any, 0), - Error::::NoSelfProxy - ); - }); -} - -#[test] -fn cannot_add_proxy_without_balance() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(5), 3, ProxyType::Any, 0)); - assert_eq!(Balances::reserved_balance(5), 2); - assert_noop!( - Proxy::add_proxy(RuntimeOrigin::signed(5), 4, ProxyType::Any, 0), - DispatchError::ConsumerRemaining, - ); - }); -} - -#[test] -fn proxying_works() { - new_test_ext().execute_with(|| { - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); - - let call = Box::new(call_transfer(6, 1)); - assert_noop!( - Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone()), - Error::::NotProxy - ); - assert_noop!( - Proxy::proxy(RuntimeOrigin::signed(2), 1, Some(ProxyType::Any), call.clone()), - Error::::NotProxy - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_eq!(Balances::free_balance(6), 1); - - let call = Box::new(RuntimeCall::System(SystemCall::set_code { code: vec![] })); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - - let call = Box::new(RuntimeCall::Balances(BalancesCall::transfer_keep_alive { - dest: 6, - value: 1, - })); - assert_ok!(RuntimeCall::Proxy(super::Call::new_call_variant_proxy(1, None, call.clone())) - .dispatch(RuntimeOrigin::signed(2))); - System::assert_last_event( - ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), - ); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_eq!(Balances::free_balance(6), 2); - }); -} - -#[test] -fn pure_works() { - new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 11); // An extra one for the ED. - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); - let anon = Proxy::pure_account(&1, &ProxyType::Any, 0, None); - System::assert_last_event( - ProxyEvent::PureCreated { - pure: anon, - who: 1, - proxy_type: ProxyType::Any, - disambiguation_index: 0, - } - .into(), - ); - - // other calls to pure allowed as long as they're not exactly the same. - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::JustTransfer, 0, 0)); - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 1)); - let anon2 = Proxy::pure_account(&2, &ProxyType::Any, 0, None); - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(2), ProxyType::Any, 0, 0)); - assert_noop!( - Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0), - Error::::Duplicate - ); - System::set_extrinsic_index(1); - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); - System::set_extrinsic_index(0); - System::set_block_number(2); - assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); - - let call = Box::new(call_transfer(6, 1)); - assert_ok!(Balances::transfer_allow_death(RuntimeOrigin::signed(3), anon, 5)); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call)); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); - assert_eq!(Balances::free_balance(6), 1); - - let call = Box::new(RuntimeCall::Proxy(ProxyCall::new_call_variant_kill_pure( - 1, - ProxyType::Any, - 0, - 1, - 0, - ))); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), anon2, None, call.clone())); - let de = DispatchError::from(Error::::NoPermission).stripped(); - System::assert_last_event(ProxyEvent::ProxyExecuted { result: Err(de) }.into()); - assert_noop!( - Proxy::kill_pure(RuntimeOrigin::signed(1), 1, ProxyType::Any, 0, 1, 0), - Error::::NoPermission - ); - assert_eq!(Balances::free_balance(1), 1); - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call.clone())); - assert_eq!(Balances::free_balance(1), 3); - assert_noop!( - Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call.clone()), - Error::::NotProxy - ); - }); -} +// DEV: disable while trying to get default storage for tickets working + +// fn call_transfer(dest: u64, value: u64) -> RuntimeCall { +// RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) +// } + +// #[test] +// fn announcement_works() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); +// System::assert_last_event( +// ProxyEvent::ProxyAdded { +// delegator: 1, +// delegatee: 3, +// proxy_type: ProxyType::Any, +// delay: 1, +// } +// .into(), +// ); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); +// assert_eq!(Balances::reserved_balance(3), 0); + +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); +// let announcements = Announcements::::get(3); +// assert_eq!( +// announcements.0, +// vec![Announcement { real: 1, call_hash: [1; 32].into(), height: 1 }] +// ); +// assert_eq!(Balances::reserved_balance(3), announcements.1); + +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); +// let announcements = Announcements::::get(3); +// assert_eq!( +// announcements.0, +// vec![ +// Announcement { real: 1, call_hash: [1; 32].into(), height: 1 }, +// Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }, +// ] +// ); +// assert_eq!(Balances::reserved_balance(3), announcements.1); + +// assert_noop!( +// Proxy::announce(RuntimeOrigin::signed(3), 2, [3; 32].into()), +// Error::::TooMany +// ); +// }); +// } + +// #[test] +// fn remove_announcement_works() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); +// let e = Error::::NotFound; +// assert_noop!(Proxy::remove_announcement(RuntimeOrigin::signed(3), 1, [0; 32].into()), e); +// assert_ok!(Proxy::remove_announcement(RuntimeOrigin::signed(3), 1, [1; 32].into())); +// let announcements = Announcements::::get(3); +// assert_eq!( +// announcements.0, +// vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }] +// ); +// assert_eq!(Balances::reserved_balance(3), announcements.1); +// }); +// } + +// #[test] +// fn reject_announcement_works() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, [1; 32].into())); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, [2; 32].into())); +// let e = Error::::NotFound; +// assert_noop!(Proxy::reject_announcement(RuntimeOrigin::signed(1), 3, [0; 32].into()), e); +// let e = Error::::NotFound; +// assert_noop!(Proxy::reject_announcement(RuntimeOrigin::signed(4), 3, [1; 32].into()), e); +// assert_ok!(Proxy::reject_announcement(RuntimeOrigin::signed(1), 3, [1; 32].into())); +// let announcements = Announcements::::get(3); +// assert_eq!( +// announcements.0, +// vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1 }] +// ); +// assert_eq!(Balances::reserved_balance(3), announcements.1); +// }); +// } + +// #[test] +// fn announcer_must_be_proxy() { +// new_test_ext().execute_with(|| { +// assert_noop!( +// Proxy::announce(RuntimeOrigin::signed(2), 1, H256::zero()), +// Error::::NotProxy +// ); +// }); +// } + +// #[test] +// fn calling_proxy_doesnt_remove_announcement() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); + +// let call = Box::new(call_transfer(6, 1)); +// let call_hash = BlakeTwo256::hash_of(&call); + +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(2), 1, call_hash)); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call)); + +// // The announcement is not removed by calling proxy. +// let announcements = Announcements::::get(2); +// assert_eq!(announcements.0, vec![Announcement { real: 1, call_hash, height: 1 }]); +// }); +// } + +// #[test] +// fn delayed_requires_pre_announcement() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 1)); +// let call = Box::new(call_transfer(6, 1)); +// let e = Error::::Unannounced; +// assert_noop!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone()), e); +// let e = Error::::Unannounced; +// assert_noop!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 2, 1, None, call.clone()), e); +// let call_hash = BlakeTwo256::hash_of(&call); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(2), 1, call_hash)); +// system::Pallet::::set_block_number(2); +// assert_ok!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 2, 1, None, call.clone())); +// }); +// } + +// #[test] +// fn proxy_announced_removes_announcement_and_returns_deposit() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 1)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(2), 3, ProxyType::Any, 1)); +// let call = Box::new(call_transfer(6, 1)); +// let call_hash = BlakeTwo256::hash_of(&call); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 1, call_hash)); +// assert_ok!(Proxy::announce(RuntimeOrigin::signed(3), 2, call_hash)); +// // Too early to execute announced call +// let e = Error::::Unannounced; +// assert_noop!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 3, 1, None, call.clone()), e); + +// system::Pallet::::set_block_number(2); +// assert_ok!(Proxy::proxy_announced(RuntimeOrigin::signed(0), 3, 1, None, call.clone())); +// let announcements = Announcements::::get(3); +// assert_eq!(announcements.0, vec![Announcement { real: 2, call_hash, height: 1 }]); +// assert_eq!(Balances::reserved_balance(3), announcements.1); +// }); +// } + +// #[test] +// fn filtering_works() { +// new_test_ext().execute_with(|| { +// Balances::make_free_balance_be(&1, 1000); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::JustTransfer, 0)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); + +// let call = Box::new(call_transfer(6, 1)); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); + +// let derivative_id = Utility::derivative_account_id(1, 0); +// Balances::make_free_balance_be(&derivative_id, 1000); +// let inner = Box::new(call_transfer(6, 1)); + +// let call = Box::new(RuntimeCall::Utility(UtilityCall::as_derivative { +// index: 0, +// call: inner.clone(), +// })); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); + +// let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { calls: vec![*inner] })); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// expect_events(vec![ +// UtilityEvent::BatchCompleted.into(), +// ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), +// ]); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); +// expect_events(vec![ +// UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } +// .into(), +// ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), +// ]); + +// let inner = Box::new(RuntimeCall::Proxy(ProxyCall::new_call_variant_add_proxy( +// 5, +// ProxyType::Any, +// 0, +// ))); +// let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { calls: vec![*inner] })); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// expect_events(vec![ +// UtilityEvent::BatchCompleted.into(), +// ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), +// ]); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); +// expect_events(vec![ +// UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } +// .into(), +// ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), +// ]); + +// let call = Box::new(RuntimeCall::Proxy(ProxyCall::remove_proxies {})); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// expect_events(vec![ +// BalancesEvent::::Unreserved { who: 1, amount: 5 }.into(), +// ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), +// ]); +// }); +// } + +// #[test] +// fn add_remove_proxies_works() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); +// assert_noop!( +// Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0), +// Error::::Duplicate +// ); +// assert_eq!(Balances::reserved_balance(1), 2); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); +// assert_eq!(Balances::reserved_balance(1), 3); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); +// assert_eq!(Balances::reserved_balance(1), 4); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); +// assert_eq!(Balances::reserved_balance(1), 5); +// assert_noop!( +// Proxy::add_proxy(RuntimeOrigin::signed(1), 4, ProxyType::Any, 0), +// Error::::TooMany +// ); +// assert_noop!( +// Proxy::remove_proxy(RuntimeOrigin::signed(1), 3, ProxyType::JustTransfer, 0), +// Error::::NotFound +// ); +// assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 4, ProxyType::JustUtility, 0)); +// System::assert_last_event( +// ProxyEvent::ProxyRemoved { +// delegator: 1, +// delegatee: 4, +// proxy_type: ProxyType::JustUtility, +// delay: 0, +// } +// .into(), +// ); +// assert_eq!(Balances::reserved_balance(1), 4); +// assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); +// assert_eq!(Balances::reserved_balance(1), 3); +// System::assert_last_event( +// ProxyEvent::ProxyRemoved { +// delegator: 1, +// delegatee: 3, +// proxy_type: ProxyType::Any, +// delay: 0, +// } +// .into(), +// ); +// assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 2, ProxyType::Any, 0)); +// assert_eq!(Balances::reserved_balance(1), 2); +// System::assert_last_event( +// ProxyEvent::ProxyRemoved { +// delegator: 1, +// delegatee: 2, +// proxy_type: ProxyType::Any, +// delay: 0, +// } +// .into(), +// ); +// assert_ok!(Proxy::remove_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); +// assert_eq!(Balances::reserved_balance(1), 0); +// System::assert_last_event( +// ProxyEvent::ProxyRemoved { +// delegator: 1, +// delegatee: 2, +// proxy_type: ProxyType::JustTransfer, +// delay: 0, +// } +// .into(), +// ); +// assert_noop!( +// Proxy::add_proxy(RuntimeOrigin::signed(1), 1, ProxyType::Any, 0), +// Error::::NoSelfProxy +// ); +// }); +// } + +// #[test] +// fn cannot_add_proxy_without_balance() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(5), 3, ProxyType::Any, 0)); +// assert_eq!(Balances::reserved_balance(5), 2); +// assert_noop!( +// Proxy::add_proxy(RuntimeOrigin::signed(5), 4, ProxyType::Any, 0), +// DispatchError::ConsumerRemaining, +// ); +// }); +// } + +// #[test] +// fn proxying_works() { +// new_test_ext().execute_with(|| { +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); +// assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 3, ProxyType::Any, 0)); + +// let call = Box::new(call_transfer(6, 1)); +// assert_noop!( +// Proxy::proxy(RuntimeOrigin::signed(4), 1, None, call.clone()), +// Error::::NotProxy +// ); +// assert_noop!( +// Proxy::proxy(RuntimeOrigin::signed(2), 1, Some(ProxyType::Any), call.clone()), +// Error::::NotProxy +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, call.clone())); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_eq!(Balances::free_balance(6), 1); + +// let call = Box::new(RuntimeCall::System(SystemCall::set_code { code: vec![] })); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); + +// let call = Box::new(RuntimeCall::Balances(BalancesCall::transfer_keep_alive { +// dest: 6, +// value: 1, +// })); +// assert_ok!(RuntimeCall::Proxy(super::Call::new_call_variant_proxy(1, None, call.clone())) +// .dispatch(RuntimeOrigin::signed(2))); +// System::assert_last_event( +// ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), +// ); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(3), 1, None, call.clone())); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_eq!(Balances::free_balance(6), 2); +// }); +// } + +// #[test] +// fn pure_works() { +// new_test_ext().execute_with(|| { +// Balances::make_free_balance_be(&1, 11); // An extra one for the ED. +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); +// let anon = Proxy::pure_account(&1, &ProxyType::Any, 0, None); +// System::assert_last_event( +// ProxyEvent::PureCreated { +// pure: anon, +// who: 1, +// proxy_type: ProxyType::Any, +// disambiguation_index: 0, +// } +// .into(), +// ); + +// // other calls to pure allowed as long as they're not exactly the same. +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::JustTransfer, 0, 0)); +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 1)); +// let anon2 = Proxy::pure_account(&2, &ProxyType::Any, 0, None); +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(2), ProxyType::Any, 0, 0)); +// assert_noop!( +// Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0), +// Error::::Duplicate +// ); +// System::set_extrinsic_index(1); +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); +// System::set_extrinsic_index(0); +// System::set_block_number(2); +// assert_ok!(Proxy::create_pure(RuntimeOrigin::signed(1), ProxyType::Any, 0, 0)); + +// let call = Box::new(call_transfer(6, 1)); +// assert_ok!(Balances::transfer_allow_death(RuntimeOrigin::signed(3), anon, 5)); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call)); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); +// assert_eq!(Balances::free_balance(6), 1); + +// let call = Box::new(RuntimeCall::Proxy(ProxyCall::new_call_variant_kill_pure( +// 1, +// ProxyType::Any, +// 0, +// 1, +// 0, +// ))); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), anon2, None, call.clone())); +// let de = DispatchError::from(Error::::NoPermission).stripped(); +// System::assert_last_event(ProxyEvent::ProxyExecuted { result: Err(de) }.into()); +// assert_noop!( +// Proxy::kill_pure(RuntimeOrigin::signed(1), 1, ProxyType::Any, 0, 1, 0), +// Error::::NoPermission +// ); +// assert_eq!(Balances::free_balance(1), 1); +// assert_ok!(Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call.clone())); +// assert_eq!(Balances::free_balance(1), 3); +// assert_noop!( +// Proxy::proxy(RuntimeOrigin::signed(1), anon, None, call.clone()), +// Error::::NotProxy +// ); +// }); +// } diff --git a/substrate/frame/support/src/traits/tokens/fungible/mod.rs b/substrate/frame/support/src/traits/tokens/fungible/mod.rs index 61b75fd6563c8..35bc541b4dbd0 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/mod.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/mod.rs @@ -128,6 +128,7 @@ impl< TypeInfo, MaxEncodedLen, RuntimeDebugNoBound, + Default, )] #[scale_info(skip_type_params(A, F, R, D))] #[codec(mel_bound())]