Skip to content

Commit 6de5cb2

Browse files
fix(permission0): allow grantor to delegate emission to itself (#107)
After discussing how the emissions will be initially used, it was clear to us that there are no cases where it makes sense to delegate emissions permission to another agent. In this case, the best way to delegate is to itself, which allows the agent to control how the emissions will flow and edit the targets at will.
1 parent 04288e8 commit 6de5cb2

File tree

4 files changed

+114
-23
lines changed

4 files changed

+114
-23
lines changed

justfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
default: check test
1+
default: fmt check test
22

33
# Build
44

@@ -11,11 +11,14 @@ build-testnet:
1111
# Development
1212

1313
check:
14-
cargo clippy
14+
cargo clippy --tests
1515

1616
test:
1717
cargo test
1818

19+
fmt:
20+
cargo fmt
21+
1922
run-localnode profile="--alice":
2023
cargo xtask run local {{profile}}
2124

pallets/permission0/src/ext/emission_impl.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ pub(crate) fn grant_emission_permission_impl<T: Config>(
131131
T::Torus::is_agent_registered(&grantee),
132132
Error::<T>::NotRegisteredAgent
133133
);
134-
ensure!(grantor != grantee, Error::<T>::SelfPermissionNotAllowed);
135134

136135
validate_emission_permission_target_weights::<T>(&targets)?;
137136

@@ -346,15 +345,11 @@ pub(crate) fn update_emission_permission<T: Config>(
346345
return Err(Error::<T>::PermissionNotFound.into());
347346
};
348347

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 {
348+
let allowed_grantor = permission.grantor == who && permission.is_updatable();
349+
let allowed_grantee =
350+
permission.grantee == who && (new_streams.is_none() && new_distribution_control.is_none());
351+
352+
if !allowed_grantor && !allowed_grantee {
358353
return Err(Error::<T>::NotAuthorizedToEdit.into());
359354
}
360355

@@ -386,6 +381,13 @@ pub(crate) fn update_emission_permission<T: Config>(
386381

387382
validate_emission_permission_streams::<T>(&new_streams, &permission.grantor)?;
388383

384+
for stream in new_streams.keys() {
385+
AccumulatedStreamAmounts::<T>::set(
386+
(&permission.grantor, stream, permission_id),
387+
Some(Zero::zero()),
388+
)
389+
}
390+
389391
*streams = new_streams;
390392
}
391393

pallets/permission0/tests/stream.rs

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ fn grantor_cannot_change_irrevocable_permission() {
338338
None,
339339
None
340340
),
341-
pallet_permission0::Error::<Test>::NotEditable
341+
pallet_permission0::Error::<Test>::NotAuthorizedToEdit
342342
);
343343
});
344344
}
@@ -401,7 +401,7 @@ fn grantor_cannot_change_arbiter_permission() {
401401
None,
402402
None
403403
),
404-
pallet_permission0::Error::<Test>::NotEditable
404+
pallet_permission0::Error::<Test>::NotAuthorizedToEdit
405405
);
406406
});
407407
}
@@ -461,7 +461,7 @@ fn grantor_cannot_change_permission_before_block() {
461461
None,
462462
None
463463
),
464-
pallet_permission0::Error::<Test>::NotEditable
464+
pallet_permission0::Error::<Test>::NotAuthorizedToEdit
465465
);
466466

467467
step_block(6);
@@ -575,10 +575,9 @@ fn updating_works() {
575575

576576
add_balance(agent_0, as_tors(10) + 1);
577577

578-
let stream_id = generate_root_stream_id(&agent_0);
579-
578+
let stream = generate_root_stream_id(&agent_0);
580579
let mut streams = BTreeMap::new();
581-
streams.insert(stream_id, Percent::from_percent(100));
580+
streams.insert(stream, Percent::from_percent(100));
582581

583582
let permission_id = assert_ok!(grant_emission_permission(
584583
agent_0,
@@ -597,19 +596,23 @@ fn updating_works() {
597596

598597
assert!(AccumulatedStreamAmounts::<Test>::contains_key((
599598
&agent_0,
600-
&stream_id,
599+
&stream,
601600
&permission_id
602601
)));
603602

604603
let mut new_targets = BoundedBTreeMap::new();
605-
new_targets.try_insert(agent_0, u16::MAX).unwrap();
604+
new_targets.try_insert(agent_1, u16::MAX).unwrap();
605+
606+
let new_stream = generate_root_stream_id(&agent_1);
607+
let mut new_streams = BTreeMap::new();
608+
new_streams.insert(new_stream, Percent::from_percent(100));
606609

607610
assert_ok!(
608611
pallet_permission0::Pallet::<Test>::update_emission_permission(
609612
get_origin(agent_0),
610613
permission_id,
611614
new_targets.clone(),
612-
Some(streams.clone().try_into().unwrap()),
615+
Some(new_streams.clone().try_into().unwrap()),
613616
Some(pallet_permission0::DistributionControl::Interval(100))
614617
)
615618
);
@@ -624,9 +627,21 @@ fn updating_works() {
624627

625628
assert_eq!(
626629
emission_scope.allocation,
627-
pallet_permission0::EmissionAllocation::Streams(streams.try_into().unwrap())
630+
pallet_permission0::EmissionAllocation::Streams(new_streams.try_into().unwrap())
628631
);
629632

633+
assert!(!AccumulatedStreamAmounts::<Test>::contains_key((
634+
&agent_0,
635+
&stream,
636+
&permission_id
637+
)));
638+
639+
assert!(AccumulatedStreamAmounts::<Test>::contains_key((
640+
&agent_0,
641+
new_stream,
642+
&permission_id,
643+
)));
644+
630645
assert_eq!(
631646
emission_scope.distribution,
632647
pallet_permission0::DistributionControl::Interval(100)
@@ -635,3 +650,74 @@ fn updating_works() {
635650
assert_eq!(emission_scope.targets, new_targets);
636651
});
637652
}
653+
654+
#[test]
655+
fn update_prevents_overarching_update_when_grantor_is_grantee() {
656+
test_utils::new_test_ext().execute_with(|| {
657+
zero_min_burn();
658+
let agent_0 = 0;
659+
register_empty_agent(agent_0);
660+
661+
let agent_1 = 1;
662+
register_empty_agent(agent_1);
663+
664+
let agent_2 = 1;
665+
register_empty_agent(agent_2);
666+
667+
let agent_3 = 1;
668+
register_empty_agent(agent_3);
669+
670+
add_balance(agent_0, as_tors(10) + 1);
671+
672+
let stream_id = generate_root_stream_id(&agent_0);
673+
let mut streams = BTreeMap::new();
674+
streams.insert(stream_id, Percent::from_percent(100));
675+
676+
let permission_id = assert_ok!(grant_emission_permission(
677+
agent_0,
678+
agent_0,
679+
pallet_permission0_api::EmissionAllocation::Streams(streams.clone()),
680+
vec![(agent_1, u16::MAX)],
681+
pallet_permission0_api::DistributionControl::Manual,
682+
pallet_permission0_api::PermissionDuration::Indefinite,
683+
pallet_permission0_api::RevocationTerms::RevocableAfter(5),
684+
pallet_permission0_api::EnforcementAuthority::None,
685+
));
686+
687+
let mut new_targets = BoundedBTreeMap::new();
688+
new_targets.try_insert(agent_1, u16::MAX).unwrap();
689+
690+
assert_err!(
691+
pallet_permission0::Pallet::<Test>::update_emission_permission(
692+
get_origin(agent_0),
693+
permission_id,
694+
new_targets.clone(),
695+
Some(BoundedBTreeMap::new()),
696+
None
697+
),
698+
pallet_permission0::Error::<Test>::NotAuthorizedToEdit
699+
);
700+
701+
assert_ok!(
702+
pallet_permission0::Pallet::<Test>::update_emission_permission(
703+
get_origin(agent_0),
704+
permission_id,
705+
new_targets.clone(),
706+
None,
707+
None
708+
)
709+
);
710+
711+
step_block(6);
712+
713+
assert_ok!(
714+
pallet_permission0::Pallet::<Test>::update_emission_permission(
715+
get_origin(agent_0),
716+
permission_id,
717+
new_targets.clone(),
718+
Some(streams.clone().try_into().unwrap()),
719+
Some(pallet_permission0::DistributionControl::Interval(100))
720+
)
721+
);
722+
});
723+
}

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
3838
spec_name: create_runtime_str!("torus-runtime"),
3939
impl_name: create_runtime_str!("torus-runtime"),
4040
authoring_version: 1,
41-
spec_version: 19,
41+
spec_version: 20,
4242
impl_version: 1,
4343
apis: apis::RUNTIME_API_VERSIONS,
4444
transaction_version: 1,

0 commit comments

Comments
 (0)