1
+ module iota_identity ::controller {
2
+ use iota::transfer::Receiving ;
3
+ use iota::borrow::{Self , Referent , Borrow };
4
+ use iota_identity::permissions;
5
+
6
+ public use fun delete_controller_cap as ControllerCap .delete;
7
+ public use fun delete_delegation_token as DelegationToken .delete;
8
+
9
+ /// This `ControllerCap` cannot delegate access.
10
+ const ECannotDelegate : u64 = 0 ;
11
+ // The permission of the provided `DelegationToken` are not
12
+ // valid to perform this operation.
13
+ const EInvalidPermissions : u64 = 1 ;
14
+
15
+ /// Event that is created when a new `DelegationToken` is minted.
16
+ public struct NewDelegationTokenEvent has copy , drop {
17
+ controller: ID ,
18
+ token: ID ,
19
+ permissions: u32 ,
20
+ }
21
+
22
+ /// Capability that allows to access mutative APIs of a `Multicontroller`.
23
+ public struct ControllerCap has key {
24
+ id: UID ,
25
+ can_delegate: bool ,
26
+ access_token: Referent <DelegationToken >,
27
+ }
28
+
29
+ public fun id (self: &ControllerCap ): &UID {
30
+ &self.id
31
+ }
32
+
33
+ /// Borrows this `ControllerCap`'s access token.
34
+ public fun borrow (self: &mut ControllerCap ): (DelegationToken , Borrow ) {
35
+ self.access_token.borrow ()
36
+ }
37
+
38
+ /// Returns the borrowed access token together with the hot potato.
39
+ public fun put_back (self: &mut ControllerCap , token: DelegationToken , borrow: Borrow ) {
40
+ self.access_token.put_back (token, borrow);
41
+ }
42
+
43
+ /// Creates a delegation token for this controller. The created `DelegationToken`
44
+ /// will have full permissions. Use `delegate_with_permissions` to set or unset
45
+ /// specific permissions.
46
+ public fun delegate (self: &ControllerCap , ctx: &mut TxContext ): DelegationToken {
47
+ assert !(self.can_delegate, ECannotDelegate );
48
+ new_delegation_token (self.id.to_inner (), permissions::all (), ctx)
49
+ }
50
+
51
+ /// Creates a delegation token for this controller, specifying the delegate's permissions.
52
+ public fun delegate_with_permissions (self: &ControllerCap , permissions: u32 , ctx: &mut TxContext ): DelegationToken {
53
+ assert !(self.can_delegate, ECannotDelegate );
54
+ new_delegation_token (self.id.to_inner (), permissions, ctx)
55
+ }
56
+
57
+ /// A token that allows an entity to act in a Controller's stead.
58
+ public struct DelegationToken has key , store {
59
+ id: UID ,
60
+ permissions: u32 ,
61
+ controller: ID ,
62
+ }
63
+
64
+ /// Returns the controller's ID of this `DelegationToken`.
65
+ public fun controller (self: &DelegationToken ): ID {
66
+ self.controller
67
+ }
68
+
69
+ /// Returns the permissions of this `DelegationToken`.
70
+ public fun permissions (self: &DelegationToken ): u32 {
71
+ self.permissions
72
+ }
73
+
74
+ /// Returns true if this `DelegationToken` has permission `permission`.
75
+ public fun has_permission (self: &DelegationToken , permission: u32 ): bool {
76
+ self.permissions & permission != 0
77
+ }
78
+
79
+ /// Aborts if this `DelegationToken` doesn't have permission `permission`.
80
+ public fun assert_has_permission (self: &DelegationToken , permission: u32 ) {
81
+ assert !(self.has_permission (permission), EInvalidPermissions )
82
+ }
83
+
84
+ /// Creates a new `ControllerCap`.
85
+ public (package ) fun new (can_delegate: bool , ctx: &mut TxContext ): ControllerCap {
86
+ let id = object::new (ctx);
87
+ let access_token = borrow::new (new_delegation_token (id.to_inner (), permissions::all (), ctx), ctx);
88
+
89
+ ControllerCap {
90
+ id,
91
+ access_token,
92
+ can_delegate,
93
+ }
94
+ }
95
+
96
+ /// Transfer a `ControllerCap`.
97
+ public (package ) fun transfer (cap: ControllerCap , recipient: address ) {
98
+ transfer::transfer (cap, recipient)
99
+ }
100
+
101
+ /// Receives a `ControllerCap`.
102
+ public (package ) fun receive (owner: &mut UID , cap: Receiving <ControllerCap >): ControllerCap {
103
+ transfer::receive (owner, cap)
104
+ }
105
+
106
+ public (package ) fun new_delegation_token (
107
+ controller: ID ,
108
+ permissions: u32 ,
109
+ ctx: &mut TxContext
110
+ ): DelegationToken {
111
+ let id = object::new (ctx);
112
+
113
+ iota::event ::emit (NewDelegationTokenEvent {
114
+ controller,
115
+ token: id.to_inner (),
116
+ permissions,
117
+ });
118
+
119
+ DelegationToken {
120
+ id,
121
+ controller,
122
+ permissions,
123
+ }
124
+ }
125
+
126
+ public (package ) fun delete_controller_cap (cap: ControllerCap ) {
127
+ let ControllerCap {
128
+ access_token,
129
+ id,
130
+ ..
131
+ } = cap;
132
+
133
+ delete_delegation_token (access_token.destroy ());
134
+ object::delete (id);
135
+ }
136
+
137
+ public (package ) fun delete_delegation_token (token: DelegationToken ) {
138
+ let DelegationToken {
139
+ id,
140
+ ..
141
+ } = token;
142
+ object::delete (id);
143
+ }
144
+ }
0 commit comments