@flowtyio/flow-contracts 0.1.0-beta.11 → 0.1.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/hybrid-custody/CapabilityDelegator.cdc +25 -25
- package/contracts/hybrid-custody/CapabilityFactory.cdc +18 -17
- package/contracts/hybrid-custody/CapabilityFilter.cdc +38 -22
- package/contracts/hybrid-custody/HybridCustody.cdc +305 -232
- package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
- package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Third-party imports
|
|
2
2
|
import "MetadataViews"
|
|
3
|
+
import "ViewResolver"
|
|
4
|
+
import "Burner"
|
|
3
5
|
|
|
4
6
|
// HC-owned imports
|
|
5
7
|
import "CapabilityFactory"
|
|
@@ -27,39 +29,43 @@ import "CapabilityFilter"
|
|
|
27
29
|
///
|
|
28
30
|
/// Repo reference: https://github.com/onflow/hybrid-custody
|
|
29
31
|
///
|
|
30
|
-
|
|
32
|
+
access(all) contract HybridCustody {
|
|
33
|
+
access(all) entitlement Owner
|
|
34
|
+
access(all) entitlement Child
|
|
35
|
+
access(all) entitlement Publish
|
|
36
|
+
access(all) entitlement Manage
|
|
31
37
|
|
|
32
38
|
/* --- Canonical Paths --- */
|
|
33
39
|
//
|
|
34
40
|
// Note: Paths for ChildAccount & Delegator are derived from the parent's address
|
|
35
41
|
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
access(all) let OwnedAccountStoragePath: StoragePath
|
|
43
|
+
access(all) let OwnedAccountPublicPath: PublicPath
|
|
44
|
+
access(all) let OwnedAccountPrivatePath: PrivatePath
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
access(all) let ManagerStoragePath: StoragePath
|
|
47
|
+
access(all) let ManagerPublicPath: PublicPath
|
|
48
|
+
access(all) let ManagerPrivatePath: PrivatePath
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
access(all) let LinkedAccountPrivatePath: PrivatePath
|
|
51
|
+
access(all) let BorrowableAccountPrivatePath: PrivatePath
|
|
46
52
|
|
|
47
53
|
/* --- Events --- */
|
|
48
54
|
//
|
|
49
55
|
/// Manager creation event
|
|
50
|
-
|
|
56
|
+
access(all) event CreatedManager(id: UInt64)
|
|
51
57
|
/// OwnedAccount creation event
|
|
52
|
-
|
|
58
|
+
access(all) event CreatedOwnedAccount(id: UInt64, child: Address)
|
|
53
59
|
/// ChildAccount added/removed from Manager
|
|
54
60
|
/// active : added to Manager
|
|
55
61
|
/// !active : removed from Manager
|
|
56
|
-
|
|
62
|
+
access(all) event AccountUpdated(id: UInt64?, child: Address, parent: Address?, active: Bool)
|
|
57
63
|
/// OwnedAccount added/removed or sealed
|
|
58
64
|
/// active && owner != nil : added to Manager
|
|
59
65
|
/// !active && owner == nil : removed from Manager
|
|
60
|
-
|
|
66
|
+
access(all) event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool)
|
|
61
67
|
/// ChildAccount ready to be redeemed by emitted pendingParent
|
|
62
|
-
|
|
68
|
+
access(all) event ChildAccountPublished(
|
|
63
69
|
ownedAcctID: UInt64,
|
|
64
70
|
childAcctID: UInt64,
|
|
65
71
|
capDelegatorID: UInt64,
|
|
@@ -70,49 +76,52 @@ pub contract HybridCustody {
|
|
|
70
76
|
pendingParent: Address
|
|
71
77
|
)
|
|
72
78
|
/// OwnedAccount granted ownership to a new address, publishing a Capability for the pendingOwner
|
|
73
|
-
|
|
79
|
+
access(all) event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address)
|
|
74
80
|
/// Account has been sealed - keys revoked, new AuthAccount Capability generated
|
|
75
|
-
|
|
81
|
+
access(all) event AccountSealed(id: UInt64, address: Address, parents: [Address])
|
|
76
82
|
|
|
77
83
|
/// An OwnedAccount shares the BorrowableAccount capability to itelf with ChildAccount resources
|
|
78
84
|
///
|
|
79
|
-
|
|
80
|
-
access(contract) fun
|
|
81
|
-
|
|
85
|
+
access(all) resource interface BorrowableAccount {
|
|
86
|
+
access(contract) view fun _borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account
|
|
87
|
+
access(all) view fun check(): Bool
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
/// Public methods anyone can call on an OwnedAccount
|
|
85
91
|
///
|
|
86
|
-
|
|
92
|
+
access(all) resource interface OwnedAccountPublic {
|
|
87
93
|
/// Returns the addresses of all parent accounts
|
|
88
|
-
|
|
94
|
+
access(all) view fun getParentAddresses(): [Address]
|
|
89
95
|
|
|
90
96
|
/// Returns associated parent addresses and their redeemed status - true if redeemed, false if pending
|
|
91
|
-
|
|
97
|
+
access(all) view fun getParentStatuses(): {Address: Bool}
|
|
92
98
|
|
|
93
99
|
/// Returns true if the given address is a parent of this child and has redeemed it. Returns false if the given
|
|
94
100
|
/// address is a parent of this child and has NOT redeemed it. Returns nil if the given address it not a parent
|
|
95
101
|
/// of this child account.
|
|
96
|
-
|
|
102
|
+
access(all) view fun getRedeemedStatus(addr: Address): Bool?
|
|
97
103
|
|
|
98
104
|
/// A callback function to mark a parent as redeemed on the child account.
|
|
99
105
|
access(contract) fun setRedeemed(_ addr: Address)
|
|
106
|
+
|
|
107
|
+
/// A helper function to find what controller Id to ask for if you are looking for a specific type of capability
|
|
108
|
+
access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64?
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
/// Private interface accessible to the owner of the OwnedAccount
|
|
103
112
|
///
|
|
104
|
-
|
|
113
|
+
access(all) resource interface OwnedAccountPrivate {
|
|
105
114
|
/// Deletes the ChildAccount resource being used to share access to this OwnedAccount with the supplied parent
|
|
106
115
|
/// address, and unlinks the paths it was using to reach the underlying account.
|
|
107
|
-
|
|
116
|
+
access(Owner | Remove) fun removeParent(parent: Address): Bool
|
|
108
117
|
|
|
109
118
|
/// Sets up a new ChildAccount resource for the given parentAddress to redeem. This child account uses the
|
|
110
119
|
/// supplied factory and filter to manage what can be obtained from the child account, and a new
|
|
111
120
|
/// CapabilityDelegator resource is created for the sharing of one-off capabilities. Each of these pieces of
|
|
112
121
|
/// access control are managed through the child account.
|
|
113
|
-
|
|
122
|
+
access(Publish | Owner) fun publishToParent(
|
|
114
123
|
parentAddress: Address,
|
|
115
|
-
factory: Capability<&
|
|
124
|
+
factory: Capability<&{CapabilityFactory.Getter}>,
|
|
116
125
|
filter: Capability<&{CapabilityFilter.Filter}>
|
|
117
126
|
) {
|
|
118
127
|
pre {
|
|
@@ -124,7 +133,7 @@ pub contract HybridCustody {
|
|
|
124
133
|
/// Passes ownership of this child account to the given address. Once executed, all active keys on the child
|
|
125
134
|
/// account will be revoked, and the active AuthAccount Capability being used by to obtain capabilities will be
|
|
126
135
|
/// rotated, preventing anyone without the newly generated Capability from gaining access to the account.
|
|
127
|
-
|
|
136
|
+
access(Owner) fun giveOwnership(to: Address)
|
|
128
137
|
|
|
129
138
|
/// Revokes all keys on an account, unlinks all currently active AuthAccount capabilities, then makes a new one
|
|
130
139
|
/// and replaces the OwnedAccount's underlying AuthAccount Capability with the new one to ensure that all
|
|
@@ -132,12 +141,12 @@ pub contract HybridCustody {
|
|
|
132
141
|
/// Unless this method is executed via the giveOwnership function, this will leave an account **without** an
|
|
133
142
|
/// owner.
|
|
134
143
|
/// USE WITH EXTREME CAUTION.
|
|
135
|
-
|
|
144
|
+
access(Owner) fun seal()
|
|
136
145
|
|
|
137
146
|
// setCapabilityFactoryForParent
|
|
138
147
|
// Override the existing CapabilityFactory Capability for a given parent. This will allow the owner of the
|
|
139
148
|
// account to start managing their own factory of capabilities to be able to retrieve
|
|
140
|
-
|
|
149
|
+
access(Owner) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&{CapabilityFactory.Getter}>) {
|
|
141
150
|
pre {
|
|
142
151
|
cap.check(): "Invalid CapabilityFactory.Getter Capability provided"
|
|
143
152
|
}
|
|
@@ -145,7 +154,7 @@ pub contract HybridCustody {
|
|
|
145
154
|
|
|
146
155
|
/// Override the existing CapabilityFilter Capability for a given parent. This will allow the owner of the
|
|
147
156
|
/// account to start managing their own filter for retrieving Capabilities on Private Paths
|
|
148
|
-
|
|
157
|
+
access(Owner) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) {
|
|
149
158
|
pre {
|
|
150
159
|
cap.check(): "Invalid CapabilityFilter Capability provided"
|
|
151
160
|
}
|
|
@@ -153,66 +162,67 @@ pub contract HybridCustody {
|
|
|
153
162
|
|
|
154
163
|
/// Adds a capability to a parent's managed @ChildAccount resource. The Capability can be made public,
|
|
155
164
|
/// permitting anyone to borrow it.
|
|
156
|
-
|
|
165
|
+
access(Owner) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) {
|
|
157
166
|
pre {
|
|
158
167
|
cap.check<&AnyResource>(): "Invalid Capability provided"
|
|
159
168
|
}
|
|
160
169
|
}
|
|
161
170
|
|
|
162
171
|
/// Removes a Capability from the CapabilityDelegator used by the specified parent address
|
|
163
|
-
|
|
172
|
+
access(Owner) fun removeCapabilityFromDelegator(parent: Address, cap: Capability)
|
|
164
173
|
|
|
165
174
|
/// Returns the address of this OwnedAccount
|
|
166
|
-
|
|
175
|
+
access(all) view fun getAddress(): Address
|
|
167
176
|
|
|
168
177
|
/// Checks if this OwnedAccount is a child of the specified address
|
|
169
|
-
|
|
178
|
+
access(all) view fun isChildOf(_ addr: Address): Bool
|
|
170
179
|
|
|
171
180
|
/// Returns all addresses which are parents of this OwnedAccount
|
|
172
|
-
|
|
181
|
+
access(all) view fun getParentAddresses(): [Address]
|
|
173
182
|
|
|
174
183
|
/// Borrows this OwnedAccount's AuthAccount Capability
|
|
175
|
-
|
|
184
|
+
access(Owner) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account
|
|
176
185
|
|
|
177
186
|
/// Returns the current owner of this account, if there is one
|
|
178
|
-
|
|
187
|
+
access(all) view fun getOwner(): Address?
|
|
179
188
|
|
|
180
189
|
/// Returns the pending owner of this account, if there is one
|
|
181
|
-
|
|
190
|
+
access(all) view fun getPendingOwner(): Address?
|
|
182
191
|
|
|
183
192
|
/// A callback which is invoked when a parent redeems an owned account
|
|
184
193
|
access(contract) fun setOwnerCallback(_ addr: Address)
|
|
185
194
|
|
|
186
195
|
/// Destroys all outstanding AuthAccount capabilities on this owned account, and creates a new one for the
|
|
187
196
|
/// OwnedAccount to use
|
|
188
|
-
|
|
197
|
+
access(Owner) fun rotateAuthAccount()
|
|
189
198
|
|
|
190
199
|
/// Revokes all keys on this account
|
|
191
|
-
|
|
200
|
+
access(Owner) fun revokeAllKeys()
|
|
192
201
|
}
|
|
193
202
|
|
|
194
203
|
/// Public methods exposed on a ChildAccount resource. OwnedAccountPublic will share some methods here, but isn't
|
|
195
204
|
/// necessarily the same.
|
|
196
205
|
///
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
access(all) resource interface AccountPublic {
|
|
207
|
+
access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability?
|
|
208
|
+
access(all) view fun getPublicCapFromDelegator(type: Type): Capability?
|
|
209
|
+
access(all) view fun getAddress(): Address
|
|
210
|
+
access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}?
|
|
211
|
+
access(all) view fun getCapabilityFilter(): &{CapabilityFilter.Filter}?
|
|
212
|
+
access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64?
|
|
201
213
|
}
|
|
202
214
|
|
|
203
215
|
/// Methods accessible to the designated parent of a ChildAccount
|
|
204
216
|
///
|
|
205
|
-
|
|
206
|
-
|
|
217
|
+
access(all) resource interface AccountPrivate {
|
|
218
|
+
access(Child) view fun getCapability(controllerID: UInt64, type: Type): Capability? {
|
|
207
219
|
post {
|
|
208
220
|
result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)):
|
|
209
221
|
"Capability is not allowed by this account's Parent"
|
|
210
222
|
}
|
|
211
223
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
pub fun getPublicCapFromDelegator(type: Type): Capability?
|
|
215
|
-
pub fun getPrivateCapFromDelegator(type: Type): Capability? {
|
|
224
|
+
access(all) view fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}?
|
|
225
|
+
access(Child) view fun getPrivateCapFromDelegator(type: Type): Capability? {
|
|
216
226
|
post {
|
|
217
227
|
result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)):
|
|
218
228
|
"Capability is not allowed by this account's Parent"
|
|
@@ -229,14 +239,14 @@ pub contract HybridCustody {
|
|
|
229
239
|
|
|
230
240
|
/// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts
|
|
231
241
|
///
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
242
|
+
access(all) resource interface ManagerPrivate {
|
|
243
|
+
access(Manage) fun addAccount(cap: Capability<auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}>)
|
|
244
|
+
access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}?
|
|
245
|
+
access(Manage) fun removeChild(addr: Address)
|
|
246
|
+
access(Manage) fun addOwnedAccount(cap: Capability<auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}>)
|
|
247
|
+
access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}?
|
|
248
|
+
access(Manage) fun removeOwned(addr: Address)
|
|
249
|
+
access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) {
|
|
240
250
|
pre {
|
|
241
251
|
cap == nil || cap!.check(): "Invalid Manager Capability Filter"
|
|
242
252
|
}
|
|
@@ -245,39 +255,40 @@ pub contract HybridCustody {
|
|
|
245
255
|
|
|
246
256
|
/// Functions anyone can call on a manager to get information about an account such as What child accounts it has
|
|
247
257
|
/// Functions anyone can call on a manager to get information about an account such as what child accounts it has
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
258
|
+
access(all) resource interface ManagerPublic {
|
|
259
|
+
access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}?
|
|
260
|
+
access(all) fun getChildAddresses(): [Address]
|
|
261
|
+
access(all) fun getOwnedAddresses(): [Address]
|
|
262
|
+
access(all) fun getChildAccountDisplay(address: Address): MetadataViews.Display?
|
|
253
263
|
access(contract) fun removeParentCallback(child: Address)
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
/// A resource for an account which fills the Parent role of the Child-Parent account management Model. A Manager
|
|
257
267
|
/// can redeem or remove child accounts, and obtain any capabilities exposed by the child account to them.
|
|
258
268
|
///
|
|
259
|
-
|
|
269
|
+
access(all) resource Manager: ManagerPrivate, ManagerPublic, ViewResolver.Resolver, Burner.Burnable {
|
|
270
|
+
access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid)
|
|
260
271
|
|
|
261
272
|
/// Mapping of restricted access child account Capabilities indexed by their address
|
|
262
|
-
|
|
273
|
+
access(self) let childAccounts: {Address: Capability<auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}>}
|
|
263
274
|
/// Mapping of unrestricted owned account Capabilities indexed by their address
|
|
264
|
-
|
|
275
|
+
access(self) let ownedAccounts: {Address: Capability<auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}>}
|
|
265
276
|
|
|
266
277
|
/// A bucket of structs so that the Manager resource can be easily extended with new functionality.
|
|
267
|
-
|
|
278
|
+
access(self) let data: {String: AnyStruct}
|
|
268
279
|
/// A bucket of resources so that the Manager resource can be easily extended with new functionality.
|
|
269
|
-
|
|
280
|
+
access(self) let resources: @{String: AnyResource}
|
|
270
281
|
|
|
271
282
|
/// An optional filter to gate what capabilities are permitted to be returned from a child account For example,
|
|
272
283
|
/// Dapper Wallet parent account's should not be able to retrieve any FungibleToken Provider capabilities.
|
|
273
|
-
|
|
284
|
+
access(self) var filter: Capability<&{CapabilityFilter.Filter}>?
|
|
274
285
|
|
|
275
286
|
// display metadata for a child account exists on its parent
|
|
276
|
-
|
|
287
|
+
access(self) let childAccountDisplays: {Address: MetadataViews.Display}
|
|
277
288
|
|
|
278
289
|
/// Sets the Display on the ChildAccount. If nil, the display is removed.
|
|
279
290
|
///
|
|
280
|
-
|
|
291
|
+
access(Manage) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) {
|
|
281
292
|
pre {
|
|
282
293
|
self.childAccounts[address] != nil: "There is no child account with this address"
|
|
283
294
|
}
|
|
@@ -293,7 +304,7 @@ pub contract HybridCustody {
|
|
|
293
304
|
/// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be
|
|
294
305
|
/// added to the ChildAccount
|
|
295
306
|
///
|
|
296
|
-
|
|
307
|
+
access(Manage) fun addAccount(cap: Capability<auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) {
|
|
297
308
|
pre {
|
|
298
309
|
self.childAccounts[cap.address] == nil: "There is already a child account with this address"
|
|
299
310
|
}
|
|
@@ -311,17 +322,17 @@ pub contract HybridCustody {
|
|
|
311
322
|
|
|
312
323
|
/// Sets the default Filter Capability for this Manager. Does not propagate to child accounts.
|
|
313
324
|
///
|
|
314
|
-
|
|
325
|
+
access(Manage) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) {
|
|
315
326
|
pre {
|
|
316
327
|
cap == nil || cap!.check(): "supplied capability must be nil or check must pass"
|
|
317
328
|
}
|
|
318
329
|
|
|
319
330
|
self.filter = cap
|
|
320
331
|
}
|
|
321
|
-
|
|
332
|
+
|
|
322
333
|
/// Sets the Filter Capability for this Manager, propagating to the specified child account
|
|
323
334
|
///
|
|
324
|
-
|
|
335
|
+
access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) {
|
|
325
336
|
let acct = self.borrowAccount(addr: childAddress)
|
|
326
337
|
?? panic("child account not found")
|
|
327
338
|
|
|
@@ -331,7 +342,7 @@ pub contract HybridCustody {
|
|
|
331
342
|
/// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove
|
|
332
343
|
/// any associated resources and Capabilities
|
|
333
344
|
///
|
|
334
|
-
|
|
345
|
+
access(Manage) fun removeChild(addr: Address) {
|
|
335
346
|
let cap = self.childAccounts.remove(key: addr)
|
|
336
347
|
?? panic("child account not found")
|
|
337
348
|
|
|
@@ -347,9 +358,11 @@ pub contract HybridCustody {
|
|
|
347
358
|
// Get the child account id before removing capability
|
|
348
359
|
let id: UInt64 = acct.uuid
|
|
349
360
|
|
|
350
|
-
|
|
361
|
+
if self.owner != nil {
|
|
362
|
+
acct.parentRemoveChildCallback(parent: self.owner!.address)
|
|
363
|
+
}
|
|
351
364
|
|
|
352
|
-
emit AccountUpdated(id: id, child: cap.address, parent: self.owner
|
|
365
|
+
emit AccountUpdated(id: id, child: cap.address, parent: self.owner?.address, active: false)
|
|
353
366
|
}
|
|
354
367
|
|
|
355
368
|
/// Contract callback that removes a child account from the Manager's child accounts in the event a child
|
|
@@ -363,7 +376,7 @@ pub contract HybridCustody {
|
|
|
363
376
|
/// Adds an owned account to the Manager's list of owned accounts, setting the Manager account as the owner of
|
|
364
377
|
/// the given account
|
|
365
378
|
///
|
|
366
|
-
|
|
379
|
+
access(Manage) fun addOwnedAccount(cap: Capability<auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}>) {
|
|
367
380
|
pre {
|
|
368
381
|
self.ownedAccounts[cap.address] == nil: "There is already an owned account with this address"
|
|
369
382
|
}
|
|
@@ -384,7 +397,7 @@ pub contract HybridCustody {
|
|
|
384
397
|
|
|
385
398
|
/// Returns a reference to a child account
|
|
386
399
|
///
|
|
387
|
-
|
|
400
|
+
access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? {
|
|
388
401
|
let cap = self.childAccounts[addr]
|
|
389
402
|
if cap == nil {
|
|
390
403
|
return nil
|
|
@@ -395,7 +408,7 @@ pub contract HybridCustody {
|
|
|
395
408
|
|
|
396
409
|
/// Returns a reference to a child account's public AccountPublic interface
|
|
397
410
|
///
|
|
398
|
-
|
|
411
|
+
access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? {
|
|
399
412
|
let cap = self.childAccounts[addr]
|
|
400
413
|
if cap == nil {
|
|
401
414
|
return nil
|
|
@@ -406,7 +419,7 @@ pub contract HybridCustody {
|
|
|
406
419
|
|
|
407
420
|
/// Returns a reference to an owned account
|
|
408
421
|
///
|
|
409
|
-
|
|
422
|
+
access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? {
|
|
410
423
|
if let cap = self.ownedAccounts[addr] {
|
|
411
424
|
return cap.borrow()
|
|
412
425
|
}
|
|
@@ -417,7 +430,7 @@ pub contract HybridCustody {
|
|
|
417
430
|
/// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove
|
|
418
431
|
/// any associated resources and Capabilities
|
|
419
432
|
///
|
|
420
|
-
|
|
433
|
+
access(Manage) fun removeOwned(addr: Address) {
|
|
421
434
|
if let acct = self.ownedAccounts.remove(key: addr) {
|
|
422
435
|
if acct.check() {
|
|
423
436
|
acct.borrow()!.seal()
|
|
@@ -437,7 +450,7 @@ pub contract HybridCustody {
|
|
|
437
450
|
/// mechanism intended to easily transfer 'root' access on this account to another account and an attempt to
|
|
438
451
|
/// minimize access vectors.
|
|
439
452
|
///
|
|
440
|
-
|
|
453
|
+
access(Manage) fun giveOwnership(addr: Address, to: Address) {
|
|
441
454
|
let acct = self.ownedAccounts.remove(key: addr)
|
|
442
455
|
?? panic("account not found")
|
|
443
456
|
|
|
@@ -446,31 +459,31 @@ pub contract HybridCustody {
|
|
|
446
459
|
|
|
447
460
|
/// Returns an array of child account addresses
|
|
448
461
|
///
|
|
449
|
-
|
|
462
|
+
access(all) view fun getChildAddresses(): [Address] {
|
|
450
463
|
return self.childAccounts.keys
|
|
451
464
|
}
|
|
452
465
|
|
|
453
466
|
/// Returns an array of owned account addresses
|
|
454
467
|
///
|
|
455
|
-
|
|
468
|
+
access(all) view fun getOwnedAddresses(): [Address] {
|
|
456
469
|
return self.ownedAccounts.keys
|
|
457
470
|
}
|
|
458
471
|
|
|
459
472
|
/// Retrieves the parent-defined display for the given child account
|
|
460
473
|
///
|
|
461
|
-
|
|
474
|
+
access(all) view fun getChildAccountDisplay(address: Address): MetadataViews.Display? {
|
|
462
475
|
return self.childAccountDisplays[address]
|
|
463
476
|
}
|
|
464
477
|
|
|
465
478
|
/// Returns the types of supported views - none at this time
|
|
466
479
|
///
|
|
467
|
-
|
|
480
|
+
access(all) view fun getViews(): [Type] {
|
|
468
481
|
return []
|
|
469
482
|
}
|
|
470
483
|
|
|
471
484
|
/// Resolves the given view if supported - none at this time
|
|
472
485
|
///
|
|
473
|
-
|
|
486
|
+
access(all) view fun resolveView(_ view: Type): AnyStruct? {
|
|
474
487
|
return nil
|
|
475
488
|
}
|
|
476
489
|
|
|
@@ -487,8 +500,19 @@ pub contract HybridCustody {
|
|
|
487
500
|
self.resources <- {}
|
|
488
501
|
}
|
|
489
502
|
|
|
490
|
-
|
|
491
|
-
|
|
503
|
+
// When a manager resource is destroyed, attempt to remove this parent from every
|
|
504
|
+
// child account it currently has
|
|
505
|
+
//
|
|
506
|
+
// Destruction will fail if there are any owned account to prevent loss of access to an account
|
|
507
|
+
access(contract) fun burnCallback() {
|
|
508
|
+
pre {
|
|
509
|
+
// Prevent accidental burning of a resource that has ownership of other accounts
|
|
510
|
+
self.ownedAccounts.length == 0: "cannot destroy a manager with owned accounts"
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
for c in self.childAccounts.keys {
|
|
514
|
+
self.removeChild(addr: c)
|
|
515
|
+
}
|
|
492
516
|
}
|
|
493
517
|
}
|
|
494
518
|
|
|
@@ -501,27 +525,29 @@ pub contract HybridCustody {
|
|
|
501
525
|
/// able to manage all ChildAccount resources it shares, without worrying about whether the upstream parent can do
|
|
502
526
|
/// anything to prevent it.
|
|
503
527
|
///
|
|
504
|
-
|
|
528
|
+
access(all) resource ChildAccount: AccountPrivate, AccountPublic, ViewResolver.Resolver, Burner.Burnable {
|
|
529
|
+
access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, address: Address = self.childCap.address, parent: Address = self.parent)
|
|
530
|
+
|
|
505
531
|
/// A Capability providing access to the underlying child account
|
|
506
|
-
access(self) let childCap: Capability<&{BorrowableAccount, OwnedAccountPublic,
|
|
532
|
+
access(self) let childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>
|
|
507
533
|
|
|
508
534
|
/// The CapabilityFactory Manager is a ChildAccount's way of limiting what types can be asked for by its parent
|
|
509
535
|
/// account. The CapabilityFactory returns Capabilities which can be casted to their appropriate types once
|
|
510
536
|
/// obtained, but only if the child account has configured their factory to allow it. For instance, a
|
|
511
537
|
/// ChildAccount might choose to expose NonFungibleToken.Provider, but not FungibleToken.Provider
|
|
512
|
-
|
|
538
|
+
access(self) var factory: Capability<&{CapabilityFactory.Getter}>
|
|
513
539
|
|
|
514
540
|
/// The CapabilityFilter is a restriction put at the front of obtaining any non-public Capability. Some wallets
|
|
515
541
|
/// might want to give access to NonFungibleToken.Provider, but only to **some** of the collections it manages,
|
|
516
542
|
/// not all of them.
|
|
517
|
-
|
|
543
|
+
access(self) var filter: Capability<&{CapabilityFilter.Filter}>
|
|
518
544
|
|
|
519
545
|
/// The CapabilityDelegator is a way to share one-off capabilities from the child account. These capabilities
|
|
520
546
|
/// can be public OR private and are separate from the factory which returns a capability at a given path as a
|
|
521
547
|
/// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a
|
|
522
548
|
/// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot
|
|
523
549
|
/// collection, but only to the path that the collection exists in.
|
|
524
|
-
|
|
550
|
+
access(self) let delegator: Capability<auth(Capabilities) &{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>
|
|
525
551
|
|
|
526
552
|
/// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If
|
|
527
553
|
/// this filter is not nil, any Capability returned through the `getCapability` function checks that the
|
|
@@ -536,11 +562,11 @@ pub contract HybridCustody {
|
|
|
536
562
|
|
|
537
563
|
/// ChildAccount resources have a 1:1 association with parent accounts, the named parent Address here is the
|
|
538
564
|
/// one with a Capability on this resource.
|
|
539
|
-
|
|
565
|
+
access(all) let parent: Address
|
|
540
566
|
|
|
541
567
|
/// Returns the Address of the underlying child account
|
|
542
568
|
///
|
|
543
|
-
|
|
569
|
+
access(all) view fun getAddress(): Address {
|
|
544
570
|
return self.childCap.address
|
|
545
571
|
}
|
|
546
572
|
|
|
@@ -560,24 +586,24 @@ pub contract HybridCustody {
|
|
|
560
586
|
|
|
561
587
|
/// Sets the CapabiltyFactory.Manager Capability
|
|
562
588
|
///
|
|
563
|
-
|
|
589
|
+
access(contract) fun setCapabilityFactory(cap: Capability<&{CapabilityFactory.Getter}>) {
|
|
564
590
|
self.factory = cap
|
|
565
591
|
}
|
|
566
592
|
|
|
567
593
|
/// Sets the Filter Capability as the one provided
|
|
568
594
|
///
|
|
569
|
-
|
|
595
|
+
access(contract) fun setCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>) {
|
|
570
596
|
self.filter = cap
|
|
571
597
|
}
|
|
572
598
|
|
|
573
599
|
/// The main function to a child account's capabilities from a parent account. When a PrivatePath type is used,
|
|
574
600
|
/// the CapabilityFilter will be borrowed and the Capability being returned will be checked against it to
|
|
575
|
-
/// ensure that borrowing is permitted.
|
|
601
|
+
/// ensure that borrowing is permitted. If not allowed, nil is returned.
|
|
576
602
|
/// Also know that this method retrieves Capabilities via the CapabilityFactory path. To retrieve arbitrary
|
|
577
603
|
/// Capabilities, see `getPrivateCapFromDelegator()` and `getPublicCapFromDelegator()` which use the
|
|
578
604
|
/// `Delegator` retrieval path.
|
|
579
605
|
///
|
|
580
|
-
|
|
606
|
+
access(Child) view fun getCapability(controllerID: UInt64, type: Type): Capability? {
|
|
581
607
|
let child = self.childCap.borrow() ?? panic("failed to borrow child account")
|
|
582
608
|
|
|
583
609
|
let f = self.factory.borrow()!.getFactory(type)
|
|
@@ -585,12 +611,17 @@ pub contract HybridCustody {
|
|
|
585
611
|
return nil
|
|
586
612
|
}
|
|
587
613
|
|
|
588
|
-
let acct = child.
|
|
614
|
+
let acct = child._borrowAccount()
|
|
615
|
+
let tmp = f!.getCapability(acct: acct, controllerID: controllerID)
|
|
616
|
+
if tmp == nil {
|
|
617
|
+
return nil
|
|
618
|
+
}
|
|
589
619
|
|
|
590
|
-
let cap =
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
620
|
+
let cap = tmp!
|
|
621
|
+
// Check that private capabilities are allowed by either internal or manager filter (if assigned)
|
|
622
|
+
// If not allowed, return nil
|
|
623
|
+
if self.filter.borrow()!.allowed(cap: cap) == false || (self.getManagerCapabilityFilter()?.allowed(cap: cap) ?? true) == false {
|
|
624
|
+
return nil
|
|
594
625
|
}
|
|
595
626
|
|
|
596
627
|
return cap
|
|
@@ -599,7 +630,7 @@ pub contract HybridCustody {
|
|
|
599
630
|
/// Retrieves a private Capability from the Delegator or nil none is found of the given type. Useful for
|
|
600
631
|
/// arbitrary Capability retrieval
|
|
601
632
|
///
|
|
602
|
-
|
|
633
|
+
access(Child) view fun getPrivateCapFromDelegator(type: Type): Capability? {
|
|
603
634
|
if let d = self.delegator.borrow() {
|
|
604
635
|
return d.getPrivateCapability(type)
|
|
605
636
|
}
|
|
@@ -610,7 +641,7 @@ pub contract HybridCustody {
|
|
|
610
641
|
/// Retrieves a public Capability from the Delegator or nil none is found of the given type. Useful for
|
|
611
642
|
/// arbitrary Capability retrieval
|
|
612
643
|
///
|
|
613
|
-
|
|
644
|
+
access(all) view fun getPublicCapFromDelegator(type: Type): Capability? {
|
|
614
645
|
if let d = self.delegator.borrow() {
|
|
615
646
|
return d.getPublicCapability(type)
|
|
616
647
|
}
|
|
@@ -620,37 +651,43 @@ pub contract HybridCustody {
|
|
|
620
651
|
/// Enables retrieval of public Capabilities of the given type from the specified path or nil if none is found.
|
|
621
652
|
/// Callers should be aware this method uses the `CapabilityFactory` retrieval path.
|
|
622
653
|
///
|
|
623
|
-
|
|
624
|
-
|
|
654
|
+
access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? {
|
|
655
|
+
let child = self.childCap.borrow() ?? panic("failed to borrow child account")
|
|
656
|
+
|
|
657
|
+
let f = self.factory.borrow()!.getFactory(type)
|
|
658
|
+
if f == nil {
|
|
659
|
+
return nil
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
let acct = child._borrowAccount()
|
|
663
|
+
return f!.getPublicCapability(acct: acct, path: path)
|
|
625
664
|
}
|
|
626
665
|
|
|
627
666
|
/// Returns a reference to the stored managerCapabilityFilter if one exists
|
|
628
667
|
///
|
|
629
|
-
|
|
668
|
+
access(all) view fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? {
|
|
630
669
|
return self.managerCapabilityFilter != nil ? self.managerCapabilityFilter!.borrow() : nil
|
|
631
670
|
}
|
|
632
671
|
|
|
633
672
|
/// Sets the child account as redeemed by the given Address
|
|
634
673
|
///
|
|
635
674
|
access(contract) fun setRedeemed(_ addr: Address) {
|
|
636
|
-
let acct = self.childCap.borrow()!.
|
|
637
|
-
|
|
638
|
-
o.setRedeemed(addr)
|
|
639
|
-
}
|
|
675
|
+
let acct = self.childCap.borrow()!._borrowAccount()
|
|
676
|
+
acct.storage.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath)?.setRedeemed(addr)
|
|
640
677
|
}
|
|
641
678
|
|
|
642
679
|
/// Returns a reference to the stored delegator, generally used for arbitrary Capability retrieval
|
|
643
680
|
///
|
|
644
|
-
|
|
681
|
+
access(Owner) fun borrowCapabilityDelegator(): auth(Capabilities) &CapabilityDelegator.Delegator? {
|
|
645
682
|
let path = HybridCustody.getCapabilityDelegatorIdentifier(self.parent)
|
|
646
|
-
return self.childCap.borrow()!.
|
|
683
|
+
return self.childCap.borrow()!._borrowAccount().storage.borrow<auth(Capabilities) &CapabilityDelegator.Delegator>(
|
|
647
684
|
from: StoragePath(identifier: path)!
|
|
648
685
|
)
|
|
649
686
|
}
|
|
650
687
|
|
|
651
688
|
/// Returns a list of supported metadata views
|
|
652
689
|
///
|
|
653
|
-
|
|
690
|
+
access(all) view fun getViews(): [Type] {
|
|
654
691
|
return [
|
|
655
692
|
Type<MetadataViews.Display>()
|
|
656
693
|
]
|
|
@@ -658,17 +695,22 @@ pub contract HybridCustody {
|
|
|
658
695
|
|
|
659
696
|
/// Resolves a view of the given type if supported
|
|
660
697
|
///
|
|
661
|
-
|
|
698
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
662
699
|
switch view {
|
|
663
700
|
case Type<MetadataViews.Display>():
|
|
664
701
|
let childAddress = self.getAddress()
|
|
665
|
-
let
|
|
702
|
+
let tmp = getAccount(self.parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath)
|
|
703
|
+
if tmp == nil {
|
|
704
|
+
return nil
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
let manager = tmp!
|
|
666
708
|
|
|
667
709
|
if !manager.check() {
|
|
668
710
|
return nil
|
|
669
711
|
}
|
|
670
712
|
|
|
671
|
-
return manager
|
|
713
|
+
return manager.borrow()!.getChildAccountDisplay(address: childAddress)
|
|
672
714
|
}
|
|
673
715
|
return nil
|
|
674
716
|
}
|
|
@@ -681,22 +723,22 @@ pub contract HybridCustody {
|
|
|
681
723
|
return
|
|
682
724
|
}
|
|
683
725
|
|
|
684
|
-
let child: &
|
|
726
|
+
let child: &{HybridCustody.BorrowableAccount} = self.childCap.borrow()!
|
|
685
727
|
if !child.check() {
|
|
686
728
|
return
|
|
687
729
|
}
|
|
688
730
|
|
|
689
|
-
let acct = child.
|
|
690
|
-
if let ownedAcct = acct.borrow
|
|
731
|
+
let acct = child._borrowAccount()
|
|
732
|
+
if let ownedAcct = acct.storage.borrow<auth(Owner) &OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) {
|
|
691
733
|
ownedAcct.removeParent(parent: parent)
|
|
692
734
|
}
|
|
693
735
|
}
|
|
694
736
|
|
|
695
737
|
init(
|
|
696
|
-
_ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic,
|
|
697
|
-
_ factory: Capability<&
|
|
738
|
+
_ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>,
|
|
739
|
+
_ factory: Capability<&{CapabilityFactory.Getter}>,
|
|
698
740
|
_ filter: Capability<&{CapabilityFilter.Filter}>,
|
|
699
|
-
_ delegator: Capability
|
|
741
|
+
_ delegator: Capability<auth(Capabilities) &{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>,
|
|
700
742
|
_ parent: Address
|
|
701
743
|
) {
|
|
702
744
|
pre {
|
|
@@ -716,8 +758,30 @@ pub contract HybridCustody {
|
|
|
716
758
|
self.resources <- {}
|
|
717
759
|
}
|
|
718
760
|
|
|
719
|
-
|
|
720
|
-
|
|
761
|
+
/// Returns a capability to this child account's CapabilityFilter
|
|
762
|
+
///
|
|
763
|
+
access(all) view fun getCapabilityFilter(): &{CapabilityFilter.Filter}? {
|
|
764
|
+
return self.filter.check() ? self.filter.borrow() : nil
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/// Returns a capability to this child account's CapabilityFactory
|
|
768
|
+
///
|
|
769
|
+
access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? {
|
|
770
|
+
return self.factory.check() ? self.factory.borrow() : nil
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? {
|
|
774
|
+
let child = self.childCap.borrow()
|
|
775
|
+
if child == nil {
|
|
776
|
+
return nil
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return child!.getControllerIDForType(type: type, forPath: forPath)
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// When a ChildAccount is destroyed, attempt to remove it from the parent account as well
|
|
783
|
+
access(contract) fun burnCallback() {
|
|
784
|
+
self.parentRemoveChildCallback(parent: self.parent)
|
|
721
785
|
}
|
|
722
786
|
}
|
|
723
787
|
|
|
@@ -730,18 +794,19 @@ pub contract HybridCustody {
|
|
|
730
794
|
/// accounts would still exist, allowing a form of Hybrid Custody which has no true owner over an account, but
|
|
731
795
|
/// shared partial ownership.
|
|
732
796
|
///
|
|
733
|
-
|
|
797
|
+
access(all) resource OwnedAccount: OwnedAccountPrivate, BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver, Burner.Burnable {
|
|
798
|
+
access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, addr: Address = self.acct.address)
|
|
734
799
|
/// Capability on the underlying account object
|
|
735
|
-
access(self) var acct: Capability
|
|
800
|
+
access(self) var acct: Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>
|
|
736
801
|
|
|
737
802
|
/// Mapping of current and pending parents, true and false respectively
|
|
738
|
-
|
|
803
|
+
access(all) let parents: {Address: Bool}
|
|
739
804
|
/// Address of the pending owner, if one exists
|
|
740
|
-
|
|
805
|
+
access(all) var pendingOwner: Address?
|
|
741
806
|
/// Address of the current owner, if one exists
|
|
742
|
-
|
|
807
|
+
access(all) var acctOwner: Address?
|
|
743
808
|
/// Owned status of this account
|
|
744
|
-
|
|
809
|
+
access(all) var currentlyOwned: Bool
|
|
745
810
|
|
|
746
811
|
/// A bucket of structs so that the OwnedAccount resource can be easily extended with new functionality.
|
|
747
812
|
access(self) let data: {String: AnyStruct}
|
|
@@ -792,12 +857,12 @@ pub contract HybridCustody {
|
|
|
792
857
|
/// 4. Publish the newly made private link to the designated parent's inbox for them to claim on their @Manager
|
|
793
858
|
/// resource.
|
|
794
859
|
///
|
|
795
|
-
|
|
860
|
+
access(Publish | Owner) fun publishToParent(
|
|
796
861
|
parentAddress: Address,
|
|
797
|
-
factory: Capability<&
|
|
862
|
+
factory: Capability<&{CapabilityFactory.Getter}>,
|
|
798
863
|
filter: Capability<&{CapabilityFilter.Filter}>
|
|
799
864
|
) {
|
|
800
|
-
pre{
|
|
865
|
+
pre {
|
|
801
866
|
self.parents[parentAddress] == nil: "Address pending or already redeemed as parent"
|
|
802
867
|
}
|
|
803
868
|
let capDelegatorIdentifier = HybridCustody.getCapabilityDelegatorIdentifier(parentAddress)
|
|
@@ -808,41 +873,32 @@ pub contract HybridCustody {
|
|
|
808
873
|
let capDelegatorStorage = StoragePath(identifier: capDelegatorIdentifier)!
|
|
809
874
|
let acct = self.borrowAccount()
|
|
810
875
|
|
|
811
|
-
assert(acct.borrow<&AnyResource>(from: capDelegatorStorage) == nil, message: "conflicting resource found in capability delegator storage slot for parentAddress")
|
|
812
|
-
assert(acct.borrow<&AnyResource>(from: childAccountStorage) == nil, message: "conflicting resource found in child account storage slot for parentAddress")
|
|
876
|
+
assert(acct.storage.borrow<&AnyResource>(from: capDelegatorStorage) == nil, message: "conflicting resource found in capability delegator storage slot for parentAddress")
|
|
877
|
+
assert(acct.storage.borrow<&AnyResource>(from: childAccountStorage) == nil, message: "conflicting resource found in child account storage slot for parentAddress")
|
|
813
878
|
|
|
814
|
-
if acct.borrow<&CapabilityDelegator.Delegator>(from: capDelegatorStorage) == nil {
|
|
879
|
+
if acct.storage.borrow<&CapabilityDelegator.Delegator>(from: capDelegatorStorage) == nil {
|
|
815
880
|
let delegator <- CapabilityDelegator.createDelegator()
|
|
816
|
-
acct.save(<-delegator, to: capDelegatorStorage)
|
|
881
|
+
acct.storage.save(<-delegator, to: capDelegatorStorage)
|
|
817
882
|
}
|
|
818
883
|
|
|
819
884
|
let capDelegatorPublic = PublicPath(identifier: capDelegatorIdentifier)!
|
|
820
|
-
let capDelegatorPrivate = PrivatePath(identifier: capDelegatorIdentifier)!
|
|
885
|
+
// let capDelegatorPrivate = PrivatePath(identifier: capDelegatorIdentifier)!
|
|
821
886
|
|
|
822
|
-
acct.
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
)
|
|
826
|
-
acct.link<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(
|
|
827
|
-
capDelegatorPrivate,
|
|
828
|
-
target: capDelegatorStorage
|
|
829
|
-
)
|
|
830
|
-
let delegator = acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(
|
|
831
|
-
capDelegatorPrivate
|
|
832
|
-
)
|
|
887
|
+
let pubCap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(capDelegatorStorage)
|
|
888
|
+
acct.capabilities.publish(pubCap, at: capDelegatorPublic)
|
|
889
|
+
|
|
890
|
+
let delegator = acct.capabilities.storage.issue<auth(Capabilities) &{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(capDelegatorStorage)
|
|
833
891
|
assert(delegator.check(), message: "failed to setup capability delegator for parent address")
|
|
834
892
|
|
|
835
|
-
let borrowableCap = self.borrowAccount().
|
|
836
|
-
HybridCustody.
|
|
893
|
+
let borrowableCap = self.borrowAccount().capabilities.storage.issue<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>(
|
|
894
|
+
HybridCustody.OwnedAccountStoragePath
|
|
837
895
|
)
|
|
838
|
-
let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress)
|
|
839
896
|
|
|
897
|
+
let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress)
|
|
840
898
|
let childAccountPrivatePath = PrivatePath(identifier: identifier)!
|
|
841
899
|
|
|
842
|
-
acct.save(<-childAcct, to: childAccountStorage)
|
|
843
|
-
acct.
|
|
844
|
-
|
|
845
|
-
let delegatorCap = acct.getCapability<&ChildAccount{AccountPrivate, AccountPublic, MetadataViews.Resolver}>(childAccountPrivatePath)
|
|
900
|
+
acct.storage.save(<-childAcct, to: childAccountStorage)
|
|
901
|
+
let delegatorCap = acct.capabilities.storage.issue<auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}>(childAccountStorage)
|
|
846
902
|
assert(delegatorCap.check(), message: "Delegator capability check failed")
|
|
847
903
|
|
|
848
904
|
acct.inbox.publish(delegatorCap, name: identifier, recipient: parentAddress)
|
|
@@ -862,38 +918,43 @@ pub contract HybridCustody {
|
|
|
862
918
|
|
|
863
919
|
/// Checks the validity of the encapsulated account Capability
|
|
864
920
|
///
|
|
865
|
-
|
|
921
|
+
access(all) view fun check(): Bool {
|
|
866
922
|
return self.acct.check()
|
|
867
923
|
}
|
|
868
924
|
|
|
869
925
|
/// Returns a reference to the encapsulated account object
|
|
870
926
|
///
|
|
871
|
-
|
|
872
|
-
return self.acct.borrow()
|
|
927
|
+
access(Owner) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account {
|
|
928
|
+
return self.acct.borrow() ?? panic("unable to borrow Account Capability")
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Used internally so that child account resources are able to borrow their underlying Account reference
|
|
932
|
+
access(contract) view fun _borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account {
|
|
933
|
+
return self.borrowAccount()
|
|
873
934
|
}
|
|
874
935
|
|
|
875
936
|
/// Returns the addresses of all associated parents pending and active
|
|
876
937
|
///
|
|
877
|
-
|
|
938
|
+
access(all) view fun getParentAddresses(): [Address] {
|
|
878
939
|
return self.parents.keys
|
|
879
940
|
}
|
|
880
941
|
|
|
881
942
|
/// Returns whether the given address is a parent of this account
|
|
882
943
|
///
|
|
883
|
-
|
|
944
|
+
access(all) view fun isChildOf(_ addr: Address): Bool {
|
|
884
945
|
return self.parents[addr] != nil
|
|
885
946
|
}
|
|
886
947
|
|
|
887
948
|
/// Returns nil if the given address is not a parent, false if the parent has not redeemed the child account
|
|
888
949
|
/// yet, and true if they have
|
|
889
950
|
///
|
|
890
|
-
|
|
951
|
+
access(all) view fun getRedeemedStatus(addr: Address): Bool? {
|
|
891
952
|
return self.parents[addr]
|
|
892
953
|
}
|
|
893
954
|
|
|
894
955
|
/// Returns associated parent addresses and their redeemed status
|
|
895
956
|
///
|
|
896
|
-
|
|
957
|
+
access(all) view fun getParentStatuses(): {Address: Bool} {
|
|
897
958
|
return self.parents
|
|
898
959
|
}
|
|
899
960
|
|
|
@@ -901,7 +962,7 @@ pub contract HybridCustody {
|
|
|
901
962
|
/// configured for the provided parent address. Once done, the parent will not have any valid capabilities with
|
|
902
963
|
/// which to access the child account.
|
|
903
964
|
///
|
|
904
|
-
|
|
965
|
+
access(Owner | Remove) fun removeParent(parent: Address): Bool {
|
|
905
966
|
if self.parents[parent] == nil {
|
|
906
967
|
return false
|
|
907
968
|
}
|
|
@@ -909,21 +970,28 @@ pub contract HybridCustody {
|
|
|
909
970
|
let capDelegatorIdentifier = HybridCustody.getCapabilityDelegatorIdentifier(parent)
|
|
910
971
|
|
|
911
972
|
let acct = self.borrowAccount()
|
|
912
|
-
acct.unlink(PrivatePath(identifier: identifier)!)
|
|
913
|
-
acct.unlink(PublicPath(identifier: identifier)!)
|
|
914
973
|
|
|
915
|
-
|
|
916
|
-
|
|
974
|
+
// get all controllers which target this storage path
|
|
975
|
+
let storagePath = StoragePath(identifier: identifier)!
|
|
976
|
+
let childAccountControllers = acct.capabilities.storage.getControllers(forPath: storagePath)
|
|
977
|
+
for c in childAccountControllers {
|
|
978
|
+
c.delete()
|
|
979
|
+
}
|
|
980
|
+
Burner.burn(<- acct.storage.load<@AnyResource>(from: storagePath))
|
|
917
981
|
|
|
918
|
-
|
|
919
|
-
|
|
982
|
+
let delegatorStoragePath = StoragePath(identifier: capDelegatorIdentifier)!
|
|
983
|
+
let delegatorControllers = acct.capabilities.storage.getControllers(forPath: delegatorStoragePath)
|
|
984
|
+
for c in delegatorControllers {
|
|
985
|
+
c.delete()
|
|
986
|
+
}
|
|
987
|
+
Burner.burn(<- acct.storage.load<@AnyResource>(from: delegatorStoragePath))
|
|
920
988
|
|
|
921
989
|
self.parents.remove(key: parent)
|
|
922
990
|
emit AccountUpdated(id: self.uuid, child: self.acct.address, parent: parent, active: false)
|
|
923
991
|
|
|
924
|
-
let parentManager = getAccount(parent).
|
|
925
|
-
if parentManager
|
|
926
|
-
parentManager
|
|
992
|
+
let parentManager = getAccount(parent).capabilities.get<&{ManagerPublic}>(HybridCustody.ManagerPublicPath)
|
|
993
|
+
if parentManager?.check() == true {
|
|
994
|
+
parentManager!.borrow()?.removeParentCallback(child: acct.address)
|
|
927
995
|
}
|
|
928
996
|
|
|
929
997
|
return true
|
|
@@ -931,21 +999,21 @@ pub contract HybridCustody {
|
|
|
931
999
|
|
|
932
1000
|
/// Returns the address of the encapsulated account
|
|
933
1001
|
///
|
|
934
|
-
|
|
1002
|
+
access(all) view fun getAddress(): Address {
|
|
935
1003
|
return self.acct.address
|
|
936
1004
|
}
|
|
937
1005
|
|
|
938
1006
|
/// Returns the address of the pending owner if one is assigned. Pending owners are assigned when ownership has
|
|
939
1007
|
/// been granted, but has not yet been redeemed.
|
|
940
1008
|
///
|
|
941
|
-
|
|
1009
|
+
access(all) view fun getPendingOwner(): Address? {
|
|
942
1010
|
return self.pendingOwner
|
|
943
1011
|
}
|
|
944
1012
|
|
|
945
1013
|
/// Returns the address of the current owner if one is assigned. Current owners are assigned when ownership has
|
|
946
1014
|
/// been redeemed.
|
|
947
1015
|
///
|
|
948
|
-
|
|
1016
|
+
access(all) view fun getOwner(): Address? {
|
|
949
1017
|
if !self.currentlyOwned {
|
|
950
1018
|
return nil
|
|
951
1019
|
}
|
|
@@ -961,22 +1029,17 @@ pub contract HybridCustody {
|
|
|
961
1029
|
/// mechanism intended to easily transfer 'root' access on this account to another account and an attempt to
|
|
962
1030
|
/// minimize access vectors.
|
|
963
1031
|
///
|
|
964
|
-
|
|
1032
|
+
access(Owner) fun giveOwnership(to: Address) {
|
|
965
1033
|
self.seal()
|
|
966
1034
|
|
|
967
1035
|
let acct = self.borrowAccount()
|
|
968
|
-
|
|
969
|
-
if self.acctOwner != nil {
|
|
970
|
-
acct.unlink(
|
|
971
|
-
PrivatePath(identifier: HybridCustody.getOwnerIdentifier(self.acctOwner!))!
|
|
972
|
-
)
|
|
973
|
-
}
|
|
1036
|
+
|
|
974
1037
|
// Link a Capability for the new owner, retrieve & publish
|
|
975
1038
|
let identifier = HybridCustody.getOwnerIdentifier(to)
|
|
976
|
-
let cap = acct.
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1039
|
+
let cap = acct.capabilities.storage.issue<auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath)
|
|
1040
|
+
|
|
1041
|
+
// make sure we can borrow the newly issued owned account
|
|
1042
|
+
cap.borrow()!.borrowAccount()
|
|
980
1043
|
|
|
981
1044
|
acct.inbox.publish(cap, name: identifier, recipient: to)
|
|
982
1045
|
|
|
@@ -988,7 +1051,7 @@ pub contract HybridCustody {
|
|
|
988
1051
|
|
|
989
1052
|
/// Revokes all keys on the underlying account
|
|
990
1053
|
///
|
|
991
|
-
|
|
1054
|
+
access(Owner) fun revokeAllKeys() {
|
|
992
1055
|
let acct = self.borrowAccount()
|
|
993
1056
|
|
|
994
1057
|
// Revoke all keys
|
|
@@ -1007,33 +1070,25 @@ pub contract HybridCustody {
|
|
|
1007
1070
|
/// assumes ownership of an account to guarantee that the previous owner doesn't maintain admin access to the
|
|
1008
1071
|
/// account via other AuthAccount Capabilities.
|
|
1009
1072
|
///
|
|
1010
|
-
|
|
1073
|
+
access(Owner) fun rotateAuthAccount() {
|
|
1011
1074
|
let acct = self.borrowAccount()
|
|
1012
1075
|
|
|
1013
1076
|
// Find all active AuthAccount capabilities so they can be removed after we make the new auth account cap
|
|
1014
|
-
let
|
|
1015
|
-
acct.forEachPrivate(fun (path: PrivatePath, type: Type): Bool {
|
|
1016
|
-
if type.identifier == "Capability<&AuthAccount>" {
|
|
1017
|
-
pathsToUnlink.append(path)
|
|
1018
|
-
}
|
|
1019
|
-
return true
|
|
1020
|
-
})
|
|
1077
|
+
let controllersToDestroy = acct.capabilities.account.getControllers()
|
|
1021
1078
|
|
|
1022
1079
|
// Link a new AuthAccount Capability
|
|
1023
|
-
|
|
1024
|
-
// capability to this path before it is made, thus maintaining ownership despite making it look like they
|
|
1025
|
-
// gave it away. Until capability controllers, this method should not be fully trusted.
|
|
1026
|
-
let authAcctPath = "HybridCustodyRelinquished".concat(HybridCustody.account.address.toString()).concat(getCurrentBlock().height.toString())
|
|
1027
|
-
let acctCap = acct.linkAccount(PrivatePath(identifier: authAcctPath)!)!
|
|
1080
|
+
let acctCap = acct.capabilities.account.issue<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>()
|
|
1028
1081
|
|
|
1029
1082
|
self.acct = acctCap
|
|
1030
1083
|
let newAcct = self.acct.borrow()!
|
|
1031
1084
|
|
|
1032
1085
|
// cleanup, remove all previously found paths. We had to do it in this order because we will be unlinking
|
|
1033
1086
|
// the existing path which will cause a deference issue with the originally borrowed auth account
|
|
1034
|
-
for
|
|
1035
|
-
newAcct.
|
|
1087
|
+
for con in controllersToDestroy {
|
|
1088
|
+
newAcct.capabilities.account.getController(byCapabilityID: con.capabilityID)?.delete()
|
|
1036
1089
|
}
|
|
1090
|
+
|
|
1091
|
+
assert(self.acct.check(), message: "new auth account capability is not valid")
|
|
1037
1092
|
}
|
|
1038
1093
|
|
|
1039
1094
|
/// Revokes all keys on an account, unlinks all currently active AuthAccount capabilities, then makes a new one
|
|
@@ -1043,7 +1098,7 @@ pub contract HybridCustody {
|
|
|
1043
1098
|
///
|
|
1044
1099
|
/// USE WITH EXTREME CAUTION.
|
|
1045
1100
|
///
|
|
1046
|
-
|
|
1101
|
+
access(Owner) fun seal() {
|
|
1047
1102
|
self.rotateAuthAccount()
|
|
1048
1103
|
self.revokeAllKeys() // There needs to be a path to giving ownership that doesn't revoke keys
|
|
1049
1104
|
emit AccountSealed(id: self.uuid, address: self.acct.address, parents: self.parents.keys)
|
|
@@ -1052,16 +1107,16 @@ pub contract HybridCustody {
|
|
|
1052
1107
|
|
|
1053
1108
|
/// Retrieves a reference to the ChildAccount associated with the given parent account if one exists.
|
|
1054
1109
|
///
|
|
1055
|
-
|
|
1110
|
+
access(Owner) fun borrowChildAccount(parent: Address): auth(Capabilities) &ChildAccount? {
|
|
1056
1111
|
let identifier = HybridCustody.getChildAccountIdentifier(parent)
|
|
1057
|
-
return self.borrowAccount().borrow
|
|
1112
|
+
return self.borrowAccount().storage.borrow<auth(Capabilities) &ChildAccount>(from: StoragePath(identifier: identifier)!)
|
|
1058
1113
|
}
|
|
1059
1114
|
|
|
1060
1115
|
/// Sets the CapabilityFactory Manager for the specified parent in the associated ChildAccount.
|
|
1061
1116
|
///
|
|
1062
|
-
|
|
1117
|
+
access(Owner) fun setCapabilityFactoryForParent(
|
|
1063
1118
|
parent: Address,
|
|
1064
|
-
cap: Capability<&
|
|
1119
|
+
cap: Capability<&{CapabilityFactory.Getter}>
|
|
1065
1120
|
) {
|
|
1066
1121
|
let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address")
|
|
1067
1122
|
p.setCapabilityFactory(cap: cap)
|
|
@@ -1069,21 +1124,21 @@ pub contract HybridCustody {
|
|
|
1069
1124
|
|
|
1070
1125
|
/// Sets the Filter for the specified parent in the associated ChildAccount.
|
|
1071
1126
|
///
|
|
1072
|
-
|
|
1127
|
+
access(Owner) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) {
|
|
1073
1128
|
let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address")
|
|
1074
1129
|
p.setCapabilityFilter(cap: cap)
|
|
1075
1130
|
}
|
|
1076
1131
|
|
|
1077
1132
|
/// Retrieves a reference to the Delegator associated with the given parent account if one exists.
|
|
1078
1133
|
///
|
|
1079
|
-
|
|
1134
|
+
access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(Mutate) &CapabilityDelegator.Delegator? {
|
|
1080
1135
|
let identifier = HybridCustody.getCapabilityDelegatorIdentifier(parent)
|
|
1081
|
-
return self.borrowAccount().borrow
|
|
1136
|
+
return self.borrowAccount().storage.borrow<auth(Mutate) &CapabilityDelegator.Delegator>(from: StoragePath(identifier: identifier)!)
|
|
1082
1137
|
}
|
|
1083
1138
|
|
|
1084
1139
|
/// Adds the provided Capability to the Delegator associated with the given parent account.
|
|
1085
1140
|
///
|
|
1086
|
-
|
|
1141
|
+
access(Owner) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) {
|
|
1087
1142
|
let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address")
|
|
1088
1143
|
let delegator = self.borrowCapabilityDelegatorForParent(parent: parent)
|
|
1089
1144
|
?? panic("could not borrow capability delegator resource for parent address")
|
|
@@ -1092,20 +1147,20 @@ pub contract HybridCustody {
|
|
|
1092
1147
|
|
|
1093
1148
|
/// Removes the provided Capability from the Delegator associated with the given parent account.
|
|
1094
1149
|
///
|
|
1095
|
-
|
|
1150
|
+
access(Owner) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) {
|
|
1096
1151
|
let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address")
|
|
1097
1152
|
let delegator = self.borrowCapabilityDelegatorForParent(parent: parent)
|
|
1098
1153
|
?? panic("could not borrow capability delegator resource for parent address")
|
|
1099
1154
|
delegator.removeCapability(cap: cap)
|
|
1100
1155
|
}
|
|
1101
1156
|
|
|
1102
|
-
|
|
1157
|
+
access(all) view fun getViews(): [Type] {
|
|
1103
1158
|
return [
|
|
1104
1159
|
Type<MetadataViews.Display>()
|
|
1105
1160
|
]
|
|
1106
1161
|
}
|
|
1107
1162
|
|
|
1108
|
-
|
|
1163
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
1109
1164
|
switch view {
|
|
1110
1165
|
case Type<MetadataViews.Display>():
|
|
1111
1166
|
return self.display
|
|
@@ -1115,12 +1170,27 @@ pub contract HybridCustody {
|
|
|
1115
1170
|
|
|
1116
1171
|
/// Sets this OwnedAccount's display to the one provided
|
|
1117
1172
|
///
|
|
1118
|
-
|
|
1173
|
+
access(Owner) fun setDisplay(_ d: MetadataViews.Display) {
|
|
1119
1174
|
self.display = d
|
|
1120
1175
|
}
|
|
1121
1176
|
|
|
1177
|
+
access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? {
|
|
1178
|
+
let acct = self.acct.borrow()
|
|
1179
|
+
if acct == nil {
|
|
1180
|
+
return nil
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
for c in acct!.capabilities.storage.getControllers(forPath: forPath) {
|
|
1184
|
+
if c.borrowType.isSubtype(of: type) {
|
|
1185
|
+
return c.capabilityID
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
return nil
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1122
1192
|
init(
|
|
1123
|
-
_ acct: Capability
|
|
1193
|
+
_ acct: Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>
|
|
1124
1194
|
) {
|
|
1125
1195
|
self.acct = acct
|
|
1126
1196
|
|
|
@@ -1134,36 +1204,39 @@ pub contract HybridCustody {
|
|
|
1134
1204
|
self.display = nil
|
|
1135
1205
|
}
|
|
1136
1206
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1207
|
+
// When an OwnedAccount is destroyed, remove it from every configured parent account
|
|
1208
|
+
access(contract) fun burnCallback() {
|
|
1209
|
+
for p in self.parents.keys {
|
|
1210
|
+
self.removeParent(parent: p)
|
|
1211
|
+
}
|
|
1139
1212
|
}
|
|
1140
1213
|
}
|
|
1141
1214
|
|
|
1142
1215
|
/// Utility function to get the path identifier for a parent address when interacting with a ChildAccount and its
|
|
1143
1216
|
/// parents
|
|
1144
1217
|
///
|
|
1145
|
-
|
|
1218
|
+
access(all) view fun getChildAccountIdentifier(_ addr: Address): String {
|
|
1146
1219
|
return "ChildAccount_".concat(addr.toString())
|
|
1147
1220
|
}
|
|
1148
1221
|
|
|
1149
1222
|
/// Utility function to get the path identifier for a parent address when interacting with a Delegator and its
|
|
1150
1223
|
/// parents
|
|
1151
1224
|
///
|
|
1152
|
-
|
|
1225
|
+
access(all) view fun getCapabilityDelegatorIdentifier(_ addr: Address): String {
|
|
1153
1226
|
return "ChildCapabilityDelegator_".concat(addr.toString())
|
|
1154
1227
|
}
|
|
1155
1228
|
|
|
1156
1229
|
/// Utility function to get the path identifier for a parent address when interacting with an OwnedAccount and its
|
|
1157
1230
|
/// owners
|
|
1158
1231
|
///
|
|
1159
|
-
|
|
1232
|
+
access(all) view fun getOwnerIdentifier(_ addr: Address): String {
|
|
1160
1233
|
return "HybridCustodyOwnedAccount_".concat(HybridCustody.account.address.toString()).concat(addr.toString())
|
|
1161
1234
|
}
|
|
1162
1235
|
|
|
1163
1236
|
/// Returns an OwnedAccount wrapping the provided AuthAccount Capability.
|
|
1164
1237
|
///
|
|
1165
|
-
|
|
1166
|
-
acct: Capability
|
|
1238
|
+
access(all) fun createOwnedAccount(
|
|
1239
|
+
acct: Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>
|
|
1167
1240
|
): @OwnedAccount {
|
|
1168
1241
|
pre {
|
|
1169
1242
|
acct.check(): "invalid auth account capability"
|
|
@@ -1176,7 +1249,7 @@ pub contract HybridCustody {
|
|
|
1176
1249
|
|
|
1177
1250
|
/// Returns a new Manager with the provided Filter as default (if not nil).
|
|
1178
1251
|
///
|
|
1179
|
-
|
|
1252
|
+
access(all) fun createManager(filter: Capability<&{CapabilityFilter.Filter}>?): @Manager {
|
|
1180
1253
|
pre {
|
|
1181
1254
|
filter == nil || filter!.check(): "Invalid CapabilityFilter Filter capability provided"
|
|
1182
1255
|
}
|