11use crate :: {
2+ generate_permission_id, get_total_allocated_percentage, pallet,
23 permission:: { emission:: * , * } ,
3- * ,
4+ update_permission_indices, AccumulatedStreamAmounts , BalanceOf , Config , DistributionControl ,
5+ EmissionAllocation , EmissionScope , EnforcementTracking , Error , Event , NegativeImbalanceOf ,
6+ Pallet , PermissionContract , PermissionDuration , PermissionId , PermissionScope , Permissions ,
47} ;
58
69use pallet_permission0_api:: {
@@ -10,7 +13,7 @@ use pallet_permission0_api::{
1013} ;
1114use polkadot_sdk:: {
1215 frame_support:: { dispatch:: DispatchResult , ensure, traits:: ReservableCurrency } ,
13- frame_system:: { self , ensure_signed_or_root} ,
16+ frame_system:: { self , ensure_signed , ensure_signed_or_root} ,
1417 polkadot_sdk_frame:: prelude:: { BlockNumberFor , OriginFor } ,
1518 sp_core:: { Get , TryCollect } ,
1619 sp_runtime:: {
@@ -129,32 +132,12 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
129132 Error :: <T >:: NotRegisteredAgent
130133 ) ;
131134 ensure ! ( grantor != grantee, Error :: <T >:: SelfPermissionNotAllowed ) ;
132- ensure ! ( !targets. is_empty( ) , Error :: <T >:: NoTargetsSpecified ) ;
133135
134- for ( target, weight) in & targets {
135- ensure ! ( * weight > 0 , Error :: <T >:: InvalidTargetWeight ) ;
136- ensure ! (
137- T :: Torus :: is_agent_registered( target) ,
138- Error :: <T >:: NotRegisteredAgent
139- ) ;
140- }
136+ validate_emission_permission_target_weights :: < T > ( & targets) ?;
141137
142138 match & allocation {
143139 EmissionAllocation :: Streams ( streams) => {
144- for ( stream, percentage) in streams {
145- ensure ! ( * percentage <= Percent :: one( ) , Error :: <T >:: InvalidPercentage ) ;
146-
147- let total_allocated = get_total_allocated_percentage :: < T > ( & grantor, stream) ;
148- let new_total_allocated = match total_allocated. checked_add ( percentage) {
149- Some ( new_total_allocated) => new_total_allocated,
150- None => return Err ( Error :: < T > :: TotalAllocationExceeded . into ( ) ) ,
151- } ;
152-
153- ensure ! (
154- new_total_allocated <= Percent :: one( ) ,
155- Error :: <T >:: TotalAllocationExceeded
156- ) ;
157- }
140+ validate_emission_permission_streams :: < T > ( streams, & grantor) ?;
158141 }
159142 EmissionAllocation :: FixedAmount ( amount) => {
160143 ensure ! ( * amount > BalanceOf :: <T >:: zero( ) , Error :: <T >:: InvalidAmount ) ;
@@ -172,22 +155,7 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
172155 }
173156 }
174157
175- match & distribution {
176- DistributionControl :: Automatic ( threshold) => {
177- ensure ! (
178- * threshold >= T :: MinAutoDistributionThreshold :: get( ) ,
179- Error :: <T >:: InvalidThreshold
180- ) ;
181- }
182- DistributionControl :: Interval ( interval) => {
183- ensure ! ( !interval. is_zero( ) , Error :: <T >:: InvalidInterval ) ;
184- }
185- DistributionControl :: AtBlock ( block) => {
186- let current_block = <polkadot_sdk:: frame_system:: Pallet < T > >:: block_number ( ) ;
187- ensure ! ( * block > current_block, Error :: <T >:: InvalidInterval ) ;
188- }
189- _ => { }
190- }
158+ validate_emission_permission_distribution :: < T > ( & distribution) ?;
191159
192160 if let Some ( parent) = parent_id {
193161 let parent_contract =
@@ -362,3 +330,136 @@ pub fn toggle_permission_accumulation_impl<T: Config>(
362330
363331 Ok ( ( ) )
364332}
333+
334+ pub ( crate ) fn update_emission_permission < T : Config > (
335+ origin : OriginFor < T > ,
336+ permission_id : PermissionId ,
337+ new_targets : BoundedBTreeMap < T :: AccountId , u16 , T :: MaxTargetsPerPermission > ,
338+ new_streams : Option < BoundedBTreeMap < StreamId , Percent , T :: MaxStreamsPerPermission > > ,
339+ new_distribution_control : Option < DistributionControl < T > > ,
340+ ) -> DispatchResult {
341+ let who = ensure_signed ( origin) ?;
342+
343+ let permission = Permissions :: < T > :: get ( permission_id) ;
344+
345+ let Some ( mut permission) = permission else {
346+ return Err ( Error :: < T > :: PermissionNotFound . into ( ) ) ;
347+ } ;
348+
349+ if permission. grantor == who {
350+ if !permission. is_updatable ( ) {
351+ return Err ( Error :: < T > :: NotEditable . into ( ) ) ;
352+ }
353+ } else if permission. grantee == who {
354+ if new_streams. is_some ( ) || new_distribution_control. is_some ( ) {
355+ return Err ( Error :: < T > :: NotAuthorizedToEdit . into ( ) ) ;
356+ }
357+ } else {
358+ return Err ( Error :: < T > :: NotAuthorizedToEdit . into ( ) ) ;
359+ }
360+
361+ let mut scope = permission. scope . clone ( ) ;
362+ match & mut scope {
363+ PermissionScope :: Emission ( emission_scope) => {
364+ validate_emission_permission_target_weights :: < T > ( & new_targets) ?;
365+
366+ emission_scope. targets = new_targets;
367+
368+ let EmissionAllocation :: Streams ( streams) = & mut emission_scope. allocation else {
369+ return Err ( Error :: < T > :: NotEditable . into ( ) ) ;
370+ } ;
371+
372+ if let Some ( new_streams) = new_streams {
373+ crate :: permission:: emission:: do_distribute_emission :: < T > (
374+ permission_id,
375+ & permission,
376+ DistributionReason :: Manual ,
377+ ) ;
378+
379+ for stream in streams. keys ( ) {
380+ AccumulatedStreamAmounts :: < T > :: remove ( (
381+ & permission. grantor ,
382+ stream,
383+ & permission_id,
384+ ) ) ;
385+ }
386+
387+ validate_emission_permission_streams :: < T > ( & new_streams, & permission. grantor ) ?;
388+
389+ * streams = new_streams;
390+ }
391+
392+ if let Some ( new_distribution_control) = new_distribution_control {
393+ validate_emission_permission_distribution :: < T > ( & new_distribution_control) ?;
394+
395+ emission_scope. distribution = new_distribution_control;
396+ }
397+ }
398+ _ => return Err ( Error :: < T > :: NotEditable . into ( ) ) ,
399+ }
400+
401+ permission. scope = scope;
402+ Permissions :: < T > :: set ( permission_id, Some ( permission) ) ;
403+
404+ Ok ( ( ) )
405+ }
406+
407+ fn validate_emission_permission_target_weights < T : Config > (
408+ targets : & BoundedBTreeMap < T :: AccountId , u16 , T :: MaxTargetsPerPermission > ,
409+ ) -> DispatchResult {
410+ ensure ! ( !targets. is_empty( ) , Error :: <T >:: NoTargetsSpecified ) ;
411+
412+ for ( target, weight) in targets {
413+ ensure ! ( * weight > 0 , Error :: <T >:: InvalidTargetWeight ) ;
414+ ensure ! (
415+ T :: Torus :: is_agent_registered( target) ,
416+ Error :: <T >:: NotRegisteredAgent
417+ ) ;
418+ }
419+
420+ Ok ( ( ) )
421+ }
422+ fn validate_emission_permission_streams < T : Config > (
423+ streams : & BoundedBTreeMap < StreamId , Percent , T :: MaxStreamsPerPermission > ,
424+ grantor : & T :: AccountId ,
425+ ) -> DispatchResult {
426+ for ( stream, percentage) in streams {
427+ ensure ! ( * percentage <= Percent :: one( ) , Error :: <T >:: InvalidPercentage ) ;
428+
429+ let total_allocated = get_total_allocated_percentage :: < T > ( grantor, stream) ;
430+ let new_total_allocated = match total_allocated. checked_add ( percentage) {
431+ Some ( new_total_allocated) => new_total_allocated,
432+ None => return Err ( Error :: < T > :: TotalAllocationExceeded . into ( ) ) ,
433+ } ;
434+
435+ ensure ! (
436+ new_total_allocated <= Percent :: one( ) ,
437+ Error :: <T >:: TotalAllocationExceeded
438+ ) ;
439+ }
440+
441+ Ok ( ( ) )
442+ }
443+
444+ fn validate_emission_permission_distribution < T : Config > (
445+ distribution : & DistributionControl < T > ,
446+ ) -> DispatchResult {
447+ match distribution {
448+ DistributionControl :: Automatic ( threshold) => {
449+ ensure ! (
450+ * threshold >= T :: MinAutoDistributionThreshold :: get( ) ,
451+ Error :: <T >:: InvalidThreshold
452+ ) ;
453+ }
454+ DistributionControl :: Interval ( interval) => {
455+ ensure ! ( !interval. is_zero( ) , Error :: <T >:: InvalidInterval ) ;
456+ }
457+ DistributionControl :: AtBlock ( block) => {
458+ let current_block = <polkadot_sdk:: frame_system:: Pallet < T > >:: block_number ( ) ;
459+ ensure ! ( * block > current_block, Error :: <T >:: InvalidInterval ) ;
460+ }
461+ _ => { }
462+ }
463+
464+ Ok ( ( ) )
465+ }
0 commit comments