From 68025500a138c209bf32f2a904fba8baefdb0722 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 18 Jul 2023 18:56:06 -0700 Subject: [PATCH 1/6] first capcon transaction as an example --- transactions/hybrid-custody/setup_manager.cdc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/transactions/hybrid-custody/setup_manager.cdc b/transactions/hybrid-custody/setup_manager.cdc index 746d2a9..7963e3b 100644 --- a/transactions/hybrid-custody/setup_manager.cdc +++ b/transactions/hybrid-custody/setup_manager.cdc @@ -13,11 +13,10 @@ transaction(filterAddress: Address?, filterPath: PublicPath?) { acct.save(<- m, to: HybridCustody.ManagerStoragePath) } - acct.unlink(HybridCustody.ManagerPublicPath) - acct.unlink(HybridCustody.ManagerPrivatePath) + acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.ManagerPrivatePath, target: HybridCustody.ManagerStoragePath) - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath, target: HybridCustody.ManagerStoragePath) + let publicCap = acct.capabilities.storage.issue<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath) + acct.capabilities.publish(publicCap, at: HybridCustody.ManagerPublicPath) } } \ No newline at end of file From a26caa115e856d556cf416a1126ade5d656991c3 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 19 Jul 2023 06:50:57 -0700 Subject: [PATCH 2/6] handle two other transactions --- .../hybrid-custody/set_manager_filter_cap.cdc | 3 +- transactions/hybrid-custody/setup_manager.cdc | 2 -- .../hybrid-custody/setup_multi_sig.cdc | 29 ++++++++----------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/transactions/hybrid-custody/set_manager_filter_cap.cdc b/transactions/hybrid-custody/set_manager_filter_cap.cdc index 401fd92..90f84b2 100644 --- a/transactions/hybrid-custody/set_manager_filter_cap.cdc +++ b/transactions/hybrid-custody/set_manager_filter_cap.cdc @@ -6,7 +6,8 @@ transaction(filterAddress: Address, childAddress: Address) { let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") - let cap = getAccount(filterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let cap = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("capability not found") assert(cap.check(), message: "capability filter is not valid") m.setManagerCapabilityFilter(cap: cap, childAddress: childAddress) diff --git a/transactions/hybrid-custody/setup_manager.cdc b/transactions/hybrid-custody/setup_manager.cdc index 7963e3b..794938f 100644 --- a/transactions/hybrid-custody/setup_manager.cdc +++ b/transactions/hybrid-custody/setup_manager.cdc @@ -14,9 +14,7 @@ transaction(filterAddress: Address?, filterPath: PublicPath?) { } acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) - let publicCap = acct.capabilities.storage.issue<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath) acct.capabilities.publish(publicCap, at: HybridCustody.ManagerPublicPath) } } - \ No newline at end of file diff --git a/transactions/hybrid-custody/setup_multi_sig.cdc b/transactions/hybrid-custody/setup_multi_sig.cdc index 32937fb..0ba3d5d 100644 --- a/transactions/hybrid-custody/setup_multi_sig.cdc +++ b/transactions/hybrid-custody/setup_multi_sig.cdc @@ -11,10 +11,7 @@ import "MetadataViews" transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, childAccountFilterAddress: Address) { prepare(childAcct: AuthAccount, parentAcct: AuthAccount) { // --------------------- Begin setup of child account --------------------- - var acctCap = childAcct.getCapability<&AuthAccount>(HybridCustody.LinkedAccountPrivatePath) - if !acctCap.check() { - acctCap = childAcct.linkAccount(HybridCustody.LinkedAccountPrivatePath)! - } + var acctCap = childAcct.capabilities.account.issue<&AuthAccount>() if childAcct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { let ownedAccount <- HybridCustody.createOwnedAccount(acct: acctCap) @@ -22,17 +19,15 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, } // check that paths are all configured properly - childAcct.unlink(HybridCustody.OwnedAccountPrivatePath) - childAcct.link<&HybridCustody.OwnedAccount{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPrivatePath, target: HybridCustody.OwnedAccountStoragePath) - - childAcct.unlink(HybridCustody.OwnedAccountPublicPath) - childAcct.link<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPublicPath, target: HybridCustody.OwnedAccountStoragePath) + childAcct.capabilities.unpublish(HybridCustody.OwnedAccountPublicPath) + let ownedPublicCap = childAcct.capabilities.storage.issue<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountStoragePath) + childAcct.capabilities.publish(ownedPublicCap, at: HybridCustody.OwnedAccountPublicPath) // --------------------- End setup of child account --------------------- // --------------------- Begin setup of parent account --------------------- var filter: Capability<&{CapabilityFilter.Filter}>? = nil if parentFilterAddress != nil { - filter = getAccount(parentFilterAddress!).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + filter = getAccount(parentFilterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) } if parentAcct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { @@ -40,21 +35,21 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, parentAcct.save(<- m, to: HybridCustody.ManagerStoragePath) } - parentAcct.unlink(HybridCustody.ManagerPublicPath) - parentAcct.unlink(HybridCustody.ManagerPrivatePath) - - parentAcct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.OwnedAccountPrivatePath, target: HybridCustody.ManagerStoragePath) - parentAcct.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath, target: HybridCustody.ManagerStoragePath) + parentAcct.capabilities.unpublish(HybridCustody.ManagerPublicPath) + let managerPublicCap = parentAcct.capabilities.storage.issue<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath) + parentAcct.capabilities.publish(managerPublicCap, at: HybridCustody.ManagerPublicPath) // --------------------- End setup of parent account --------------------- // Publish account to parent let owned = childAcct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(childAccountFactoryAddress).getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(childAccountFactoryAddress).capabilities.get<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + ?? panic("capability not found") assert(factory.check(), message: "factory address is not configured properly") - let filterForChild = getAccount(childAccountFilterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let filterForChild = getAccount(childAccountFilterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("filter capability not found") assert(filterForChild.check(), message: "capability filter is not configured properly") owned.publishToParent(parentAddress: parentAcct.address, factory: factory, filter: filterForChild) From 0d453f9b1e4dbe6554fa94c9501d3f4cd4d63c83 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 19 Jul 2023 19:00:24 -0700 Subject: [PATCH 3/6] add new method to CapabilityFactory.Getter --- contracts/CapabilityFactory.cdc | 1 + contracts/HybridCustody.cdc | 28 +++++++++++++++++++ contracts/factories/FTAllFactory.cdc | 4 +++ contracts/factories/FTProviderFactory.cdc | 4 +++ .../factories/NFTCollectionPublicFactory.cdc | 4 +++ .../NFTProviderAndCollectionFactory.cdc | 4 +++ contracts/factories/NFTProviderFactory.cdc | 4 +++ .../hybrid-custody/accept_ownership.cdc | 2 +- 8 files changed, 50 insertions(+), 1 deletion(-) diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index ee777f4..67a35ae 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -23,6 +23,7 @@ pub contract CapabilityFactory { /// pub struct interface Factory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability } /// Getter defines an interface for retrieval of a Factory if contained within the implementing resource diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 193c87b..f122437 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -209,6 +209,14 @@ pub contract HybridCustody { "Capability is not allowed by this account's Parent" } } + + pub fun issueCapability(from: StoragePath, type: Type): Capability? { + post { + result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)): + "Capability is not allowed by this account's Parent" + } + } + pub fun getPublicCapability(path: PublicPath, type: Type): Capability? pub fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? pub fun getPublicCapFromDelegator(type: Type): Capability? @@ -584,6 +592,19 @@ pub contract HybridCustody { return cap } + pub fun issueCapability(from: StoragePath, type: Type): Capability? { + let child = self.childCap.borrow() ?? panic("failed to borrow child account") + let f = self.factory.borrow()!.getFactory(type) + if f == nil { + return nil + } + + let acct = child.borrowAccount() + let cap = f!.issueCapability(acct: acct, from: from) + assert(self.filter.borrow()!.allowed(cap: cap), message: "requested capability is not allowed") + return cap + } + /// Retrieves a private Capability from the Delegator or nil none is found of the given type /// pub fun getPrivateCapFromDelegator(type: Type): Capability? { @@ -1001,6 +1022,8 @@ pub contract HybridCustody { return true }) + let controllers = acct.capabilities.account.getControllers() + // Link a new AuthAccount Capability // NOTE: This path cannot be sufficiently randomly generated, an app calling this function could build a // capability to this path before it is made, thus maintaining ownership despite making it look like they @@ -1016,6 +1039,11 @@ pub contract HybridCustody { for p in pathsToUnlink { newAcct.unlink(p) } + + // also revoke all keys via capcons + for c in controllers { + c.delete() + } } /// Revokes all keys on an account, unlinks all currently active AuthAccount capabilities, then makes a new one diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index 46f506b..1892a21 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -6,5 +6,9 @@ pub contract FTAllFactory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { return acct.getCapability<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(path) } + + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability { + return acct.capabilities.storage.issue<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(from) + } } } \ No newline at end of file diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index e27dd0a..b95c780 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -6,5 +6,9 @@ pub contract FTProviderFactory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { return acct.getCapability<&{FungibleToken.Provider}>(path) } + + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability { + return acct.capabilities.storage.issue<&{FungibleToken.Provider}>(from) + } } } \ No newline at end of file diff --git a/contracts/factories/NFTCollectionPublicFactory.cdc b/contracts/factories/NFTCollectionPublicFactory.cdc index 0e9df83..2f2b70d 100644 --- a/contracts/factories/NFTCollectionPublicFactory.cdc +++ b/contracts/factories/NFTCollectionPublicFactory.cdc @@ -6,5 +6,9 @@ pub contract NFTCollectionPublicFactory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { return acct.getCapability<&{NonFungibleToken.CollectionPublic}>(path) } + + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability { + return acct.capabilities.storage.issue<&{NonFungibleToken.CollectionPublic}>(from) + } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index a79755e..c5d8c98 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -6,5 +6,9 @@ pub contract NFTProviderAndCollectionFactory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { return acct.getCapability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(path) } + + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability { + return acct.capabilities.storage.issue<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(from) + } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index 7bf547e..e3c614e 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -6,5 +6,9 @@ pub contract NFTProviderFactory { pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { return acct.getCapability<&{NonFungibleToken.Provider}>(path) } + + pub fun issueCapability(acct: &AuthAccount, from: StoragePath): Capability { + return acct.capabilities.storage.issue<&{NonFungibleToken.Provider}>(from) + } } } \ No newline at end of file diff --git a/transactions/hybrid-custody/accept_ownership.cdc b/transactions/hybrid-custody/accept_ownership.cdc index 0d3026d..570e985 100644 --- a/transactions/hybrid-custody/accept_ownership.cdc +++ b/transactions/hybrid-custody/accept_ownership.cdc @@ -15,7 +15,7 @@ transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPa let m <- HybridCustody.createManager(filter: filter) acct.save(<- m, to: HybridCustody.ManagerStoragePath) - acct.unlink(HybridCustody.ManagerPublicPath) + acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) acct.unlink(HybridCustody.ManagerPrivatePath) acct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.ManagerPrivatePath, target: HybridCustody.ManagerStoragePath) From 6cbf04e4285bcdac78762b84f0a8cf466df1789c Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 19 Jul 2023 21:02:27 -0700 Subject: [PATCH 4/6] remove most link and unlink api usage --- contracts/HybridCustody.cdc | 57 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index f122437..9a9ca8f 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -822,19 +822,12 @@ pub contract HybridCustody { } let capDelegatorPublic = PublicPath(identifier: capDelegatorIdentifier)! - let capDelegatorPrivate = PrivatePath(identifier: capDelegatorIdentifier)! - acct.link<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic}>( - capDelegatorPublic, - target: capDelegatorStorage - ) - acct.link<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>( - capDelegatorPrivate, - target: capDelegatorStorage - ) - let delegator = acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>( - capDelegatorPrivate - ) + let delegatorCap = acct.capabilities.storage.issue<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic}>(capDelegatorStorage) + acct.capabilities.publish(delegatorCap, at: capDelegatorPublic) + assert(delegatorCap.check(), message: "Delegator capability check failed") + + let delegator = acct.capabilities.storage.issue<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(capDelegatorStorage) assert(delegator.check(), message: "failed to setup capability delegator for parent address") let borrowableCap = self.borrowAccount().getCapability<&{BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver}>( @@ -842,15 +835,11 @@ pub contract HybridCustody { ) let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress) - let childAccountPrivatePath = PrivatePath(identifier: identifier)! - - acct.save(<-childAcct, to: childAccountStorage) - acct.link<&ChildAccount{AccountPrivate, AccountPublic, MetadataViews.Resolver}>(childAccountPrivatePath, target: childAccountStorage) - - let delegatorCap = acct.getCapability<&ChildAccount{AccountPrivate, AccountPublic, MetadataViews.Resolver}>(childAccountPrivatePath) + acct.save(<-childAcct, to: childAccountStorage) + let childCap = acct.capabilities.storage.issue<&ChildAccount{AccountPrivate, AccountPublic, MetadataViews.Resolver}>(childAccountStorage) assert(delegatorCap.check(), message: "Delegator capability check failed") - acct.inbox.publish(delegatorCap, name: identifier, recipient: parentAddress) + acct.inbox.publish(childCap, name: identifier, recipient: parentAddress) self.parents[parentAddress] = false emit ChildAccountPublished( @@ -914,11 +903,23 @@ pub contract HybridCustody { let capDelegatorIdentifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) let acct = self.borrowAccount() - acct.unlink(PrivatePath(identifier: identifier)!) - acct.unlink(PublicPath(identifier: identifier)!) - acct.unlink(PrivatePath(identifier: capDelegatorIdentifier)!) - acct.unlink(PublicPath(identifier: capDelegatorIdentifier)!) + // destroy delegator capabilities + let childStoragePath = StoragePath(identifier: capDelegatorIdentifier)! + acct.capabilities.storage.forEachController(forPath: childStoragePath, fun (c: &StorageCapabilityController): Bool { + c.delete() + return true + }) + acct.capabilities.unpublish(PublicPath(identifier: identifier)!) + + + // destroy delegator capabilities + let delegatorStoragePath = StoragePath(identifier: capDelegatorIdentifier)! + acct.capabilities.storage.forEachController(forPath: delegatorStoragePath, fun (c: &StorageCapabilityController): Bool { + c.delete() + return true + }) + acct.capabilities.unpublish(PublicPath(identifier: capDelegatorIdentifier)!) destroy <- acct.load<@AnyResource>(from: StoragePath(identifier: identifier)!) destroy <- acct.load<@AnyResource>(from: StoragePath(identifier: capDelegatorIdentifier)!) @@ -971,6 +972,7 @@ pub contract HybridCustody { let acct = self.borrowAccount() // Unlink existing owner's Capability if owner exists + // TODO: what to do here? if self.acctOwner != nil { acct.unlink( PrivatePath(identifier: HybridCustody.getOwnerIdentifier(self.acctOwner!))! @@ -978,11 +980,8 @@ pub contract HybridCustody { } // Link a Capability for the new owner, retrieve & publish let identifier = HybridCustody.getOwnerIdentifier(to) - let cap = acct.link<&{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}>( - PrivatePath(identifier: identifier)!, - target: HybridCustody.OwnedAccountStoragePath - ) ?? panic("failed to link child account capability") + let cap = acct.capabilities.storage.issue<&{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountStoragePath) acct.inbox.publish(cap, name: identifier, recipient: to) self.pendingOwner = to @@ -1029,13 +1028,15 @@ pub contract HybridCustody { // capability to this path before it is made, thus maintaining ownership despite making it look like they // gave it away. Until capability controllers, this method should not be fully trusted. let authAcctPath = "HybridCustodyRelinquished".concat(HybridCustody.account.address.toString()).concat(getCurrentBlock().height.toString()) - let acctCap = acct.linkAccount(PrivatePath(identifier: authAcctPath)!)! + let acctCap = acct.capabilities.account.issue<&AuthAccount>() + self.acct = acctCap let newAcct = self.acct.borrow()! // cleanup, remove all previously found paths. We had to do it in this order because we will be unlinking // the existing path which will cause a deference issue with the originally borrowed auth account + // TODO: remove once capability controllers are the only way to access Caps on an account for p in pathsToUnlink { newAcct.unlink(p) } From 3950339edd6c0f6d39cd22445432cf499ca5703f Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 19 Jul 2023 21:23:01 -0700 Subject: [PATCH 5/6] remove uses of getCapability --- contracts/HybridCustody.cdc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 9a9ca8f..febbb2e 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -668,9 +668,9 @@ pub contract HybridCustody { switch view { case Type(): let childAddress = self.getAddress() - let manager = getAccount(self.parent).getCapability<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) + let manager = getAccount(self.parent).capabilities.get<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) - if !manager.check() { + if manager == nil || !manager!.check() { return nil } @@ -830,9 +830,7 @@ pub contract HybridCustody { let delegator = acct.capabilities.storage.issue<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(capDelegatorStorage) assert(delegator.check(), message: "failed to setup capability delegator for parent address") - let borrowableCap = self.borrowAccount().getCapability<&{BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver}>( - HybridCustody.OwnedAccountPrivatePath - ) + let borrowableCap = self.borrowAccount().capabilities.storage.issue<&{BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountStoragePath) let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress) acct.save(<-childAcct, to: childAccountStorage) @@ -927,9 +925,9 @@ pub contract HybridCustody { self.parents.remove(key: parent) emit AccountUpdated(id: self.uuid, child: self.acct.address, parent: parent, active: false) - let parentManager = getAccount(parent).getCapability<&Manager{ManagerPublic}>(HybridCustody.ManagerPublicPath) - if parentManager.check() { - parentManager.borrow()?.removeParentCallback(child: self.owner!.address) + let parentManager = getAccount(parent).capabilities.get<&Manager{ManagerPublic}>(HybridCustody.ManagerPublicPath) + if parentManager != nil && parentManager!.check() { + parentManager!.borrow()!.removeParentCallback(child: self.owner!.address) } return true @@ -972,12 +970,18 @@ pub contract HybridCustody { let acct = self.borrowAccount() // Unlink existing owner's Capability if owner exists - // TODO: what to do here? + // TODO: remove this once linking is removed from cadence if self.acctOwner != nil { acct.unlink( PrivatePath(identifier: HybridCustody.getOwnerIdentifier(self.acctOwner!))! ) } + + acct.capabilities.storage.forEachController(forPath: HybridCustody.OwnedAccountStoragePath, fun (c: &StorageCapabilityController): Bool { + c.delete() + return true + }) + // Link a Capability for the new owner, retrieve & publish let identifier = HybridCustody.getOwnerIdentifier(to) From 521a299f2ffca46974941b1433bbc1cc8c8ef14f Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 19 Jul 2023 22:32:06 -0700 Subject: [PATCH 6/6] fix tests - use both capcons and previous linking apis --- contracts/HybridCustody.cdc | 12 ++++++------ test/HybridCustody_tests.cdc | 2 -- .../hybrid-custody/set_manager_filter_cap.cdc | 10 +++++++--- .../hybrid-custody/setup_multi_sig.cdc | 19 ++++++++++++------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index febbb2e..294a1ab 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -904,10 +904,10 @@ pub contract HybridCustody { // destroy delegator capabilities let childStoragePath = StoragePath(identifier: capDelegatorIdentifier)! - acct.capabilities.storage.forEachController(forPath: childStoragePath, fun (c: &StorageCapabilityController): Bool { + let childControllers = acct.capabilities.storage.getControllers(forPath: childStoragePath) + for c in childControllers { c.delete() - return true - }) + } acct.capabilities.unpublish(PublicPath(identifier: identifier)!) @@ -977,10 +977,10 @@ pub contract HybridCustody { ) } - acct.capabilities.storage.forEachController(forPath: HybridCustody.OwnedAccountStoragePath, fun (c: &StorageCapabilityController): Bool { + let controllers = acct.capabilities.storage.getControllers(forPath: HybridCustody.OwnedAccountStoragePath) + for c in controllers { c.delete() - return true - }) + } // Link a Capability for the new owner, retrieve & publish let identifier = HybridCustody.getOwnerIdentifier(to) diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index e7881bd..7701f6e 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -433,7 +433,6 @@ pub fun testRemoveChildAccount() { setupChildAndParent_FilterKindAll(child: child, parent: parent) checkForAddresses(child: child, parent: parent) - assert(isParent(child: child, parent: parent) == true, message: "is not parent of child account") txExecutor("hybrid-custody/remove_child_account.cdc", [parent], [child.address], nil, nil) assert(isParent(child: child, parent: parent) == false, message: "child account was not removed from parent") @@ -710,7 +709,6 @@ pub fun testGetChildAccountFTCapabilities(){ let ftTypeIds = scriptExecutor("hybrid-custody/get_child_account_ft_capabilities.cdc", [parent.address])! as! {Address: [String]} assert(ftTypeIds[child.address]![0] == nftIdentifier, message: "typeId should be: ".concat(nftIdentifier)) - } pub fun testBlockchainNativeOnboarding() { diff --git a/transactions/hybrid-custody/set_manager_filter_cap.cdc b/transactions/hybrid-custody/set_manager_filter_cap.cdc index 90f84b2..86dfc0f 100644 --- a/transactions/hybrid-custody/set_manager_filter_cap.cdc +++ b/transactions/hybrid-custody/set_manager_filter_cap.cdc @@ -6,9 +6,13 @@ transaction(filterAddress: Address, childAddress: Address) { let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") - let cap = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("capability not found") - assert(cap.check(), message: "capability filter is not valid") + var cap = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + + if cap == nil { + cap = getAccount(filterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + } + assert(cap != nil, message: "manager capability not found") + assert(cap!.check(), message: "capability filter is not valid") m.setManagerCapabilityFilter(cap: cap, childAddress: childAddress) } diff --git a/transactions/hybrid-custody/setup_multi_sig.cdc b/transactions/hybrid-custody/setup_multi_sig.cdc index 0ba3d5d..0da6ca9 100644 --- a/transactions/hybrid-custody/setup_multi_sig.cdc +++ b/transactions/hybrid-custody/setup_multi_sig.cdc @@ -44,15 +44,20 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, let owned = childAcct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(childAccountFactoryAddress).capabilities.get<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) - ?? panic("capability not found") - assert(factory.check(), message: "factory address is not configured properly") + var factory = getAccount(childAccountFactoryAddress).capabilities.get<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + if factory == nil { + factory = getAccount(childAccountFactoryAddress).getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + } + + assert(factory!.check(), message: "factory address is not configured properly") - let filterForChild = getAccount(childAccountFilterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("filter capability not found") - assert(filterForChild.check(), message: "capability filter is not configured properly") + var filterForChild = getAccount(childAccountFilterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + if filterForChild == nil { + filterForChild = getAccount(childAccountFilterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + } + assert(filterForChild!.check(), message: "capability filter is not configured properly") - owned.publishToParent(parentAddress: parentAcct.address, factory: factory, filter: filterForChild) + owned.publishToParent(parentAddress: parentAcct.address, factory: factory!, filter: filterForChild!) // claim the account on the parent let inboxName = HybridCustody.getChildAccountIdentifier(parentAcct.address)