Skip to content

Commit

Permalink
add poke_deposit extrinsic to pallet-proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
UtkarshBhardwaj007 committed Mar 4, 2025
1 parent 4b39ff0 commit 269c381
Show file tree
Hide file tree
Showing 13 changed files with 516 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
5 changes: 5 additions & 0 deletions polkadot/runtime/rococo/src/weights/pallet_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
5 changes: 5 additions & 0 deletions polkadot/runtime/westend/src/weights/pallet_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,9 @@ impl<T: frame_system::Config> pallet_proxy::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn poke_deposit() -> Weight {
Weight::from_parts(20_734_482, 4706)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
}
98 changes: 98 additions & 0 deletions substrate/frame/proxy/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}

fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
frame_system::Pallet::<T>::assert_has_event(generic_event.into());
}

fn add_proxies<T: Config>(n: u32, maybe_who: Option<T::AccountId>) -> Result<(), &'static str> {
let caller = maybe_who.unwrap_or_else(whitelisted_caller);
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value() / 2u32.into());
Expand Down Expand Up @@ -341,5 +345,99 @@ mod benchmarks {
Ok(())
}

#[benchmark]
fn poke_deposit() -> Result<(), BenchmarkError> {
// Create accounts using the same pattern as other benchmarks
let account_1: T::AccountId = account("account", 1, SEED);
let account_2: T::AccountId = account("account", 2, SEED);
let account_3: T::AccountId = account("account", 3, SEED);

// Fund accounts
T::Currency::make_free_balance_be(&account_1, BalanceOf::<T>::max_value() / 100u8.into());
T::Currency::make_free_balance_be(&account_2, BalanceOf::<T>::max_value() / 100u8.into());
T::Currency::make_free_balance_be(&account_3, BalanceOf::<T>::max_value() / 100u8.into());

// Add proxy relationships
Proxy::<T>::add_proxy(
RawOrigin::Signed(account_1.clone()).into(),
T::Lookup::unlookup(account_2.clone()),
T::ProxyType::default(),
BlockNumberFor::<T>::zero()
)?;
Proxy::<T>::add_proxy(
RawOrigin::Signed(account_2.clone()).into(),
T::Lookup::unlookup(account_3.clone()),
T::ProxyType::default(),
BlockNumberFor::<T>::zero()
)?;
let (proxies, initial_proxy_deposit) = Proxies::<T>::get(&account_2);
assert!(!initial_proxy_deposit.is_zero());
assert_eq!(initial_proxy_deposit, T::Currency::reserved_balance(&account_2));

// Create announcement
Proxy::<T>::announce(
RawOrigin::Signed(account_2.clone()).into(),
T::Lookup::unlookup(account_1.clone()),
T::CallHasher::hash_of(&("add_announcement", 1))
)?;
let (announcements, initial_announcement_deposit) = Announcements::<T>::get(&account_2);
assert!(!initial_announcement_deposit.is_zero());
assert_eq!(initial_announcement_deposit.saturating_add(initial_proxy_deposit), T::Currency::reserved_balance(&account_2));

// Artificially inflate deposits and reserve the extra amount
let extra_proxy_deposit = initial_proxy_deposit; // Double the deposit
let extra_announcement_deposit = initial_announcement_deposit; // Double the deposit
let total = extra_proxy_deposit.saturating_add(extra_announcement_deposit);

T::Currency::reserve(&account_2, total)?;

let initial_reserved = T::Currency::reserved_balance(&account_2);
assert_eq!(initial_reserved, total.saturating_add(total)); // Double
// Update storage with increased deposits
Proxies::<T>::insert(&account_2, (proxies, initial_proxy_deposit.saturating_add(extra_proxy_deposit)));
Announcements::<T>::insert(
&account_2,
(announcements, initial_announcement_deposit.saturating_add(extra_announcement_deposit))
);

// Verify artificial state
let (_, inflated_proxy_deposit) = Proxies::<T>::get(&account_2);
let (_, inflated_announcement_deposit) = Announcements::<T>::get(&account_2);
assert_eq!(inflated_proxy_deposit, initial_proxy_deposit.saturating_add(extra_proxy_deposit));
assert_eq!(inflated_announcement_deposit, initial_announcement_deposit.saturating_add(extra_announcement_deposit));

#[extrinsic_call]
_(RawOrigin::Signed(account_2.clone()));

// Verify results
let (_, final_proxy_deposit) = Proxies::<T>::get(&account_2);
let (_, final_announcement_deposit) = Announcements::<T>::get(&account_2);
assert_eq!(final_proxy_deposit, initial_proxy_deposit);
assert_eq!(final_announcement_deposit, initial_announcement_deposit);

let final_reserved = T::Currency::reserved_balance(&account_2);
assert_eq!(final_reserved, initial_reserved.saturating_sub(total));

// Verify events
assert_has_event::<T>(
Event::DepositPoked {
who: account_2.clone(),
kind: DepositKind::Proxies,
old_deposit: inflated_proxy_deposit,
new_deposit: final_proxy_deposit,
}.into()
);
assert_last_event::<T>(
Event::DepositPoked {
who: account_2,
kind: DepositKind::Announcements,
old_deposit: inflated_announcement_deposit,
new_deposit: final_announcement_deposit,
}.into(),
);

Ok(())
}

impl_benchmark_test_suite!(Proxy, crate::tests::new_test_ext(), crate::tests::Test);
}
128 changes: 126 additions & 2 deletions substrate/frame/proxy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ pub struct Announcement<AccountId, Hash, BlockNumber> {
height: BlockNumber,
}

/// The type of deposit
#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo, DecodeWithMemTracking)]
pub enum DepositKind {
/// Proxy registration deposit
Proxies,
/// Announcement deposit
Announcements,
}

#[frame::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -529,6 +538,110 @@ pub mod pallet {

Ok(())
}

/// Poke / Adjust deposits made for proxies and announcements based on current values.
///
/// The dispatch origin for this call must be _Signed_.
///
/// The transaction fee is waived if the deposit amount has changed.
///
/// Emits `DepositPoked` if successful.
#[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::poke_deposit())]
pub fn poke_deposit(
origin: OriginFor<T>,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let mut deposit_updated = false;

// Check and update proxy deposits
Proxies::<T>::try_mutate_exists(&who, |maybe_proxies| -> DispatchResult {
let (proxies, old_deposit) = maybe_proxies.take().unwrap_or_default();
let maybe_new_deposit = Self::rejig_deposit(
&who,
old_deposit,
T::ProxyDepositBase::get(),
T::ProxyDepositFactor::get(),
proxies.len(),
)?;

match maybe_new_deposit {
Some(new_deposit) if new_deposit != old_deposit => {
*maybe_proxies = Some((proxies, new_deposit));
deposit_updated = true;
Self::deposit_event(Event::DepositPoked {
who: who.clone(),
kind: DepositKind::Proxies,
old_deposit,
new_deposit,
});
},
Some(_) => {
*maybe_proxies = Some((proxies, old_deposit));
},
None => {
*maybe_proxies = None;
if !old_deposit.is_zero() {
deposit_updated = true;
Self::deposit_event(Event::DepositPoked {
who: who.clone(),
kind: DepositKind::Proxies,
old_deposit,
new_deposit: BalanceOf::<T>::zero(),
});
}
},
}
Ok(())
})?;

// Check and update announcement deposits
Announcements::<T>::try_mutate_exists(&who, |maybe_announcements| -> DispatchResult {
let (announcements, old_deposit) = maybe_announcements.take().unwrap_or_default();
let maybe_new_deposit = Self::rejig_deposit(
&who,
old_deposit,
T::AnnouncementDepositBase::get(),
T::AnnouncementDepositFactor::get(),
announcements.len(),
)?;

match maybe_new_deposit {
Some(new_deposit) if new_deposit != old_deposit => {
*maybe_announcements = Some((announcements, new_deposit));
deposit_updated = true;
Self::deposit_event(Event::DepositPoked {
who: who.clone(),
kind: DepositKind::Announcements,
old_deposit,
new_deposit,
});
},
Some(_) => {
*maybe_announcements = Some((announcements, old_deposit));
},
None => {
*maybe_announcements = None;
if !old_deposit.is_zero() {
deposit_updated = true;
Self::deposit_event(Event::DepositPoked {
who: who.clone(),
kind: DepositKind::Announcements,
old_deposit,
new_deposit: BalanceOf::<T>::zero(),
});
}
},
}
Ok(())
})?;

Ok(if deposit_updated {
Pays::No.into()
} else {
Pays::Yes.into()
})
}
}

#[pallet::event]
Expand Down Expand Up @@ -560,6 +673,13 @@ pub mod pallet {
proxy_type: T::ProxyType,
delay: BlockNumberFor<T>,
},
/// A deposit stored for proxies or announcements was poked / updated.
DepositPoked {
who: T::AccountId,
kind: DepositKind,
old_deposit: BalanceOf<T>,
new_deposit: BalanceOf<T>,
},
}

#[pallet::error]
Expand Down Expand Up @@ -779,9 +899,13 @@ impl<T: Config> Pallet<T> {
let new_deposit =
if len == 0 { BalanceOf::<T>::zero() } else { base + factor * (len as u32).into() };
if new_deposit > old_deposit {
T::Currency::reserve(who, new_deposit - old_deposit)?;
T::Currency::reserve(who, new_deposit.saturating_sub(old_deposit))?;
} else if new_deposit < old_deposit {
T::Currency::unreserve(who, old_deposit - new_deposit);
let excess = old_deposit.saturating_sub(new_deposit);
let remaining_unreserved = T::Currency::unreserve(who, excess);
if !remaining_unreserved.is_zero() {
defensive!("Failed to unreserve full amount. (Requested, Actual)", (excess, excess.saturating_sub(remaining_unreserved)));
}
}
Ok(if len == 0 { None } else { Some(new_deposit) })
}
Expand Down
Loading

0 comments on commit 269c381

Please sign in to comment.