-
Notifications
You must be signed in to change notification settings - Fork 2.7k
permissionless bond_extra in nomination pools
#12608
Changes from 20 commits
c5cde02
3ab9cd7
59958d5
9d54b8a
8efecfe
f7b0a2d
8931433
9f83103
9d63fdb
a3718f6
4c6a4e7
8207d51
0401174
a4b6ec2
db9c1b8
4d8bc6f
b5eda08
58173e0
b110526
126bc8d
a45d615
ab1e7bb
ab064f7
5f25374
619e9b9
15c286f
1a1479d
b21097b
4ffe8f5
fcd63b2
f6254fa
ce1ebc9
62edda4
1211229
6e4f2b4
832281d
e242799
011d733
d9590b1
04d6b13
b8be98c
d8fac0e
79f9b7e
184d6f2
0e0cc6f
be3cc5e
768c63d
549a743
e823b43
1c17bcc
9b1eb00
9996341
6fa711c
0f9f730
4bdf22a
2965fd9
7c16c8e
ef63fdf
f8cedba
4ac673b
0ea2309
a39573c
f7a6568
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -411,6 +411,21 @@ enum AccountType { | |
| Reward, | ||
| } | ||
|
|
||
| /// Account to bond pending reward of a member. | ||
| #[derive(Encode, Decode, MaxEncodedLen, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] | ||
| pub enum RewardClaim { | ||
| /// Only the pool member themself can claim their reward. | ||
| Permissioned, | ||
| /// Anyone can claim the reward of this member. | ||
| Permissionless, | ||
| } | ||
|
|
||
| impl Default for RewardClaim { | ||
rossbulat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| fn default() -> Self { | ||
| Self::Permissioned | ||
| } | ||
| } | ||
|
|
||
| /// A member in a pool. | ||
| #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebugNoBound, CloneNoBound)] | ||
| #[cfg_attr(feature = "std", derive(frame_support::PartialEqNoBound, DefaultNoBound))] | ||
|
|
@@ -1316,6 +1331,11 @@ pub mod pallet { | |
| pub type ReversePoolIdLookup<T: Config> = | ||
| CountedStorageMap<_, Twox64Concat, T::AccountId, PoolId, OptionQuery>; | ||
|
|
||
| /// Map from a pool member account to their preference regarding reward payout | ||
Doordashcon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #[pallet::storage] | ||
| pub type RewardClaimPermission<T: Config> = | ||
rossbulat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| StorageMap<_, Twox64Concat, T::AccountId, RewardClaim, ValueQuery>; | ||
Ank4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #[pallet::genesis_config] | ||
| pub struct GenesisConfig<T: Config> { | ||
| pub min_join_bond: BalanceOf<T>, | ||
|
|
@@ -1718,6 +1738,7 @@ pub mod pallet { | |
| // Now that we know everything has worked write the items to storage. | ||
| SubPoolsStorage::insert(&member.pool_id, sub_pools); | ||
| Self::put_member_with_pools(&member_account, member, bonded_pool, reward_pool); | ||
| <RewardClaimPermission<T>>::remove(member_account); | ||
rossbulat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Ok(()) | ||
| } | ||
|
|
@@ -2117,6 +2138,80 @@ pub mod pallet { | |
| ensure!(bonded_pool.can_nominate(&who), Error::<T>::NotNominator); | ||
| T::Staking::chill(&bonded_pool.bonded_account()) | ||
| } | ||
|
|
||
| /// Bond pending rewards of `member_account` into the pool they already belong. | ||
| /// | ||
| /// Note: `member_account` must pass `RewardClaim::Permissionless` to `set_reward_claim`, | ||
| /// making this call permissionless. | ||
| #[pallet::call_index(14)] | ||
| #[pallet::weight( | ||
| T::WeightInfo::bond_extra_transfer() | ||
| .max(T::WeightInfo::bond_extra_reward()) | ||
| )] | ||
| pub fn bond_extra_pending_rewards_other( | ||
|
||
| origin: OriginFor<T>, | ||
| member_account: AccountIdLookupOf<T>, | ||
| ) -> DispatchResult { | ||
| ensure_signed(origin)?; | ||
| let member_account = T::Lookup::lookup(member_account)?; | ||
| let (mut member, mut bonded_pool, mut reward_pool) = | ||
| Self::get_member_with_pools(&member_account)?; | ||
|
|
||
| ensure!( | ||
| RewardClaimPermission::<T>::get(&member_account) == RewardClaim::Permissionless, | ||
| Error::<T>::DoesNotHavePermission | ||
| ); | ||
|
|
||
| reward_pool.update_records(bonded_pool.id, bonded_pool.points)?; | ||
| ensure!(!member.active_points().is_zero(), Error::<T>::FullyUnbonding); | ||
|
|
||
| let current_reward_counter = | ||
| reward_pool.current_reward_counter(bonded_pool.id, bonded_pool.points)?; | ||
| let pending_rewards = member.pending_rewards(current_reward_counter)?; | ||
|
|
||
| if !pending_rewards.is_zero() { | ||
| member.last_recorded_reward_counter = current_reward_counter; | ||
| reward_pool.register_claimed_reward(pending_rewards); | ||
| } | ||
|
|
||
| let points_issued = bonded_pool.try_bond_funds( | ||
| &bonded_pool.reward_account(), | ||
| pending_rewards, | ||
| BondType::Later, | ||
| )?; | ||
|
|
||
| bonded_pool.ok_to_be_open()?; | ||
| member.points = member.points.saturating_add(points_issued); | ||
|
|
||
| Self::deposit_event(Event::<T>::Bonded { | ||
| member: member_account.clone(), | ||
| pool_id: member.pool_id, | ||
| bonded: pending_rewards, | ||
| joined: false, | ||
| }); | ||
|
|
||
| Self::put_member_with_pools(&member_account, member, bonded_pool, reward_pool); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Set reward claim permission. | ||
| /// | ||
| /// # Arguments | ||
Doordashcon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// | ||
| /// * `Origin` - Member of a pool. | ||
| /// * `actor` - Account to claim reward. | ||
| #[pallet::call_index(15)] | ||
| #[pallet::weight(T::DbWeight::get().reads_writes(1, 1))] | ||
| pub fn set_reward_claim(origin: OriginFor<T>, actor: RewardClaim) -> DispatchResult { | ||
| let who = ensure_signed(origin)?; | ||
|
|
||
| ensure!(PoolMembers::<T>::contains_key(&who), Error::<T>::PoolMemberNotFound); | ||
| <RewardClaimPermission<T>>::mutate(who, |source| { | ||
| *source = actor; | ||
| }); | ||
| Ok(()) | ||
| } | ||
rossbulat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| #[pallet::hooks] | ||
|
|
@@ -2303,7 +2398,7 @@ impl<T: Config> Pallet<T> { | |
| // We check for zero above | ||
| .div(current_points) | ||
| } | ||
|
|
||
| // TODO: Investigate logic here to add conditional event emission on different account types. | ||
| /// If the member has some rewards, transfer a payout from the reward pool to the member. | ||
| // Emits events and potentially modifies pool state if any arithmetic saturates, but does | ||
| // not persist any of the mutable inputs to storage. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.