@@ -31,10 +31,14 @@ use frame_support::{assert_ok, ensure, traits::Get};
3131use frame_system:: RawOrigin as RuntimeOrigin ;
3232use pallet_nomination_pools:: {
3333 BalanceOf , BondExtra , BondedPoolInner , BondedPools , ClaimPermission , ClaimPermissions ,
34- ConfigOp , MaxPoolMembers , MaxPoolMembersPerPool , MaxPools , Metadata , MinCreateBond ,
35- MinJoinBond , Pallet as Pools , PoolMembers , PoolRoles , PoolState , RewardPools , SubPoolsStorage ,
34+ Commission , CommissionChangeRate , ConfigOp , GlobalMaxCommission , MaxPoolMembers ,
35+ MaxPoolMembersPerPool , MaxPools , Metadata , MinCreateBond , MinJoinBond , Pallet as Pools ,
36+ PoolMembers , PoolRoles , PoolState , RewardPools , SubPoolsStorage ,
37+ } ;
38+ use sp_runtime:: {
39+ traits:: { Bounded , StaticLookup , Zero } ,
40+ Perbill ,
3641} ;
37- use sp_runtime:: traits:: { Bounded , StaticLookup , Zero } ;
3842use sp_staking:: { EraIndex , StakingInterface } ;
3943// `frame_benchmarking::benchmarks!` macro needs this
4044use pallet_nomination_pools:: Call ;
@@ -69,6 +73,7 @@ fn create_funded_user_with_balance<T: pallet_nomination_pools::Config>(
6973fn create_pool_account < T : pallet_nomination_pools:: Config > (
7074 n : u32 ,
7175 balance : BalanceOf < T > ,
76+ commission : Option < Perbill > ,
7277) -> ( T :: AccountId , T :: AccountId ) {
7378 let ed = CurrencyOf :: < T > :: minimum_balance ( ) ;
7479 let pool_creator: T :: AccountId =
@@ -84,6 +89,16 @@ fn create_pool_account<T: pallet_nomination_pools::Config>(
8489 )
8590 . unwrap ( ) ;
8691
92+ if let Some ( c) = commission {
93+ let pool_id = pallet_nomination_pools:: LastPoolId :: < T > :: get ( ) ;
94+ Pools :: < T > :: set_commission (
95+ RuntimeOrigin :: Signed ( pool_creator. clone ( ) ) . into ( ) ,
96+ pool_id,
97+ Some ( ( c, pool_creator. clone ( ) ) ) ,
98+ )
99+ . expect ( "pool just created, commission can be set by root; qed" ) ;
100+ }
101+
87102 let pool_account = pallet_nomination_pools:: BondedPools :: < T > :: iter ( )
88103 . find ( |( _, bonded_pool) | bonded_pool. roles . depositor == pool_creator)
89104 . map ( |( pool_id, _) | Pools :: < T > :: create_bonded_account ( pool_id) )
@@ -134,14 +149,18 @@ impl<T: Config> ListScenario<T> {
134149 sp_std:: mem:: forget ( i) ;
135150
136151 // Create accounts with the origin weight
137- let ( pool_creator1, pool_origin1) = create_pool_account :: < T > ( USER_SEED + 1 , origin_weight) ;
152+ let ( pool_creator1, pool_origin1) =
153+ create_pool_account :: < T > ( USER_SEED + 1 , origin_weight, Some ( Perbill :: from_percent ( 50 ) ) ) ;
154+
138155 T :: Staking :: nominate (
139156 & pool_origin1,
140157 // NOTE: these don't really need to be validators.
141158 vec ! [ account( "random_validator" , 0 , USER_SEED ) ] ,
142159 ) ?;
143160
144- let ( _, pool_origin2) = create_pool_account :: < T > ( USER_SEED + 2 , origin_weight) ;
161+ let ( _, pool_origin2) =
162+ create_pool_account :: < T > ( USER_SEED + 2 , origin_weight, Some ( Perbill :: from_percent ( 50 ) ) ) ;
163+
145164 T :: Staking :: nominate (
146165 & pool_origin2,
147166 vec ! [ account( "random_validator" , 0 , USER_SEED ) ] . clone ( ) ,
@@ -157,7 +176,9 @@ impl<T: Config> ListScenario<T> {
157176 dest_weight_as_vote. try_into ( ) . map_err ( |_| "could not convert u64 to Balance" ) ?;
158177
159178 // Create an account with the worst case destination weight
160- let ( _, pool_dest1) = create_pool_account :: < T > ( USER_SEED + 3 , dest_weight) ;
179+ let ( _, pool_dest1) =
180+ create_pool_account :: < T > ( USER_SEED + 3 , dest_weight, Some ( Perbill :: from_percent ( 50 ) ) ) ;
181+
161182 T :: Staking :: nominate ( & pool_dest1, vec ! [ account( "random_validator" , 0 , USER_SEED ) ] ) ?;
162183
163184 let weight_of = pallet_staking:: Pallet :: < T > :: weight_of_fn ( ) ;
@@ -269,18 +290,19 @@ frame_benchmarking::benchmarks! {
269290
270291 } : _( RuntimeOrigin :: Signed ( claimer) , T :: Lookup :: unlookup( scenario. creator1. clone( ) ) , BondExtra :: Rewards )
271292 verify {
293+ // commission of 50% deducted here.
272294 assert!(
273295 T :: Staking :: active_stake( & scenario. origin1) . unwrap( ) >=
274- scenario. dest_weight
296+ scenario. dest_weight / 2u32 . into ( )
275297 ) ;
276298 }
277299
278300 claim_payout {
279301 let claimer: T :: AccountId = account( "claimer" , USER_SEED + 4 , 0 ) ;
280-
302+ let commission = Perbill :: from_percent ( 50 ) ;
281303 let origin_weight = Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ;
282304 let ed = CurrencyOf :: <T >:: minimum_balance( ) ;
283- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , origin_weight) ;
305+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , origin_weight, Some ( commission ) ) ;
284306 let reward_account = Pools :: <T >:: create_reward_account( 1 ) ;
285307
286308 // Send funds to the reward account of the pool
@@ -301,11 +323,11 @@ frame_benchmarking::benchmarks! {
301323 verify {
302324 assert_eq!(
303325 CurrencyOf :: <T >:: free_balance( & depositor) ,
304- origin_weight * 2u32 . into ( )
326+ origin_weight + commission * origin_weight
305327 ) ;
306328 assert_eq!(
307329 CurrencyOf :: <T >:: free_balance( & reward_account) ,
308- ed + Zero :: zero ( )
330+ ed + commission * origin_weight
309331 ) ;
310332 }
311333
@@ -345,7 +367,7 @@ frame_benchmarking::benchmarks! {
345367 let s in 0 .. MAX_SPANS ;
346368
347369 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) ;
348- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
370+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
349371
350372 // Add a new member
351373 let min_join_bond = MinJoinBond :: <T >:: get( ) . max( CurrencyOf :: <T >:: minimum_balance( ) ) ;
@@ -387,7 +409,7 @@ frame_benchmarking::benchmarks! {
387409 let s in 0 .. MAX_SPANS ;
388410
389411 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) ;
390- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
412+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
391413
392414 // Add a new member
393415 let min_join_bond = MinJoinBond :: <T >:: get( ) . max( CurrencyOf :: <T >:: minimum_balance( ) ) ;
@@ -433,7 +455,7 @@ frame_benchmarking::benchmarks! {
433455 let s in 0 .. MAX_SPANS ;
434456
435457 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) ;
436- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
458+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
437459 let depositor_lookup = T :: Lookup :: unlookup( depositor. clone( ) ) ;
438460
439461 // We set the pool to the destroying state so the depositor can leave
@@ -523,15 +545,16 @@ frame_benchmarking::benchmarks! {
523545 assert_eq!(
524546 new_pool,
525547 BondedPoolInner {
526- points: min_create_bond,
527- state: PoolState :: Open ,
548+ commission: Commission :: default ( ) ,
528549 member_counter: 1 ,
550+ points: min_create_bond,
529551 roles: PoolRoles {
530552 depositor: depositor. clone( ) ,
531553 root: Some ( depositor. clone( ) ) ,
532554 nominator: Some ( depositor. clone( ) ) ,
533555 bouncer: Some ( depositor. clone( ) ) ,
534556 } ,
557+ state: PoolState :: Open ,
535558 }
536559 ) ;
537560 assert_eq!(
@@ -545,7 +568,7 @@ frame_benchmarking::benchmarks! {
545568
546569 // Create a pool
547570 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ;
548- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
571+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
549572
550573 // Create some accounts to nominate. For the sake of benchmarking they don't need to be
551574 // actual validators
@@ -562,15 +585,16 @@ frame_benchmarking::benchmarks! {
562585 assert_eq!(
563586 new_pool,
564587 BondedPoolInner {
565- points: min_create_bond,
566- state: PoolState :: Open ,
588+ commission: Commission :: default ( ) ,
567589 member_counter: 1 ,
590+ points: min_create_bond,
568591 roles: PoolRoles {
569592 depositor: depositor. clone( ) ,
570593 root: Some ( depositor. clone( ) ) ,
571594 nominator: Some ( depositor. clone( ) ) ,
572595 bouncer: Some ( depositor. clone( ) ) ,
573- }
596+ } ,
597+ state: PoolState :: Open ,
574598 }
575599 ) ;
576600 assert_eq!(
@@ -582,7 +606,7 @@ frame_benchmarking::benchmarks! {
582606 set_state {
583607 // Create a pool
584608 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) ;
585- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
609+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
586610 BondedPools :: <T >:: mutate( & 1 , |maybe_pool| {
587611 // Force the pool into an invalid state
588612 maybe_pool. as_mut( ) . map( |mut pool| pool. points = min_create_bond * 10u32 . into( ) ) ;
@@ -599,7 +623,7 @@ frame_benchmarking::benchmarks! {
599623 let n in 1 .. <T as pallet_nomination_pools:: Config >:: MaxMetadataLen :: get( ) ;
600624
601625 // Create a pool
602- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ) ;
626+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , None ) ;
603627
604628 // Create metadata of the max possible size
605629 let metadata: Vec <u8 > = ( 0 ..n) . map( |_| 42 ) . collect( ) ;
@@ -617,18 +641,20 @@ frame_benchmarking::benchmarks! {
617641 ConfigOp :: Set ( BalanceOf :: <T >:: max_value( ) ) ,
618642 ConfigOp :: Set ( u32 :: MAX ) ,
619643 ConfigOp :: Set ( u32 :: MAX ) ,
620- ConfigOp :: Set ( u32 :: MAX )
644+ ConfigOp :: Set ( u32 :: MAX ) ,
645+ ConfigOp :: Set ( Perbill :: max_value( ) )
621646 ) verify {
622647 assert_eq!( MinJoinBond :: <T >:: get( ) , BalanceOf :: <T >:: max_value( ) ) ;
623648 assert_eq!( MinCreateBond :: <T >:: get( ) , BalanceOf :: <T >:: max_value( ) ) ;
624649 assert_eq!( MaxPools :: <T >:: get( ) , Some ( u32 :: MAX ) ) ;
625650 assert_eq!( MaxPoolMembers :: <T >:: get( ) , Some ( u32 :: MAX ) ) ;
626651 assert_eq!( MaxPoolMembersPerPool :: <T >:: get( ) , Some ( u32 :: MAX ) ) ;
652+ assert_eq!( GlobalMaxCommission :: <T >:: get( ) , Some ( Perbill :: max_value( ) ) ) ;
627653 }
628654
629655 update_roles {
630656 let first_id = pallet_nomination_pools:: LastPoolId :: <T >:: get( ) + 1 ;
631- let ( root, _) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ) ;
657+ let ( root, _) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , None ) ;
632658 let random: T :: AccountId = account( "but is anything really random in computers..?" , 0 , USER_SEED ) ;
633659 } : _(
634660 RuntimeOrigin :: Signed ( root. clone( ) ) ,
@@ -650,7 +676,7 @@ frame_benchmarking::benchmarks! {
650676
651677 chill {
652678 // Create a pool
653- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ) ;
679+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , None ) ;
654680
655681 // Nominate with the pool.
656682 let validators: Vec <_> = ( 0 ..T :: MaxNominations :: get( ) )
@@ -666,10 +692,68 @@ frame_benchmarking::benchmarks! {
666692 assert!( T :: Staking :: nominations( Pools :: <T >:: create_bonded_account( 1 ) ) . is_none( ) ) ;
667693 }
668694
695+ set_commission {
696+ // Create a pool - do not set a commission yet.
697+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , None ) ;
698+ // set a max commission
699+ Pools :: <T >:: set_commission_max( RuntimeOrigin :: Signed ( depositor. clone( ) ) . into( ) , 1u32 . into( ) , Perbill :: from_percent( 50 ) ) . unwrap( ) ;
700+ // set a change rate
701+ Pools :: <T >:: set_commission_change_rate( RuntimeOrigin :: Signed ( depositor. clone( ) ) . into( ) , 1u32 . into( ) , CommissionChangeRate {
702+ max_increase: Perbill :: from_percent( 20 ) ,
703+ min_delay: 0u32 . into( ) ,
704+ } ) . unwrap( ) ;
705+
706+ } : _( RuntimeOrigin :: Signed ( depositor. clone( ) ) , 1u32 . into( ) , Some ( ( Perbill :: from_percent( 20 ) , depositor. clone( ) ) ) )
707+ verify {
708+ assert_eq!( BondedPools :: <T >:: get( 1 ) . unwrap( ) . commission, Commission {
709+ current: Some ( ( Perbill :: from_percent( 20 ) , depositor) ) ,
710+ max: Some ( Perbill :: from_percent( 50 ) ) ,
711+ change_rate: Some ( CommissionChangeRate {
712+ max_increase: Perbill :: from_percent( 20 ) ,
713+ min_delay: 0u32 . into( )
714+ } ) ,
715+ throttle_from: Some ( 1u32 . into( ) ) ,
716+ } ) ;
717+ }
718+
719+ set_commission_max {
720+ // Create a pool, setting a commission that will update when max commission is set.
721+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , Some ( Perbill :: from_percent( 50 ) ) ) ;
722+ } : _( RuntimeOrigin :: Signed ( depositor. clone( ) ) , 1u32 . into( ) , Perbill :: from_percent( 50 ) )
723+ verify {
724+ assert_eq!(
725+ BondedPools :: <T >:: get( 1 ) . unwrap( ) . commission, Commission {
726+ current: Some ( ( Perbill :: from_percent( 50 ) , depositor) ) ,
727+ max: Some ( Perbill :: from_percent( 50 ) ) ,
728+ change_rate: None ,
729+ throttle_from: Some ( 0u32 . into( ) ) ,
730+ } ) ;
731+ }
732+
733+ set_commission_change_rate {
734+ // Create a pool
735+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) , None ) ;
736+ } : _( RuntimeOrigin :: Signed ( depositor. clone( ) ) , 1u32 . into( ) , CommissionChangeRate {
737+ max_increase: Perbill :: from_percent( 50 ) ,
738+ min_delay: 1000u32 . into( ) ,
739+ } )
740+ verify {
741+ assert_eq!(
742+ BondedPools :: <T >:: get( 1 ) . unwrap( ) . commission, Commission {
743+ current: None ,
744+ max: None ,
745+ change_rate: Some ( CommissionChangeRate {
746+ max_increase: Perbill :: from_percent( 50 ) ,
747+ min_delay: 1000u32 . into( ) ,
748+ } ) ,
749+ throttle_from: Some ( 1_u32 . into( ) ) ,
750+ } ) ;
751+ }
752+
669753 set_claim_permission {
670754 // Create a pool
671755 let min_create_bond = Pools :: <T >:: depositor_min_bond( ) ;
672- let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond) ;
756+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , min_create_bond, None ) ;
673757
674758 // Join pool
675759 let min_join_bond = MinJoinBond :: <T >:: get( ) . max( CurrencyOf :: <T >:: minimum_balance( ) ) ;
@@ -688,6 +772,31 @@ frame_benchmarking::benchmarks! {
688772 assert_eq!( ClaimPermissions :: <T >:: get( joiner) , ClaimPermission :: PermissionlessAll ) ;
689773 }
690774
775+ claim_commission {
776+ let claimer: T :: AccountId = account( "claimer_member" , USER_SEED + 4 , 0 ) ;
777+ let commission = Perbill :: from_percent( 50 ) ;
778+ let origin_weight = Pools :: <T >:: depositor_min_bond( ) * 2u32 . into( ) ;
779+ let ed = CurrencyOf :: <T >:: minimum_balance( ) ;
780+ let ( depositor, pool_account) = create_pool_account:: <T >( 0 , origin_weight, Some ( commission) ) ;
781+ let reward_account = Pools :: <T >:: create_reward_account( 1 ) ;
782+ CurrencyOf :: <T >:: make_free_balance_be( & reward_account, ed + origin_weight) ;
783+
784+ // member claims a payout to make some commission available.
785+ let _ = Pools :: <T >:: claim_payout( RuntimeOrigin :: Signed ( claimer) . into( ) ) ;
786+
787+ whitelist_account!( depositor) ;
788+ } : _( RuntimeOrigin :: Signed ( depositor. clone( ) ) , 1u32 . into( ) )
789+ verify {
790+ assert_eq!(
791+ CurrencyOf :: <T >:: free_balance( & depositor) ,
792+ origin_weight + commission * origin_weight
793+ ) ;
794+ assert_eq!(
795+ CurrencyOf :: <T >:: free_balance( & reward_account) ,
796+ ed + commission * origin_weight
797+ ) ;
798+ }
799+
691800 impl_benchmark_test_suite!(
692801 Pallet ,
693802 crate :: mock:: new_test_ext( ) ,
0 commit comments