From 82d8da80c3cbcb29729423d0b688f2f07a183dda Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Sat, 23 Mar 2024 16:02:26 -0700 Subject: [PATCH 01/34] - Update all HybridCustody contract dependencies - Switch dependency management to npm package for now since submodules aren't yet fully working --- .gitignore | 3 +- .gitmodules | 10 +- contracts/CapabilityDelegator.cdc | 50 +-- contracts/CapabilityFactory.cdc | 34 +- contracts/CapabilityFilter.cdc | 48 +-- contracts/factories/FTAllFactory.cdc | 16 +- contracts/factories/FTBalanceFactory.cdc | 16 +- contracts/factories/FTProviderFactory.cdc | 16 +- .../factories/FTReceiverBalanceFactory.cdc | 16 +- contracts/factories/FTReceiverFactory.cdc | 16 +- .../factories/NFTCollectionPublicFactory.cdc | 16 +- .../NFTProviderAndCollectionFactory.cdc | 16 +- contracts/factories/NFTProviderFactory.cdc | 16 +- contracts/standard/ExampleNFT2.cdc | 328 ++++++++---------- contracts/standard/ExampleToken.cdc | 246 ++++++++----- flow.json | 133 ++++--- modules/flow-ft | 1 + modules/flow-nft | 2 +- modules/flow-utils | 2 +- package-lock.json | 35 ++ package.json | 17 + 21 files changed, 622 insertions(+), 415 deletions(-) create mode 160000 modules/flow-ft create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore index 84dd629..3c54981 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ coverage.lcov .idea *.pkey *.private -*.pem \ No newline at end of file +*.pem +node_modules/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index ee884a8..0f2df34 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,9 @@ [submodule "modules/flow-nft"] path = modules/flow-nft - url = https://github.com/Flowtyio/flow-nft.git -[submodule "flow-ft"] - path = flow-ft - url = https://github.com/Flowtyio/flow-ft.git + url = https://github.com/onflow/flow-nft.git [submodule "modules/flow-utils"] path = modules/flow-utils - url = https://github.com/Flowtyio/flow-utils.git + url = https://github.com/green-goo-dao/flow-utils.git +[submodule "modules/flow-ft"] + path = modules/flow-ft + url = https://github.com/onflow/flow-ft.git diff --git a/contracts/CapabilityDelegator.cdc b/contracts/CapabilityDelegator.cdc index f342aaf..b574456 100644 --- a/contracts/CapabilityDelegator.cdc +++ b/contracts/CapabilityDelegator.cdc @@ -7,48 +7,48 @@ /// private `Delegator` can only be borrowed from the child account when you have access to the full `ChildAccount` /// resource. /// -pub contract CapabilityDelegator { +access(all) contract CapabilityDelegator { /* --- Canonical Paths --- */ // - pub let StoragePath: StoragePath - pub let PrivatePath: PrivatePath - pub let PublicPath: PublicPath + access(all) let StoragePath: StoragePath + access(all) let PrivatePath: PrivatePath + access(all) let PublicPath: PublicPath /* --- Events --- */ // - pub event DelegatorCreated(id: UInt64) - pub event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool) + access(all) event DelegatorCreated(id: UInt64) + access(all) event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool) /// Private interface for Capability retrieval /// - pub resource interface GetterPrivate { - pub fun getPrivateCapability(_ type: Type): Capability? { + access(all) resource interface GetterPrivate { + access(Capabilities) view fun getPrivateCapability(_ type: Type): Capability? { post { result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type" } } - pub fun findFirstPrivateType(_ type: Type): Type? - pub fun getAllPrivate(): [Capability] + access(all) view fun findFirstPrivateType(_ type: Type): Type? + access(Capabilities) fun getAllPrivate(): [Capability] } /// Exposes public Capability retrieval /// - pub resource interface GetterPublic { - pub fun getPublicCapability(_ type: Type): Capability? { + access(all) resource interface GetterPublic { + access(all) view fun getPublicCapability(_ type: Type): Capability? { post { - result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type " + result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type" } } - pub fun findFirstPublicType(_ type: Type): Type? - pub fun getAllPublic(): [Capability] + access(all) view fun findFirstPublicType(_ type: Type): Type? + access(all) view fun getAllPublic(): [Capability] } /// This Delegator is used to store Capabilities, partitioned by public and private access with corresponding /// GetterPublic and GetterPrivate conformances.AccountCapabilityController /// - pub resource Delegator: GetterPublic, GetterPrivate { + access(all) resource Delegator: GetterPublic, GetterPrivate { access(self) let privateCapabilities: {Type: Capability} access(self) let publicCapabilities: {Type: Capability} @@ -56,7 +56,7 @@ pub contract CapabilityDelegator { // /// Returns the public Capability of the given Type if it exists /// - pub fun getPublicCapability(_ type: Type): Capability? { + access(all) view fun getPublicCapability(_ type: Type): Capability? { return self.publicCapabilities[type] } @@ -66,7 +66,7 @@ pub contract CapabilityDelegator { /// @param type: Type of the Capability to retrieve /// @return Capability of the given Type if it exists, nil otherwise /// - pub fun getPrivateCapability(_ type: Type): Capability? { + access(Capabilities) view fun getPrivateCapability(_ type: Type): Capability? { return self.privateCapabilities[type] } @@ -74,7 +74,7 @@ pub contract CapabilityDelegator { /// /// @return List of all public Capabilities /// - pub fun getAllPublic(): [Capability] { + access(all) view fun getAllPublic(): [Capability] { return self.publicCapabilities.values } @@ -82,7 +82,7 @@ pub contract CapabilityDelegator { /// /// @return List of all private Capabilities /// - pub fun getAllPrivate(): [Capability] { + access(Capabilities) fun getAllPrivate(): [Capability] { return self.privateCapabilities.values } @@ -91,7 +91,7 @@ pub contract CapabilityDelegator { /// @param type: Type to check for subtypes /// @return First public Type that is a subtype of the given Type, nil otherwise /// - pub fun findFirstPublicType(_ type: Type): Type? { + access(all) view fun findFirstPublicType(_ type: Type): Type? { for t in self.publicCapabilities.keys { if t.isSubtype(of: type) { return t @@ -106,7 +106,7 @@ pub contract CapabilityDelegator { /// @param type: Type to check for subtypes /// @return First private Type that is a subtype of the given Type, nil otherwise /// - pub fun findFirstPrivateType(_ type: Type): Type? { + access(all) view fun findFirstPrivateType(_ type: Type): Type? { for t in self.privateCapabilities.keys { if t.isSubtype(of: type) { return t @@ -122,7 +122,7 @@ pub contract CapabilityDelegator { /// @param cap: Capability to add /// @param isPublic: Whether the Capability should be public or private /// - pub fun addCapability(cap: Capability, isPublic: Bool) { + access(Mutate) fun addCapability(cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } @@ -138,7 +138,7 @@ pub contract CapabilityDelegator { /// /// @param cap: Capability to remove /// - pub fun removeCapability(cap: Capability) { + access(Mutate) fun removeCapability(cap: Capability) { if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) { emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false) } @@ -158,7 +158,7 @@ pub contract CapabilityDelegator { /// /// @return Newly created Delegator /// - pub fun createDelegator(): @Delegator { + access(all) fun createDelegator(): @Delegator { let delegator <- create Delegator() emit DelegatorCreated(id: delegator.uuid) return <- delegator diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index ee777f4..15b993b 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -13,37 +13,37 @@ /// Capabilities is critical to the use case of Hybrid Custody. It's advised to use Factories sparingly and only for /// cases where Capabilities must be castable by the caller. /// -pub contract CapabilityFactory { +access(all) contract CapabilityFactory { - pub let StoragePath: StoragePath - pub let PrivatePath: PrivatePath - pub let PublicPath: PublicPath + access(all) let StoragePath: StoragePath + access(all) let PrivatePath: PrivatePath + access(all) let PublicPath: PublicPath /// Factory structures a common interface for Capability retrieval from a given account at a specified path /// - pub struct interface Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability + access(all) struct interface Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? } /// Getter defines an interface for retrieval of a Factory if contained within the implementing resource /// - pub resource interface Getter { - pub fun getSupportedTypes(): [Type] - pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? + access(all) resource interface Getter { + access(all) view fun getSupportedTypes(): [Type] + access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? } /// Manager is a resource that contains Factories and implements the Getter interface for retrieval of contained /// Factories /// - pub resource Manager: Getter { + access(all) resource Manager: Getter { /// Mapping of Factories indexed on Type of Capability they retrieve - pub let factories: {Type: {CapabilityFactory.Factory}} + access(all) let factories: {Type: {CapabilityFactory.Factory}} /// Retrieves a list of Types supported by contained Factories /// /// @return List of Types supported by the Manager /// - pub fun getSupportedTypes(): [Type] { + access(all) view fun getSupportedTypes(): [Type] { return self.factories.keys } @@ -51,7 +51,7 @@ pub contract CapabilityFactory { /// /// @param t: Type the Factory is indexed on /// - pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? { + access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? { return self.factories[t] } @@ -60,7 +60,7 @@ pub contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to add /// - pub fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Mutate) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { pre { !self.factories.containsKey(t): "Factory of given type already exists" } @@ -72,7 +72,7 @@ pub contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to replace existing Factory /// - pub fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Mutate) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { self.factories[t] = f } @@ -80,7 +80,7 @@ pub contract CapabilityFactory { /// /// @param t: Type the Factory is indexed on /// - pub fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { + access(Mutate) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { return self.factories.remove(key: t) } @@ -92,7 +92,7 @@ pub contract CapabilityFactory { /// Creates a Manager resource /// /// @return Manager resource - pub fun createFactoryManager(): @Manager { + access(all) fun createFactoryManager(): @Manager { return <- create Manager() } diff --git a/contracts/CapabilityFilter.cdc b/contracts/CapabilityFilter.cdc index 7a76509..07f08c8 100644 --- a/contracts/CapabilityFilter.cdc +++ b/contracts/CapabilityFilter.cdc @@ -6,29 +6,29 @@ /// - `AllowlistFilter` - A filter which contains a mapping of allowed Types /// - `AllowAllFilter` - A passthrough, all requested capabilities are allowed /// -pub contract CapabilityFilter { +access(all) contract CapabilityFilter { /* --- Canonical Paths --- */ // - pub let StoragePath: StoragePath - pub let PublicPath: PublicPath - pub let PrivatePath: PrivatePath + access(all) let StoragePath: StoragePath + access(all) let PublicPath: PublicPath + access(all) let PrivatePath: PrivatePath /* --- Events --- */ // - pub event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool) + access(all) event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool) /// `Filter` is a simple interface with methods to determine if a Capability is allowed and retrieve details about /// the Filter itself /// - pub resource interface Filter { - pub fun allowed(cap: Capability): Bool - pub fun getDetails(): AnyStruct + access(all) resource interface Filter { + access(all) view fun allowed(cap: Capability): Bool + access(all) view fun getDetails(): AnyStruct } /// `DenylistFilter` is a `Filter` which contains a mapping of denied Types /// - pub resource DenylistFilter: Filter { + access(all) resource DenylistFilter: Filter { /// Represents the underlying types which should not ever be returned by a RestrictedChildAccount. The filter /// will borrow a requested capability, and make sure that the type it gets back is not in the list of denied @@ -39,7 +39,7 @@ pub contract CapabilityFilter { /// /// @param type: The type to add to the denied types mapping /// - pub fun addType(_ type: Type) { + access(Mutate) fun addType(_ type: Type) { self.deniedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -48,7 +48,7 @@ pub contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - pub fun removeType(_ type: Type) { + access(Mutate) fun removeType(_ type: Type) { if let removed = self.deniedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -56,7 +56,7 @@ pub contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - pub fun removeAllTypes() { + access(Mutate) fun removeAllTypes() { for type in self.deniedTypes.keys { self.removeType(type) } @@ -67,7 +67,7 @@ pub contract CapabilityFilter { /// @param cap: The capability to check /// @return: true if the capability is allowed, false otherwise /// - pub fun allowed(cap: Capability): Bool { + access(all) view fun allowed(cap: Capability): Bool { if let item = cap.borrow<&AnyResource>() { return !self.deniedTypes.containsKey(item.getType()) } @@ -80,7 +80,7 @@ pub contract CapabilityFilter { /// @return A struct containing details about this filter including this Filter's Type indexed on the `type` /// key as well as types denied indexed on the `deniedTypes` key /// - pub fun getDetails(): AnyStruct { + access(all) view fun getDetails(): AnyStruct { return { "type": self.getType(), "deniedTypes": self.deniedTypes.keys @@ -94,7 +94,7 @@ pub contract CapabilityFilter { /// `AllowlistFilter` is a `Filter` which contains a mapping of allowed Types /// - pub resource AllowlistFilter: Filter { + access(all) resource AllowlistFilter: Filter { // allowedTypes // Represents the set of underlying types which are allowed to be // returned by a RestrictedChildAccount. The filter will borrow @@ -106,7 +106,7 @@ pub contract CapabilityFilter { /// /// @param type: The type to add to the allowed types mapping /// - pub fun addType(_ type: Type) { + access(Mutate) fun addType(_ type: Type) { self.allowedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -115,7 +115,7 @@ pub contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - pub fun removeType(_ type: Type) { + access(Mutate) fun removeType(_ type: Type) { if let removed = self.allowedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -123,7 +123,7 @@ pub contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - pub fun removeAllTypes() { + access(Mutate) fun removeAllTypes() { for type in self.allowedTypes.keys { self.removeType(type) } @@ -134,7 +134,7 @@ pub contract CapabilityFilter { /// @param cap: The capability to check /// @return: true if the capability is allowed, false otherwise /// - pub fun allowed(cap: Capability): Bool { + access(all) view fun allowed(cap: Capability): Bool { if let item = cap.borrow<&AnyResource>() { return self.allowedTypes.containsKey(item.getType()) } @@ -147,7 +147,7 @@ pub contract CapabilityFilter { /// @return A struct containing details about this filter including this Filter's Type indexed on the `type` /// key as well as types allowed indexed on the `allowedTypes` key /// - pub fun getDetails(): AnyStruct { + access(all) view fun getDetails(): AnyStruct { return { "type": self.getType(), "allowedTypes": self.allowedTypes.keys @@ -161,13 +161,13 @@ pub contract CapabilityFilter { /// AllowAllFilter is a passthrough, all requested capabilities are allowed /// - pub resource AllowAllFilter: Filter { + access(all) resource AllowAllFilter: Filter { /// Determines if a requested capability is allowed by this `Filter` /// /// @param cap: The capability to check /// @return: true since this filter is a passthrough /// - pub fun allowed(cap: Capability): Bool { + access(all) view fun allowed(cap: Capability): Bool { return true } @@ -176,7 +176,7 @@ pub contract CapabilityFilter { /// @return A struct containing details about this filter including this Filter's Type indexed on the `type` /// key /// - pub fun getDetails(): AnyStruct { + access(all) view fun getDetails(): AnyStruct { return { "type": self.getType() } @@ -188,7 +188,7 @@ pub contract CapabilityFilter { /// @param t: The type of `Filter` to create /// @return: A new instance of the given `Filter` type /// - pub fun create(_ t: Type): @AnyResource{Filter} { + access(all) fun createFilter(_ t: Type): @{Filter} { post { result.getType() == t } diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index 46f506b..57166a1 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "FungibleToken" -pub contract FTAllFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(path) +access(all) contract FTAllFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/FTBalanceFactory.cdc b/contracts/factories/FTBalanceFactory.cdc index bd9d097..dae94d1 100644 --- a/contracts/factories/FTBalanceFactory.cdc +++ b/contracts/factories/FTBalanceFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "FungibleToken" -pub contract FTBalanceFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{FungibleToken.Balance}>(path) +access(all) contract FTBalanceFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{FungibleToken.Balance}>() { + return nil + } + + return con.capability as! Capability<&{FungibleToken.Balance}> + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index e27dd0a..b60d64c 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "FungibleToken" -pub contract FTProviderFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{FungibleToken.Provider}>(path) +access(all) contract FTProviderFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability<&auth(FungibleToken.Withdraw) &{FungibleToken.Provider}> + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/FTReceiverBalanceFactory.cdc b/contracts/factories/FTReceiverBalanceFactory.cdc index 49673d5..f0f016d 100644 --- a/contracts/factories/FTReceiverBalanceFactory.cdc +++ b/contracts/factories/FTReceiverBalanceFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "FungibleToken" -pub contract FTReceiverBalanceFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{FungibleToken.Receiver, FungibleToken.Balance}>(path) +access(all) contract FTReceiverBalanceFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{FungibleToken.Receiver, FungibleToken.Balance}>() { + return nil + } + + return con.capability as! Capability<&{FungibleToken.Receiver, FungibleToken.Balance}> + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/FTReceiverFactory.cdc b/contracts/factories/FTReceiverFactory.cdc index 03ade5c..a0d3ded 100644 --- a/contracts/factories/FTReceiverFactory.cdc +++ b/contracts/factories/FTReceiverFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "FungibleToken" -pub contract FTReceiverFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{FungibleToken.Receiver}>(path) +access(all) contract FTReceiverFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{FungibleToken.Receiver}>() { + return nil + } + + return con.capability as! Capability<&{FungibleToken.Receiver}> + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/NFTCollectionPublicFactory.cdc b/contracts/factories/NFTCollectionPublicFactory.cdc index 0e9df83..e0ab607 100644 --- a/contracts/factories/NFTCollectionPublicFactory.cdc +++ b/contracts/factories/NFTCollectionPublicFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "NonFungibleToken" -pub contract NFTCollectionPublicFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{NonFungibleToken.CollectionPublic}>(path) +access(all) contract NFTCollectionPublicFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{NonFungibleToken.CollectionPublic}>() { + return nil + } + + return con.capability as! Capability<&{NonFungibleToken.CollectionPublic}> + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index a79755e..cf06f97 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "NonFungibleToken" -pub contract NFTProviderAndCollectionFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(path) +access(all) contract NFTProviderAndCollectionFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability + } + + return nil } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index 7bf547e..7322b89 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -1,10 +1,18 @@ import "CapabilityFactory" import "NonFungibleToken" -pub contract NFTProviderFactory { - pub struct Factory: CapabilityFactory.Factory { - pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability { - return acct.getCapability<&{NonFungibleToken.Provider}>(path) +access(all) contract NFTProviderFactory { + access(all) struct Factory: CapabilityFactory.Factory { + access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability + } + + return nil } } } \ No newline at end of file diff --git a/contracts/standard/ExampleNFT2.cdc b/contracts/standard/ExampleNFT2.cdc index 0af7730..21f417c 100644 --- a/contracts/standard/ExampleNFT2.cdc +++ b/contracts/standard/ExampleNFT2.cdc @@ -12,64 +12,47 @@ import "NonFungibleToken" import "MetadataViews" import "ViewResolver" +import "FungibleToken" -pub contract ExampleNFT2: NonFungibleToken, ViewResolver { +access(all) contract ExampleNFT2: ViewResolver { - /// Total supply of ExampleNFTs in existence - pub var totalSupply: UInt64 + access(all) var totalSupply: UInt64 - /// The event that is emitted when the contract is created - pub event ContractInitialized() + access(all) event ContractInitialized() + access(all) event Withdraw(id: UInt64, from: Address?) + access(all) event Deposit(id: UInt64, to: Address?) - /// The event that is emitted when an NFT is withdrawn from a Collection - pub event Withdraw(id: UInt64, from: Address?) + access(all) event CollectionCreated(id: UInt64) + access(all) event CollectionDestroyed(id: UInt64) - /// The event that is emitted when an NFT is deposited to a Collection - pub event Deposit(id: UInt64, to: Address?) + access(all) let CollectionStoragePath: StoragePath + access(all) let CollectionPublicPath: PublicPath + access(all) let MinterStoragePath: StoragePath + access(all) let MinterPublicPath: PublicPath - /// Storage and Public Paths - pub let CollectionStoragePath: StoragePath - pub let CollectionPublicPath: PublicPath - pub let MinterStoragePath: StoragePath + access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver { + access(all) let id: UInt64 - /// The core resource that represents a Non Fungible Token. - /// New instances will be created using the NFTMinter resource - /// and stored in the Collection resource - /// - pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver { - - /// The unique ID that each NFT has - pub let id: UInt64 - - /// Metadata fields - pub let name: String - pub let description: String - pub let thumbnail: String + access(all) let name: String + access(all) let description: String + access(all) let thumbnail: String access(self) let royalties: [MetadataViews.Royalty] - access(self) let metadata: {String: AnyStruct} - + init( id: UInt64, name: String, description: String, thumbnail: String, - royalties: [MetadataViews.Royalty], - metadata: {String: AnyStruct}, + royalties: [MetadataViews.Royalty] ) { self.id = id self.name = name self.description = description self.thumbnail = thumbnail self.royalties = royalties - self.metadata = metadata } - - /// Function that returns all the Metadata Views implemented by a Non Fungible Token - /// - /// @return An array of Types defining the implemented views. This value will be used by - /// developers to know which parameter to pass to the resolveView() method. - /// - pub fun getViews(): [Type] { + + access(all) view fun getViews(): [Type] { return [ Type(), Type(), @@ -77,17 +60,11 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { Type(), Type(), Type(), - Type(), - Type() + Type() ] } - /// Function that resolves a metadata view for this token. - /// - /// @param view: The Type of the desired view. - /// @return A structure representing the requested view. - /// - pub fun resolveView(_ view: Type): AnyStruct? { + access(all) view fun resolveView(_ view: Type): AnyStruct? { switch view { case Type(): return MetadataViews.Display( @@ -119,11 +96,9 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { return MetadataViews.NFTCollectionData( storagePath: ExampleNFT2.CollectionStoragePath, publicPath: ExampleNFT2.CollectionPublicPath, - providerPath: /private/exampleNFT2Collection, - publicCollection: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic}>(), - publicLinkedType: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(), - providerLinkedType: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(), - createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection { + publicCollection: Type<&ExampleNFT2.Collection>(), + publicLinkedType: Type<&ExampleNFT2.Collection>(), + createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} { return <-ExampleNFT2.createEmptyCollection() }) ) @@ -144,34 +119,18 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") } ) - case Type(): - // exclude mintedTime and foo to show other uses of Traits - let excludedTraits = ["mintedTime", "foo"] - let traitsView = MetadataViews.dictToTraits(dict: self.metadata, excludedNames: excludedTraits) - - // mintedTime is a unix timestamp, we should mark it with a displayType so platforms know how to show it. - let mintedTimeTrait = MetadataViews.Trait(name: "mintedTime", value: self.metadata["mintedTime"]!, displayType: "Date", rarity: nil) - traitsView.addTrait(mintedTimeTrait) - - // foo is a trait with its own rarity - let fooTraitRarity = MetadataViews.Rarity(score: 10.0, max: 100.0, description: "Common") - let fooTrait = MetadataViews.Trait(name: "foo", value: self.metadata["foo"], displayType: nil, rarity: fooTraitRarity) - traitsView.addTrait(fooTrait) - - return traitsView - } return nil } + + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- ExampleNFT2.createEmptyCollection() + } } - /// Defines the methods that are particular to this NFT contract collection - /// - pub resource interface ExampleNFT2CollectionPublic { - pub fun deposit(token: @NonFungibleToken.NFT) - pub fun getIDs(): [UInt64] - pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT - pub fun borrowExampleNFT(id: UInt64): &ExampleNFT2.NFT? { + access(all) resource interface ExampleNFT2CollectionPublic: NonFungibleToken.Collection { + access(all) fun deposit(token: @{NonFungibleToken.NFT}) + access(all) fun borrowExampleNFT2(id: UInt64): &ExampleNFT2.NFT? { post { (result == nil) || (result?.id == id): "Cannot borrow ExampleNFT2 reference: the ID of the returned reference is incorrect" @@ -179,25 +138,24 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { } } - /// The resource that will be holding the NFTs inside any account. - /// In order to be able to manage NFTs any account will need to create - /// an empty collection first - /// - pub resource Collection: ExampleNFT2CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection { + access(all) resource Collection: ExampleNFT2CollectionPublic { + access(all) event ResourceDestroyed(id: UInt64 = self.uuid) + // dictionary of NFT conforming tokens // NFT is a resource type with an `UInt64` ID field - pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} + access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}} init () { self.ownedNFTs <- {} + emit CollectionCreated(id: self.uuid) + } + + access(all) view fun getLength(): Int { + return self.ownedNFTs.length } - /// Removes an NFT from the collection and moves it to the caller - /// - /// @param withdrawID: The ID of the NFT that wants to be withdrawn - /// @return The NFT resource that has been taken out of the collection - /// - pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { + // withdraw removes an NFT from the collection and moves it to the caller + access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) @@ -205,11 +163,9 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { return <-token } - /// Adds an NFT to the collections dictionary and adds the ID to the id array - /// - /// @param token: The NFT resource to be included in the collection - /// - pub fun deposit(token: @NonFungibleToken.NFT) { + // deposit takes a NFT and adds it to the collections dictionary + // and adds the ID to the id array + access(all) fun deposit(token: @{NonFungibleToken.NFT}) { let token <- token as! @ExampleNFT2.NFT let id: UInt64 = token.id @@ -222,95 +178,110 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { destroy oldToken } - /// Helper method for getting the collection IDs - /// - /// @return An array containing the IDs of the NFTs in the collection - /// - pub fun getIDs(): [UInt64] { + // getIDs returns an array of the IDs that are in the collection + access(all) view fun getIDs(): [UInt64] { return self.ownedNFTs.keys } - /// Gets a reference to an NFT in the collection so that - /// the caller can read its metadata and call its methods - /// - /// @param id: The ID of the wanted NFT - /// @return A reference to the wanted NFT resource - /// - pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { - return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! + // borrowNFT gets a reference to an NFT in the collection + // so that the caller can read its metadata and call its methods + access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { + return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)! } - /// Gets a reference to an NFT in the collection so that - /// the caller can read its metadata and call its methods - /// - /// @param id: The ID of the wanted NFT - /// @return A reference to the wanted NFT resource - /// - pub fun borrowExampleNFT(id: UInt64): &ExampleNFT2.NFT? { + access(all) fun borrowExampleNFT2(id: UInt64): &ExampleNFT2.NFT? { if self.ownedNFTs[id] != nil { // Create an authorized reference to allow downcasting - let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! + let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)! return ref as! &ExampleNFT2.NFT } return nil } - /// Gets a reference to the NFT only conforming to the `{MetadataViews.Resolver}` - /// interface so that the caller can retrieve the views that the NFT - /// is implementing and resolve them - /// - /// @param id: The ID of the wanted NFT - /// @return The resource reference conforming to the Resolver interface - /// - pub fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} { - let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)! - let exampleNFT = nft as! &ExampleNFT2.NFT - return exampleNFT as &AnyResource{MetadataViews.Resolver} + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- create Collection() } - destroy() { - destroy self.ownedNFTs + access(all) view fun getSupportedNFTTypes(): {Type: Bool} { + return { + Type<@ExampleNFT2.NFT>(): true + } + } + + access(all) view fun isSupportedNFTType(type: Type): Bool { + return type == Type<@ExampleNFT2.NFT>() } } - /// Allows anyone to create a new empty collection - /// - /// @return The new Collection resource - /// - pub fun createEmptyCollection(): @NonFungibleToken.Collection { + // public function that anyone can call to create a new empty collection + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { return <- create Collection() } - /// Resource that an admin or something similar would own to be - /// able to mint new NFTs - /// - pub resource NFTMinter { - - /// Mints a new NFT with a new ID and deposit it in the - /// recipients collection using their collection reference - /// - /// @param recipient: A capability to the collection where the new NFT will be deposited - /// @param name: The name for the NFT metadata - /// @param description: The description for the NFT metadata - /// @param thumbnail: The thumbnail for the NFT metadata - /// @param royalties: An array of Royalty structs, see MetadataViews docs - /// - pub fun mintNFT( + // Resource that an admin or something similar would own to be + // able to mint new NFTs + // + access(all) resource NFTMinter { + + // mintNFT mints a new NFT with a new ID + // and deposit it in the recipients collection using their collection reference + access(all) fun mintNFT( recipient: &{NonFungibleToken.CollectionPublic}, name: String, description: String, thumbnail: String, - royalties: [MetadataViews.Royalty] + royaltyReceipient: Address, ) { - let metadata: {String: AnyStruct} = {} - let currentBlock = getCurrentBlock() - metadata["mintedBlock"] = currentBlock.height - metadata["mintedTime"] = currentBlock.timestamp - metadata["minter"] = recipient.owner!.address + ExampleNFT2.totalSupply = ExampleNFT2.totalSupply + 1 + self.mintNFTWithId(recipient: recipient, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: royaltyReceipient, id: ExampleNFT2.totalSupply) + } - // this piece of metadata will be used to show embedding rarity into a trait - metadata["foo"] = "bar" + access(all) fun mintNFTWithId( + recipient: &{NonFungibleToken.CollectionPublic}, + name: String, + description: String, + thumbnail: String, + royaltyReceipient: Address, + id: UInt64 + ) { + let royaltyRecipient = getAccount(royaltyReceipient).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)! + let cutInfo = MetadataViews.Royalty(receiver: royaltyRecipient, cut: 0.05, description: "") + // create a new NFT + var newNFT <- create NFT( + id: id, + name: name, + description: description, + thumbnail: thumbnail, + royalties: [cutInfo] + ) + + // deposit it in the recipient's account using their reference + recipient.deposit(token: <-newNFT) + } + + // mintNFT mints a new NFT with a new ID + // and deposit it in the recipients collection using their collection reference + access(all) fun mintNFTWithRoyaltyCuts( + recipient: &{NonFungibleToken.CollectionPublic}, + name: String, + description: String, + thumbnail: String, + royaltyReceipients: [Address], + royaltyCuts: [UFix64] + ) { + assert(royaltyReceipients.length == royaltyCuts.length, message: "mismatched royalty recipients and cuts") + let royalties: [MetadataViews.Royalty] = [] + + var index = 0 + while index < royaltyReceipients.length { + let royaltyRecipient = getAccount(royaltyReceipients[index]).capabilities.get<&{FungibleToken.Receiver}>(/public/placeholder)! + let cutInfo = MetadataViews.Royalty(receiver: royaltyRecipient, cut: royaltyCuts[index], description: "") + royalties.append(cutInfo) + index = index + 1 + } + + ExampleNFT2.totalSupply = ExampleNFT2.totalSupply + 1 // create a new NFT var newNFT <- create NFT( @@ -318,14 +289,11 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { name: name, description: description, thumbnail: thumbnail, - royalties: royalties, - metadata: metadata, + royalties: royalties ) // deposit it in the recipient's account using their reference recipient.deposit(token: <-newNFT) - - ExampleNFT2.totalSupply = ExampleNFT2.totalSupply + UInt64(1) } } @@ -334,19 +302,17 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { /// @param view: The Type of the desired view. /// @return A structure representing the requested view. /// - pub fun resolveView(_ view: Type): AnyStruct? { - switch view { + access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? { + switch viewType { case Type(): return MetadataViews.NFTCollectionData( - storagePath: ExampleNFT2.CollectionStoragePath, - publicPath: ExampleNFT2.CollectionPublicPath, - providerPath: /private/exampleNFT2Collection, - publicCollection: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic}>(), - publicLinkedType: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(), - providerLinkedType: Type<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(), - createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection { - return <-ExampleNFT2.createEmptyCollection() - }) + storagePath: ExampleNFT2.CollectionStoragePath, + publicPath: ExampleNFT2.CollectionPublicPath, + publicCollection: Type<&ExampleNFT2.Collection>(), + publicLinkedType: Type<&ExampleNFT2.Collection>(), + createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} { + return <-ExampleNFT2.createEmptyCollection() + }) ) case Type(): let media = MetadataViews.Media( @@ -355,6 +321,16 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { ), mediaType: "image/svg+xml" ) + return MetadataViews.NFTCollectionDisplay( + name: "The Example Collection", + description: "This collection is used as an example to help you develop your next Flow NFT.", + externalURL: MetadataViews.ExternalURL("https://example-nft.onflow.org"), + squareImage: media, + bannerImage: media, + socials: { + "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") + } + ) } return nil } @@ -364,7 +340,7 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { /// @return An array of Types defining the implemented views. This value will be used by /// developers to know which parameter to pass to the resolveView() method. /// - pub fun getViews(): [Type] { + access(all) view fun getContractViews(resourceType: Type?): [Type] { return [ Type(), Type() @@ -379,20 +355,20 @@ pub contract ExampleNFT2: NonFungibleToken, ViewResolver { self.CollectionStoragePath = /storage/exampleNFT2Collection self.CollectionPublicPath = /public/exampleNFT2Collection self.MinterStoragePath = /storage/exampleNFT2Minter + self.MinterPublicPath = /public/exampleNFT2Minter // Create a Collection resource and save it to storage let collection <- create Collection() - self.account.save(<-collection, to: self.CollectionStoragePath) + self.account.storage.save(<-collection, to: self.CollectionStoragePath) + let cap = self.account.capabilities.storage.issue<&ExampleNFT2.Collection>(self.CollectionStoragePath) + self.account.capabilities.publish(cap, at: self.CollectionPublicPath) - // create a public capability for the collection - self.account.link<&ExampleNFT2.Collection{NonFungibleToken.CollectionPublic, ExampleNFT2.ExampleNFT2CollectionPublic, MetadataViews.ResolverCollection}>( - self.CollectionPublicPath, - target: self.CollectionStoragePath - ) // Create a Minter resource and save it to storage let minter <- create NFTMinter() - self.account.save(<-minter, to: self.MinterStoragePath) + self.account.storage.save(<-minter, to: self.MinterStoragePath) + + let minterCap = self.account.capabilities.storage.issue<&ExampleNFT2.NFTMinter>(self.MinterStoragePath) emit ContractInitialized() } diff --git a/contracts/standard/ExampleToken.cdc b/contracts/standard/ExampleToken.cdc index 13873a4..9047ac6 100644 --- a/contracts/standard/ExampleToken.cdc +++ b/contracts/standard/ExampleToken.cdc @@ -1,38 +1,49 @@ import "FungibleToken" import "MetadataViews" +import "FungibleTokenMetadataViews" -pub contract ExampleToken: FungibleToken { +access(all) contract ExampleToken: FungibleToken { /// Total supply of ExampleTokens in existence - pub var totalSupply: UFix64 - - /// Storage and Public Paths - pub let VaultStoragePath: StoragePath - pub let VaultPublicPath: PublicPath - pub let ReceiverPublicPath: PublicPath - pub let AdminStoragePath: StoragePath + access(all) var totalSupply: UFix64 + /// TokensInitialized + /// /// The event that is emitted when the contract is created - pub event TokensInitialized(initialSupply: UFix64) + access(all) event TokensInitialized(initialSupply: UFix64) + /// TokensWithdrawn + /// /// The event that is emitted when tokens are withdrawn from a Vault - pub event TokensWithdrawn(amount: UFix64, from: Address?) + access(all) event TokensWithdrawn(amount: UFix64, from: Address?) + /// TokensDeposited + /// /// The event that is emitted when tokens are deposited to a Vault - pub event TokensDeposited(amount: UFix64, to: Address?) + access(all) event TokensDeposited(amount: UFix64, to: Address?) + /// TokensMinted + /// /// The event that is emitted when new tokens are minted - pub event TokensMinted(amount: UFix64) + access(all) event TokensMinted(amount: UFix64) + /// TokensBurned + /// /// The event that is emitted when tokens are destroyed - pub event TokensBurned(amount: UFix64) + access(all) event TokensBurned(amount: UFix64) + /// MinterCreated + /// /// The event that is emitted when a new minter resource is created - pub event MinterCreated(allowedAmount: UFix64) + access(all) event MinterCreated(allowedAmount: UFix64) + /// BurnerCreated + /// /// The event that is emitted when a new burner resource is created - pub event BurnerCreated() + access(all) event BurnerCreated() + /// Vault + /// /// Each user stores an instance of only the Vault in their storage /// The functions in the Vault and governed by the pre and post conditions /// in FungibleToken when they are called. @@ -43,41 +54,76 @@ pub contract ExampleToken: FungibleToken { /// out of thin air. A special Minter resource needs to be defined to mint /// new tokens. /// - pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance { + access(all) resource Vault: FungibleToken.Vault { /// The total balance of this vault - pub var balance: UFix64 + access(all) var balance: UFix64 - /// Initialize the balance at resource creation time + // initialize the balance at resource creation time init(balance: UFix64) { self.balance = balance } + access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool { + return amount <= self.balance + } + + access(all) view fun getSupportedVaultTypes(): {Type: Bool} { + return {self.getType(): true} + } + + access(all) view fun isSupportedVaultType(type: Type): Bool { + if (type == self.getType()) { return true } else { return false } + } + + access(all) fun createEmptyVault(): @{FungibleToken.Vault} { + return <-create Vault(balance: 0.0) + } + + /// Get all the Metadata Views implemented by ExampleToken + /// + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getViews(): [Type]{ + return ExampleToken.getContractViews(resourceType: nil) + } + + /// Get a Metadata View from ExampleToken + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveView(_ view: Type): AnyStruct? { + return ExampleToken.resolveContractView(resourceType: nil, viewType: view) + } + + /// withdraw + /// /// Function that takes an amount as an argument /// and withdraws that amount from the Vault. + /// /// It creates a new temporary Vault that is used to hold /// the money that is being transferred. It returns the newly /// created Vault to the context that called so it can be deposited /// elsewhere. /// - /// @param amount: The amount of tokens to be withdrawn from the vault - /// @return The Vault resource containing the withdrawn funds - /// - pub fun withdraw(amount: UFix64): @FungibleToken.Vault { + access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} { self.balance = self.balance - amount emit TokensWithdrawn(amount: amount, from: self.owner?.address) return <-create Vault(balance: amount) } + /// deposit + /// /// Function that takes a Vault object as an argument and adds /// its balance to the balance of the owners Vault. + /// /// It is allowed to destroy the sent Vault because the Vault /// was a temporary holder of the tokens. The Vault's balance has /// been consumed and therefore can be destroyed. /// - /// @param from: The Vault resource containing the funds that will be deposited - /// - pub fun deposit(from: @FungibleToken.Vault) { + access(all) fun deposit(from: @{FungibleToken.Vault}) { let vault <- from as! @ExampleToken.Vault self.balance = self.balance + vault.balance emit TokensDeposited(amount: vault.balance, to: self.owner?.address) @@ -85,64 +131,58 @@ pub contract ExampleToken: FungibleToken { destroy vault } - destroy() { - if self.balance > 0.0 { - ExampleToken.totalSupply = ExampleToken.totalSupply - self.balance - } + access(contract) fun burnCallback() { + ExampleToken.totalSupply = ExampleToken.totalSupply - self.balance } - } + /// createEmptyVault + /// /// Function that creates a new Vault with a balance of zero /// and returns it to the calling context. A user must call this function /// and store the returned Vault in their storage in order to allow their /// account to be able to receive deposits of this token type. /// - /// @return The new Vault resource - /// - pub fun createEmptyVault(): @Vault { + access(all) fun createEmptyVault(vaultType: Type): @Vault { return <-create Vault(balance: 0.0) } - pub resource Administrator { + access(all) resource Administrator { - /// Function that creates and returns a new minter resource + /// createNewMinter /// - /// @param allowedAmount: The maximum quantity of tokens that the minter could create - /// @return The Minter resource that would allow to mint tokens + /// Function that creates and returns a new minter resource /// - + access(all) fun createNewMinter(allowedAmount: UFix64): @Minter { + emit MinterCreated(allowedAmount: allowedAmount) + return <-create Minter(allowedAmount: allowedAmount) + } - /// Function that creates and returns a new burner resource + /// createNewBurner /// - /// @return The Burner resource + /// Function that creates and returns a new burner resource /// - pub fun createNewBurner(): @Burner { + access(all) fun createNewBurner(): @Burner { emit BurnerCreated() return <-create Burner() } } - // EMULATOR ONLY, anyone can mint tokens - pub fun createNewMinter(allowedAmount: UFix64): @Minter { - emit MinterCreated(allowedAmount: allowedAmount) - return <-create Minter(allowedAmount: allowedAmount) - } - + /// Minter + /// /// Resource object that token admin accounts can hold to mint new tokens. /// - pub resource Minter { + access(all) resource Minter { /// The amount of tokens that the minter is allowed to mint - pub var allowedAmount: UFix64 + access(all) var allowedAmount: UFix64 + /// mintTokens + /// /// Function that mints new tokens, adds them to the total supply, /// and returns them to the calling context. /// - /// @param amount: The quantity of tokens to mint - /// @return The Vault resource containing the minted tokens - /// - pub fun mintTokens(amount: UFix64): @ExampleToken.Vault { + access(all) fun mintTokens(amount: UFix64): @ExampleToken.Vault { pre { amount > 0.0: "Amount minted must be greater than zero" amount <= self.allowedAmount: "Amount minted must be less than the allowed amount" @@ -158,18 +198,20 @@ pub contract ExampleToken: FungibleToken { } } + /// Burner + /// /// Resource object that token admin accounts can hold to burn tokens. /// - pub resource Burner { + access(all) resource Burner { + /// burnTokens + /// /// Function that destroys a Vault instance, effectively burning the tokens. /// /// Note: the burned tokens are automatically subtracted from the /// total supply in the Vault destructor. /// - /// @param from: The Vault resource containing the tokens to burn - /// - pub fun burnTokens(from: @FungibleToken.Vault) { + access(all) fun burnTokens(from: @{FungibleToken.Vault}) { let vault <- from as! @ExampleToken.Vault let amount = vault.balance destroy vault @@ -177,35 +219,81 @@ pub contract ExampleToken: FungibleToken { } } + /// Gets a list of the metadata views that this contract supports + access(all) view fun getContractViews(resourceType: Type?): [Type] { + return [Type(), + Type(), + Type(), + Type()] + } + + /// Get a Metadata View from ExampleToken + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? { + switch viewType { + case Type(): + return FungibleTokenMetadataViews.FTView( + ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTDisplay?, + ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ) + case Type(): + let media = MetadataViews.Media( + file: MetadataViews.HTTPFile( + url: "example.com" + ), + mediaType: "image/svg+xml" + ) + let medias = MetadataViews.Medias([media]) + return FungibleTokenMetadataViews.FTDisplay( + name: "EXAMPLE Token", + symbol: "EXAMPLE", + description: "This is an example token", + externalURL: MetadataViews.ExternalURL("https://flow.com"), + logos: medias, + socials: { + "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") + } + ) + case Type(): + let vaultRef = ExampleToken.account.storage.borrow(from: /storage/exampleTokenVault) + ?? panic("Could not borrow reference to the contract's Vault!") + return FungibleTokenMetadataViews.FTVaultData( + storagePath: /storage/exampleTokenVault, + receiverPath: /public/exampleTokenReceiver, + metadataPath: /public/exampleTokenBalance, + receiverLinkedType: Type<&{FungibleToken.Receiver, FungibleToken.Vault}>(), + metadataLinkedType: Type<&{FungibleToken.Balance, FungibleToken.Vault}>(), + createEmptyVaultFunction: (fun (): @{FungibleToken.Vault} { + return <-vaultRef.createEmptyVault() + }) + ) + case Type(): + return FungibleTokenMetadataViews.TotalSupply(totalSupply: ExampleToken.totalSupply) + } + return nil + } + init() { self.totalSupply = 1000.0 - self.VaultStoragePath = /storage/exampleTokenVault - self.VaultPublicPath = /public/exampleTokenMetadata - self.ReceiverPublicPath = /public/exampleTokenReceiver - self.AdminStoragePath = /storage/exampleTokenAdmin - // Create the Vault with the total supply of tokens and save it in storage. + // Create the Vault with the total supply of tokens and save it in storage + // let vault <- create Vault(balance: self.totalSupply) - self.account.save(<-vault, to: self.VaultStoragePath) - - // Create a public capability to the stored Vault that exposes - // the `deposit` method through the `Receiver` interface. - self.account.link<&{FungibleToken.Receiver}>( - self.ReceiverPublicPath, - target: self.VaultStoragePath - ) - - // Create a public capability to the stored Vault that only exposes - // the `balance` field and the `resolveView` method through the `Balance` interface - self.account.link<&ExampleToken.Vault{FungibleToken.Balance}>( - self.VaultPublicPath, - target: self.VaultStoragePath - ) + self.account.storage.save(<-vault, to: /storage/exampleTokenVault) + + let cap = self.account.capabilities.storage.issue<&{FungibleToken.Vault}>(/storage/exampleTokenVault) + self.account.capabilities.publish(cap, at: /public/exampleTokenReceiver) + self.account.capabilities.publish(cap, at: /public/exampleTokenBalance) + let admin <- create Administrator() - self.account.save(<-admin, to: self.AdminStoragePath) + self.account.storage.save(<-admin, to: /storage/exampleTokenAdmin) // Emit an event that shows that the contract was initialized + // emit TokensInitialized(initialSupply: self.totalSupply) } -} +} \ No newline at end of file diff --git a/flow.json b/flow.json index 967a5f2..02ccfe9 100644 --- a/flow.json +++ b/flow.json @@ -1,21 +1,5 @@ { "contracts": { - "AddressUtils": { - "source": "./modules/flow-utils/cadence/contracts/AddressUtils.cdc", - "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "31ad40c07a2a9788", - "mainnet": "a340dc0a4ec828ab" - } - }, - "ArrayUtils": { - "source": "./modules/flow-utils/cadence/contracts/ArrayUtils.cdc", - "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "31ad40c07a2a9788", - "mainnet": "a340dc0a4ec828ab" - } - }, "CapabilityDelegator": { "source": "./contracts/CapabilityDelegator.cdc", "aliases": { @@ -106,22 +90,6 @@ "mainnet": "d8a7e05a7ac670c0" } }, - "FlowToken": { - "source": "", - "aliases": { - "emulator": "0ae53cb6e3f42a79", - "testnet": "7e60df042a9c0868", - "mainnet": "1654653399040a61" - } - }, - "FungibleToken": { - "source": "./modules/flow-nft/contracts/utility/FungibleToken.cdc", - "aliases": { - "emulator": "ee82856bf20e2aa6", - "testnet": "9a0766d93b6608b7", - "mainnet": "f233dcee88fe0abe" - } - }, "HybridCustody": { "source": "./contracts/HybridCustody.cdc", "aliases": { @@ -131,14 +99,6 @@ "mainnet": "d8a7e05a7ac670c0" } }, - "MetadataViews": { - "source": "./modules/flow-nft/contracts/MetadataViews.cdc", - "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "631e88ae7f1d7c20", - "mainnet": "1d7e57aa55817448" - } - }, "NFTCollectionPublicFactory": { "source": "./contracts/factories/NFTCollectionPublicFactory.cdc", "aliases": { @@ -165,28 +125,84 @@ "testnet": "294e44e1ec6993c6" } }, + "FungibleToken": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/FungibleToken.cdc", + "aliases": { + "emulator": "0xee82856bf20e2aa6", + "testnet": "0x9a0766d93b6608b7", + "mainnet": "0xf233dcee88fe0abe" + } + }, + "FungibleTokenMetadataViews": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/FungibleTokenMetadataViews.cdc", + "aliases": { + "emulator": "0xee82856bf20e2aa6", + "testnet": "0x9a0766d93b6608b7", + "mainnet": "0xf233dcee88fe0abe" + } + }, + "Burner": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/Burner.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x631e88ae7f1d7c20", + "mainnet": "0x1d7e57aa55817448" + } + }, + "FlowToken": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/FlowToken.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868", + "mainnet": "0x1654653399040a61" + } + }, "NonFungibleToken": { - "source": "./modules/flow-nft/contracts/NonFungibleToken.cdc", + "source": "./node_modules/@flowtyio/flow-contracts/contracts/NonFungibleToken.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "631e88ae7f1d7c20", - "mainnet": "1d7e57aa55817448" + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x631e88ae7f1d7c20", + "mainnet": "0x1d7e57aa55817448" } }, "StringUtils": { - "source": "./modules/flow-utils/cadence/contracts/StringUtils.cdc", + "source": "./node_modules/@flowtyio/flow-contracts/contracts/flow-utils/StringUtils.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "31ad40c07a2a9788", - "mainnet": "a340dc0a4ec828ab" + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x31ad40c07a2a9788", + "mainnet": "0xa340dc0a4ec828ab" + } + }, + "ArrayUtils": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/flow-utils/ArrayUtils.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x31ad40c07a2a9788", + "mainnet": "0xa340dc0a4ec828ab" + } + }, + "AddressUtils": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/flow-utils/AddressUtils.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x31ad40c07a2a9788", + "mainnet": "0xa340dc0a4ec828ab" + } + }, + "MetadataViews": { + "source": "./node_modules/@flowtyio/flow-contracts/contracts/MetadataViews.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x631e88ae7f1d7c20", + "mainnet": "0x1d7e57aa55817448" } }, "ViewResolver": { - "source": "./modules/flow-nft/contracts/ViewResolver.cdc", + "source": "./node_modules/@flowtyio/flow-contracts/contracts/ViewResolver.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testnet": "631e88ae7f1d7c20", - "mainnet": "1d7e57aa55817448" + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x631e88ae7f1d7c20", + "mainnet": "0x1d7e57aa55817448" } } }, @@ -285,6 +301,10 @@ "hashAlgorithm": "SHA2_256", "resourceID": "projects/dl-flow-admin/locations/global/keyRings/hybrid-custody-testnet/cryptoKeys/hybrid-custody-testnet-key/cryptoKeyVersions/1" } + }, + "emulator-flowtoken": { + "address": "0ae53cb6e3f42a79", + "key": "686779d775e5fcbf8d2f4a85cb4c53525d02b7ef53230d180fc16f35d9b7d025" } }, "deployments": { @@ -310,10 +330,15 @@ "NFTCollectionPublicFactory", "ExampleNFT", "ExampleNFT2", - "ExampleToken" + "ExampleToken", + "Burner" ], "emulator-ft": [ - "FungibleToken" + "FungibleToken", + "FungibleTokenMetadataViews" + ], + "emulator-flowtoken": [ + "FlowToken" ] }, "testnet": { diff --git a/modules/flow-ft b/modules/flow-ft new file mode 160000 index 0000000..a31032a --- /dev/null +++ b/modules/flow-ft @@ -0,0 +1 @@ +Subproject commit a31032af9b68d92b2c01eb85cc2103fae698bb19 diff --git a/modules/flow-nft b/modules/flow-nft index 9b6dc02..4c0c684 160000 --- a/modules/flow-nft +++ b/modules/flow-nft @@ -1 +1 @@ -Subproject commit 9b6dc02853d49d2dadf13d08b1922c58f879add4 +Subproject commit 4c0c684baed98e2ffd7a8f9d27973c1db5dd1239 diff --git a/modules/flow-utils b/modules/flow-utils index 23100ed..c10ce02 160000 --- a/modules/flow-utils +++ b/modules/flow-utils @@ -1 +1 @@ -Subproject commit 23100ed21d0f05c7874af158b4a05648ac707011 +Subproject commit c10ce024fad1abc67cde1e551ddc1e5f5771226c diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..adba3c5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,35 @@ +{ + "name": "hybrid-custody", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hybrid-custody", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@flowtyio/flow-contracts": "^0.1.0-beta.11" + } + }, + "node_modules/@flowtyio/flow-contracts": { + "version": "0.1.0-beta.11", + "resolved": "https://registry.npmjs.org/@flowtyio/flow-contracts/-/flow-contracts-0.1.0-beta.11.tgz", + "integrity": "sha512-4D1JHCrV6KxRgKEsfGxzVxAYrEjq51N0tlVy7gi+Ne7YhWQ+Jp7ha+QwPxuLIYkjMZjMzoM/dD6WedZQERgFSg==", + "dependencies": { + "commander": "^11.0.0" + }, + "bin": { + "flow-contracts": "index.js" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6ec1b14 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "hybrid-custody", + "version": "1.0.0", + "description": "![Tests](https://github.com/onflow/hybrid-custody/actions/workflows/integration-tests.yml/badge.svg) [![codecov](https://codecov.io/gh/onflow/hybrid-custody/branch/main/graph/badge.svg?token=5GWD5NHEKF)](https://codecov.io/gh/onflow/hybrid-custody)", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@flowtyio/flow-contracts": "^0.1.0-beta.11" + } +} From acaa263335ceaa3a3709bcd4a9c67b81aee2f336 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Sun, 31 Mar 2024 19:54:07 -0700 Subject: [PATCH 02/34] address all contract errors/warnings --- contracts/HybridCustody.cdc | 459 ++++++++++++++++++------------------ 1 file changed, 229 insertions(+), 230 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 1c5795d..6ff01b6 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -1,5 +1,6 @@ // Third-party imports import "MetadataViews" +import "ViewResolver" // HC-owned imports import "CapabilityFactory" @@ -27,39 +28,42 @@ import "CapabilityFilter" /// /// Repo reference: https://github.com/onflow/hybrid-custody /// -pub contract HybridCustody { +access(all) contract HybridCustody { + + access(all) entitlement Restricted + access(all) entitlement Owner /* --- Canonical Paths --- */ // // Note: Paths for ChildAccount & Delegator are derived from the parent's address // - pub let OwnedAccountStoragePath: StoragePath - pub let OwnedAccountPublicPath: PublicPath - pub let OwnedAccountPrivatePath: PrivatePath + access(all) let OwnedAccountStoragePath: StoragePath + access(all) let OwnedAccountPublicPath: PublicPath + access(all) let OwnedAccountPrivatePath: PrivatePath - pub let ManagerStoragePath: StoragePath - pub let ManagerPublicPath: PublicPath - pub let ManagerPrivatePath: PrivatePath + access(all) let ManagerStoragePath: StoragePath + access(all) let ManagerPublicPath: PublicPath + access(all) let ManagerPrivatePath: PrivatePath - pub let LinkedAccountPrivatePath: PrivatePath - pub let BorrowableAccountPrivatePath: PrivatePath + access(all) let LinkedAccountPrivatePath: PrivatePath + access(all) let BorrowableAccountPrivatePath: PrivatePath /* --- Events --- */ // /// Manager creation event - pub event CreatedManager(id: UInt64) + access(all) event CreatedManager(id: UInt64) /// OwnedAccount creation event - pub event CreatedOwnedAccount(id: UInt64, child: Address) + access(all) event CreatedOwnedAccount(id: UInt64, child: Address) /// ChildAccount added/removed from Manager /// active : added to Manager /// !active : removed from Manager - pub event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool) + access(all) event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool) /// OwnedAccount added/removed or sealed /// active && owner != nil : added to Manager /// !active && owner == nil : removed from Manager - pub event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool) + access(all) event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool) /// ChildAccount ready to be redeemed by emitted pendingParent - pub event ChildAccountPublished( + access(all) event ChildAccountPublished( ownedAcctID: UInt64, childAcctID: UInt64, capDelegatorID: UInt64, @@ -70,30 +74,30 @@ pub contract HybridCustody { pendingParent: Address ) /// OwnedAccount granted ownership to a new address, publishing a Capability for the pendingOwner - pub event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address) + access(all) event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address) /// Account has been sealed - keys revoked, new AuthAccount Capability generated - pub event AccountSealed(id: UInt64, address: Address, parents: [Address]) + access(all) event AccountSealed(id: UInt64, address: Address, parents: [Address]) /// An OwnedAccount shares the BorrowableAccount capability to itelf with ChildAccount resources /// - pub resource interface BorrowableAccount { - access(contract) fun borrowAccount(): &AuthAccount - pub fun check(): Bool + access(all) resource interface BorrowableAccount { + access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account + access(all) view fun check(): Bool } /// Public methods anyone can call on an OwnedAccount /// - pub resource interface OwnedAccountPublic { + access(all) resource interface OwnedAccountPublic { /// Returns the addresses of all parent accounts - pub fun getParentAddresses(): [Address] + access(all) view fun getParentAddresses(): [Address] /// Returns associated parent addresses and their redeemed status - true if redeemed, false if pending - pub fun getParentStatuses(): {Address: Bool} + access(all) view fun getParentStatuses(): {Address: Bool} /// Returns true if the given address is a parent of this child and has redeemed it. Returns false if the given /// address is a parent of this child and has NOT redeemed it. Returns nil if the given address it not a parent /// of this child account. - pub fun getRedeemedStatus(addr: Address): Bool? + access(all) view fun getRedeemedStatus(addr: Address): Bool? /// A callback function to mark a parent as redeemed on the child account. access(contract) fun setRedeemed(_ addr: Address) @@ -101,18 +105,18 @@ pub contract HybridCustody { /// Private interface accessible to the owner of the OwnedAccount /// - pub resource interface OwnedAccountPrivate { + access(all) resource interface OwnedAccountPrivate { /// Deletes the ChildAccount resource being used to share access to this OwnedAccount with the supplied parent /// address, and unlinks the paths it was using to reach the underlying account. - pub fun removeParent(parent: Address): Bool + access(Restricted) fun removeParent(parent: Address): Bool /// Sets up a new ChildAccount resource for the given parentAddress to redeem. This child account uses the /// supplied factory and filter to manage what can be obtained from the child account, and a new /// CapabilityDelegator resource is created for the sharing of one-off capabilities. Each of these pieces of /// access control are managed through the child account. - pub fun publishToParent( + access(Restricted) fun publishToParent( parentAddress: Address, - factory: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>, + factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> ) { pre { @@ -124,7 +128,7 @@ pub contract HybridCustody { /// Passes ownership of this child account to the given address. Once executed, all active keys on the child /// account will be revoked, and the active AuthAccount Capability being used by to obtain capabilities will be /// rotated, preventing anyone without the newly generated Capability from gaining access to the account. - pub fun giveOwnership(to: Address) + access(Owner) fun giveOwnership(to: Address) /// Revokes all keys on an account, unlinks all currently active AuthAccount capabilities, then makes a new one /// and replaces the OwnedAccount's underlying AuthAccount Capability with the new one to ensure that all @@ -132,12 +136,12 @@ pub contract HybridCustody { /// Unless this method is executed via the giveOwnership function, this will leave an account **without** an /// owner. /// USE WITH EXTREME CAUTION. - pub fun seal() + access(Owner) fun seal() // setCapabilityFactoryForParent // Override the existing CapabilityFactory Capability for a given parent. This will allow the owner of the // account to start managing their own factory of capabilities to be able to retrieve - pub fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>) { + access(Restricted) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&{CapabilityFactory.Getter}>) { pre { cap.check(): "Invalid CapabilityFactory.Getter Capability provided" } @@ -145,7 +149,7 @@ pub contract HybridCustody { /// Override the existing CapabilityFilter Capability for a given parent. This will allow the owner of the /// account to start managing their own filter for retrieving Capabilities on Private Paths - pub fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { + access(Restricted) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { pre { cap.check(): "Invalid CapabilityFilter Capability provided" } @@ -153,68 +157,67 @@ pub contract HybridCustody { /// Adds a capability to a parent's managed @ChildAccount resource. The Capability can be made public, /// permitting anyone to borrow it. - pub fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { + access(Restricted) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } } /// Removes a Capability from the CapabilityDelegator used by the specified parent address - pub fun removeCapabilityFromDelegator(parent: Address, cap: Capability) + access(Restricted) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) /// Returns the address of this OwnedAccount - pub fun getAddress(): Address + access(all) view fun getAddress(): Address /// Checks if this OwnedAccount is a child of the specified address - pub fun isChildOf(_ addr: Address): Bool + access(all) view fun isChildOf(_ addr: Address): Bool /// Returns all addresses which are parents of this OwnedAccount - pub fun getParentAddresses(): [Address] + access(all) view fun getParentAddresses(): [Address] /// Borrows this OwnedAccount's AuthAccount Capability - pub fun borrowAccount(): &AuthAccount? + access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account /// Returns the current owner of this account, if there is one - pub fun getOwner(): Address? + access(all) view fun getOwner(): Address? /// Returns the pending owner of this account, if there is one - pub fun getPendingOwner(): Address? + access(all) view fun getPendingOwner(): Address? /// A callback which is invoked when a parent redeems an owned account access(contract) fun setOwnerCallback(_ addr: Address) /// Destroys all outstanding AuthAccount capabilities on this owned account, and creates a new one for the /// OwnedAccount to use - pub fun rotateAuthAccount() + access(Owner) fun rotateAuthAccount() /// Revokes all keys on this account - pub fun revokeAllKeys() + access(Owner) fun revokeAllKeys() } /// Public methods exposed on a ChildAccount resource. OwnedAccountPublic will share some methods here, but isn't /// necessarily the same. /// - pub resource interface AccountPublic { - pub fun getPublicCapability(path: PublicPath, type: Type): Capability? - pub fun getPublicCapFromDelegator(type: Type): Capability? - pub fun getAddress(): Address - pub fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? - pub fun getCapabilityFilter(): &{CapabilityFilter.Filter}? + access(all) resource interface AccountPublic { + // TODO: This has been disabled because you cannot get a capability without providing a type T anymore in Cadence 1.0 + // access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? + access(all) view fun getPublicCapFromDelegator(type: Type): Capability? + access(all) view fun getAddress(): Address + access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? + access(all) view fun getCapabilityFilter(): &{CapabilityFilter.Filter}? } /// Methods accessible to the designated parent of a ChildAccount /// - pub resource interface AccountPrivate { - pub fun getCapability(path: CapabilityPath, type: Type): Capability? { + access(all) resource interface AccountPrivate { + access(Capabilities) view fun getCapability(controllerID: UInt64, 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? - pub fun getPrivateCapFromDelegator(type: Type): Capability? { + access(all) view fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? + access(Capabilities) view fun getPrivateCapFromDelegator(type: Type): Capability? { post { result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)): "Capability is not allowed by this account's Parent" @@ -231,14 +234,14 @@ pub contract HybridCustody { /// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts /// - pub resource interface ManagerPrivate { - pub fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, MetadataViews.Resolver}>) - pub fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, MetadataViews.Resolver}? - pub fun removeChild(addr: Address) - pub fun addOwnedAccount(cap: Capability<&{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}>) - pub fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}? - pub fun removeOwned(addr: Address) - pub fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(all) resource interface ManagerPrivate { + access(Restricted) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) + access(Restricted) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? + access(Restricted) fun removeChild(addr: Address) + access(Owner) fun addOwnedAccount(cap: Capability) + access(Restricted) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? + access(Restricted) fun removeOwned(addr: Address) + access(Restricted) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { pre { cap == nil || cap!.check(): "Invalid Manager Capability Filter" } @@ -247,39 +250,39 @@ pub contract HybridCustody { /// Functions anyone can call on a manager to get information about an account such as What child accounts it has /// Functions anyone can call on a manager to get information about an account such as what child accounts it has - pub resource interface ManagerPublic { - pub fun borrowAccountPublic(addr: Address): &{AccountPublic, MetadataViews.Resolver}? - pub fun getChildAddresses(): [Address] - pub fun getOwnedAddresses(): [Address] - pub fun getChildAccountDisplay(address: Address): MetadataViews.Display? + access(all) resource interface ManagerPublic { + access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? + access(all) fun getChildAddresses(): [Address] + access(all) fun getOwnedAddresses(): [Address] + access(all) fun getChildAccountDisplay(address: Address): MetadataViews.Display? access(contract) fun removeParentCallback(child: Address) } /// A resource for an account which fills the Parent role of the Child-Parent account management Model. A Manager /// can redeem or remove child accounts, and obtain any capabilities exposed by the child account to them. /// - pub resource Manager: ManagerPrivate, ManagerPublic, MetadataViews.Resolver { + access(all) resource Manager: ManagerPrivate, ManagerPublic, ViewResolver.Resolver { /// Mapping of restricted access child account Capabilities indexed by their address - pub let childAccounts: {Address: Capability<&{AccountPrivate, AccountPublic, MetadataViews.Resolver}>} + access(self) let childAccounts: {Address: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>} /// Mapping of unrestricted owned account Capabilities indexed by their address - pub let ownedAccounts: {Address: Capability<&{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}>} + access(self) let ownedAccounts: {Address: Capability} /// A bucket of structs so that the Manager resource can be easily extended with new functionality. - pub let data: {String: AnyStruct} + access(self) let data: {String: AnyStruct} /// A bucket of resources so that the Manager resource can be easily extended with new functionality. - pub let resources: @{String: AnyResource} + access(self) let resources: @{String: AnyResource} /// An optional filter to gate what capabilities are permitted to be returned from a child account For example, /// Dapper Wallet parent account's should not be able to retrieve any FungibleToken Provider capabilities. - pub var filter: Capability<&{CapabilityFilter.Filter}>? + access(self) var filter: Capability<&{CapabilityFilter.Filter}>? // display metadata for a child account exists on its parent - pub let childAccountDisplays: {Address: MetadataViews.Display} + access(self) let childAccountDisplays: {Address: MetadataViews.Display} /// Sets the Display on the ChildAccount. If nil, the display is removed. /// - pub fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { + access(Restricted) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { pre { self.childAccounts[address] != nil: "There is no child account with this address" } @@ -295,7 +298,7 @@ pub contract HybridCustody { /// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be /// added to the ChildAccount /// - pub fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, MetadataViews.Resolver}>) { + access(Restricted) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) { pre { self.childAccounts[cap.address] == nil: "There is already a child account with this address" } @@ -313,7 +316,7 @@ pub contract HybridCustody { /// Sets the default Filter Capability for this Manager. Does not propagate to child accounts. /// - pub fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { + access(Restricted) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { pre { cap == nil || cap!.check(): "supplied capability must be nil or check must pass" } @@ -323,7 +326,7 @@ pub contract HybridCustody { /// Sets the Filter Capability for this Manager, propagating to the specified child account /// - pub fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Restricted) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { let acct = self.borrowAccount(addr: childAddress) ?? panic("child account not found") @@ -333,7 +336,7 @@ pub contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - pub fun removeChild(addr: Address) { + access(Restricted) fun removeChild(addr: Address) { let cap = self.childAccounts.remove(key: addr) ?? panic("child account not found") @@ -365,7 +368,7 @@ pub contract HybridCustody { /// Adds an owned account to the Manager's list of owned accounts, setting the Manager account as the owner of /// the given account /// - pub fun addOwnedAccount(cap: Capability<&{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}>) { + access(Owner) fun addOwnedAccount(cap: Capability) { pre { self.ownedAccounts[cap.address] == nil: "There is already an owned account with this address" } @@ -386,7 +389,7 @@ pub contract HybridCustody { /// Returns a reference to a child account /// - pub fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, MetadataViews.Resolver}? { + access(Restricted) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? { let cap = self.childAccounts[addr] if cap == nil { return nil @@ -397,7 +400,7 @@ pub contract HybridCustody { /// Returns a reference to a child account's public AccountPublic interface /// - pub fun borrowAccountPublic(addr: Address): &{AccountPublic, MetadataViews.Resolver}? { + access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? { let cap = self.childAccounts[addr] if cap == nil { return nil @@ -408,7 +411,7 @@ pub contract HybridCustody { /// Returns a reference to an owned account /// - pub fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, MetadataViews.Resolver}? { + access(Restricted) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { if let cap = self.ownedAccounts[addr] { return cap.borrow() } @@ -419,7 +422,7 @@ pub contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - pub fun removeOwned(addr: Address) { + access(Restricted) fun removeOwned(addr: Address) { if let acct = self.ownedAccounts.remove(key: addr) { if acct.check() { acct.borrow()!.seal() @@ -439,7 +442,7 @@ pub contract HybridCustody { /// mechanism intended to easily transfer 'root' access on this account to another account and an attempt to /// minimize access vectors. /// - pub fun giveOwnership(addr: Address, to: Address) { + access(Owner) fun giveOwnership(addr: Address, to: Address) { let acct = self.ownedAccounts.remove(key: addr) ?? panic("account not found") @@ -448,31 +451,31 @@ pub contract HybridCustody { /// Returns an array of child account addresses /// - pub fun getChildAddresses(): [Address] { + access(all) view fun getChildAddresses(): [Address] { return self.childAccounts.keys } /// Returns an array of owned account addresses /// - pub fun getOwnedAddresses(): [Address] { + access(all) view fun getOwnedAddresses(): [Address] { return self.ownedAccounts.keys } /// Retrieves the parent-defined display for the given child account /// - pub fun getChildAccountDisplay(address: Address): MetadataViews.Display? { + access(all) view fun getChildAccountDisplay(address: Address): MetadataViews.Display? { return self.childAccountDisplays[address] } /// Returns the types of supported views - none at this time /// - pub fun getViews(): [Type] { + access(all) view fun getViews(): [Type] { return [] } /// Resolves the given view if supported - none at this time /// - pub fun resolveView(_ view: Type): AnyStruct? { + access(all) view fun resolveView(_ view: Type): AnyStruct? { return nil } @@ -489,9 +492,10 @@ pub contract HybridCustody { self.resources <- {} } - destroy () { - destroy self.resources - } + // TODO: burnCallback and ResourceDestroyed event + // destroy () { + // destroy self.resources + // } } /// The ChildAccount resource sits between a child account and a parent and is stored on the same account as the @@ -503,27 +507,27 @@ pub contract HybridCustody { /// able to manage all ChildAccount resources it shares, without worrying about whether the upstream parent can do /// anything to prevent it. /// - pub resource ChildAccount: AccountPrivate, AccountPublic, MetadataViews.Resolver { + access(all) resource ChildAccount: AccountPrivate, AccountPublic, ViewResolver.Resolver { /// A Capability providing access to the underlying child account - access(self) let childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver}> + access(self) let childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}> /// The CapabilityFactory Manager is a ChildAccount's way of limiting what types can be asked for by its parent /// account. The CapabilityFactory returns Capabilities which can be casted to their appropriate types once /// obtained, but only if the child account has configured their factory to allow it. For instance, a /// ChildAccount might choose to expose NonFungibleToken.Provider, but not FungibleToken.Provider - pub var factory: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}> + access(self) var factory: Capability<&{CapabilityFactory.Getter}> /// The CapabilityFilter is a restriction put at the front of obtaining any non-public Capability. Some wallets /// might want to give access to NonFungibleToken.Provider, but only to **some** of the collections it manages, /// not all of them. - pub var filter: Capability<&{CapabilityFilter.Filter}> + access(self) var filter: Capability<&{CapabilityFilter.Filter}> /// The CapabilityDelegator is a way to share one-off capabilities from the child account. These capabilities /// can be public OR private and are separate from the factory which returns a capability at a given path as a /// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a /// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot /// collection, but only to the path that the collection exists in. - pub let delegator: Capability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}> + access(self) let delegator: Capability /// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If /// this filter is not nil, any Capability returned through the `getCapability` function checks that the @@ -538,11 +542,11 @@ pub contract HybridCustody { /// ChildAccount resources have a 1:1 association with parent accounts, the named parent Address here is the /// one with a Capability on this resource. - pub let parent: Address + access(all) let parent: Address /// Returns the Address of the underlying child account /// - pub fun getAddress(): Address { + access(all) view fun getAddress(): Address { return self.childCap.address } @@ -562,13 +566,13 @@ pub contract HybridCustody { /// Sets the CapabiltyFactory.Manager Capability /// - pub fun setCapabilityFactory(cap: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>) { + access(Restricted) fun setCapabilityFactory(cap: Capability<&{CapabilityFactory.Getter}>) { self.factory = cap } /// Sets the Filter Capability as the one provided /// - pub fun setCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>) { + access(Restricted) fun setCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>) { self.filter = cap } @@ -579,7 +583,7 @@ pub contract HybridCustody { /// Capabilities, see `getPrivateCapFromDelegator()` and `getPublicCapFromDelegator()` which use the /// `Delegator` retrieval path. /// - pub fun getCapability(path: CapabilityPath, type: Type): Capability? { + access(Capabilities) view fun getCapability(controllerID: UInt64, type: Type): Capability? { let child = self.childCap.borrow() ?? panic("failed to borrow child account") let f = self.factory.borrow()!.getFactory(type) @@ -588,14 +592,15 @@ pub contract HybridCustody { } let acct = child.borrowAccount() - let cap = f!.getCapability(acct: acct, path: path) + let tmp = f!.getCapability(acct: acct, controllerID: controllerID) + if tmp == nil { + return nil + } + let cap = tmp! // Check that private capabilities are allowed by either internal or manager filter (if assigned) // If not allowed, return nil - if path.getType() == Type() && ( - self.filter.borrow()!.allowed(cap: cap) == false || - (self.getManagerCapabilityFilter()?.allowed(cap: cap) ?? true) == false - ) { + if self.filter.borrow()!.allowed(cap: cap) == false || (self.getManagerCapabilityFilter()?.allowed(cap: cap) ?? true) == false { return nil } @@ -605,7 +610,7 @@ pub contract HybridCustody { /// Retrieves a private Capability from the Delegator or nil none is found of the given type. Useful for /// arbitrary Capability retrieval /// - pub fun getPrivateCapFromDelegator(type: Type): Capability? { + access(Capabilities) view fun getPrivateCapFromDelegator(type: Type): Capability? { if let d = self.delegator.borrow() { return d.getPrivateCapability(type) } @@ -616,23 +621,25 @@ pub contract HybridCustody { /// Retrieves a public Capability from the Delegator or nil none is found of the given type. Useful for /// arbitrary Capability retrieval /// - pub fun getPublicCapFromDelegator(type: Type): Capability? { + access(all) view fun getPublicCapFromDelegator(type: Type): Capability? { if let d = self.delegator.borrow() { return d.getPublicCapability(type) } return nil } + /// TODO: This has been disabled because you cannot get a capability without providing a type T anymore in Cadence 1.0 + // /// Enables retrieval of public Capabilities of the given type from the specified path or nil if none is found. /// Callers should be aware this method uses the `CapabilityFactory` retrieval path. /// - pub fun getPublicCapability(path: PublicPath, type: Type): Capability? { - return self.getCapability(path: path, type: type) - } + // access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? { + // return self.getCapability(path: path, type: type) + // } /// Returns a reference to the stored managerCapabilityFilter if one exists /// - pub fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? { + access(all) view fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? { return self.managerCapabilityFilter != nil ? self.managerCapabilityFilter!.borrow() : nil } @@ -640,23 +647,23 @@ pub contract HybridCustody { /// access(contract) fun setRedeemed(_ addr: Address) { let acct = self.childCap.borrow()!.borrowAccount() - if let o = acct.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) { + if let o = acct.storage.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) { o.setRedeemed(addr) } } /// Returns a reference to the stored delegator, generally used for arbitrary Capability retrieval /// - pub fun borrowCapabilityDelegator(): &CapabilityDelegator.Delegator? { + access(Restricted) fun borrowCapabilityDelegator(): &CapabilityDelegator.Delegator? { let path = HybridCustody.getCapabilityDelegatorIdentifier(self.parent) - return self.childCap.borrow()!.borrowAccount().borrow<&CapabilityDelegator.Delegator>( + return self.childCap.borrow()!.borrowAccount().storage.borrow<&CapabilityDelegator.Delegator>( from: StoragePath(identifier: path)! ) } /// Returns a list of supported metadata views /// - pub fun getViews(): [Type] { + access(all) view fun getViews(): [Type] { return [ Type() ] @@ -664,17 +671,22 @@ pub contract HybridCustody { /// Resolves a view of the given type if supported /// - pub fun resolveView(_ view: Type): AnyStruct? { + access(all) fun resolveView(_ view: Type): AnyStruct? { switch view { case Type(): let childAddress = self.getAddress() - let manager = getAccount(self.parent).getCapability<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) + let tmp = getAccount(self.parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) + if tmp == nil { + return nil + } + + let manager = tmp! if !manager.check() { return nil } - return manager!.borrow()!.getChildAccountDisplay(address: childAddress) + return manager.borrow()!.getChildAccountDisplay(address: childAddress) } return nil } @@ -687,22 +699,22 @@ pub contract HybridCustody { return } - let child: &AnyResource{HybridCustody.BorrowableAccount} = self.childCap.borrow()! + let child: &{HybridCustody.BorrowableAccount} = self.childCap.borrow()! if !child.check() { return } let acct = child.borrowAccount() - if let ownedAcct = acct.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) { + if let ownedAcct = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) { ownedAcct.removeParent(parent: parent) } } init( - _ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver}>, - _ factory: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>, + _ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>, + _ factory: Capability<&{CapabilityFactory.Getter}>, _ filter: Capability<&{CapabilityFilter.Filter}>, - _ delegator: Capability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>, + _ delegator: Capability, _ parent: Address ) { pre { @@ -724,19 +736,20 @@ pub contract HybridCustody { /// Returns a capability to this child account's CapabilityFilter /// - pub fun getCapabilityFilter(): &{CapabilityFilter.Filter}? { + access(all) view fun getCapabilityFilter(): &{CapabilityFilter.Filter}? { return self.filter.check() ? self.filter.borrow() : nil } /// Returns a capability to this child account's CapabilityFactory /// - pub fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? { + access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? { return self.factory.check() ? self.factory.borrow() : nil } - destroy () { - destroy <- self.resources - } + // TODO: burnCallback and ResourceDestoryed event + // destroy () { + // destroy <- self.resources + // } } /// A resource which sits on the account it manages to make it easier for apps to configure the behavior they want @@ -748,18 +761,18 @@ pub contract HybridCustody { /// accounts would still exist, allowing a form of Hybrid Custody which has no true owner over an account, but /// shared partial ownership. /// - pub resource OwnedAccount: OwnedAccountPrivate, BorrowableAccount, OwnedAccountPublic, MetadataViews.Resolver { + access(all) resource OwnedAccount: OwnedAccountPrivate, BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver { /// Capability on the underlying account object - access(self) var acct: Capability<&AuthAccount> + access(self) var acct: Capability /// Mapping of current and pending parents, true and false respectively - pub let parents: {Address: Bool} + access(all) let parents: {Address: Bool} /// Address of the pending owner, if one exists - pub var pendingOwner: Address? + access(all) var pendingOwner: Address? /// Address of the current owner, if one exists - pub var acctOwner: Address? + access(all) var acctOwner: Address? /// Owned status of this account - pub var currentlyOwned: Bool + access(all) var currentlyOwned: Bool /// A bucket of structs so that the OwnedAccount resource can be easily extended with new functionality. access(self) let data: {String: AnyStruct} @@ -810,12 +823,12 @@ pub contract HybridCustody { /// 4. Publish the newly made private link to the designated parent's inbox for them to claim on their @Manager /// resource. /// - pub fun publishToParent( + access(Restricted) fun publishToParent( parentAddress: Address, - factory: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>, + factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> ) { - pre{ + pre { self.parents[parentAddress] == nil: "Address pending or already redeemed as parent" } let capDelegatorIdentifier = HybridCustody.getCapabilityDelegatorIdentifier(parentAddress) @@ -826,41 +839,32 @@ pub contract HybridCustody { let capDelegatorStorage = StoragePath(identifier: capDelegatorIdentifier)! let acct = self.borrowAccount() - assert(acct.borrow<&AnyResource>(from: capDelegatorStorage) == nil, message: "conflicting resource found in capability delegator storage slot for parentAddress") - assert(acct.borrow<&AnyResource>(from: childAccountStorage) == nil, message: "conflicting resource found in child account storage slot for parentAddress") + assert(acct.storage.borrow<&AnyResource>(from: capDelegatorStorage) == nil, message: "conflicting resource found in capability delegator storage slot for parentAddress") + assert(acct.storage.borrow<&AnyResource>(from: childAccountStorage) == nil, message: "conflicting resource found in child account storage slot for parentAddress") - if acct.borrow<&CapabilityDelegator.Delegator>(from: capDelegatorStorage) == nil { + if acct.storage.borrow<&CapabilityDelegator.Delegator>(from: capDelegatorStorage) == nil { let delegator <- CapabilityDelegator.createDelegator() - acct.save(<-delegator, to: capDelegatorStorage) + acct.storage.save(<-delegator, to: capDelegatorStorage) } let capDelegatorPublic = PublicPath(identifier: capDelegatorIdentifier)! - let capDelegatorPrivate = PrivatePath(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 pubCap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(capDelegatorStorage) + acct.capabilities.publish(pubCap, at: capDelegatorPublic) + + let delegator = acct.capabilities.storage.issue(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, ViewResolver.Resolver}>( + HybridCustody.OwnedAccountStoragePath ) - let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress) + 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.storage.save(<-childAcct, to: childAccountStorage) + let delegatorCap = acct.capabilities.storage.issue<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>(childAccountStorage) assert(delegatorCap.check(), message: "Delegator capability check failed") acct.inbox.publish(delegatorCap, name: identifier, recipient: parentAddress) @@ -880,38 +884,38 @@ pub contract HybridCustody { /// Checks the validity of the encapsulated account Capability /// - pub fun check(): Bool { + access(all) view fun check(): Bool { return self.acct.check() } /// Returns a reference to the encapsulated account object /// - pub fun borrowAccount(): &AuthAccount { + access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account { return self.acct.borrow()! } /// Returns the addresses of all associated parents pending and active /// - pub fun getParentAddresses(): [Address] { + access(all) view fun getParentAddresses(): [Address] { return self.parents.keys } /// Returns whether the given address is a parent of this account /// - pub fun isChildOf(_ addr: Address): Bool { + access(all) view fun isChildOf(_ addr: Address): Bool { return self.parents[addr] != nil } /// Returns nil if the given address is not a parent, false if the parent has not redeemed the child account /// yet, and true if they have /// - pub fun getRedeemedStatus(addr: Address): Bool? { + access(all) view fun getRedeemedStatus(addr: Address): Bool? { return self.parents[addr] } /// Returns associated parent addresses and their redeemed status /// - pub fun getParentStatuses(): {Address: Bool} { + access(all) view fun getParentStatuses(): {Address: Bool} { return self.parents } @@ -919,7 +923,7 @@ pub contract HybridCustody { /// configured for the provided parent address. Once done, the parent will not have any valid capabilities with /// which to access the child account. /// - pub fun removeParent(parent: Address): Bool { + access(Restricted) fun removeParent(parent: Address): Bool { if self.parents[parent] == nil { return false } @@ -927,21 +931,28 @@ 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)!) + // get all controllers which target this storage path + let storagePath = StoragePath(identifier: identifier)! + let childAccountControllers = acct.capabilities.storage.getControllers(forPath: storagePath) + for c in childAccountControllers { + c.delete() + } + destroy <- acct.storage.load<@AnyResource>(from: storagePath) - destroy <- acct.load<@AnyResource>(from: StoragePath(identifier: identifier)!) - destroy <- acct.load<@AnyResource>(from: StoragePath(identifier: capDelegatorIdentifier)!) + let delegatorStoragePath = StoragePath(identifier: capDelegatorIdentifier)! + let delegatorControllers = acct.capabilities.storage.getControllers(forPath: delegatorStoragePath) + for c in delegatorControllers { + c.delete() + } + destroy <- acct.storage.load<@AnyResource>(from: delegatorStoragePath) 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<&{ManagerPublic}>(HybridCustody.ManagerPublicPath) + if parentManager?.check() == true { + parentManager!.borrow()?.removeParentCallback(child: self.owner!.address) } return true @@ -949,21 +960,21 @@ pub contract HybridCustody { /// Returns the address of the encapsulated account /// - pub fun getAddress(): Address { + access(all) view fun getAddress(): Address { return self.acct.address } /// Returns the address of the pending owner if one is assigned. Pending owners are assigned when ownership has /// been granted, but has not yet been redeemed. /// - pub fun getPendingOwner(): Address? { + access(all) view fun getPendingOwner(): Address? { return self.pendingOwner } /// Returns the address of the current owner if one is assigned. Current owners are assigned when ownership has /// been redeemed. /// - pub fun getOwner(): Address? { + access(all) view fun getOwner(): Address? { if !self.currentlyOwned { return nil } @@ -979,23 +990,19 @@ pub contract HybridCustody { /// mechanism intended to easily transfer 'root' access on this account to another account and an attempt to /// minimize access vectors. /// - pub fun giveOwnership(to: Address) { + access(Owner) fun giveOwnership(to: Address) { self.seal() let acct = self.borrowAccount() // Unlink existing owner's Capability if owner exists if self.acctOwner != nil { - acct.unlink( - PrivatePath(identifier: HybridCustody.getOwnerIdentifier(self.acctOwner!))! - ) + acct.capabilities.account.getController(byCapabilityID: self.acct.id)?.delete() } + + // 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, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) acct.inbox.publish(cap, name: identifier, recipient: to) self.pendingOwner = to @@ -1006,7 +1013,7 @@ pub contract HybridCustody { /// Revokes all keys on the underlying account /// - pub fun revokeAllKeys() { + access(Owner) fun revokeAllKeys() { let acct = self.borrowAccount() // Revoke all keys @@ -1025,35 +1032,26 @@ pub contract HybridCustody { /// assumes ownership of an account to guarantee that the previous owner doesn't maintain admin access to the /// account via other AuthAccount Capabilities. /// - pub fun rotateAuthAccount() { + access(Owner) fun rotateAuthAccount() { let acct = self.borrowAccount() // Find all active AuthAccount capabilities so they can be removed after we make the new auth account cap - let pathsToUnlink: [PrivatePath] = [] - acct.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { - if type.identifier == "Capability<&AuthAccount>" { - pathsToUnlink.append(path) - } + let idsToDestroy: [UInt64] = [] + acct.capabilities.account.forEachController(fun(con: &AccountCapabilityController): Bool { + idsToDestroy.append(con.capabilityID) return true }) // 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 - // 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()) - .concat(unsafeRandom().toString()) // ensure that the path is different from the previous one - let acctCap = acct.linkAccount(PrivatePath(identifier: authAcctPath)!)! + let acctCap = acct.capabilities.account.issue() 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 - for p in pathsToUnlink { - newAcct.unlink(p) + for id in idsToDestroy { + newAcct.capabilities.account.getController(byCapabilityID: id)?.delete() } } @@ -1064,7 +1062,7 @@ pub contract HybridCustody { /// /// USE WITH EXTREME CAUTION. /// - pub fun seal() { + access(Owner) fun seal() { self.rotateAuthAccount() self.revokeAllKeys() // There needs to be a path to giving ownership that doesn't revoke keys emit AccountSealed(id: self.uuid, address: self.acct.address, parents: self.parents.keys) @@ -1073,16 +1071,16 @@ pub contract HybridCustody { /// Retrieves a reference to the ChildAccount associated with the given parent account if one exists. /// - pub fun borrowChildAccount(parent: Address): &ChildAccount? { + access(Restricted) fun borrowChildAccount(parent: Address): auth(Restricted) &ChildAccount? { let identifier = HybridCustody.getChildAccountIdentifier(parent) - return self.borrowAccount().borrow<&ChildAccount>(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Sets the CapabilityFactory Manager for the specified parent in the associated ChildAccount. /// - pub fun setCapabilityFactoryForParent( + access(Restricted) fun setCapabilityFactoryForParent( parent: Address, - cap: Capability<&CapabilityFactory.Manager{CapabilityFactory.Getter}> + cap: Capability<&{CapabilityFactory.Getter}> ) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") p.setCapabilityFactory(cap: cap) @@ -1090,21 +1088,21 @@ pub contract HybridCustody { /// Sets the Filter for the specified parent in the associated ChildAccount. /// - pub fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { + access(Restricted) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") p.setCapabilityFilter(cap: cap) } /// Retrieves a reference to the Delegator associated with the given parent account if one exists. /// - pub fun borrowCapabilityDelegatorForParent(parent: Address): &CapabilityDelegator.Delegator? { + access(Restricted) fun borrowCapabilityDelegatorForParent(parent: Address): auth(Mutate) &CapabilityDelegator.Delegator? { let identifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) - return self.borrowAccount().borrow<&CapabilityDelegator.Delegator>(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Adds the provided Capability to the Delegator associated with the given parent account. /// - pub fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { + access(Restricted) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") let delegator = self.borrowCapabilityDelegatorForParent(parent: parent) ?? panic("could not borrow capability delegator resource for parent address") @@ -1113,20 +1111,20 @@ pub contract HybridCustody { /// Removes the provided Capability from the Delegator associated with the given parent account. /// - pub fun removeCapabilityFromDelegator(parent: Address, cap: Capability) { + access(Restricted) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") let delegator = self.borrowCapabilityDelegatorForParent(parent: parent) ?? panic("could not borrow capability delegator resource for parent address") delegator.removeCapability(cap: cap) } - pub fun getViews(): [Type] { + access(all) view fun getViews(): [Type] { return [ Type() ] } - pub fun resolveView(_ view: Type): AnyStruct? { + access(all) fun resolveView(_ view: Type): AnyStruct? { switch view { case Type(): return self.display @@ -1136,12 +1134,12 @@ pub contract HybridCustody { /// Sets this OwnedAccount's display to the one provided /// - pub fun setDisplay(_ d: MetadataViews.Display) { + access(Restricted) fun setDisplay(_ d: MetadataViews.Display) { self.display = d } init( - _ acct: Capability<&AuthAccount> + _ acct: Capability ) { self.acct = acct @@ -1155,36 +1153,37 @@ pub contract HybridCustody { self.display = nil } - destroy () { - destroy <- self.resources - } + // TODO: Use the burner interface + // destroy () { + // destroy <- self.resources + // } } /// Utility function to get the path identifier for a parent address when interacting with a ChildAccount and its /// parents /// - pub fun getChildAccountIdentifier(_ addr: Address): String { + access(all) view fun getChildAccountIdentifier(_ addr: Address): String { return "ChildAccount_".concat(addr.toString()) } /// Utility function to get the path identifier for a parent address when interacting with a Delegator and its /// parents /// - pub fun getCapabilityDelegatorIdentifier(_ addr: Address): String { + access(all) view fun getCapabilityDelegatorIdentifier(_ addr: Address): String { return "ChildCapabilityDelegator_".concat(addr.toString()) } /// Utility function to get the path identifier for a parent address when interacting with an OwnedAccount and its /// owners /// - pub fun getOwnerIdentifier(_ addr: Address): String { + access(all) view fun getOwnerIdentifier(_ addr: Address): String { return "HybridCustodyOwnedAccount_".concat(HybridCustody.account.address.toString()).concat(addr.toString()) } /// Returns an OwnedAccount wrapping the provided AuthAccount Capability. /// - pub fun createOwnedAccount( - acct: Capability<&AuthAccount> + access(all) fun createOwnedAccount( + acct: Capability ): @OwnedAccount { pre { acct.check(): "invalid auth account capability" @@ -1197,7 +1196,7 @@ pub contract HybridCustody { /// Returns a new Manager with the provided Filter as default (if not nil). /// - pub fun createManager(filter: Capability<&{CapabilityFilter.Filter}>?): @Manager { + access(all) fun createManager(filter: Capability<&{CapabilityFilter.Filter}>?): @Manager { pre { filter == nil || filter!.check(): "Invalid CapabilityFilter Filter capability provided" } From dd03073abb2ad47d73ed58744f216f06d04be241 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 1 Apr 2024 08:59:41 -0700 Subject: [PATCH 03/34] split entitlements up --- contracts/HybridCustody.cdc | 67 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 6ff01b6..b0a8f61 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -30,8 +30,9 @@ import "CapabilityFilter" /// access(all) contract HybridCustody { - access(all) entitlement Restricted access(all) entitlement Owner + access(all) entitlement Publish + access(all) entitlement Manage /* --- Canonical Paths --- */ // @@ -108,13 +109,13 @@ access(all) contract HybridCustody { access(all) resource interface OwnedAccountPrivate { /// Deletes the ChildAccount resource being used to share access to this OwnedAccount with the supplied parent /// address, and unlinks the paths it was using to reach the underlying account. - access(Restricted) fun removeParent(parent: Address): Bool + access(Owner | Remove) fun removeParent(parent: Address): Bool /// Sets up a new ChildAccount resource for the given parentAddress to redeem. This child account uses the /// supplied factory and filter to manage what can be obtained from the child account, and a new /// CapabilityDelegator resource is created for the sharing of one-off capabilities. Each of these pieces of /// access control are managed through the child account. - access(Restricted) fun publishToParent( + access(Publish | Owner) fun publishToParent( parentAddress: Address, factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> @@ -141,7 +142,7 @@ access(all) contract HybridCustody { // setCapabilityFactoryForParent // Override the existing CapabilityFactory Capability for a given parent. This will allow the owner of the // account to start managing their own factory of capabilities to be able to retrieve - access(Restricted) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&{CapabilityFactory.Getter}>) { + access(Owner) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&{CapabilityFactory.Getter}>) { pre { cap.check(): "Invalid CapabilityFactory.Getter Capability provided" } @@ -149,7 +150,7 @@ access(all) contract HybridCustody { /// Override the existing CapabilityFilter Capability for a given parent. This will allow the owner of the /// account to start managing their own filter for retrieving Capabilities on Private Paths - access(Restricted) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { + access(Owner) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { pre { cap.check(): "Invalid CapabilityFilter Capability provided" } @@ -157,14 +158,14 @@ access(all) contract HybridCustody { /// Adds a capability to a parent's managed @ChildAccount resource. The Capability can be made public, /// permitting anyone to borrow it. - access(Restricted) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { + access(Owner) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } } /// Removes a Capability from the CapabilityDelegator used by the specified parent address - access(Restricted) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) + access(Owner) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) /// Returns the address of this OwnedAccount access(all) view fun getAddress(): Address @@ -235,13 +236,13 @@ access(all) contract HybridCustody { /// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts /// access(all) resource interface ManagerPrivate { - access(Restricted) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) - access(Restricted) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? - access(Restricted) fun removeChild(addr: Address) - access(Owner) fun addOwnedAccount(cap: Capability) - access(Restricted) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? - access(Restricted) fun removeOwned(addr: Address) - access(Restricted) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) + access(Manage) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? + access(Manage) fun removeChild(addr: Address) + access(Manage) fun addOwnedAccount(cap: Capability) + access(Manage) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? + access(Manage) fun removeOwned(addr: Address) + access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { pre { cap == nil || cap!.check(): "Invalid Manager Capability Filter" } @@ -298,7 +299,7 @@ access(all) contract HybridCustody { /// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be /// added to the ChildAccount /// - access(Restricted) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) { + access(Manage) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) { pre { self.childAccounts[cap.address] == nil: "There is already a child account with this address" } @@ -316,7 +317,7 @@ access(all) contract HybridCustody { /// Sets the default Filter Capability for this Manager. Does not propagate to child accounts. /// - access(Restricted) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { + access(Manage) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { pre { cap == nil || cap!.check(): "supplied capability must be nil or check must pass" } @@ -326,7 +327,7 @@ access(all) contract HybridCustody { /// Sets the Filter Capability for this Manager, propagating to the specified child account /// - access(Restricted) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { let acct = self.borrowAccount(addr: childAddress) ?? panic("child account not found") @@ -336,7 +337,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Restricted) fun removeChild(addr: Address) { + access(Manage) fun removeChild(addr: Address) { let cap = self.childAccounts.remove(key: addr) ?? panic("child account not found") @@ -368,7 +369,7 @@ access(all) contract HybridCustody { /// Adds an owned account to the Manager's list of owned accounts, setting the Manager account as the owner of /// the given account /// - access(Owner) fun addOwnedAccount(cap: Capability) { + access(Manage) fun addOwnedAccount(cap: Capability) { pre { self.ownedAccounts[cap.address] == nil: "There is already an owned account with this address" } @@ -389,7 +390,7 @@ access(all) contract HybridCustody { /// Returns a reference to a child account /// - access(Restricted) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? { + access(Manage) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? { let cap = self.childAccounts[addr] if cap == nil { return nil @@ -411,7 +412,7 @@ access(all) contract HybridCustody { /// Returns a reference to an owned account /// - access(Restricted) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { + access(Manage) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { if let cap = self.ownedAccounts[addr] { return cap.borrow() } @@ -422,7 +423,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Restricted) fun removeOwned(addr: Address) { + access(Manage) fun removeOwned(addr: Address) { if let acct = self.ownedAccounts.remove(key: addr) { if acct.check() { acct.borrow()!.seal() @@ -566,13 +567,13 @@ access(all) contract HybridCustody { /// Sets the CapabiltyFactory.Manager Capability /// - access(Restricted) fun setCapabilityFactory(cap: Capability<&{CapabilityFactory.Getter}>) { + access(contract) fun setCapabilityFactory(cap: Capability<&{CapabilityFactory.Getter}>) { self.factory = cap } /// Sets the Filter Capability as the one provided /// - access(Restricted) fun setCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>) { + access(contract) fun setCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>) { self.filter = cap } @@ -705,7 +706,7 @@ access(all) contract HybridCustody { } let acct = child.borrowAccount() - if let ownedAcct = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) { + if let ownedAcct = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) { ownedAcct.removeParent(parent: parent) } } @@ -823,7 +824,7 @@ access(all) contract HybridCustody { /// 4. Publish the newly made private link to the designated parent's inbox for them to claim on their @Manager /// resource. /// - access(Restricted) fun publishToParent( + access(Publish | Owner) fun publishToParent( parentAddress: Address, factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> @@ -923,7 +924,7 @@ access(all) contract HybridCustody { /// configured for the provided parent address. Once done, the parent will not have any valid capabilities with /// which to access the child account. /// - access(Restricted) fun removeParent(parent: Address): Bool { + access(Owner | Remove) fun removeParent(parent: Address): Bool { if self.parents[parent] == nil { return false } @@ -1071,14 +1072,14 @@ access(all) contract HybridCustody { /// Retrieves a reference to the ChildAccount associated with the given parent account if one exists. /// - access(Restricted) fun borrowChildAccount(parent: Address): auth(Restricted) &ChildAccount? { + access(Owner) fun borrowChildAccount(parent: Address): auth(Restricted) &ChildAccount? { let identifier = HybridCustody.getChildAccountIdentifier(parent) return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Sets the CapabilityFactory Manager for the specified parent in the associated ChildAccount. /// - access(Restricted) fun setCapabilityFactoryForParent( + access(Owner) fun setCapabilityFactoryForParent( parent: Address, cap: Capability<&{CapabilityFactory.Getter}> ) { @@ -1088,21 +1089,21 @@ access(all) contract HybridCustody { /// Sets the Filter for the specified parent in the associated ChildAccount. /// - access(Restricted) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { + access(Owner) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") p.setCapabilityFilter(cap: cap) } /// Retrieves a reference to the Delegator associated with the given parent account if one exists. /// - access(Restricted) fun borrowCapabilityDelegatorForParent(parent: Address): auth(Mutate) &CapabilityDelegator.Delegator? { + access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(Mutate) &CapabilityDelegator.Delegator? { let identifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Adds the provided Capability to the Delegator associated with the given parent account. /// - access(Restricted) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { + access(Owner) fun addCapabilityToDelegator(parent: Address, cap: Capability, isPublic: Bool) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") let delegator = self.borrowCapabilityDelegatorForParent(parent: parent) ?? panic("could not borrow capability delegator resource for parent address") @@ -1111,7 +1112,7 @@ access(all) contract HybridCustody { /// Removes the provided Capability from the Delegator associated with the given parent account. /// - access(Restricted) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) { + access(Owner) fun removeCapabilityFromDelegator(parent: Address, cap: Capability) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") let delegator = self.borrowCapabilityDelegatorForParent(parent: parent) ?? panic("could not borrow capability delegator resource for parent address") From ec07d6d45c0e3a610eecb5ce56b5f53d69107330 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 1 Apr 2024 10:44:15 -0700 Subject: [PATCH 04/34] remove placeholder entitlement --- contracts/HybridCustody.cdc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index b0a8f61..6f5c689 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -283,7 +283,7 @@ access(all) contract HybridCustody { /// Sets the Display on the ChildAccount. If nil, the display is removed. /// - access(Restricted) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { + access(Manage) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { pre { self.childAccounts[address] != nil: "There is no child account with this address" } @@ -655,9 +655,9 @@ access(all) contract HybridCustody { /// Returns a reference to the stored delegator, generally used for arbitrary Capability retrieval /// - access(Restricted) fun borrowCapabilityDelegator(): &CapabilityDelegator.Delegator? { + access(Owner) fun borrowCapabilityDelegator(): auth(Capabilities) &CapabilityDelegator.Delegator? { let path = HybridCustody.getCapabilityDelegatorIdentifier(self.parent) - return self.childCap.borrow()!.borrowAccount().storage.borrow<&CapabilityDelegator.Delegator>( + return self.childCap.borrow()!.borrowAccount().storage.borrow( from: StoragePath(identifier: path)! ) } @@ -1072,9 +1072,9 @@ access(all) contract HybridCustody { /// Retrieves a reference to the ChildAccount associated with the given parent account if one exists. /// - access(Owner) fun borrowChildAccount(parent: Address): auth(Restricted) &ChildAccount? { + access(Owner) fun borrowChildAccount(parent: Address): auth(Capabilities) &ChildAccount? { let identifier = HybridCustody.getChildAccountIdentifier(parent) - return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Sets the CapabilityFactory Manager for the specified parent in the associated ChildAccount. @@ -1135,7 +1135,7 @@ access(all) contract HybridCustody { /// Sets this OwnedAccount's display to the one provided /// - access(Restricted) fun setDisplay(_ d: MetadataViews.Display) { + access(Owner) fun setDisplay(_ d: MetadataViews.Display) { self.display = d } From 2bff3f38f2e8436ead56b1b2007218d522dd97a9 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 1 Apr 2024 10:49:48 -0700 Subject: [PATCH 05/34] move public capability retrieval to the CapabilityFactory --- contracts/CapabilityFactory.cdc | 1 + contracts/HybridCustody.cdc | 18 ++++++++++++------ contracts/factories/FTAllFactory.cdc | 4 ++++ contracts/factories/FTBalanceFactory.cdc | 4 ++++ contracts/factories/FTProviderFactory.cdc | 4 ++++ .../factories/FTReceiverBalanceFactory.cdc | 4 ++++ contracts/factories/FTReceiverFactory.cdc | 4 ++++ .../factories/NFTCollectionPublicFactory.cdc | 4 ++++ .../NFTProviderAndCollectionFactory.cdc | 4 ++++ contracts/factories/NFTProviderFactory.cdc | 4 ++++ 10 files changed, 45 insertions(+), 6 deletions(-) diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index 15b993b..e986e2b 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -23,6 +23,7 @@ access(all) contract CapabilityFactory { /// access(all) struct interface Factory { access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): 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 6f5c689..4aa1d4b 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -201,7 +201,7 @@ access(all) contract HybridCustody { /// access(all) resource interface AccountPublic { // TODO: This has been disabled because you cannot get a capability without providing a type T anymore in Cadence 1.0 - // access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? + access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? access(all) view fun getPublicCapFromDelegator(type: Type): Capability? access(all) view fun getAddress(): Address access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? @@ -629,14 +629,20 @@ access(all) contract HybridCustody { return nil } - /// TODO: This has been disabled because you cannot get a capability without providing a type T anymore in Cadence 1.0 - // /// Enables retrieval of public Capabilities of the given type from the specified path or nil if none is found. /// Callers should be aware this method uses the `CapabilityFactory` retrieval path. /// - // access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? { - // return self.getCapability(path: path, type: type) - // } + access(all) view fun getPublicCapability(path: PublicPath, 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() + return f!.getPublicCapability(acct: acct, path: path) + } /// Returns a reference to the stored managerCapabilityFilter if one exists /// diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index 57166a1..db4ee1e 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -14,5 +14,9 @@ access(all) contract FTAllFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return nil + } } } \ No newline at end of file diff --git a/contracts/factories/FTBalanceFactory.cdc b/contracts/factories/FTBalanceFactory.cdc index dae94d1..7d96926 100644 --- a/contracts/factories/FTBalanceFactory.cdc +++ b/contracts/factories/FTBalanceFactory.cdc @@ -14,5 +14,9 @@ access(all) contract FTBalanceFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return acct.capabilities.get<&{FungibleToken.Balance}>(path) + } } } \ No newline at end of file diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index b60d64c..880ca0a 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -14,5 +14,9 @@ access(all) contract FTProviderFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return nil + } } } \ No newline at end of file diff --git a/contracts/factories/FTReceiverBalanceFactory.cdc b/contracts/factories/FTReceiverBalanceFactory.cdc index f0f016d..067eaa4 100644 --- a/contracts/factories/FTReceiverBalanceFactory.cdc +++ b/contracts/factories/FTReceiverBalanceFactory.cdc @@ -14,5 +14,9 @@ access(all) contract FTReceiverBalanceFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return acct.capabilities.get<&{FungibleToken.Receiver, FungibleToken.Balance}>(path) + } } } \ No newline at end of file diff --git a/contracts/factories/FTReceiverFactory.cdc b/contracts/factories/FTReceiverFactory.cdc index a0d3ded..c1e9a59 100644 --- a/contracts/factories/FTReceiverFactory.cdc +++ b/contracts/factories/FTReceiverFactory.cdc @@ -14,5 +14,9 @@ access(all) contract FTReceiverFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return acct.capabilities.get<&{FungibleToken.Receiver}>(path) + } } } \ No newline at end of file diff --git a/contracts/factories/NFTCollectionPublicFactory.cdc b/contracts/factories/NFTCollectionPublicFactory.cdc index e0ab607..5902360 100644 --- a/contracts/factories/NFTCollectionPublicFactory.cdc +++ b/contracts/factories/NFTCollectionPublicFactory.cdc @@ -14,5 +14,9 @@ access(all) contract NFTCollectionPublicFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return acct.capabilities.get<&{NonFungibleToken.CollectionPublic}>(path) + } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index cf06f97..028adf4 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -14,5 +14,9 @@ access(all) contract NFTProviderAndCollectionFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return nil + } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index 7322b89..48d07b6 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -14,5 +14,9 @@ access(all) contract NFTProviderFactory { return nil } + + access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + return nil + } } } \ No newline at end of file From 58b081f73633af2a889bedb3fd376222892e8953 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 1 Apr 2024 11:24:16 -0700 Subject: [PATCH 06/34] fix CapabilityDelegator tests --- contracts/standard/ExampleNFT.cdc | 376 ++++++++++++++++++ flow.json | 2 +- scripts/delegator/find_nft_collection_cap.cdc | 6 +- scripts/delegator/find_nft_provider_cap.cdc | 8 +- scripts/delegator/get_all_private_caps.cdc | 6 +- scripts/delegator/get_all_public_caps.cdc | 6 +- scripts/delegator/get_nft_collection.cdc | 8 +- scripts/delegator/get_nft_provider.cdc | 10 +- scripts/example-nft/mint_to_account.cdc | 13 +- test/CapabilityDelegator_tests.cdc | 70 ++-- test/CapabilityFactory_tests.cdc | 4 +- test/HybridCustody_tests.cdc | 64 +-- test/test_helpers.cdc | 2 +- .../delegator/add_private_nft_collection.cdc | 8 +- .../delegator/add_public_nft_collection.cdc | 6 +- .../remove_private_nft_collection.cdc | 10 +- .../remove_public_nft_collection.cdc | 6 +- transactions/delegator/setup.cdc | 13 +- .../example-nft-2/mint_to_account.cdc | 10 +- transactions/example-nft/mint_to_account.cdc | 10 +- transactions/example-nft/setup_full.cdc | 18 +- 21 files changed, 517 insertions(+), 139 deletions(-) create mode 100644 contracts/standard/ExampleNFT.cdc diff --git a/contracts/standard/ExampleNFT.cdc b/contracts/standard/ExampleNFT.cdc new file mode 100644 index 0000000..60e1d77 --- /dev/null +++ b/contracts/standard/ExampleNFT.cdc @@ -0,0 +1,376 @@ +/* +* +* This is an example implementation of a Flow Non-Fungible Token +* It is not part of the official standard but it assumed to be +* similar to how many NFTs would implement the core functionality. +* +* This contract does not implement any sophisticated classification +* system for its NFTs. It defines a simple NFT with minimal metadata. +* +*/ + +import "NonFungibleToken" +import "MetadataViews" +import "ViewResolver" +import "FungibleToken" + +access(all) contract ExampleNFT: ViewResolver { + + access(all) var totalSupply: UInt64 + + access(all) event ContractInitialized() + access(all) event Withdraw(id: UInt64, from: Address?) + access(all) event Deposit(id: UInt64, to: Address?) + + access(all) event CollectionCreated(id: UInt64) + access(all) event CollectionDestroyed(id: UInt64) + + access(all) let CollectionStoragePath: StoragePath + access(all) let CollectionPublicPath: PublicPath + access(all) let MinterStoragePath: StoragePath + access(all) let MinterPublicPath: PublicPath + + access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver { + access(all) let id: UInt64 + + access(all) let name: String + access(all) let description: String + access(all) let thumbnail: String + access(self) let royalties: [MetadataViews.Royalty] + + init( + id: UInt64, + name: String, + description: String, + thumbnail: String, + royalties: [MetadataViews.Royalty] + ) { + self.id = id + self.name = name + self.description = description + self.thumbnail = thumbnail + self.royalties = royalties + } + + access(all) view fun getViews(): [Type] { + return [ + Type(), + Type(), + Type(), + Type(), + Type(), + Type(), + Type() + ] + } + + access(all) view fun resolveView(_ view: Type): AnyStruct? { + switch view { + case Type(): + return MetadataViews.Display( + name: self.name, + description: self.description, + thumbnail: MetadataViews.HTTPFile( + url: self.thumbnail + ) + ) + case Type(): + // There is no max number of NFTs that can be minted from this contract + // so the max edition field value is set to nil + let editionInfo = MetadataViews.Edition(name: "Example NFT Edition", number: self.id, max: nil) + let editionList: [MetadataViews.Edition] = [editionInfo] + return MetadataViews.Editions( + editionList + ) + case Type(): + return MetadataViews.Serial( + self.id + ) + case Type(): + return MetadataViews.Royalties( + self.royalties + ) + case Type(): + return MetadataViews.ExternalURL("https://example-nft.onflow.org/".concat(self.id.toString())) + case Type(): + return MetadataViews.NFTCollectionData( + storagePath: ExampleNFT.CollectionStoragePath, + publicPath: ExampleNFT.CollectionPublicPath, + publicCollection: Type<&ExampleNFT.Collection>(), + publicLinkedType: Type<&ExampleNFT.Collection>(), + createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} { + return <-ExampleNFT.createEmptyCollection() + }) + ) + case Type(): + let media = MetadataViews.Media( + file: MetadataViews.HTTPFile( + url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg" + ), + mediaType: "image/svg+xml" + ) + return MetadataViews.NFTCollectionDisplay( + name: "The Example Collection", + description: "This collection is used as an example to help you develop your next Flow NFT.", + externalURL: MetadataViews.ExternalURL("https://example-nft.onflow.org"), + squareImage: media, + bannerImage: media, + socials: { + "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") + } + ) + } + return nil + } + + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- ExampleNFT.createEmptyCollection() + } + } + + access(all) resource interface ExampleNFTCollectionPublic: NonFungibleToken.Collection { + access(all) fun deposit(token: @{NonFungibleToken.NFT}) + access(all) fun borrowExampleNFT(id: UInt64): &ExampleNFT.NFT? { + post { + (result == nil) || (result?.id == id): + "Cannot borrow ExampleNFT reference: the ID of the returned reference is incorrect" + } + } + } + + access(all) resource Collection: ExampleNFTCollectionPublic { + access(all) event ResourceDestroyed(id: UInt64 = self.uuid) + + // dictionary of NFT conforming tokens + // NFT is a resource type with an `UInt64` ID field + access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}} + + init () { + self.ownedNFTs <- {} + emit CollectionCreated(id: self.uuid) + } + + access(all) view fun getLength(): Int { + return self.ownedNFTs.length + } + + // withdraw removes an NFT from the collection and moves it to the caller + access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { + let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") + + emit Withdraw(id: token.id, from: self.owner?.address) + + return <-token + } + + // deposit takes a NFT and adds it to the collections dictionary + // and adds the ID to the id array + access(all) fun deposit(token: @{NonFungibleToken.NFT}) { + let token <- token as! @ExampleNFT.NFT + + let id: UInt64 = token.id + + // add the new token to the dictionary which removes the old one + let oldToken <- self.ownedNFTs[id] <- token + + emit Deposit(id: id, to: self.owner?.address) + + destroy oldToken + } + + // getIDs returns an array of the IDs that are in the collection + access(all) view fun getIDs(): [UInt64] { + return self.ownedNFTs.keys + } + + // borrowNFT gets a reference to an NFT in the collection + // so that the caller can read its metadata and call its methods + access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { + return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)! + } + + access(all) fun borrowExampleNFT(id: UInt64): &ExampleNFT.NFT? { + if self.ownedNFTs[id] != nil { + // Create an authorized reference to allow downcasting + let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)! + return ref as! &ExampleNFT.NFT + } + + return nil + } + + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- create Collection() + } + + access(all) view fun getSupportedNFTTypes(): {Type: Bool} { + return { + Type<@ExampleNFT.NFT>(): true + } + } + + access(all) view fun isSupportedNFTType(type: Type): Bool { + return type == Type<@ExampleNFT.NFT>() + } + } + + // public function that anyone can call to create a new empty collection + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- create Collection() + } + + // Resource that an admin or something similar would own to be + // able to mint new NFTs + // + access(all) resource NFTMinter { + + // mintNFT mints a new NFT with a new ID + // and deposit it in the recipients collection using their collection reference + access(all) fun mintNFT( + recipient: &{NonFungibleToken.CollectionPublic}, + name: String, + description: String, + thumbnail: String, + royaltyReceipient: Address, + ) { + ExampleNFT.totalSupply = ExampleNFT.totalSupply + 1 + self.mintNFTWithId(recipient: recipient, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: royaltyReceipient, id: ExampleNFT.totalSupply) + } + + access(all) fun mintNFTWithId( + recipient: &{NonFungibleToken.CollectionPublic}, + name: String, + description: String, + thumbnail: String, + royaltyReceipient: Address, + id: UInt64 + ) { + let royaltyRecipient = getAccount(royaltyReceipient).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)! + let cutInfo = MetadataViews.Royalty(receiver: royaltyRecipient, cut: 0.05, description: "") + // create a new NFT + var newNFT <- create NFT( + id: id, + name: name, + description: description, + thumbnail: thumbnail, + royalties: [cutInfo] + ) + + // deposit it in the recipient's account using their reference + recipient.deposit(token: <-newNFT) + } + + // mintNFT mints a new NFT with a new ID + // and deposit it in the recipients collection using their collection reference + access(all) fun mintNFTWithRoyaltyCuts( + recipient: &{NonFungibleToken.CollectionPublic}, + name: String, + description: String, + thumbnail: String, + royaltyReceipients: [Address], + royaltyCuts: [UFix64] + ) { + assert(royaltyReceipients.length == royaltyCuts.length, message: "mismatched royalty recipients and cuts") + let royalties: [MetadataViews.Royalty] = [] + + var index = 0 + while index < royaltyReceipients.length { + let royaltyRecipient = getAccount(royaltyReceipients[index]).capabilities.get<&{FungibleToken.Receiver}>(/public/placeholder)! + let cutInfo = MetadataViews.Royalty(receiver: royaltyRecipient, cut: royaltyCuts[index], description: "") + royalties.append(cutInfo) + index = index + 1 + } + + ExampleNFT.totalSupply = ExampleNFT.totalSupply + 1 + + // create a new NFT + var newNFT <- create NFT( + id: ExampleNFT.totalSupply, + name: name, + description: description, + thumbnail: thumbnail, + royalties: royalties + ) + + // deposit it in the recipient's account using their reference + recipient.deposit(token: <-newNFT) + } + } + + /// Function that resolves a metadata view for this contract. + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? { + switch viewType { + case Type(): + return MetadataViews.NFTCollectionData( + storagePath: ExampleNFT.CollectionStoragePath, + publicPath: ExampleNFT.CollectionPublicPath, + publicCollection: Type<&ExampleNFT.Collection>(), + publicLinkedType: Type<&ExampleNFT.Collection>(), + createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} { + return <-ExampleNFT.createEmptyCollection() + }) + ) + case Type(): + let media = MetadataViews.Media( + file: MetadataViews.HTTPFile( + url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg" + ), + mediaType: "image/svg+xml" + ) + return MetadataViews.NFTCollectionDisplay( + name: "The Example Collection", + description: "This collection is used as an example to help you develop your next Flow NFT.", + externalURL: MetadataViews.ExternalURL("https://example-nft.onflow.org"), + squareImage: media, + bannerImage: media, + socials: { + "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") + } + ) + } + return nil + } + + /// Function that returns all the Metadata Views implemented by a Non Fungible Token + /// + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getContractViews(resourceType: Type?): [Type] { + return [ + Type(), + Type() + ] + } + + init() { + // Initialize the total supply + self.totalSupply = 0 + + // Set the named paths + self.CollectionStoragePath = /storage/exampleNFTCollection + self.CollectionPublicPath = /public/exampleNFTCollection + self.MinterStoragePath = /storage/exampleNFTMinter + self.MinterPublicPath = /public/exampleNFTMinter + + // Create a Collection resource and save it to storage + let collection <- create Collection() + self.account.storage.save(<-collection, to: self.CollectionStoragePath) + let cap = self.account.capabilities.storage.issue<&ExampleNFT.Collection>(self.CollectionStoragePath) + self.account.capabilities.publish(cap, at: self.CollectionPublicPath) + + + // Create a Minter resource and save it to storage + let minter <- create NFTMinter() + self.account.storage.save(<-minter, to: self.MinterStoragePath) + + let minterCap = self.account.capabilities.storage.issue<&ExampleNFT.NFTMinter>(self.MinterStoragePath) + + emit ContractInitialized() + } +} + \ No newline at end of file diff --git a/flow.json b/flow.json index 02ccfe9..b062ee8 100644 --- a/flow.json +++ b/flow.json @@ -28,7 +28,7 @@ } }, "ExampleNFT": { - "source": "./modules/flow-nft/contracts/ExampleNFT.cdc", + "source": "./contracts/standard/ExampleNFT.cdc", "aliases": { "testing": "0000000000000007" } diff --git a/scripts/delegator/find_nft_collection_cap.cdc b/scripts/delegator/find_nft_collection_cap.cdc index f5ef04f..d184236 100644 --- a/scripts/delegator/find_nft_collection_cap.cdc +++ b/scripts/delegator/find_nft_collection_cap.cdc @@ -3,14 +3,14 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(addr: Address): Bool { +access(all) fun main(addr: Address): Bool { let acct = getAccount(addr) let delegator = - acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath).borrow() + acct.capabilities.get<&{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath)!.borrow() ?? panic("could not borrow delegator") - let desiredType = Type>() + let desiredType = Type>() let foundType = delegator.findFirstPublicType(desiredType) ?? panic("no type found") let nakedCap = delegator.getPublicCapability(foundType) ?? panic("requested capability type was not found") diff --git a/scripts/delegator/find_nft_provider_cap.cdc b/scripts/delegator/find_nft_provider_cap.cdc index 564b14b..95c4cb2 100644 --- a/scripts/delegator/find_nft_provider_cap.cdc +++ b/scripts/delegator/find_nft_provider_cap.cdc @@ -3,14 +3,14 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(addr: Address): Bool { - let acct = getAuthAccount(addr) +access(all) fun main(addr: Address): Bool { + let acct = getAuthAccount(addr) let delegator = - acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPrivate}>(CapabilityDelegator.PrivatePath).borrow() + acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let desiredType = Type>() + let desiredType = Type>() let foundType = delegator.findFirstPrivateType(desiredType) ?? panic("no type found") let nakedCap = delegator.getPrivateCapability(foundType) ?? panic("requested capability type was not found") diff --git a/scripts/delegator/get_all_private_caps.cdc b/scripts/delegator/get_all_private_caps.cdc index 8596f27..2d0ebd6 100644 --- a/scripts/delegator/get_all_private_caps.cdc +++ b/scripts/delegator/get_all_private_caps.cdc @@ -3,13 +3,13 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(address: Address): Bool { - let privateCaps: [Capability] = getAuthAccount(address).getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPrivate}>(CapabilityDelegator.PrivatePath) +access(all) fun main(address: Address): Bool { + let privateCaps: [Capability] = getAuthAccount(address).capabilities.storage.issue(CapabilityDelegator.StoragePath) .borrow() ?.getAllPrivate() ?? panic("could not borrow delegator") - let desiredType: Type = Type>() + let desiredType: Type = Type>() return privateCaps.length == 1 && privateCaps[0].getType() == desiredType } \ No newline at end of file diff --git a/scripts/delegator/get_all_public_caps.cdc b/scripts/delegator/get_all_public_caps.cdc index cc562ff..696f441 100644 --- a/scripts/delegator/get_all_public_caps.cdc +++ b/scripts/delegator/get_all_public_caps.cdc @@ -3,12 +3,12 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(address: Address): Bool { - let delegator = getAccount(address).getCapability<&{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath).borrow() +access(all) fun main(address: Address): Bool { + let delegator = getAccount(address).capabilities.get<&{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath)!.borrow() ?? panic("delegator not found") let publicCaps: [Capability] = delegator.getAllPublic() assert(publicCaps.length > 0, message: "no public capabilities found") - let desiredType: Type = Type>() + let desiredType: Type = Type>() return publicCaps[0].getType() == desiredType } \ No newline at end of file diff --git a/scripts/delegator/get_nft_collection.cdc b/scripts/delegator/get_nft_collection.cdc index 1da6458..28b693f 100644 --- a/scripts/delegator/get_nft_collection.cdc +++ b/scripts/delegator/get_nft_collection.cdc @@ -3,19 +3,19 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(addr: Address): Bool { +access(all) fun main(addr: Address): Bool { let acct = getAccount(addr) let delegator = - acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath).borrow() + acct.capabilities.get<&{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath)!.borrow() ?? panic("could not borrow delegator") - let capType = Type>() + let capType = Type>() let nakedCap = delegator.getPublicCapability(capType) ?? panic("requested capability type was not found") // we don't need to do anything with this cap, being able to cast here is enough to know // that this works - let cap = nakedCap as! Capability<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}> + let cap = nakedCap as! Capability<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}> return true } \ No newline at end of file diff --git a/scripts/delegator/get_nft_provider.cdc b/scripts/delegator/get_nft_provider.cdc index aee81eb..1e20416 100644 --- a/scripts/delegator/get_nft_provider.cdc +++ b/scripts/delegator/get_nft_provider.cdc @@ -3,19 +3,19 @@ import "CapabilityDelegator" import "NonFungibleToken" import "ExampleNFT" -pub fun main(addr: Address): Bool { - let acct = getAuthAccount(addr) +access(all) fun main(addr: Address): Bool { + let acct = getAuthAccount(addr) let delegator = - acct.getCapability<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPrivate}>(CapabilityDelegator.PrivatePath).borrow() + acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let capType = Type>() + let capType = Type>() let nakedCap = delegator.getPrivateCapability(capType) ?? panic("requested capability type was not found") // we don't need to do anything with this cap, being able to cast here is enough to know // that this works - let cap = nakedCap as! Capability<&ExampleNFT.Collection{NonFungibleToken.Provider}> + let cap = nakedCap as! Capability return true } \ No newline at end of file diff --git a/scripts/example-nft/mint_to_account.cdc b/scripts/example-nft/mint_to_account.cdc index d25f9a2..dd0b73d 100644 --- a/scripts/example-nft/mint_to_account.cdc +++ b/scripts/example-nft/mint_to_account.cdc @@ -6,15 +6,16 @@ import "ExampleNFT" transaction(receiver: Address, name: String, description: String, thumbnail: String) { let minter: &ExampleNFT.NFTMinter - prepare(acct: AuthAccount) { - self.minter = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath) ?? panic("minter not found") + prepare(acct: auth(BorrowValue) &Account) { + self.minter = acct.storage.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath) ?? panic("minter not found") } execute { - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let c = getAccount(receiver).getCapability<&{NonFungibleToken.CollectionPublic}>(d.publicPath) - let r = c.borrow() ?? panic("no receiver collection") - self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royalties: []) + let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) + ?? panic("no receiver capability found") + let r = c.borrow() ?? panic("could not borrow collection") + self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: self.minter.owner!.address) } } diff --git a/test/CapabilityDelegator_tests.cdc b/test/CapabilityDelegator_tests.cdc index 431eeed..0fd099e 100644 --- a/test/CapabilityDelegator_tests.cdc +++ b/test/CapabilityDelegator_tests.cdc @@ -37,12 +37,12 @@ fun testShareExampleNFTCollectionPublic() { let events = Test.eventsOfType(typ) Test.assertEqual(1, events.length) - let event = events[0]! as! CapabilityDelegator.DelegatorUpdated - Test.assert(event.isPublic) - Test.assert(event.active) + let e = events[0] as! CapabilityDelegator.DelegatorUpdated + Test.assert(e.isPublic) + Test.assert(e.active) - let capabilityType = Type>() - Test.assertEqual(capabilityType, event.capabilityType) + let capabilityType = Type>() + Test.assertEqual(capabilityType, e.capabilityType) } access(all) @@ -56,12 +56,12 @@ fun testShareExampleNFTCollectionPrivate() { let events = Test.eventsOfType(typ) Test.assertEqual(2, events.length) - let event = events[1]! as! CapabilityDelegator.DelegatorUpdated - Test.assert(event.isPublic == false) - Test.assert(event.active) + let e = events[1] as! CapabilityDelegator.DelegatorUpdated + Test.assert(e.isPublic == false) + Test.assert(e.active) - let capabilityType = Type>() - Test.assertEqual(capabilityType, event.capabilityType) + let capabilityType = Type>() + Test.assertEqual(capabilityType, e.capabilityType) } access(all) @@ -72,12 +72,12 @@ fun testRemoveExampleNFTCollectionPublic() { let events = Test.eventsOfType(typ) Test.assertEqual(3, events.length) - let event = events[2]! as! CapabilityDelegator.DelegatorUpdated - Test.assert(event.isPublic) - Test.assert(event.active == false) + let e = events[2] as! CapabilityDelegator.DelegatorUpdated + Test.assert(e.isPublic) + Test.assert(e.active == false) - let capabilityType = Type>() - Test.assertEqual(capabilityType, event.capabilityType) + let capabilityType = Type>() + Test.assertEqual(capabilityType, e.capabilityType) let scriptCode = loadCode("delegator/find_nft_collection_cap.cdc", "scripts") let scriptResult = Test.executeScript(scriptCode, [creator.address]) @@ -97,12 +97,12 @@ fun testRemoveExampleNFTCollectionPrivate() { let events = Test.eventsOfType(typ) Test.assertEqual(4, events.length) - let event = events[3]! as! CapabilityDelegator.DelegatorUpdated - Test.assert(event.isPublic == false) - Test.assert(event.active == false) + let e = events[3] as! CapabilityDelegator.DelegatorUpdated + Test.assert(e.isPublic == false) + Test.assert(e.active == false) - let capabilityType = Type>() - Test.assertEqual(capabilityType, event.capabilityType) + let capabilityType = Type>() + Test.assertEqual(capabilityType, e.capabilityType) let scriptCode = loadCode("delegator/find_nft_provider_cap.cdc", "scripts") let scriptResult = Test.executeScript(scriptCode, [creator.address]) @@ -119,7 +119,7 @@ fun testRemoveExampleNFTCollectionPrivate() { access(all) fun setup() { // helper nft contract so we can actually talk to nfts with tests - deploy("ExampleNFT", "../modules/flow-nft/contracts/ExampleNFT.cdc") + deploy("ExampleNFT", "../contracts/standard/ExampleNFT.cdc") // our main contract is last deploy("CapabilityDelegator", "../contracts/CapabilityDelegator.cdc") @@ -129,42 +129,42 @@ fun setup() { // BEGIN SECTION - transactions used in tests access(all) -fun setupDelegator(_ acct: Test.Account) { +fun setupDelegator(_ acct: Test.TestAccount) { txExecutor("delegator/setup.cdc", [acct], [], nil) } access(all) -fun sharePublicExampleNFT(_ acct: Test.Account) { +fun sharePublicExampleNFT(_ acct: Test.TestAccount) { txExecutor("delegator/add_public_nft_collection.cdc", [acct], [], nil) } access(all) -fun sharePrivateExampleNFT(_ acct: Test.Account) { +fun sharePrivateExampleNFT(_ acct: Test.TestAccount) { txExecutor("delegator/add_private_nft_collection.cdc", [acct], [], nil) } access(all) -fun removePublicExampleNFT(_ acct: Test.Account) { +fun removePublicExampleNFT(_ acct: Test.TestAccount) { txExecutor("delegator/remove_public_nft_collection.cdc", [acct], [], nil) } access(all) -fun removePrivateExampleNFT(_ acct: Test.Account) { +fun removePrivateExampleNFT(_ acct: Test.TestAccount) { txExecutor("delegator/remove_private_nft_collection.cdc", [acct], [], nil) } access(all) -fun setupNFTCollection(_ acct: Test.Account) { +fun setupNFTCollection(_ acct: Test.TestAccount) { txExecutor("example-nft/setup_full.cdc", [acct], [], nil) } access(all) -fun mintNFT(_ minter: Test.Account, receiver: Test.Account, name: String, description: String, thumbnail: String) { +fun mintNFT(_ minter: Test.TestAccount, receiver: Test.TestAccount, name: String, description: String, thumbnail: String) { txExecutor("example-nft/mint_to_account.cdc", [minter], [receiver.address, name, description, thumbnail], nil) } access(all) -fun mintNFTDefault(_ minter: Test.Account, receiver: Test.Account) { +fun mintNFTDefault(_ minter: Test.TestAccount, receiver: Test.TestAccount) { return mintNFT(minter, receiver: receiver, name: "example nft", description: "lorem ipsum", thumbnail: flowtyThumbnail) } @@ -173,37 +173,37 @@ fun mintNFTDefault(_ minter: Test.Account, receiver: Test.Account) { // BEGIN SECTION - scripts used in tests access(all) -fun getExampleNFTCollectionFromDelegator(_ owner: Test.Account) { +fun getExampleNFTCollectionFromDelegator(_ owner: Test.TestAccount) { let borrowed = scriptExecutor("delegator/get_nft_collection.cdc", [owner.address])! as! Bool Test.assert(borrowed, message: "failed to borrow delegator") } access(all) -fun getExampleNFTProviderFromDelegator(_ owner: Test.Account) { +fun getExampleNFTProviderFromDelegator(_ owner: Test.TestAccount) { let borrowed = scriptExecutor("delegator/get_nft_provider.cdc", [owner.address])! as! Bool Test.assert(borrowed, message: "failed to borrow delegator") } access(all) -fun getAllPublicContainsCollection(_ owner: Test.Account) { +fun getAllPublicContainsCollection(_ owner: Test.TestAccount) { let success = scriptExecutor("delegator/get_all_public_caps.cdc", [owner.address])! as! Bool Test.assert(success, message: "failed to borrow delegator") } access(all) -fun getAllPrivateContainsProvider(_ owner: Test.Account) { +fun getAllPrivateContainsProvider(_ owner: Test.TestAccount) { let success = scriptExecutor("delegator/get_all_private_caps.cdc", [owner.address])! as! Bool Test.assert(success, message: "failed to borrow delegator") } access(all) -fun findExampleNFTCollectionType(_ owner: Test.Account) { +fun findExampleNFTCollectionType(_ owner: Test.TestAccount) { let borrowed = scriptExecutor("delegator/find_nft_collection_cap.cdc", [owner.address])! as! Bool Test.assert(borrowed, message: "failed to borrow delegator") } access(all) -fun findExampleNFTProviderType(_ owner: Test.Account) { +fun findExampleNFTProviderType(_ owner: Test.TestAccount) { let borrowed = scriptExecutor("delegator/find_nft_provider_cap.cdc", [owner.address])! as! Bool Test.assert(borrowed, message: "failed to borrow delegator") } diff --git a/test/CapabilityFactory_tests.cdc b/test/CapabilityFactory_tests.cdc index cf2d7f2..9342740 100644 --- a/test/CapabilityFactory_tests.cdc +++ b/test/CapabilityFactory_tests.cdc @@ -207,12 +207,12 @@ fun setup() { // BEGIN SECTION - transactions used in tests access(all) -fun setupNFTCollection(_ acct: Test.Account) { +fun setupNFTCollection(_ acct: Test.TestAccount) { txExecutor("example-nft/setup_full.cdc", [acct], [], nil) } access(all) -fun setupCapabilityFactoryManager(_ acct: Test.Account) { +fun setupCapabilityFactoryManager(_ acct: Test.TestAccount) { txExecutor("factory/setup_nft_ft_manager.cdc", [acct], [], nil) } diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index dba70dc..15cf3bc 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -2,7 +2,7 @@ import Test import "test_helpers.cdc" access(all) let adminAccount = Test.getAccount(0x0000000000000007) -access(all) let accounts: {String: Test.Account} = {} +access(all) let accounts: {String: Test.TestAccount} = {} access(all) let app = "app" access(all) let child = "child" @@ -870,7 +870,7 @@ fun testBlockchainNativeOnboarding() { let childAddresses = scriptExecutor("hybrid-custody/get_child_addresses.cdc", [parent.address]) as! [Address]? ?? panic("problem adding blockchain native child account to signing parent") - let child = Test.Account(address: childAddresses[0], publicKey: expectedPubKey) + let child = Test.TestAccount(address: childAddresses[0], publicKey: expectedPubKey) Test.assert(checkForAddresses(child: child, parent: parent), message: "child account not linked to parent") } @@ -952,7 +952,7 @@ fun testGetChildAccountCapabilityFilterAndFactory() { // --------------- Transaction wrapper functions --------------- access(all) -fun setupChildAndParent_FilterKindAll(child: Test.Account, parent: Test.Account) { +fun setupChildAndParent_FilterKindAll(child: Test.TestAccount, parent: Test.TestAccount) { let factory = getTestAccount(nftFactory) let filter = getTestAccount(FilterKindAll) @@ -966,22 +966,22 @@ fun setupChildAndParent_FilterKindAll(child: Test.Account, parent: Test.Account) } access(all) -fun setupAccountManager(_ acct: Test.Account) { +fun setupAccountManager(_ acct: Test.TestAccount) { txExecutor("hybrid-custody/setup_manager.cdc", [acct], [nil, nil], nil) } access(all) -fun setAccountManagerWithFilter(_ acct: Test.Account, _ filterAccount: Test.Account) { +fun setAccountManagerWithFilter(_ acct: Test.TestAccount, _ filterAccount: Test.TestAccount) { txExecutor("hybrid-custody/setup_manager.cdc", [acct], [nil, nil], nil) } access(all) -fun setManagerFilterOnChild(child: Test.Account, parent: Test.Account, filterAddress: Address) { +fun setManagerFilterOnChild(child: Test.TestAccount, parent: Test.TestAccount, filterAddress: Address) { txExecutor("hybrid-custody/set_manager_filter_cap.cdc", [parent], [filterAddress, child.address], nil) } access(all) -fun setupOwnedAccount(_ acct: Test.Account, _ filterKind: String) { +fun setupOwnedAccount(_ acct: Test.TestAccount, _ filterKind: String) { let factory = getTestAccount(nftFactory) let filter = getTestAccount(filterKind) @@ -996,54 +996,54 @@ fun setupOwnedAccount(_ acct: Test.Account, _ filterKind: String) { } access(all) -fun setupFactoryManager(_ acct: Test.Account) { +fun setupFactoryManager(_ acct: Test.TestAccount) { txExecutor("factory/setup_nft_ft_manager.cdc", [acct], [], nil) } access(all) -fun setupNFTCollection(_ acct: Test.Account) { +fun setupNFTCollection(_ acct: Test.TestAccount) { txExecutor("example-nft/setup_full.cdc", [acct], [], nil) } access(all) -fun setupNFT2Collection(_ acct: Test.Account) { +fun setupNFT2Collection(_ acct: Test.TestAccount) { txExecutor("example-nft-2/setup_full.cdc", [acct], [], nil) } access(all) -fun mintNFT(_ minter: Test.Account, receiver: Test.Account, name: String, description: String, thumbnail: String) { +fun mintNFT(_ minter: Test.TestAccount, receiver: Test.TestAccount, name: String, description: String, thumbnail: String) { let filepath: String = "example-nft/mint_to_account.cdc" txExecutor(filepath, [minter], [receiver.address, name, description, thumbnail], nil) } access(all) -fun mintNFTDefault(_ minter: Test.Account, receiver: Test.Account) { +fun mintNFTDefault(_ minter: Test.TestAccount, receiver: Test.TestAccount) { return mintNFT(minter, receiver: receiver, name: "example nft", description: "lorem ipsum", thumbnail: "http://example.com/image.png") } access(all) -fun mintExampleNFT2(_ minter: Test.Account, receiver: Test.Account, name: String, description: String, thumbnail: String) { +fun mintExampleNFT2(_ minter: Test.TestAccount, receiver: Test.TestAccount, name: String, description: String, thumbnail: String) { let filepath: String = "example-nft-2/mint_to_account.cdc" txExecutor(filepath, [minter], [receiver.address, name, description, thumbnail], nil) } access(all) -fun mintExampleNFT2Default(_ minter: Test.Account, receiver: Test.Account) { +fun mintExampleNFT2Default(_ minter: Test.TestAccount, receiver: Test.TestAccount) { return mintExampleNFT2(minter, receiver: receiver, name: "example nft 2", description: "lorem ipsum", thumbnail: "http://example.com/image.png") } access(all) -fun setupFT(_ acct: Test.Account) { +fun setupFT(_ acct: Test.TestAccount) { txExecutor("example-token/setup.cdc", [acct], [], nil) } access(all) -fun setupFTProvider(_ acct: Test.Account) { +fun setupFTProvider(_ acct: Test.TestAccount) { txExecutor("example-token/setup_provider.cdc", [acct], [], nil) } access(all) -fun setupFilter(_ acct: Test.Account, _ kind: String) { +fun setupFilter(_ acct: Test.TestAccount, _ kind: String) { var filePath = "" switch kind { case FilterKindAll: @@ -1063,7 +1063,7 @@ fun setupFilter(_ acct: Test.Account, _ kind: String) { } access(all) -fun addTypeToFilter(_ acct: Test.Account, _ kind: String, _ identifier: String) { +fun addTypeToFilter(_ acct: Test.TestAccount, _ kind: String, _ identifier: String) { var filePath = "" switch kind { case FilterKindAllowList: @@ -1080,7 +1080,7 @@ fun addTypeToFilter(_ acct: Test.Account, _ kind: String, _ identifier: String) } access(all) -fun removeAllFilterTypes(_ acct: Test.Account, _ kind: String) { +fun removeAllFilterTypes(_ acct: Test.TestAccount, _ kind: String) { var filePath = "" switch kind { case FilterKindAllowList: @@ -1097,12 +1097,12 @@ fun removeAllFilterTypes(_ acct: Test.Account, _ kind: String) { } access(all) -fun addNFTCollectionToDelegator(child: Test.Account, parent: Test.Account, isPublic: Bool) { +fun addNFTCollectionToDelegator(child: Test.TestAccount, parent: Test.TestAccount, isPublic: Bool) { txExecutor("hybrid-custody/add_example_nft_collection_to_delegator.cdc", [child], [parent.address, isPublic], nil) } access(all) -fun addNFT2CollectionToDelegator(child: Test.Account, parent: Test.Account, isPublic: Bool) { +fun addNFT2CollectionToDelegator(child: Test.TestAccount, parent: Test.TestAccount, isPublic: Bool) { txExecutor("hybrid-custody/add_example_nft2_collection_to_delegator.cdc", [child], [parent.address, isPublic], nil) } // ---------------- End Transaction wrapper functions @@ -1110,32 +1110,32 @@ fun addNFT2CollectionToDelegator(child: Test.Account, parent: Test.Account, isPu // ---------------- Begin script wrapper functions access(all) -fun getParentStatusesForChild(_ child: Test.Account): {Address: Bool} { +fun getParentStatusesForChild(_ child: Test.TestAccount): {Address: Bool} { return scriptExecutor("hybrid-custody/get_parents_from_child.cdc", [child.address])! as! {Address: Bool} } access(all) -fun isParent(child: Test.Account, parent: Test.Account): Bool { +fun isParent(child: Test.TestAccount, parent: Test.TestAccount): Bool { return scriptExecutor("hybrid-custody/is_parent.cdc", [child.address, parent.address])! as! Bool } access(all) -fun checkIsRedeemed(child: Test.Account, parent: Test.Account): Bool { +fun checkIsRedeemed(child: Test.TestAccount, parent: Test.TestAccount): Bool { return scriptExecutor("hybrid-custody/is_redeemed.cdc", [child.address, parent.address])! as! Bool } access(all) -fun getNumValidKeys(_ child: Test.Account): Int { +fun getNumValidKeys(_ child: Test.TestAccount): Int { return scriptExecutor("hybrid-custody/get_num_valid_keys.cdc", [child.address])! as! Int } access(all) -fun checkAuthAccountDefaultCap(account: Test.Account): Bool { +fun checkAuthAccountDefaultCap(account: Test.TestAccount): Bool { return scriptExecutor("hybrid-custody/check_default_auth_acct_linked_path.cdc", [account.address])! as! Bool } access(all) -fun getOwner(child: Test.Account): Address? { +fun getOwner(child: Test.TestAccount): Address? { let res = scriptExecutor("hybrid-custody/get_owner_of_child.cdc", [child.address]) if res == nil { return nil @@ -1145,14 +1145,14 @@ fun getOwner(child: Test.Account): Address? { } access(all) -fun getPendingOwner(child: Test.Account): Address? { +fun getPendingOwner(child: Test.TestAccount): Address? { let res = scriptExecutor("hybrid-custody/get_pending_owner_of_child.cdc", [child.address]) return res as! Address? } access(all) -fun checkForAddresses(child: Test.Account, parent: Test.Account): Bool { +fun checkForAddresses(child: Test.TestAccount, parent: Test.TestAccount): Bool { let childAddressResult: [Address]? = (scriptExecutor("hybrid-custody/get_child_addresses.cdc", [parent.address])) as! [Address]? Test.assert(childAddressResult?.contains(child.address) == true, message: "child address not found") @@ -1162,7 +1162,7 @@ fun checkForAddresses(child: Test.Account, parent: Test.Account): Bool { } access(all) -fun getBalance(_ acct: Test.Account): UFix64 { +fun getBalance(_ acct: Test.TestAccount): UFix64 { let balance: UFix64? = (scriptExecutor("example-token/get_balance.cdc", [acct.address])! as! UFix64) return balance! } @@ -1172,7 +1172,7 @@ fun getBalance(_ acct: Test.Account): UFix64 { // ---------------- BEGIN General-purpose helper functions access(all) -fun buildTypeIdentifier(_ acct: Test.Account, _ contractName: String, _ suffix: String): String { +fun buildTypeIdentifier(_ acct: Test.TestAccount, _ contractName: String, _ suffix: String): String { let addrString = acct.address.toString() return "A.".concat(addrString.slice(from: 2, upTo: addrString.length)).concat(".").concat(contractName).concat(".").concat(suffix) } @@ -1187,7 +1187,7 @@ fun getCapabilityFilterPath(): String { // ---------------- END General-purpose helper functions access(all) -fun getTestAccount(_ name: String): Test.Account { +fun getTestAccount(_ name: String): Test.TestAccount { if accounts[name] == nil { accounts[name] = Test.createAccount() } diff --git a/test/test_helpers.cdc b/test/test_helpers.cdc index fd75998..1ae7ea2 100644 --- a/test/test_helpers.cdc +++ b/test/test_helpers.cdc @@ -49,7 +49,7 @@ fun expectScriptFailure( access(all) fun txExecutor( _ txName: String, - _ signers: [Test.Account], + _ signers: [Test.TestAccount], _ arguments: [AnyStruct], _ expectedError: String? ): Bool { diff --git a/transactions/delegator/add_private_nft_collection.cdc b/transactions/delegator/add_private_nft_collection.cdc index 29843ce..cb32068 100644 --- a/transactions/delegator/add_private_nft_collection.cdc +++ b/transactions/delegator/add_private_nft_collection.cdc @@ -5,13 +5,13 @@ import "MetadataViews" import "ExampleNFT" transaction { - prepare(acct: AuthAccount) { - let delegator = acct.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) + prepare(acct: auth(BorrowValue, Capabilities) &Account) { + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.getCapability<&ExampleNFT.Collection{NonFungibleToken.Provider}>(d.providerPath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.addCapability(cap: sharedCap, isPublic: false) } diff --git a/transactions/delegator/add_public_nft_collection.cdc b/transactions/delegator/add_public_nft_collection.cdc index 478239f..9c71b61 100644 --- a/transactions/delegator/add_public_nft_collection.cdc +++ b/transactions/delegator/add_public_nft_collection.cdc @@ -4,12 +4,12 @@ import "NonFungibleToken" import "ExampleNFT" transaction { - prepare(acct: AuthAccount) { - let delegator = acct.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) + prepare(acct: auth(BorrowValue) &Account) { + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap - = acct.getCapability<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) + = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath)! delegator.addCapability(cap: sharedCap, isPublic: true) } } \ No newline at end of file diff --git a/transactions/delegator/remove_private_nft_collection.cdc b/transactions/delegator/remove_private_nft_collection.cdc index e87afa1..a870848 100644 --- a/transactions/delegator/remove_private_nft_collection.cdc +++ b/transactions/delegator/remove_private_nft_collection.cdc @@ -5,14 +5,16 @@ import "MetadataViews" import "ExampleNFT" transaction { - prepare(acct: AuthAccount) { - let delegator = acct.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) + prepare(acct: auth(BorrowValue, Capabilities) &Account) { + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.getCapability<&ExampleNFT.Collection{NonFungibleToken.Provider}>(d.providerPath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.removeCapability(cap: sharedCap) + + acct.capabilities.storage.getController(byCapabilityID: sharedCap.id)!.delete() } } \ No newline at end of file diff --git a/transactions/delegator/remove_public_nft_collection.cdc b/transactions/delegator/remove_public_nft_collection.cdc index a1566ca..8b14546 100644 --- a/transactions/delegator/remove_public_nft_collection.cdc +++ b/transactions/delegator/remove_public_nft_collection.cdc @@ -4,12 +4,12 @@ import "NonFungibleToken" import "ExampleNFT" transaction { - prepare(acct: AuthAccount) { - let delegator = acct.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) + prepare(acct: auth(BorrowValue, Capabilities) &Account) { + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap - = acct.getCapability<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) + = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath)! delegator.removeCapability(cap: sharedCap) } } \ No newline at end of file diff --git a/transactions/delegator/setup.cdc b/transactions/delegator/setup.cdc index b1111c6..4664ebf 100644 --- a/transactions/delegator/setup.cdc +++ b/transactions/delegator/setup.cdc @@ -1,16 +1,15 @@ import "CapabilityDelegator" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) == nil { + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&CapabilityDelegator.Delegator>(from: CapabilityDelegator.StoragePath) == nil { let delegator <- CapabilityDelegator.createDelegator() - acct.save(<-delegator, to: CapabilityDelegator.StoragePath) + acct.storage.save(<-delegator, to: CapabilityDelegator.StoragePath) } - acct.unlink(CapabilityDelegator.PublicPath) - acct.unlink(CapabilityDelegator.PrivatePath) + acct.capabilities.unpublish(CapabilityDelegator.PublicPath) - acct.link<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.PublicPath, target: CapabilityDelegator.StoragePath) - acct.link<&CapabilityDelegator.Delegator{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}>(CapabilityDelegator.PrivatePath, target: CapabilityDelegator.StoragePath) + let cap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(CapabilityDelegator.StoragePath) + acct.capabilities.publish(cap, at: CapabilityDelegator.PublicPath) } } \ No newline at end of file diff --git a/transactions/example-nft-2/mint_to_account.cdc b/transactions/example-nft-2/mint_to_account.cdc index d199519..0be32eb 100644 --- a/transactions/example-nft-2/mint_to_account.cdc +++ b/transactions/example-nft-2/mint_to_account.cdc @@ -6,15 +6,15 @@ import "ExampleNFT2" transaction(receiver: Address, name: String, description: String, thumbnail: String) { let minter: &ExampleNFT2.NFTMinter - prepare(acct: AuthAccount) { - self.minter = acct.borrow<&ExampleNFT2.NFTMinter>(from: ExampleNFT2.MinterStoragePath) ?? panic("minter not found") + prepare(acct: auth(BorrowValue) &Account) { + self.minter = acct.storage.borrow<&ExampleNFT2.NFTMinter>(from: ExampleNFT2.MinterStoragePath) ?? panic("minter not found") } execute { - let d = ExampleNFT2.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT2.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let c = getAccount(receiver).getCapability<&{NonFungibleToken.CollectionPublic}>(d.publicPath) + let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) ?? panic("receiver capability was nil") let r = c.borrow() ?? panic("no receiver collection") - self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royalties: []) + self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: self.minter.owner!.address) } } diff --git a/transactions/example-nft/mint_to_account.cdc b/transactions/example-nft/mint_to_account.cdc index d25f9a2..699d022 100644 --- a/transactions/example-nft/mint_to_account.cdc +++ b/transactions/example-nft/mint_to_account.cdc @@ -6,15 +6,15 @@ import "ExampleNFT" transaction(receiver: Address, name: String, description: String, thumbnail: String) { let minter: &ExampleNFT.NFTMinter - prepare(acct: AuthAccount) { - self.minter = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath) ?? panic("minter not found") + prepare(acct: auth(BorrowValue) &Account) { + self.minter = acct.storage.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath) ?? panic("minter not found") } execute { - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let c = getAccount(receiver).getCapability<&{NonFungibleToken.CollectionPublic}>(d.publicPath) + let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) ?? panic("receiver capability was nil") let r = c.borrow() ?? panic("no receiver collection") - self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royalties: []) + self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: self.minter.owner!.address) } } diff --git a/transactions/example-nft/setup_full.cdc b/transactions/example-nft/setup_full.cdc index e8b9648..c20ad67 100644 --- a/transactions/example-nft/setup_full.cdc +++ b/transactions/example-nft/setup_full.cdc @@ -1,20 +1,20 @@ import "NonFungibleToken" import "MetadataViews" -import ExampleNFT from "ExampleNFT" +import "ExampleNFT" transaction { - prepare(acct: AuthAccount) { - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + prepare(acct: auth(Storage, Capabilities) &Account) { + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - if acct.borrow<&ExampleNFT.Collection>(from: d.storagePath) == nil { - acct.save(<- ExampleNFT.createEmptyCollection(), to: ExampleNFT.CollectionStoragePath) + if acct.storage.borrow<&ExampleNFT.Collection>(from: d.storagePath) == nil { + acct.storage.save(<- ExampleNFT.createEmptyCollection(), to: ExampleNFT.CollectionStoragePath) } - acct.unlink(d.publicPath) - acct.link<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(d.publicPath, target: d.storagePath) + acct.capabilities.unpublish(d.publicPath) + let cap = acct.capabilities.storage.issue<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(d.storagePath) + acct.capabilities.publish(cap, at: d.publicPath) - acct.unlink(d.providerPath) - acct.link<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic, NonFungibleToken.Provider}>(d.providerPath, target: d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } From 42746d43ad10ee1fb053a251a6dab19801034aec Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 1 Apr 2024 12:25:47 -0700 Subject: [PATCH 07/34] fix CapabilityFactory tests --- .../factory/get_ft_receiver_from_factory.cdc | 19 ++++-- .../factory/get_nft_provider_from_factory.cdc | 17 ++++-- .../get_supported_types_from_manager.cdc | 4 +- .../add_type_for_nft_provider_factory.cdc | 4 +- scripts/test/get_type_from_factory.cdc | 4 +- scripts/test/remove_nft_provider_factory.cdc | 6 +- scripts/test/update_nft_provider_factory.cdc | 5 +- test/CapabilityFactory_tests.cdc | 60 ++++++++++++------- transactions/example-token/setup.cdc | 29 +++++---- transactions/factory/setup_ft_manager.cdc | 23 +++---- transactions/factory/setup_nft_ft_manager.cdc | 27 +++++---- transactions/factory/setup_nft_manager.cdc | 24 ++++---- .../add_type_for_nft_provider_factory.cdc | 4 +- 13 files changed, 134 insertions(+), 92 deletions(-) diff --git a/scripts/factory/get_ft_receiver_from_factory.cdc b/scripts/factory/get_ft_receiver_from_factory.cdc index b477940..23c0afe 100644 --- a/scripts/factory/get_ft_receiver_from_factory.cdc +++ b/scripts/factory/get_ft_receiver_from_factory.cdc @@ -1,13 +1,24 @@ import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" import "FTReceiverFactory" -pub fun main(addr: Address) { - let acct = getAuthAccount(addr) - let ref = &acct as &AuthAccount +access(all) fun main(addr: Address) { + let acct = getAuthAccount(addr) let factory = FTReceiverFactory.Factory() - let receiver = factory.getCapability(acct: ref, path: ExampleToken.ReceiverPublicPath) as! Capability<&{FungibleToken.Receiver}> + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + let controllers = acct.capabilities.storage.getControllers(forPath: vaultData.storagePath) + + for c in controllers { + if c.borrowType.isSubtype(of: Type<&{FungibleToken.Receiver}>()) { + factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability<&{FungibleToken.Receiver}> + return + } + } + + panic("should not reach this point") } \ No newline at end of file diff --git a/scripts/factory/get_nft_provider_from_factory.cdc b/scripts/factory/get_nft_provider_from_factory.cdc index e04a09c..c49019c 100644 --- a/scripts/factory/get_nft_provider_from_factory.cdc +++ b/scripts/factory/get_nft_provider_from_factory.cdc @@ -4,13 +4,20 @@ import "NonFungibleToken" import "NFTProviderFactory" -pub fun main(addr: Address) { - let acct = getAuthAccount(addr) - let ref = &acct as &AuthAccount +access(all) fun main(addr: Address) { + let acct = getAuthAccount(addr) let factory = NFTProviderFactory.Factory() + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let controllers = acct.capabilities.storage.getControllers(forPath: d.storagePath) - let provider = factory.getCapability(acct: ref, path: d.providerPath) as! Capability<&{NonFungibleToken.Provider}> + for c in controllers { + if c.borrowType.isSubtype(of: Type()) { + factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability + return + } + } + + panic("should not reach this point") } \ No newline at end of file diff --git a/scripts/factory/get_supported_types_from_manager.cdc b/scripts/factory/get_supported_types_from_manager.cdc index c8e736e..45e4df3 100644 --- a/scripts/factory/get_supported_types_from_manager.cdc +++ b/scripts/factory/get_supported_types_from_manager.cdc @@ -2,8 +2,8 @@ import "CapabilityFactory" import "NonFungibleToken" -pub fun main(address: Address): [Type] { - let getterRef = getAccount(address).getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) +access(all) fun main(address: Address): [Type] { + let getterRef = getAccount(address).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! .borrow() ?? panic("CapabilityFactory Getter not found") return getterRef.getSupportedTypes() diff --git a/scripts/test/add_type_for_nft_provider_factory.cdc b/scripts/test/add_type_for_nft_provider_factory.cdc index 639d6d4..4ebab4e 100644 --- a/scripts/test/add_type_for_nft_provider_factory.cdc +++ b/scripts/test/add_type_for_nft_provider_factory.cdc @@ -3,8 +3,8 @@ import "NFTProviderFactory" import "NonFungibleToken" -pub fun main(address: Address, type: Type): Bool { - let managerRef = getAuthAccount(address).borrow<&CapabilityFactory.Manager>( +access(all) fun main(address: Address, type: Type): Bool { + let managerRef = getAuthAccount(address).storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") diff --git a/scripts/test/get_type_from_factory.cdc b/scripts/test/get_type_from_factory.cdc index b266a46..8fcac58 100644 --- a/scripts/test/get_type_from_factory.cdc +++ b/scripts/test/get_type_from_factory.cdc @@ -2,8 +2,8 @@ import "NonFungibleToken" import "CapabilityFactory" -pub fun main(address: Address, type: Type): Bool { - let managerRef = getAuthAccount(address).borrow<&CapabilityFactory.Manager>( +access(all) fun main(address: Address, type: Type): Bool { + let managerRef = getAuthAccount(address).storage.borrow<&CapabilityFactory.Manager>( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") diff --git a/scripts/test/remove_nft_provider_factory.cdc b/scripts/test/remove_nft_provider_factory.cdc index 1462644..793c658 100644 --- a/scripts/test/remove_nft_provider_factory.cdc +++ b/scripts/test/remove_nft_provider_factory.cdc @@ -3,14 +3,14 @@ import "NFTProviderFactory" import "NonFungibleToken" -pub fun main(address: Address): Bool { +access(all) fun main(address: Address): Bool { - let managerRef = getAuthAccount(address).borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let expectedType = Type() - if let removed = managerRef.removeFactory(Type<&{NonFungibleToken.Provider}>()) { + if let removed = managerRef.removeFactory(Type()) { return removed.getType() == expectedType } diff --git a/scripts/test/update_nft_provider_factory.cdc b/scripts/test/update_nft_provider_factory.cdc index 7f95c78..748b938 100644 --- a/scripts/test/update_nft_provider_factory.cdc +++ b/scripts/test/update_nft_provider_factory.cdc @@ -3,9 +3,8 @@ import "NFTProviderFactory" import "NonFungibleToken" -pub fun main(address: Address) { - - let managerRef = getAuthAccount(address).borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) +access(all) fun main(address: Address) { + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let nftProviderFactory = NFTProviderFactory.Factory() diff --git a/test/CapabilityFactory_tests.cdc b/test/CapabilityFactory_tests.cdc index 9342740..2180c30 100644 --- a/test/CapabilityFactory_tests.cdc +++ b/test/CapabilityFactory_tests.cdc @@ -33,23 +33,25 @@ fun testGetSupportedTypesFromManager() { )! as! [Type] let expectedTypes = [ - Type<&{FungibleToken.Provider}>(), + Type(), Type<&{FungibleToken.Balance}>(), Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), + Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type<&{NonFungibleToken.Provider}>() + Type() ] - Test.assertEqual(expectedTypes, supportedTypes) + for e in expectedTypes { + Test.assert(supportedTypes.contains(e), message: "missing expected type in supported types") + } } access(all) fun testAddFactoryFails() { expectScriptFailure( "test/add_type_for_nft_provider_factory.cdc", - [creator.address, Type<&{NonFungibleToken.Provider}>()], + [creator.address, Type()], "Factory of given type already exists" ) } @@ -64,17 +66,20 @@ fun testAddFactorySucceeds() { )! as! [Type] let expectedTypes = [ - Type<&{FungibleToken.Provider}>(), + Type(), Type<&{FungibleToken.Balance}>(), Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), + Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type<&{NonFungibleToken.Provider}>(), + Type(), Type<&{NonFungibleToken.Receiver}>() ] - Test.assertEqual(expectedTypes, supportedTypes) + + for e in expectedTypes { + Test.assert(supportedTypes.contains(e), message: "missing expected type in supportedTypes") + } for type in supportedTypes { let factorySuccess = scriptExecutor( @@ -116,11 +121,14 @@ fun testSetupNFTManager() { let supportedTypes = scriptExecutor("factory/get_supported_types_from_manager.cdc", [tmp.address])! as! [Type] let expectedTypes = [ - Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type<&{NonFungibleToken.Provider}>() + Type() ] - Test.assertEqual(expectedTypes, supportedTypes) + + for e in expectedTypes { + Test.assert(supportedTypes.contains(e), message: "missing type in supportedTypes: ".concat(e.identifier)) + } for type in supportedTypes { let factorySuccess = scriptExecutor( @@ -139,13 +147,16 @@ fun testSetupFTManager() { let supportedTypes = scriptExecutor("factory/get_supported_types_from_manager.cdc", [tmp.address])! as! [Type] let expectedTypes = [ - Type<&{FungibleToken.Provider}>(), + Type(), Type<&{FungibleToken.Balance}>(), Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>() + Type() ] - Test.assertEqual(expectedTypes, supportedTypes) + + for e in expectedTypes { + Test.assert(supportedTypes.contains(e), message: "missing type in supportedTypes: ".concat(e.identifier)) + } for type in supportedTypes { let factorySuccess = scriptExecutor( @@ -164,16 +175,19 @@ fun testSetupNFTFTManager() { let supportedTypes = scriptExecutor("factory/get_supported_types_from_manager.cdc", [tmp.address])! as! [Type] let expectedTypes = [ - Type<&{FungibleToken.Provider}>(), + Type(), Type<&{FungibleToken.Balance}>(), Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(), - Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), + Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type<&{NonFungibleToken.Provider}>() + Type() ] - Test.assertEqual(expectedTypes, supportedTypes) + + for e in expectedTypes { + Test.assert(supportedTypes.contains(e), message: "missing type in supportedTypes: ".concat(e.identifier)) + } for type in supportedTypes { let factorySuccess = scriptExecutor( @@ -189,7 +203,7 @@ fun testSetupNFTFTManager() { access(all) fun setup() { // helper nft & ft contract so we can actually talk to nfts & fts with tests - deploy("ExampleNFT", "../modules/flow-nft/contracts/ExampleNFT.cdc") + deploy("ExampleNFT", "../contracts/standard/ExampleNFT.cdc") deploy("ExampleToken", "../contracts/standard/ExampleToken.cdc") // our main contract is last diff --git a/transactions/example-token/setup.cdc b/transactions/example-token/setup.cdc index 3de7cc4..a94b346 100644 --- a/transactions/example-token/setup.cdc +++ b/transactions/example-token/setup.cdc @@ -1,28 +1,33 @@ import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" transaction { - prepare(acct: AuthAccount) { + prepare(acct: auth(Storage, Capabilities) &Account) { + let md = ExampleToken.resolveContractView(resourceType: nil, viewType: Type())! as! FungibleTokenMetadataViews.FTVaultData // Create a new ExampleToken Vault and put it in storage if one doesn't exist - if acct.borrow<&ExampleToken.Vault>(from: ExampleToken.VaultStoragePath) == nil { - acct.save( - <-ExampleToken.createEmptyVault(), - to: ExampleToken.VaultStoragePath - ) + if acct.storage.borrow<&ExampleToken.Vault>(from: md.storagePath) == nil { + acct.storage.save( + <-ExampleToken.createEmptyVault(vaultType: Type<@ExampleToken.Vault>()), + to: md.storagePath + ) } // Create a public capability to the Vault that only exposes // the deposit function through the Receiver interface - acct.link<&ExampleToken.Vault{FungibleToken.Receiver, FungibleToken.Balance}>( - ExampleToken.ReceiverPublicPath, - target: ExampleToken.VaultStoragePath + acct.capabilities.unpublish(md.receiverPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{FungibleToken.Receiver, FungibleToken.Balance}>(md.storagePath), + at: md.receiverPath ) // Create a public capability to the Vault that exposes the Balance and Resolver interfaces - acct.link<&ExampleToken.Vault{FungibleToken.Balance}>( - ExampleToken.VaultPublicPath, - target: ExampleToken.VaultStoragePath + acct.capabilities.unpublish(md.metadataPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{FungibleToken.Balance}>(md.storagePath), + at: md.metadataPath ) + } } \ No newline at end of file diff --git a/transactions/factory/setup_ft_manager.cdc b/transactions/factory/setup_ft_manager.cdc index fcd4631..1806525 100644 --- a/transactions/factory/setup_ft_manager.cdc +++ b/transactions/factory/setup_ft_manager.cdc @@ -8,29 +8,32 @@ import "FTReceiverFactory" import "FTAllFactory" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { let f <- CapabilityFactory.createFactoryManager() - acct.save(<-f, to: CapabilityFactory.StoragePath) + acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { - acct.unlink(CapabilityFactory.PublicPath) - acct.link<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath, target: CapabilityFactory.StoragePath) + if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + acct.capabilities.unpublish(CapabilityFactory.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + at: CapabilityFactory.PublicPath + ) } assert( - acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), message: "CapabilityFactory is not setup properly" ) - let manager = acct.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") - manager.updateFactory(Type<&{FungibleToken.Provider}>(), FTProviderFactory.Factory()) + manager.updateFactory(Type(), FTProviderFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Balance}>(), FTBalanceFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver}>(), FTReceiverFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), FTReceiverBalanceFactory.Factory()) - manager.updateFactory(Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(), FTAllFactory.Factory()) + manager.updateFactory(Type(), FTAllFactory.Factory()) } } diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 3c47e49..703a478 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -12,32 +12,33 @@ import "FTReceiverFactory" import "FTAllFactory" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { let f <- CapabilityFactory.createFactoryManager() - acct.save(<-f, to: CapabilityFactory.StoragePath) + acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { - acct.unlink(CapabilityFactory.PublicPath) - acct.link<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath, target: CapabilityFactory.StoragePath) + if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + acct.capabilities.unpublish(CapabilityFactory.PublicPath) + + let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) + acct.capabilities.publish(cap, at: CapabilityFactory.PublicPath) } assert( - acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), message: "CapabilityFactory is not setup properly" ) - let manager = acct.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) - ?? panic("manager not found") + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type<&{NonFungibleToken.Provider}>(), NFTProviderFactory.Factory()) - manager.updateFactory(Type<&{FungibleToken.Provider}>(), FTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), FTProviderFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Balance}>(), FTBalanceFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver}>(), FTReceiverFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), FTReceiverBalanceFactory.Factory()) - manager.updateFactory(Type<&{FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance}>(), FTAllFactory.Factory()) + manager.updateFactory(Type(), FTAllFactory.Factory()) } } diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index 7ca5590..3472d18 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -6,27 +6,29 @@ import "NFTProviderAndCollectionFactory" import "NFTProviderFactory" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { let f <- CapabilityFactory.createFactoryManager() - acct.save(<-f, to: CapabilityFactory.StoragePath) + acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { - acct.unlink(CapabilityFactory.PublicPath) - acct.link<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath, target: CapabilityFactory.StoragePath) - } + + acct.capabilities.unpublish(CapabilityFactory.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + at: CapabilityFactory.PublicPath + ) assert( - acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), message: "CapabilityFactory is not setup properly" ) - let manager = acct.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type<&{NonFungibleToken.Provider}>(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) } } diff --git a/transactions/test/add_type_for_nft_provider_factory.cdc b/transactions/test/add_type_for_nft_provider_factory.cdc index 4c847f9..af6d6da 100644 --- a/transactions/test/add_type_for_nft_provider_factory.cdc +++ b/transactions/test/add_type_for_nft_provider_factory.cdc @@ -4,8 +4,8 @@ import "NFTProviderFactory" import "NonFungibleToken" transaction(type: Type) { - prepare(account: AuthAccount) { - let managerRef = account.borrow<&CapabilityFactory.Manager>( + prepare(account: auth(Storage) &Account) { + let managerRef = account.storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") From 1301040b9fa975cc9ce79a027b88fb964f9716af Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 2 Apr 2024 18:33:55 -0700 Subject: [PATCH 08/34] fix HybridCustody tests --- contracts/HybridCustody.cdc | 80 +++++++++++++------ contracts/factories/FTProviderFactory.cdc | 2 +- contracts/standard/ExampleToken.cdc | 6 ++ scripts/example-nft-2/get_ids.cdc | 6 +- scripts/example-nft/get_ids.cdc | 6 +- scripts/example-token/get_balance.cdc | 10 ++- .../factory/get_ft_balance_from_factory.cdc | 12 +-- .../factory/get_ft_provider_from_factory.cdc | 24 ++++-- .../get_nft_provider_from_factory_allowed.cdc | 26 ++++-- .../check_default_auth_acct_linked_path.cdc | 6 -- .../hybrid-custody/get_account_cap_con_id.cdc | 11 +++ .../hybrid-custody/get_all_flow_balances.cdc | 4 +- .../get_child_account_ft_capabilities.cdc | 41 +++++----- .../get_child_account_nft_capabilities.cdc | 41 +++++----- .../hybrid-custody/get_child_addresses.cdc | 6 +- .../get_collection_from_inbox.cdc | 17 ++-- ...t_examplenft_collection_from_delegator.cdc | 5 +- .../get_ft_provider_capability.cdc | 29 +++++-- .../get_nft_collection_public_capability.cdc | 13 +-- .../get_nft_provider_capability.cdc | 14 ++-- scripts/hybrid-custody/get_num_valid_keys.cdc | 4 +- scripts/hybrid-custody/get_owner_of_child.cdc | 6 +- .../hybrid-custody/get_parent_addresses.cdc | 6 +- .../get_pending_owner_of_child.cdc | 6 +- .../get_spec_balance_from_public.cdc | 13 ++- .../hybrid-custody/has_address_as_child.cdc | 6 +- scripts/hybrid-custody/has_child_accounts.cdc | 6 +- scripts/hybrid-custody/has_owned_accounts.cdc | 6 +- scripts/hybrid-custody/is_parent.cdc | 6 +- scripts/hybrid-custody/is_redeemed.cdc | 6 +- .../metadata/assert_owned_account_display.cdc | 6 +- .../metadata/resolve_child_display_name.cdc | 6 +- .../metadata/resolve_owned_display_name.cdc | 6 +- .../hybrid-custody/verify_child_address.cdc | 6 +- .../can_get_child_factory_and_filter_caps.cdc | 19 ++++- .../create_manager_with_invalid_filter.cdc | 8 +- .../test/get_all_vault_bal_from_storage.cdc | 14 ++-- scripts/test/get_flow_balance.cdc | 2 +- .../get_nft_provider_capability_optional.cdc | 14 ++-- .../test/test_get_accessible_child_nfts.cdc | 52 ++++++------ ...t_get_all_collection_data_from_storage.cdc | 25 +++--- .../test_get_nft_display_view_from_public.cdc | 37 ++++----- scripts/test_imports.cdc | 2 +- test/HybridCustody_tests.cdc | 56 ++++++++----- .../setup_nft_filter_and_factory_manager.cdc | 41 ++++++---- transactions/example-nft-2/setup_full.cdc | 18 +++-- transactions/example-token/mint_tokens.cdc | 12 +-- transactions/example-token/setup_provider.cdc | 12 +-- .../filter/allow/add_type_to_list.cdc | 4 +- .../filter/allow/remove_all_types.cdc | 4 +- transactions/filter/allow/setup.cdc | 15 ++-- transactions/filter/deny/add_type_to_list.cdc | 4 +- transactions/filter/deny/remove_all_types.cdc | 4 +- transactions/filter/deny/setup.cdc | 15 ++-- transactions/filter/setup_allow_all.cdc | 17 ++-- .../hybrid-custody/accept_ownership.cdc | 31 ++++--- ...d_example_nft2_collection_to_delegator.cdc | 9 +-- ...dd_example_nft_collection_to_delegator.cdc | 9 +-- .../metadata/set_child_account_display.cdc | 4 +- .../metadata/set_owned_account_display.cdc | 4 +- ..._resource_to_parent_child_storage_slot.cdc | 6 +- .../onboarding/blockchain_native.cdc | 73 ++++++++--------- .../hybrid-custody/publish_to_parent.cdc | 8 +- .../hybrid-custody/redeem_account.cdc | 29 ++++--- .../hybrid-custody/relinquish_ownership.cdc | 4 +- .../hybrid-custody/remove_child_account.cdc | 4 +- .../remove_parent_from_child.cdc | 6 +- .../send_child_ft_with_parent.cdc | 22 +++-- .../set_default_manager_cap.cdc | 7 +- .../hybrid-custody/set_manager_filter_cap.cdc | 7 +- transactions/hybrid-custody/setup_manager.cdc | 23 ++++-- .../hybrid-custody/setup_multi_sig.cdc | 69 ++++++++++------ .../hybrid-custody/setup_owned_account.cdc | 29 +++---- ...up_owned_account_and_publish_to_parent.cdc | 51 ++++++------ .../hybrid-custody/transfer_ownership.cdc | 4 +- .../transfer_ownership_from_manager.cdc | 4 +- .../misc/unlink_from_storage_paths.cdc | 10 +++ transactions/misc/unlink_paths.cdc | 7 -- 78 files changed, 735 insertions(+), 508 deletions(-) delete mode 100644 scripts/hybrid-custody/check_default_auth_acct_linked_path.cdc create mode 100644 scripts/hybrid-custody/get_account_cap_con_id.cdc create mode 100644 transactions/misc/unlink_from_storage_paths.cdc delete mode 100644 transactions/misc/unlink_paths.cdc diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 4aa1d4b..4bc851f 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -31,6 +31,7 @@ import "CapabilityFilter" access(all) contract HybridCustody { access(all) entitlement Owner + access(all) entitlement Child access(all) entitlement Publish access(all) entitlement Manage @@ -102,6 +103,9 @@ access(all) contract HybridCustody { /// A callback function to mark a parent as redeemed on the child account. access(contract) fun setRedeemed(_ addr: Address) + + /// A helper function to find what controller Id to ask for if you are looking for a specific type of capability + access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? } /// Private interface accessible to the owner of the OwnedAccount @@ -206,19 +210,20 @@ access(all) contract HybridCustody { access(all) view fun getAddress(): Address access(all) view fun getCapabilityFactoryManager(): &{CapabilityFactory.Getter}? access(all) view fun getCapabilityFilter(): &{CapabilityFilter.Filter}? + access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? } /// Methods accessible to the designated parent of a ChildAccount /// access(all) resource interface AccountPrivate { - access(Capabilities) view fun getCapability(controllerID: UInt64, type: Type): Capability? { + access(Child) view fun getCapability(controllerID: UInt64, type: Type): Capability? { post { result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)): "Capability is not allowed by this account's Parent" } } access(all) view fun getManagerCapabilityFilter(): &{CapabilityFilter.Filter}? - access(Capabilities) view fun getPrivateCapFromDelegator(type: Type): Capability? { + access(Child) view fun getPrivateCapFromDelegator(type: Type): Capability? { post { result == nil || [true, nil].contains(self.getManagerCapabilityFilter()?.allowed(cap: result!)): "Capability is not allowed by this account's Parent" @@ -236,8 +241,8 @@ access(all) contract HybridCustody { /// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts /// access(all) resource interface ManagerPrivate { - access(Manage) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) - access(Manage) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? + access(Manage) fun addAccount(cap: Capability) + access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? access(Manage) fun removeChild(addr: Address) access(Manage) fun addOwnedAccount(cap: Capability) access(Manage) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? @@ -265,7 +270,7 @@ access(all) contract HybridCustody { access(all) resource Manager: ManagerPrivate, ManagerPublic, ViewResolver.Resolver { /// Mapping of restricted access child account Capabilities indexed by their address - access(self) let childAccounts: {Address: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>} + access(self) let childAccounts: {Address: Capability} /// Mapping of unrestricted owned account Capabilities indexed by their address access(self) let ownedAccounts: {Address: Capability} @@ -299,7 +304,7 @@ access(all) contract HybridCustody { /// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be /// added to the ChildAccount /// - access(Manage) fun addAccount(cap: Capability<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>) { + access(Manage) fun addAccount(cap: Capability) { pre { self.childAccounts[cap.address] == nil: "There is already a child account with this address" } @@ -390,7 +395,7 @@ access(all) contract HybridCustody { /// Returns a reference to a child account /// - access(Manage) fun borrowAccount(addr: Address): &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? { + access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? { let cap = self.childAccounts[addr] if cap == nil { return nil @@ -443,7 +448,7 @@ access(all) contract HybridCustody { /// mechanism intended to easily transfer 'root' access on this account to another account and an attempt to /// minimize access vectors. /// - access(Owner) fun giveOwnership(addr: Address, to: Address) { + access(Manage) fun giveOwnership(addr: Address, to: Address) { let acct = self.ownedAccounts.remove(key: addr) ?? panic("account not found") @@ -584,7 +589,7 @@ access(all) contract HybridCustody { /// Capabilities, see `getPrivateCapFromDelegator()` and `getPublicCapFromDelegator()` which use the /// `Delegator` retrieval path. /// - access(Capabilities) view fun getCapability(controllerID: UInt64, type: Type): Capability? { + access(Child) view fun getCapability(controllerID: UInt64, type: Type): Capability? { let child = self.childCap.borrow() ?? panic("failed to borrow child account") let f = self.factory.borrow()!.getFactory(type) @@ -611,7 +616,7 @@ access(all) contract HybridCustody { /// Retrieves a private Capability from the Delegator or nil none is found of the given type. Useful for /// arbitrary Capability retrieval /// - access(Capabilities) view fun getPrivateCapFromDelegator(type: Type): Capability? { + access(Child) view fun getPrivateCapFromDelegator(type: Type): Capability? { if let d = self.delegator.borrow() { return d.getPrivateCapability(type) } @@ -753,6 +758,15 @@ access(all) contract HybridCustody { return self.factory.check() ? self.factory.borrow() : nil } + access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? { + let child = self.childCap.borrow() + if child == nil { + return nil + } + + return child!.getControllerIDForType(type: type, forPath: forPath) + } + // TODO: burnCallback and ResourceDestoryed event // destroy () { // destroy <- self.resources @@ -871,7 +885,7 @@ access(all) contract HybridCustody { let childAccountPrivatePath = PrivatePath(identifier: identifier)! acct.storage.save(<-childAcct, to: childAccountStorage) - let delegatorCap = acct.capabilities.storage.issue<&{AccountPrivate, AccountPublic, ViewResolver.Resolver}>(childAccountStorage) + let delegatorCap = acct.capabilities.storage.issue(childAccountStorage) assert(delegatorCap.check(), message: "Delegator capability check failed") acct.inbox.publish(delegatorCap, name: identifier, recipient: parentAddress) @@ -898,7 +912,7 @@ access(all) contract HybridCustody { /// Returns a reference to the encapsulated account object /// access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account { - return self.acct.borrow()! + return self.acct.borrow() ?? panic("unable to borrow Account Capability") } /// Returns the addresses of all associated parents pending and active @@ -1002,14 +1016,19 @@ access(all) contract HybridCustody { let acct = self.borrowAccount() // Unlink existing owner's Capability if owner exists - if self.acctOwner != nil { - acct.capabilities.account.getController(byCapabilityID: self.acct.id)?.delete() - } - + // TODO: is this still needed? Sealing the account should revoke and rotate all + // existing account links which should mean this one is already gone. + // if self.acctOwner != nil { + // acct.capabilities.account.getController(byCapabilityID: self.acct.id)?.delete() + // } // Link a Capability for the new owner, retrieve & publish let identifier = HybridCustody.getOwnerIdentifier(to) - let cap = acct.capabilities.storage.issue<&{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) + let cap = acct.capabilities.storage.issue(HybridCustody.OwnedAccountStoragePath) + + // make sure we can borrow the newly issued owned account + cap.borrow()!.borrowAccount() + acct.inbox.publish(cap, name: identifier, recipient: to) self.pendingOwner = to @@ -1043,11 +1062,7 @@ access(all) contract HybridCustody { let acct = self.borrowAccount() // Find all active AuthAccount capabilities so they can be removed after we make the new auth account cap - let idsToDestroy: [UInt64] = [] - acct.capabilities.account.forEachController(fun(con: &AccountCapabilityController): Bool { - idsToDestroy.append(con.capabilityID) - return true - }) + let controllersToDestroy = acct.capabilities.account.getControllers() // Link a new AuthAccount Capability let acctCap = acct.capabilities.account.issue() @@ -1057,9 +1072,11 @@ access(all) contract HybridCustody { // 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 - for id in idsToDestroy { - newAcct.capabilities.account.getController(byCapabilityID: id)?.delete() + for con in controllersToDestroy { + newAcct.capabilities.account.getController(byCapabilityID: con.capabilityID)?.delete() } + + assert(self.acct.check(), message: "new auth account capability is not valid") } /// Revokes all keys on an account, unlinks all currently active AuthAccount capabilities, then makes a new one @@ -1145,6 +1162,21 @@ access(all) contract HybridCustody { self.display = d } + access(all) view fun getControllerIDForType(type: Type, forPath: StoragePath): UInt64? { + let acct = self.acct.borrow() + if acct == nil { + return nil + } + + for c in acct!.capabilities.storage.getControllers(forPath: forPath) { + if c.borrowType.isSubtype(of: type) { + return c.capabilityID + } + } + + return nil + } + init( _ acct: Capability ) { diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index 880ca0a..b81ee13 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -9,7 +9,7 @@ access(all) contract FTProviderFactory { return nil } - return con.capability as! Capability<&auth(FungibleToken.Withdraw) &{FungibleToken.Provider}> + return con.capability as! Capability } return nil diff --git a/contracts/standard/ExampleToken.cdc b/contracts/standard/ExampleToken.cdc index 9047ac6..18b2c7c 100644 --- a/contracts/standard/ExampleToken.cdc +++ b/contracts/standard/ExampleToken.cdc @@ -276,6 +276,12 @@ access(all) contract ExampleToken: FungibleToken { return nil } + // EMULATOR ONLY, anyone can mint tokens + access(all) fun createNewMinter(allowedAmount: UFix64): @Minter { + emit MinterCreated(allowedAmount: allowedAmount) + return <-create Minter(allowedAmount: allowedAmount) + } + init() { self.totalSupply = 1000.0 diff --git a/scripts/example-nft-2/get_ids.cdc b/scripts/example-nft-2/get_ids.cdc index dc15c95..0bc27cc 100644 --- a/scripts/example-nft-2/get_ids.cdc +++ b/scripts/example-nft-2/get_ids.cdc @@ -1,8 +1,8 @@ import "ExampleNFT2" -pub fun main(addr: Address): [UInt64] { - let acct = getAuthAccount(addr) - let collection = acct.borrow<&ExampleNFT2.Collection>(from: ExampleNFT2.CollectionStoragePath) +access(all) fun main(addr: Address): [UInt64] { + let acct = getAuthAccount(addr) + let collection = acct.storage.borrow<&ExampleNFT2.Collection>(from: ExampleNFT2.CollectionStoragePath) ?? panic("collection not found") return collection.getIDs() } \ No newline at end of file diff --git a/scripts/example-nft/get_ids.cdc b/scripts/example-nft/get_ids.cdc index dfb4bed..e42c150 100644 --- a/scripts/example-nft/get_ids.cdc +++ b/scripts/example-nft/get_ids.cdc @@ -1,8 +1,8 @@ import "ExampleNFT" -pub fun main(addr: Address): [UInt64] { - let acct = getAuthAccount(addr) - let collection = acct.borrow<&ExampleNFT.Collection>(from: ExampleNFT.CollectionStoragePath) +access(all) fun main(addr: Address): [UInt64] { + let acct = getAuthAccount(addr) + let collection = acct.storage.borrow<&ExampleNFT.Collection>(from: ExampleNFT.CollectionStoragePath) ?? panic("collection not found") return collection.getIDs() } \ No newline at end of file diff --git a/scripts/example-token/get_balance.cdc b/scripts/example-token/get_balance.cdc index 120cf61..f665ac5 100644 --- a/scripts/example-token/get_balance.cdc +++ b/scripts/example-token/get_balance.cdc @@ -1,10 +1,14 @@ import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" -pub fun main(account: Address): UFix64 { +access(all) fun main(account: Address): UFix64 { let acct = getAccount(account) - let vaultRef = acct.getCapability(ExampleToken.VaultPublicPath) - .borrow<&ExampleToken.Vault{FungibleToken.Balance}>() + + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + + let vaultRef = acct.capabilities.get<&{FungibleToken.Balance}>(vaultData.metadataPath)!.borrow() ?? panic("Could not borrow Balance reference to the Vault") return vaultRef.balance diff --git a/scripts/factory/get_ft_balance_from_factory.cdc b/scripts/factory/get_ft_balance_from_factory.cdc index f6b713b..829a665 100644 --- a/scripts/factory/get_ft_balance_from_factory.cdc +++ b/scripts/factory/get_ft_balance_from_factory.cdc @@ -1,13 +1,13 @@ import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" import "FTBalanceFactory" -pub fun main(addr: Address) { - let acct = getAuthAccount(addr) - let ref = &acct as &AuthAccount - +access(all) fun main(addr: Address) { + let acct = getAuthAccount(addr) let factory = FTBalanceFactory.Factory() - - let provider = factory.getCapability(acct: ref, path: ExampleToken.VaultPublicPath) as! Capability<&{FungibleToken.Balance}> + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + factory.getPublicCapability(acct: acct, path: vaultData.metadataPath)! as! Capability<&{FungibleToken.Balance}> } \ No newline at end of file diff --git a/scripts/factory/get_ft_provider_from_factory.cdc b/scripts/factory/get_ft_provider_from_factory.cdc index 510c277..c3d7f31 100644 --- a/scripts/factory/get_ft_provider_from_factory.cdc +++ b/scripts/factory/get_ft_provider_from_factory.cdc @@ -1,13 +1,25 @@ import "FungibleToken" +import "ExampleToken" +import "FungibleTokenMetadataViews" import "FTProviderFactory" -pub fun main(addr: Address) { - let acct = getAuthAccount(addr) - let ref = &acct as &AuthAccount - +access(all) fun main(addr: Address) { + let acct = getAuthAccount(addr) let factory = FTProviderFactory.Factory() - let providerPath = /private/exampleTokenProvider - let provider = factory.getCapability(acct: ref, path: providerPath) as! Capability<&{FungibleToken.Provider}> + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + + acct.capabilities.storage.issue(vaultData.storagePath) + + let controllers = acct.capabilities.storage.getControllers(forPath: vaultData.storagePath) + for c in controllers { + if c.borrowType.isSubtype(of: Type()) { + factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability + return + } + } + + panic("should not reach this point") } \ No newline at end of file diff --git a/scripts/factory/get_nft_provider_from_factory_allowed.cdc b/scripts/factory/get_nft_provider_from_factory_allowed.cdc index cc8e960..4c963da 100644 --- a/scripts/factory/get_nft_provider_from_factory_allowed.cdc +++ b/scripts/factory/get_nft_provider_from_factory_allowed.cdc @@ -9,20 +9,30 @@ import "NFTProviderFactory" /// Determines if ExampleNFT Provider both has a Factory at the ruleAddr and is allowed by the AllowlistFilter found in /// the ruleAddr account. /// -pub fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { - let ruleAcct = getAuthAccount(filterFactoryAddr) - let providerAcct = &getAuthAccount(providerAddr) as! &AuthAccount +access(all) fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { + let ruleAcct = getAuthAccount(filterFactoryAddr) + let providerAcct = getAuthAccount(providerAddr) - let factoryManager = ruleAcct.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) + let factoryManager = ruleAcct.storage.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) ?? panic("Problem borrowing CapabilityFactory Manager") - let factory = factoryManager.getFactory(Type<&{NonFungibleToken.Provider}>()) + let factory = factoryManager.getFactory(Type()) ?? panic("No factory for NFT Provider found") - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let provider = factory.getCapability(acct: providerAcct, path: d.providerPath) as! Capability<&{NonFungibleToken.Provider}> + var controllerID: UInt64? = nil + for c in providerAcct.capabilities.storage.getControllers(forPath: d.storagePath) { + if c.borrowType.isSubtype(of: Type()) { + controllerID = c.capabilityID + break + } + } - let filter = ruleAcct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) + assert(controllerID != nil, message: "could not find existing provider capcon") + + let provider = factory.getCapability(acct: providerAcct, controllerID: controllerID!)! as! Capability + + let filter = ruleAcct.storage.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) ?? panic("Problem borrowing CapabilityFilter AllowlistFilter") return filter.allowed(cap: provider) diff --git a/scripts/hybrid-custody/check_default_auth_acct_linked_path.cdc b/scripts/hybrid-custody/check_default_auth_acct_linked_path.cdc deleted file mode 100644 index ed57ad1..0000000 --- a/scripts/hybrid-custody/check_default_auth_acct_linked_path.cdc +++ /dev/null @@ -1,6 +0,0 @@ -import "HybridCustody" - -pub fun main(addr: Address): Bool { - let acct = getAuthAccount(addr) - return acct.getCapability<&AuthAccount>(HybridCustody.LinkedAccountPrivatePath).check() -} \ No newline at end of file diff --git a/scripts/hybrid-custody/get_account_cap_con_id.cdc b/scripts/hybrid-custody/get_account_cap_con_id.cdc new file mode 100644 index 0000000..ed25c89 --- /dev/null +++ b/scripts/hybrid-custody/get_account_cap_con_id.cdc @@ -0,0 +1,11 @@ +import "HybridCustody" + +access(all) fun main(addr: Address): UInt64? { + let acct: auth(Capabilities) &Account = getAuthAccount(addr) + let controllers = acct.capabilities.account.getControllers() + if controllers.length == 0 { + return nil + } + + return controllers[0].capabilityID +} \ No newline at end of file diff --git a/scripts/hybrid-custody/get_all_flow_balances.cdc b/scripts/hybrid-custody/get_all_flow_balances.cdc index fb93613..d1efc56 100644 --- a/scripts/hybrid-custody/get_all_flow_balances.cdc +++ b/scripts/hybrid-custody/get_all_flow_balances.cdc @@ -3,7 +3,7 @@ import "HybridCustody" /// Queries for $FLOW balance of a given Address and all its associated accounts /// -pub fun main(address: Address): {Address: UFix64} { +access(all) fun main(address: Address): {Address: UFix64} { // Get the balance for the given address let balances: {Address: UFix64} = { address: getAccount(address).balance } @@ -12,7 +12,7 @@ pub fun main(address: Address): {Address: UFix64} { /* Iterate over any associated accounts */ // - if let managerRef = getAuthAccount(address).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { + if let managerRef = getAuthAccount(address).storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { for childAccount in managerRef.getChildAddresses() { balances.insert(key: childAccount, getAccount(childAccount).balance) diff --git a/scripts/hybrid-custody/get_child_account_ft_capabilities.cdc b/scripts/hybrid-custody/get_child_account_ft_capabilities.cdc index b102d64..761ed49 100644 --- a/scripts/hybrid-custody/get_child_account_ft_capabilities.cdc +++ b/scripts/hybrid-custody/get_child_account_ft_capabilities.cdc @@ -3,38 +3,41 @@ import "FungibleToken" // This script iterates through a parent's child accounts, // identifies private paths with an accessible FungibleToken.Provider, and returns the corresponding typeIds -pub fun main(addr: Address):AnyStruct { - let account = getAuthAccount(addr) - let manager = getAuthAccount(addr).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic ("manager does not exist") +access(all) fun main(addr: Address):AnyStruct { + let account = getAuthAccount(addr) + let manager = getAuthAccount(addr).storage.borrow(from: HybridCustody.ManagerStoragePath) + ?? panic ("manager does not exist") - var typeIdsWithProvider = {} as {Address: [String]} + var typeIdsWithProvider: {Address: [String]} = {} - let providerType = Type>() + let providerType = Type() // Iterate through child accounts for address in manager.getChildAddresses() { - let addr = getAuthAccount(address) + let addr = getAuthAccount(address) let foundTypes: [String] = [] let childAcct = manager.borrowAccount(addr: address) ?? panic("child account not found") // get all private paths - addr.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { - // Check which private paths have FT Provider AND can be borrowed - if !type.isSubtype(of: providerType){ - return true - } - if let cap = childAcct.getCapability(path: path, type: Type<&{FungibleToken.Provider}>()) { - let providerCap = cap as! Capability<&{FungibleToken.Provider}> - if !providerCap.check(){ - return true + for s in addr.storage.storagePaths { + for c in addr.capabilities.storage.getControllers(forPath: s) { + if !c.borrowType.isSubtype(of: providerType){ + continue } + if let cap = childAcct.getCapability(controllerID: c.capabilityID, type: providerType) { + let providerCap = cap as! Capability<&{FungibleToken.Provider}> + + if !providerCap.check(){ + continue + } + foundTypes.append(cap.borrow<&AnyResource>()!.getType().identifier) + typeIdsWithProvider[address] = foundTypes + break } - return true - }) - - typeIdsWithProvider[address] = foundTypes + } + } } return typeIdsWithProvider diff --git a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc index 3d3a64a..85978f4 100644 --- a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc +++ b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc @@ -3,38 +3,41 @@ import "NonFungibleToken" // This script iterates through a parent's child accounts, // identifies private paths with an accessible NonFungibleToken.Provider, and returns the corresponding typeIds -pub fun main(addr: Address):AnyStruct { - let account = getAuthAccount(addr) - let manager = getAuthAccount(addr).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic ("manager does not exist") +access(all) fun main(addr: Address): AnyStruct { + let account = getAuthAccount(addr) + let manager = getAuthAccount(addr).storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic ("manager does not exist") - var typeIdsWithProvider = {} as {Address: [String]} + var typeIdsWithProvider: {Address: [String]} = {} - let providerType = Type>() + let providerType = Type() // Iterate through child accounts for address in manager.getChildAddresses() { - let addr = getAuthAccount(address) + let addr = getAuthAccount(address) let foundTypes: [String] = [] let childAcct = manager.borrowAccount(addr: address) ?? panic("child account not found") // get all private paths - addr.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { - // Check which private paths have NFT Provider AND can be borrowed - if !type.isSubtype(of: providerType){ - return true - } - if let cap = childAcct.getCapability(path: path, type: Type<&{NonFungibleToken.Provider}>()) { - let providerCap = cap as! Capability<&{NonFungibleToken.Provider}> - if !providerCap.check(){ - return true + for s in addr.storage.storagePaths { + let controllers = addr.capabilities.storage.getControllers(forPath: s) + for c in controllers { + if !c.borrowType.isSubtype(of: providerType) { + continue } + if let cap = childAcct.getCapability(controllerID: c.capabilityID, type: providerType) { + let providerCap = cap as! Capability + + if !providerCap.check(){ + continue + } + foundTypes.append(cap.borrow<&AnyResource>()!.getType().identifier) + typeIdsWithProvider[address] = foundTypes + break } - return true - }) - - typeIdsWithProvider[address] = foundTypes + } + } } return typeIdsWithProvider diff --git a/scripts/hybrid-custody/get_child_addresses.cdc b/scripts/hybrid-custody/get_child_addresses.cdc index daea862..29f4876 100644 --- a/scripts/hybrid-custody/get_child_addresses.cdc +++ b/scripts/hybrid-custody/get_child_addresses.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(parent: Address): [Address] { - let acct = getAuthAccount(parent) - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address): [Address] { + let acct = getAuthAccount(parent) + let manager = acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") return manager.getChildAddresses() } \ No newline at end of file diff --git a/scripts/hybrid-custody/get_collection_from_inbox.cdc b/scripts/hybrid-custody/get_collection_from_inbox.cdc index 2a173fd..bb83cb0 100644 --- a/scripts/hybrid-custody/get_collection_from_inbox.cdc +++ b/scripts/hybrid-custody/get_collection_from_inbox.cdc @@ -2,13 +2,20 @@ import "HybridCustody" import "NonFungibleToken" import "ExampleNFT" -pub fun main(parent: Address, child: Address) { - let acct = getAuthAccount(parent) +access(all) fun main(parent: Address, child: Address) { + let acct = getAuthAccount(parent) + let childAcct: auth(Storage, Capabilities, Inbox) &Account = getAuthAccount(child) let inboxIdentifier = HybridCustody.getChildAccountIdentifier(parent) - let cap = acct.inbox.claim<&HybridCustody.ChildAccount{HybridCustody.AccountPrivate}>(inboxIdentifier, provider: child) + let cap = acct.inbox.claim(inboxIdentifier, provider: child) ?? panic("no inbox entry found") - cap.borrow()!.getCapability(path: ExampleNFT.CollectionPublicPath, type: Type<&{NonFungibleToken.CollectionPublic}>()) - ?? panic("capability not found") + for c in childAcct.capabilities.storage.getControllers(forPath: ExampleNFT.CollectionStoragePath) { + if c.borrowType.isSubtype(of: Type<&{NonFungibleToken.CollectionPublic}>()) { + cap.borrow()!.getCapability(controllerID: c.capabilityID, type: Type<&{NonFungibleToken.CollectionPublic}>()) + return + } + } + + panic("this should not be reached") } \ No newline at end of file diff --git a/scripts/hybrid-custody/get_examplenft_collection_from_delegator.cdc b/scripts/hybrid-custody/get_examplenft_collection_from_delegator.cdc index c655bba..5f47d34 100644 --- a/scripts/hybrid-custody/get_examplenft_collection_from_delegator.cdc +++ b/scripts/hybrid-custody/get_examplenft_collection_from_delegator.cdc @@ -1,8 +1,9 @@ import "HybridCustody" import "ExampleNFT" +import "NonFungibleToken" -pub fun main(parent: Address, child: Address, isPublic: Bool) { - let m = getAuthAccount(parent).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address, isPublic: Bool) { + let m = getAuthAccount(parent).storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") let acct = m.borrowAccount(addr: child) ?? panic("child account not found in manager") diff --git a/scripts/hybrid-custody/get_ft_provider_capability.cdc b/scripts/hybrid-custody/get_ft_provider_capability.cdc index 19cd9e7..119c123 100644 --- a/scripts/hybrid-custody/get_ft_provider_capability.cdc +++ b/scripts/hybrid-custody/get_ft_provider_capability.cdc @@ -2,16 +2,35 @@ import "HybridCustody" import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" // Verify that a child address borrowed as a child will let the parent borrow an FT provider capability -pub fun main(parent: Address, child: Address) { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address) { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = m.borrowAccount(addr: child) ?? panic("child account not found") - let nakedCap = childAcct.getCapability(path: /private/exampleTokenProvider, type: Type<&{FungibleToken.Provider}>()) - ?? panic("Could not borrow reference to the owner's Vault!") + + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + + // find the et provider + var controllerID: UInt64? = nil + let desiredType = Type() + let childAuthAcct = getAuthAccount(child) + for c in childAuthAcct.capabilities.storage.getControllers(forPath: vaultData.storagePath) { + if c.borrowType.isSubtype(of: desiredType) { + controllerID = c.capabilityID + break + } + } + + assert(controllerID != nil, message: "could not find controller id for FungibleToken Provider") + + + let nakedCap = childAcct.getCapability(controllerID: controllerID!, type: Type()) + ?? panic("Could not borrow reference to the owner's Vault!") let providerCap = nakedCap as! Capability<&{FungibleToken.Provider}> assert(providerCap.check(), message: "invalid provider capability") providerCap.borrow()! diff --git a/scripts/hybrid-custody/get_nft_collection_public_capability.cdc b/scripts/hybrid-custody/get_nft_collection_public_capability.cdc index 18da81f..8ce0b40 100644 --- a/scripts/hybrid-custody/get_nft_collection_public_capability.cdc +++ b/scripts/hybrid-custody/get_nft_collection_public_capability.cdc @@ -5,16 +5,19 @@ import "MetadataViews" import "ExampleNFT" // Verify that a child address borrowed as a child will let the parent borrow an NFT provider capability -pub fun main(parent: Address, child: Address) { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address) { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = m.borrowAccount(addr: child) ?? panic("child account not found") - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData + let type = Type<&{NonFungibleToken.CollectionPublic}>() + let controllerId = childAcct.getControllerIDForType(type: type, forPath: d.storagePath) + ?? panic("no controller ID found for desired type") - let nakedCap = childAcct.getCapability(path: d.providerPath, type: Type<&{NonFungibleToken.CollectionPublic}>()) + let nakedCap = childAcct.getCapability(controllerID: controllerId, type: type) ?? panic("capability not found") let cap = nakedCap as! Capability<&{NonFungibleToken.CollectionPublic}> diff --git a/scripts/hybrid-custody/get_nft_provider_capability.cdc b/scripts/hybrid-custody/get_nft_provider_capability.cdc index f2401fb..d80c390 100644 --- a/scripts/hybrid-custody/get_nft_provider_capability.cdc +++ b/scripts/hybrid-custody/get_nft_provider_capability.cdc @@ -5,16 +5,20 @@ import "MetadataViews" import "ExampleNFT" // Verify that a child address borrowed as a child will let the parent borrow an NFT provider capability -pub fun main(parent: Address, child: Address) { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address) { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = m.borrowAccount(addr: child) ?? panic("child account not found") - let d = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let nakedCap = childAcct.getCapability(path: d.providerPath, type: Type<&{NonFungibleToken.Provider}>()) + let desiredType = Type() + let controllerID = childAcct.getControllerIDForType(type: desiredType, forPath: d.storagePath) + ?? panic("no capability found for desired type") + + let nakedCap = childAcct.getCapability(controllerID: controllerID, type: desiredType) ?? panic("capability not found") let cap = nakedCap as! Capability<&{NonFungibleToken.Provider}> diff --git a/scripts/hybrid-custody/get_num_valid_keys.cdc b/scripts/hybrid-custody/get_num_valid_keys.cdc index 2d87364..5242da3 100644 --- a/scripts/hybrid-custody/get_num_valid_keys.cdc +++ b/scripts/hybrid-custody/get_num_valid_keys.cdc @@ -1,5 +1,5 @@ -pub fun main(addr: Address): Int { - let acct = getAuthAccount(addr) +access(all) fun main(addr: Address): Int { + let acct = getAuthAccount(addr) var count = 0 acct.keys.forEach(fun (key: AccountKey): Bool { diff --git a/scripts/hybrid-custody/get_owner_of_child.cdc b/scripts/hybrid-custody/get_owner_of_child.cdc index 9d05416..05fbaa7 100644 --- a/scripts/hybrid-custody/get_owner_of_child.cdc +++ b/scripts/hybrid-custody/get_owner_of_child.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(addr: Address): Address? { - let acct = getAuthAccount(addr) - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(addr: Address): Address? { + let acct = getAuthAccount(addr) + let o = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account missing") return o.getOwner() diff --git a/scripts/hybrid-custody/get_parent_addresses.cdc b/scripts/hybrid-custody/get_parent_addresses.cdc index b4a1c94..46fa77c 100644 --- a/scripts/hybrid-custody/get_parent_addresses.cdc +++ b/scripts/hybrid-custody/get_parent_addresses.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(child: Address): [Address] { - let acct = getAuthAccount(child) - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(child: Address): [Address] { + let acct = getAuthAccount(child) + let o = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") return o.getParentAddresses() } \ No newline at end of file diff --git a/scripts/hybrid-custody/get_pending_owner_of_child.cdc b/scripts/hybrid-custody/get_pending_owner_of_child.cdc index e733bec..1cf9f63 100644 --- a/scripts/hybrid-custody/get_pending_owner_of_child.cdc +++ b/scripts/hybrid-custody/get_pending_owner_of_child.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(addr: Address): Address? { - let acct = getAuthAccount(addr) - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(addr: Address): Address? { + let acct = getAuthAccount(addr) + let o = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account missing") return o.getPendingOwner() diff --git a/scripts/hybrid-custody/get_spec_balance_from_public.cdc b/scripts/hybrid-custody/get_spec_balance_from_public.cdc index a44db15..0d044bd 100644 --- a/scripts/hybrid-custody/get_spec_balance_from_public.cdc +++ b/scripts/hybrid-custody/get_spec_balance_from_public.cdc @@ -3,13 +3,18 @@ import "HybridCustody" /// Returns the balance of the object (presumably a FungibleToken Vault) at the given path in the specified account /// -pub fun getVaultBalance(_ address: Address, _ balancePath: PublicPath): UFix64 { - return getAccount(address).getCapability<&{FungibleToken.Balance}>(balancePath).borrow()?.balance ?? 0.0 +access(all) fun getVaultBalance(_ address: Address, _ balancePath: PublicPath): UFix64 { + let cap = getAccount(address).capabilities.get<&{FungibleToken.Balance}>(balancePath) + if cap == nil { + return 0.0 + } + + return cap!.borrow()?.balance ?? 0.0 } /// Queries for FT.Vault balance of all FT.Vaults at given path in the specified account and all of its associated accounts /// -pub fun main(address: Address, balancePath: PublicPath): {Address: UFix64} { +access(all) fun main(address: Address, balancePath: PublicPath): {Address: UFix64} { // Get the balance for the given address let balances: {Address: UFix64} = { address: getVaultBalance(address, balancePath) } @@ -18,7 +23,7 @@ pub fun main(address: Address, balancePath: PublicPath): {Address: UFix64} { /* Iterate over any associated accounts */ // - if let managerRef = getAuthAccount(address).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { + if let managerRef = getAuthAccount(address).storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { for childAccount in managerRef.getChildAddresses() { balances.insert(key: childAccount, getVaultBalance(address, balancePath)) diff --git a/scripts/hybrid-custody/has_address_as_child.cdc b/scripts/hybrid-custody/has_address_as_child.cdc index 5bc5fe8..7f54937 100644 --- a/scripts/hybrid-custody/has_address_as_child.cdc +++ b/scripts/hybrid-custody/has_address_as_child.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(parent: Address, child: Address): Bool { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address): Bool { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") let childAccount = m.borrowAccount(addr: child) diff --git a/scripts/hybrid-custody/has_child_accounts.cdc b/scripts/hybrid-custody/has_child_accounts.cdc index 63f87cb..818a0b9 100644 --- a/scripts/hybrid-custody/has_child_accounts.cdc +++ b/scripts/hybrid-custody/has_child_accounts.cdc @@ -2,9 +2,9 @@ import "HybridCustody" /// Returns whether the given Address has a HybridCustod.Manager with child accounts or not /// -pub fun main(parent: Address): Bool { - let acct = getAuthAccount(parent) - if let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { +access(all) fun main(parent: Address): Bool { + let acct = getAuthAccount(parent) + if let manager = acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { return manager.getChildAddresses().length > 0 } return false diff --git a/scripts/hybrid-custody/has_owned_accounts.cdc b/scripts/hybrid-custody/has_owned_accounts.cdc index 4f6d9f3..c0ad0dc 100644 --- a/scripts/hybrid-custody/has_owned_accounts.cdc +++ b/scripts/hybrid-custody/has_owned_accounts.cdc @@ -2,9 +2,9 @@ import "HybridCustody" /// Returns whether the given Address has a HybridCustod.Manager with owned accounts or not /// -pub fun main(parent: Address): Bool { - let acct = getAuthAccount(parent) - if let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { +access(all) fun main(parent: Address): Bool { + let acct = getAuthAccount(parent) + if let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) { return manager.getOwnedAddresses().length > 0 } return false diff --git a/scripts/hybrid-custody/is_parent.cdc b/scripts/hybrid-custody/is_parent.cdc index ae82d71..d277f5b 100644 --- a/scripts/hybrid-custody/is_parent.cdc +++ b/scripts/hybrid-custody/is_parent.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(child: Address, parent: Address): Bool { - let acct = getAuthAccount(child) - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(child: Address, parent: Address): Bool { + let acct = getAuthAccount(child) + let owned = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") return owned.isChildOf(parent) diff --git a/scripts/hybrid-custody/is_redeemed.cdc b/scripts/hybrid-custody/is_redeemed.cdc index aecdedb..dfda220 100644 --- a/scripts/hybrid-custody/is_redeemed.cdc +++ b/scripts/hybrid-custody/is_redeemed.cdc @@ -1,8 +1,8 @@ import "HybridCustody" -pub fun main(child: Address, parent: Address): Bool { - let acct = getAuthAccount(child) - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(child: Address, parent: Address): Bool { + let acct = getAuthAccount(child) + let owned = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") return owned.getRedeemedStatus(addr: parent) ?? panic("no status found") diff --git a/scripts/hybrid-custody/metadata/assert_owned_account_display.cdc b/scripts/hybrid-custody/metadata/assert_owned_account_display.cdc index be49386..4dbe2bc 100644 --- a/scripts/hybrid-custody/metadata/assert_owned_account_display.cdc +++ b/scripts/hybrid-custody/metadata/assert_owned_account_display.cdc @@ -1,9 +1,9 @@ import "HybridCustody" import "MetadataViews" -pub fun main(addr: Address, name: String, desc: String, thumbnail: String): Bool { - let acct = getAuthAccount(addr) - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(addr: Address, name: String, desc: String, thumbnail: String): Bool { + let acct = getAuthAccount(addr) + let owned = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("no owned account found") let display = owned.resolveView(Type())! as! MetadataViews.Display diff --git a/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc b/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc index 24baaa0..2cec87f 100644 --- a/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc +++ b/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc @@ -1,9 +1,9 @@ import "HybridCustody" import "MetadataViews" -pub fun main(parent: Address, child: Address): String { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address): String { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") let c = m.borrowAccount(addr: child) ?? panic("child not found") diff --git a/scripts/hybrid-custody/metadata/resolve_owned_display_name.cdc b/scripts/hybrid-custody/metadata/resolve_owned_display_name.cdc index 4e056bd..5164f1d 100644 --- a/scripts/hybrid-custody/metadata/resolve_owned_display_name.cdc +++ b/scripts/hybrid-custody/metadata/resolve_owned_display_name.cdc @@ -1,9 +1,9 @@ import "HybridCustody" import "MetadataViews" -pub fun main(child: Address): String { - let acct = getAuthAccount(child) - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) +access(all) fun main(child: Address): String { + let acct = getAuthAccount(child) + let o = acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") let d = o.resolveView(Type())! as! MetadataViews.Display diff --git a/scripts/hybrid-custody/verify_child_address.cdc b/scripts/hybrid-custody/verify_child_address.cdc index 0105895..607bfac 100644 --- a/scripts/hybrid-custody/verify_child_address.cdc +++ b/scripts/hybrid-custody/verify_child_address.cdc @@ -4,9 +4,9 @@ import "HybridCustody" Verify that a owned address borrowed as a child matches the address it is mapped to in the account manager */ -pub fun main(parent: Address, child: Address) { - let acct = getAuthAccount(parent) - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address) { + let acct = getAuthAccount(parent) + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = m.borrowAccount(addr: child) ?? panic("child account not found") diff --git a/scripts/test/can_get_child_factory_and_filter_caps.cdc b/scripts/test/can_get_child_factory_and_filter_caps.cdc index f4b28c4..03c9f7d 100644 --- a/scripts/test/can_get_child_factory_and_filter_caps.cdc +++ b/scripts/test/can_get_child_factory_and_filter_caps.cdc @@ -2,12 +2,25 @@ import "HybridCustody" // @addr - The address of the child account // @parent - The parent account that this child is assigned to -pub fun main(addr: Address, parent: Address): Bool { +access(all) fun main(addr: Address, parent: Address): Bool { let identifier = HybridCustody.getChildAccountIdentifier(parent) let path = PrivatePath(identifier: identifier) ?? panic("invalid public path identifier for parent address") - let acctPublic = getAuthAccount(addr).getCapability<&HybridCustody.ChildAccount{HybridCustody.AccountPublic}>(path) - .borrow() ?? panic("account public not found") + let acct = getAuthAccount(addr) + var controllerID: UInt64? = nil + for c in acct.capabilities.storage.getControllers(forPath: StoragePath(identifier: identifier)!) { + if c.borrowType.isSubtype(of: Type<&{HybridCustody.AccountPublic}>()) { + controllerID = c.capabilityID + break + } + } + + assert(controllerID != nil, message: "could not find controller id for parent identifier") + + let controller = getAuthAccount(addr).capabilities.storage.getController(byCapabilityID: controllerID!) + ?? panic("controller not found") + let cap = controller.capability as! Capability<&{HybridCustody.AccountPublic}> + let acctPublic = cap.borrow()! let factory = acctPublic.getCapabilityFactoryManager() assert(factory != nil, message: "capability factory is not valid") diff --git a/scripts/test/create_manager_with_invalid_filter.cdc b/scripts/test/create_manager_with_invalid_filter.cdc index fc8e90e..e40688b 100644 --- a/scripts/test/create_manager_with_invalid_filter.cdc +++ b/scripts/test/create_manager_with_invalid_filter.cdc @@ -1,9 +1,13 @@ import "CapabilityFilter" import "HybridCustody" -pub fun main(address: Address): Bool { +access(all) fun main(address: Address): Bool { + let acct = getAuthAccount(address) // Retrieving invalid Filter capability - let invalidFilterCap = getAuthAccount(address).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PrivatePath) + let invalidFilterCap = acct.capabilities.storage.issue<&{CapabilityFilter.Filter}>(CapabilityFilter.StoragePath) + + acct.capabilities.storage.getController(byCapabilityID: invalidFilterCap.id)!.delete() + // This step should fail due to CapabilityFilter.Filter Capability check on Manager init let manager <- HybridCustody.createManager(filter: invalidFilterCap) // Destroy and return diff --git a/scripts/test/get_all_vault_bal_from_storage.cdc b/scripts/test/get_all_vault_bal_from_storage.cdc index 2218904..368b3bc 100644 --- a/scripts/test/get_all_vault_bal_from_storage.cdc +++ b/scripts/test/get_all_vault_bal_from_storage.cdc @@ -4,9 +4,9 @@ import "HybridCustody" /// Returns a mapping of balances indexed on the Type of resource containing the balance /// -pub fun getAllBalancesInStorage(_ address: Address): {String: UFix64} { +access(all) fun getAllBalancesInStorage(_ address: Address): {String: UFix64} { // Get the account - let account: AuthAccount = getAuthAccount(address) + let account: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account = getAuthAccount(address) // Init for return value let balances: {String: UFix64} = {} // Track seen Types in array @@ -14,10 +14,10 @@ pub fun getAllBalancesInStorage(_ address: Address): {String: UFix64} { // Assign the type we'll need let balanceType: Type = Type<@{FungibleToken.Balance}>() // Iterate over all stored items & get the path if the type is what we're looking for - account.forEachStored(fun (path: StoragePath, type: Type): Bool { + account.storage.forEachStored(fun (path: StoragePath, type: Type): Bool { if type.isInstance(balanceType) || type.isSubtype(of: balanceType) { // Get a reference to the resource & its balance - let vaultRef = account.borrow<&{FungibleToken.Balance}>(from: path)! + let vaultRef = account.storage.borrow<&{FungibleToken.Balance}>(from: path)! // Insert a new values if it's the first time we've seen the type if !seen.contains(type) { balances.insert(key: type.identifier, vaultRef.balance) @@ -34,7 +34,7 @@ pub fun getAllBalancesInStorage(_ address: Address): {String: UFix64} { /// Queries for FT.Vault balance of all FT.Vaults in the specified account and all of its associated accounts /// -pub fun main(address: Address): {Address: {String: UFix64}} { +access(all) fun main(address: Address): {Address: {String: UFix64}} { // Get the balance for the given address let balances: {Address: {String: UFix64}} = { address: getAllBalancesInStorage(address) } @@ -43,9 +43,7 @@ pub fun main(address: Address): {Address: {String: UFix64}} { /* Iterate over any associated accounts */ // - if let managerRef = getAuthAccount(address) - .borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { - + if let managerRef = getAuthAccount(address).storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { for childAccount in managerRef.getChildAddresses() { balances.insert(key: childAccount, getAllBalancesInStorage(address)) seen.append(childAccount) diff --git a/scripts/test/get_flow_balance.cdc b/scripts/test/get_flow_balance.cdc index d2c5aef..497f649 100644 --- a/scripts/test/get_flow_balance.cdc +++ b/scripts/test/get_flow_balance.cdc @@ -1,3 +1,3 @@ -pub fun main(address: Address): UFix64 { +access(all) fun main(address: Address): UFix64 { return getAccount(address).balance } \ No newline at end of file diff --git a/scripts/test/get_nft_provider_capability_optional.cdc b/scripts/test/get_nft_provider_capability_optional.cdc index 85b8b06..635cb9d 100644 --- a/scripts/test/get_nft_provider_capability_optional.cdc +++ b/scripts/test/get_nft_provider_capability_optional.cdc @@ -5,16 +5,20 @@ import "MetadataViews" import "ExampleNFT" // Verify that a child address borrowed as a child will let the parent borrow an NFT provider capability -pub fun main(parent: Address, child: Address, returnsNil: Bool): Bool { - let acct = getAuthAccount(parent) - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) +access(all) fun main(parent: Address, child: Address, returnsNil: Bool): Bool { + let acct = getAuthAccount(parent) + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = manager.borrowAccount(addr: child) ?? panic("child account not found") - let collectionData = ExampleNFT.resolveView(Type())! as! MetadataViews.NFTCollectionData + let collectionData = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let nakedCap = childAcct.getCapability(path: collectionData.providerPath, type: Type<&{NonFungibleToken.Provider}>()) + let type = Type() + let controllerID = childAcct.getControllerIDForType(type: type, forPath: collectionData.storagePath) + ?? panic("could not find controller for desired type") + + let nakedCap = childAcct.getCapability(controllerID: controllerID, type: type) return returnsNil ? nakedCap == nil : nakedCap?.borrow<&{NonFungibleToken.Provider}>() != nil } \ No newline at end of file diff --git a/scripts/test/test_get_accessible_child_nfts.cdc b/scripts/test/test_get_accessible_child_nfts.cdc index 43b1375..587dc6b 100644 --- a/scripts/test/test_get_accessible_child_nfts.cdc +++ b/scripts/test/test_get_accessible_child_nfts.cdc @@ -10,7 +10,7 @@ import "MetadataViews" /// Assertion method to ensure passing test /// -pub fun assertPassing(result: {Address: {UInt64: MetadataViews.Display}}, expectedAddressToIDs: {Address: [UInt64]}) { +access(all) fun assertPassing(result: {Address: {UInt64: MetadataViews.Display}}, expectedAddressToIDs: {Address: [UInt64]}) { for address in expectedAddressToIDs.keys { let expectedIDs: [UInt64] = expectedAddressToIDs[address]! @@ -22,42 +22,44 @@ pub fun assertPassing(result: {Address: {UInt64: MetadataViews.Display}}, expect } } -pub fun main(addr: Address, expectedAddressToIDs: {Address: [UInt64]}){ - let manager = getAuthAccount(addr).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) ?? panic ("manager does not exist") +access(all) fun main(addr: Address, expectedAddressToIDs: {Address: [UInt64]}){ + let manager = getAuthAccount(addr).storage.borrow(from: HybridCustody.ManagerStoragePath) + ?? panic ("manager does not exist") - var typeIdsWithProvider = {} as {Address: [String]} - var nftViews = {} as {Address: {UInt64: MetadataViews.Display}} + var typeIdsWithProvider: {Address: [String]} = {} + var nftViews: {Address: {UInt64: MetadataViews.Display}} = {} - let providerType = Type>() + let providerType = Type() let collectionType: Type = Type<@{NonFungibleToken.CollectionPublic}>() for address in manager.getChildAddresses() { - let acct = getAuthAccount(address) + let acct = getAuthAccount(address) let foundTypes: [String] = [] let views: {UInt64: MetadataViews.Display} = {} let childAcct = manager.borrowAccount(addr: address) ?? panic("child account not found") - // get all private paths - acct.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { - // Check which private paths have NFT Provider AND can be borrowed - if !type.isSubtype(of: providerType){ - return true - } - - if let cap: Capability = childAcct.getCapability(path: path, type: Type<&{NonFungibleToken.Provider}>()) { - let providerCap = cap as! Capability<&{NonFungibleToken.Provider}> - if !providerCap.check(){ - return true + for s in acct.storage.storagePaths { + for c in acct.capabilities.storage.getControllers(forPath: s) { + if !c.borrowType.isSubtype(of: providerType){ + continue } - foundTypes.append(cap.borrow<&AnyResource>()!.getType().identifier) + if let cap: Capability = childAcct.getCapability(controllerID: c.capabilityID, type: providerType) { + let providerCap = cap as! Capability<&{NonFungibleToken.Provider}> + + if !providerCap.check(){ + continue + } + + foundTypes.append(cap.borrow<&AnyResource>()!.getType().identifier) + typeIdsWithProvider[address] = foundTypes + break + } } - return true - }) - typeIdsWithProvider[address] = foundTypes + } // iterate storage, check if typeIdsWithProvider contains the typeId, if so, add to views - acct.forEachStored(fun (path: StoragePath, type: Type): Bool { + acct.storage.forEachStored(fun (path: StoragePath, type: Type): Bool { if typeIdsWithProvider[address] == nil { return true @@ -73,10 +75,10 @@ pub fun main(addr: Address, expectedAddressToIDs: {Address: [UInt64]}){ if type.isInstance(collectionType) { continue } - if let collection = acct.borrow<&{NonFungibleToken.CollectionPublic}>(from: path) { + if let collection = acct.storage.borrow<&{NonFungibleToken.CollectionPublic}>(from: path) { // Iterate over IDs & resolve the view for id in collection.getIDs() { - let nft = collection.borrowNFT(id: id) + let nft = collection.borrowNFT(id)! if let display = nft.resolveView(Type())! as? MetadataViews.Display { views.insert(key: id, display) } diff --git a/scripts/test/test_get_all_collection_data_from_storage.cdc b/scripts/test/test_get_all_collection_data_from_storage.cdc index 4838084..78cd3a4 100644 --- a/scripts/test/test_get_all_collection_data_from_storage.cdc +++ b/scripts/test/test_get_all_collection_data_from_storage.cdc @@ -1,5 +1,6 @@ import "NonFungibleToken" import "MetadataViews" +import "ViewResolver" import "HybridCustody" /* @@ -10,7 +11,7 @@ import "HybridCustody" /// Assertion method to ensure passing test /// -pub fun assertPassing(result: {Address: [MetadataViews.NFTCollectionData]}, expectedAddressToCollectionLength: {Address: Int}) { +access(all) fun assertPassing(result: {Address: [MetadataViews.NFTCollectionData]}, expectedAddressToCollectionLength: {Address: Int}) { for address in result.keys { if expectedAddressToCollectionLength[address] == nil { panic("Address ".concat(address.toString()).concat(" found but not expected!")) @@ -23,29 +24,31 @@ pub fun assertPassing(result: {Address: [MetadataViews.NFTCollectionData]}, expe /// Helper function that retrieves data about all publicly accessible NFTs in an account /// -pub fun getAllViewsFromAddress(_ address: Address): [MetadataViews.NFTCollectionData] { +access(all) fun getAllViewsFromAddress(_ address: Address): [MetadataViews.NFTCollectionData] { - let account: AuthAccount = getAuthAccount(address) + let account: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account = getAuthAccount(address) let data: [MetadataViews.NFTCollectionData] = [] - let collectionType: Type = Type<@{NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection}>() + let collectionType: Type = Type<@{NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection}>() let viewType: Type = Type() // Iterate over each public path - account.forEachStored(fun (path: StoragePath, type: Type): Bool { + account.storage.forEachStored(fun (path: StoragePath, type: Type): Bool { // Return if not the type we're looking for if !type.isInstance(collectionType) && !type.isSubtype(of: collectionType) { return true } - if let collectionRef = account - .borrow<&{NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection}>(from: path) { + if let collectionRef = account.storage + .borrow<&{NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection}>(from: path) { // Return early if no Resolver found in the Collection let ids: [UInt64]= collectionRef.getIDs() if ids.length == 0 { return true } + // Otherwise, attempt to get the NFTCollectionData & append if exists - if let dataView = collectionRef.borrowViewResolver(id: ids[0]).resolveView(viewType) as! MetadataViews.NFTCollectionData? { + let nft = collectionRef.borrowNFT(ids[0]) ?? panic("nft not found") + if let dataView = nft.resolveView(viewType) as! MetadataViews.NFTCollectionData? { data.append(dataView) } } @@ -57,16 +60,16 @@ pub fun getAllViewsFromAddress(_ address: Address): [MetadataViews.NFTCollection /// Script that retrieve data about all NFT Collections in the storage of an account and any of its child accounts /// // pub fun main(address: Address): {Address: [MetadataViews.NFTCollectionData]} { -pub fun main(address: Address, expectedAddressToCollectionLength: {Address: Int}) { +access(all) fun main(address: Address, expectedAddressToCollectionLength: {Address: Int}) { let allNFTData: {Address: [MetadataViews.NFTCollectionData]} = {address: getAllViewsFromAddress(address)} let seen: [Address] = [address] /* Iterate over any child accounts */ // - if let managerRef = getAccount(address).getCapability<&HybridCustody.Manager{HybridCustody.ManagerPublic}>( + if let managerRef = getAccount(address).capabilities.get<&{HybridCustody.ManagerPublic}>( HybridCustody.ManagerPublicPath - ).borrow() { + )!.borrow() { for childAddress in managerRef.getChildAddresses() { allNFTData.insert(key: childAddress, getAllViewsFromAddress(childAddress)) diff --git a/scripts/test/test_get_nft_display_view_from_public.cdc b/scripts/test/test_get_nft_display_view_from_public.cdc index 7ceca66..4ecd874 100644 --- a/scripts/test/test_get_nft_display_view_from_public.cdc +++ b/scripts/test/test_get_nft_display_view_from_public.cdc @@ -1,5 +1,8 @@ import "NonFungibleToken" import "MetadataViews" +import "ViewResolver" +import "ExampleNFT" + import "HybridCustody" /* @@ -10,34 +13,29 @@ import "HybridCustody" /// Assertion method to ensure passing test /// -pub fun assertPassing(result: {Address: {UInt64: MetadataViews.Display}}, expectedAddressToIDs: {Address: [UInt64]}) { - +access(all) fun assertPassing(result: {Address: {UInt64: MetadataViews.Display}}, expectedAddressToIDs: {Address: [UInt64]}) { for address in result.keys { - if expectedAddressToIDs[address] == nil { - panic("Address ".concat(address.toString()).concat(" found but not expected!")) - } - let expectedIDs: [UInt64] = expectedAddressToIDs[address]! - for i, id in result[address]!.keys { - if expectedIDs[i] != id { - panic("Resulting ID does not match expected ID!") - } + let expectedIDs: [UInt64] = expectedAddressToIDs[address] ?? panic("address expected but not found") + + for id in result[address]!.keys { + assert(expectedIDs.contains(id), message: "id expected but was not found") } } } /// Returns resolved Display from given address at specified path for each ID or nil if ResolverCollection is not found /// -pub fun getViews(_ address: Address, _ resolverCollectionPath: PublicPath): {UInt64: MetadataViews.Display} { - - let account: PublicAccount = getAccount(address) +access(all) fun getViews(_ address: Address, _ resolverCollectionPath: PublicPath): {UInt64: MetadataViews.Display} { + let account: &Account = getAccount(address) let views: {UInt64: MetadataViews.Display} = {} // Borrow the Collection if let collection = account - .getCapability<&{NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection}>(resolverCollectionPath).borrow() { + .capabilities.get<&{NonFungibleToken.CollectionPublic}>(resolverCollectionPath)!.borrow() { // Iterate over IDs & resolve the view for id in collection.getIDs() { - let display = collection.borrowViewResolver(id: id).resolveView(Type()) as! MetadataViews.Display + let nft = collection.borrowNFT(id) ?? panic("could not borrow NFT") + let display = nft.resolveView(Type())! as! MetadataViews.Display views.insert(key: id, display) } } @@ -48,18 +46,17 @@ pub fun getViews(_ address: Address, _ resolverCollectionPath: PublicPath): {UIn /// Queries for MetadataViews.Display each NFT across all associated accounts from Collections at the provided /// PublicPath /// -// pub fun main(address: Address, resolverCollectionPath: PublicPath): {Address: {UInt64: MetadataViews.Display}} { -pub fun main(address: Address, resolverCollectionPath: PublicPath, expectedAddressToIDs: {Address: [UInt64]}) { - +access(all) fun main(address: Address, resolverCollectionPath: PublicPath, expectedAddressToIDs: {Address: [UInt64]}) { let allViews: {Address: {UInt64: MetadataViews.Display}} = {address: getViews(address, resolverCollectionPath)} let seen: [Address] = [address] /* Iterate over any associated accounts */ // - if let managerRef = getAuthAccount(address).borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { + if let managerRef = getAuthAccount(address).storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) { for childAccount in managerRef.getChildAddresses() { - allViews.insert(key: childAccount, getViews(address, resolverCollectionPath)) + let views = getViews(childAccount, resolverCollectionPath) + allViews.insert(key: childAccount, views) seen.append(childAccount) } diff --git a/scripts/test_imports.cdc b/scripts/test_imports.cdc index f3c32a6..7fd5e30 100644 --- a/scripts/test_imports.cdc +++ b/scripts/test_imports.cdc @@ -1,5 +1,5 @@ import "HybridCustody" -pub fun main(): Bool { +access(all) fun main(): Bool { return true } \ No newline at end of file diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index 15cf3bc..8522089 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -17,8 +17,8 @@ access(all) let FilterKindAll = "all" access(all) let FilterKindAllowList = "allowlist" access(all) let FilterKindDenyList = "denylist" -access(all) let exampleNFTPublicIdentifier = "ExampleNFTCollection" -access(all) let exampleNFT2PublicIdentifier = "ExampleNFT2Collection" +access(all) let exampleNFTPublicIdentifier = "exampleNFTCollection" +access(all) let exampleNFT2PublicIdentifier = "exampleNFT2Collection" // --------------- Test cases --------------- @@ -52,6 +52,8 @@ fun testSetupFactoryWithFT() { let tmp = Test.createAccount() setupFactoryManager(tmp) + txExecutor("example-token/setup.cdc", [tmp], [], nil) + scriptExecutor("factory/get_ft_provider_from_factory.cdc", [tmp.address]) scriptExecutor("factory/get_ft_balance_from_factory.cdc", [tmp.address]) scriptExecutor("factory/get_ft_receiver_from_factory.cdc", [tmp.address]) @@ -65,17 +67,18 @@ fun testSetupChildAccount() { access(all) fun testPublishAccount() { - let tmp = Test.createAccount() - setupOwnedAccount(tmp, FilterKindAll) + let child = Test.createAccount() + let parent = Test.createAccount() + + setupOwnedAccount(child, FilterKindAll) + setupNFTCollection(child) let factory = getTestAccount(nftFactory) let filter = getTestAccount(FilterKindAll) - let parent = Test.createAccount() - - txExecutor("hybrid-custody/publish_to_parent.cdc", [tmp], [parent.address, factory.address, filter.address], nil) + txExecutor("hybrid-custody/publish_to_parent.cdc", [child], [parent.address, factory.address, filter.address], nil) - scriptExecutor("hybrid-custody/get_collection_from_inbox.cdc", [parent.address, tmp.address]) + scriptExecutor("hybrid-custody/get_collection_from_inbox.cdc", [parent.address, child.address]) } access(all) @@ -103,6 +106,9 @@ fun testSetupOwnedAccountAndPublishRedeemed() { let factory = getTestAccount(nftFactory) let filter = getTestAccount(FilterKindAll) + setupFilter(filter, FilterKindAll) + setupFactoryManager(factory) + let parent = Test.createAccount() txExecutor("hybrid-custody/setup_owned_account_and_publish_to_parent.cdc", [child], [parent.address, factory.address, filter.address, nil, nil, nil], nil) @@ -119,6 +125,9 @@ fun testSetupOwnedAccountWithDisplayPublishRedeemed() { let factory = getTestAccount(nftFactory) let filter = getTestAccount(FilterKindAll) + setupFilter(filter, FilterKindAll) + setupFactoryManager(factory) + let parent = Test.createAccount() let name = "Test" @@ -270,7 +279,10 @@ fun testSeal() { let numKeysBefore = getNumValidKeys(child) Test.assert(numKeysBefore > 0, message: "no keys to revoke") - Test.assert(checkAuthAccountDefaultCap(account: child), message: "Missing Auth Account Capability at default path") + + // Get the controller ID for the current Account capability + let controllerID = getAccountCapControllerID(account: child) + ?? panic("controller ID should not be nil") let owner = getOwner(child: child) Test.assert(owner! == child.address, message: "mismatched owner") @@ -278,7 +290,9 @@ fun testSeal() { txExecutor("hybrid-custody/relinquish_ownership.cdc", [child], [], nil) let numKeysAfter = getNumValidKeys(child) Test.assert(numKeysAfter == 0, message: "not all keys were revoked") - Test.assert(!checkAuthAccountDefaultCap(account: child), message: "Found Auth Account Capability at default path") + let newControllerID = getAccountCapControllerID(account: child) + ?? panic("new controller ID should not be nil") + Test.assert(newControllerID != controllerID, message: "Found Auth Account Capability at default path") let ownerAfter = getOwner(child: child) Test.assert(ownerAfter == nil, message: "should not have an owner anymore") } @@ -767,6 +781,8 @@ fun testGetChildAccountNFTCapabilities(){ let isPublic = true setupNFT2Collection(child) + setupNFTCollection(child) + addNFTCollectionToDelegator(child: child, parent: parent, isPublic: isPublic) addNFT2CollectionToDelegator(child: child, parent: parent, isPublic: isPublic) @@ -793,6 +809,9 @@ fun testGetNFTsAccessibleFromChildAccount(){ setupNFTCollection(child) setupNFT2Collection(child) + setupNFTCollection(parent) + setupNFT2Collection(parent) + mintNFTDefault(accounts[exampleNFT]!, receiver: child) let expectedChildIDs = (scriptExecutor("example-nft/get_ids.cdc", [child.address]) as! [UInt64]?)! @@ -810,7 +829,7 @@ fun testGetNFTsAccessibleFromChildAccount(){ {child.address: expectedChildIDs} ]) - // Mint new nfts from ExampleNFT2 and assert that get_accessible_child_nfts.cdc does not return these nfts. + // // Mint new nfts from ExampleNFT2 and assert that get_accessible_child_nfts.cdc does not return these nfts. mintExampleNFT2Default(accounts[exampleNFT2]!, receiver: child) let expectedChildIDs2 = (scriptExecutor("example-nft-2/get_ids.cdc", [child.address]) as! [UInt64]?)! let expectedAddressToIDs2: {Address: [UInt64]} = {child.address: expectedChildIDs2, parent.address: expectedParentIDs} @@ -821,11 +840,11 @@ fun testGetNFTsAccessibleFromChildAccount(){ ) // revoke the ExampleNFT2 provider capability, preventing it from being returned. - let paths: [CapabilityPath] = [ - /private/exampleNFT2Collection, - /private/exampleNFTCollection + let paths: [StoragePath] = [ + /storage/exampleNFT2Collection, + /storage/exampleNFTCollection ] - txExecutor("misc/unlink_paths.cdc", [child], [paths], nil) + txExecutor("misc/unlink_from_storage_paths.cdc", [child], [paths], nil) let expectedAddressToIDsFails: {Address: [UInt64]} = {child.address: expectedChildIDs2} expectScriptFailure( @@ -846,7 +865,6 @@ fun testGetChildAccountFTCapabilities(){ let ftTypeIds = scriptExecutor("hybrid-custody/get_child_account_ft_capabilities.cdc", [parent.address])! as! {Address: [String]} Test.assert(ftTypeIds[child.address]![0] == nftIdentifier, message: "typeId should be: ".concat(nftIdentifier)) - } access(all) @@ -1130,8 +1148,8 @@ fun getNumValidKeys(_ child: Test.TestAccount): Int { } access(all) -fun checkAuthAccountDefaultCap(account: Test.TestAccount): Bool { - return scriptExecutor("hybrid-custody/check_default_auth_acct_linked_path.cdc", [account.address])! as! Bool +fun getAccountCapControllerID(account: Test.TestAccount): UInt64? { + return scriptExecutor("hybrid-custody/get_account_cap_con_id.cdc", [account.address]) as! UInt64? } access(all) @@ -1223,7 +1241,7 @@ fun setup() { accounts["nftCapFactory"] = adminAccount // helper nft contract so we can actually talk to nfts with tests - deploy("ExampleNFT", "../modules/flow-nft/contracts/ExampleNFT.cdc") + deploy("ExampleNFT", "../contracts/standard/ExampleNFT.cdc") deploy("ExampleNFT2", "../contracts/standard/ExampleNFT2.cdc") deploy("ExampleToken", "../contracts/standard/ExampleToken.cdc") diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index 8510adf..0cc267c 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -45,50 +45,57 @@ access(all) fun withoutPrefix(_ input: String): String{ /// For more info, see docs at https://developers.onflow.org/docs/hybrid-custody/ //// transaction(nftContractAddress: Address, nftContractName: String) { - prepare(acct: AuthAccount) { + prepare(acct: auth(Storage, Capabilities) &Account) { /* --- CapabilityFactory Manager configuration --- */ // - if acct.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { + if acct.storage.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { let f <- CapabilityFactory.createFactoryManager() - acct.save(<-f, to: CapabilityFactory.StoragePath) + acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { - acct.unlink(CapabilityFactory.PublicPath) - acct.link<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath, target: CapabilityFactory.StoragePath) + if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + acct.capabilities.unpublish(CapabilityFactory.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + at: CapabilityFactory.PublicPath + ) } assert( - acct.getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() == true, message: "CapabilityFactory is not setup properly" ) - let factoryManager = acct.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) + let factoryManager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") // Add NFT-related Factories to the Manager factoryManager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - factoryManager.updateFactory(Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(), NFTProviderAndCollectionFactory.Factory()) - factoryManager.updateFactory(Type<&{NonFungibleToken.Provider}>(), NFTProviderFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderFactory.Factory()) /* --- AllowlistFilter configuration --- */ // - if acct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) == nil { - acct.save(<-CapabilityFilter.create(Type<@CapabilityFilter.AllowlistFilter>()), to: CapabilityFilter.StoragePath) + if acct.storage.borrow<&AnyResource>(from: CapabilityFilter.StoragePath) == nil { + acct.storage.save(<-CapabilityFilter.createFilter(Type<@CapabilityFilter.AllowlistFilter>()), to: CapabilityFilter.StoragePath) } - if !acct.getCapability<&CapabilityFilter.AllowlistFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check() { - acct.unlink(CapabilityFilter.PublicPath) - acct.link<&CapabilityFilter.AllowlistFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath, target: CapabilityFilter.StoragePath) + if acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() != true { + acct.capabilities.unpublish(CapabilityFilter.PublicPath) + + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFilter.Filter}>(CapabilityFilter.StoragePath), + at: CapabilityFilter.PublicPath + ) } assert( - acct.getCapability<&CapabilityFilter.AllowlistFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(), + acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "AllowlistFilter is not setup properly" ) - let filter = acct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("AllowlistFilter does not exist") // Construct an NFT Collection Type from the provided args & add to the AllowlistFilter diff --git a/transactions/example-nft-2/setup_full.cdc b/transactions/example-nft-2/setup_full.cdc index f9358e5..b72b7a1 100644 --- a/transactions/example-nft-2/setup_full.cdc +++ b/transactions/example-nft-2/setup_full.cdc @@ -4,17 +4,19 @@ import "MetadataViews" import "ExampleNFT2" transaction { - prepare(acct: AuthAccount) { - let d = ExampleNFT2.resolveView(Type())! as! MetadataViews.NFTCollectionData + prepare(acct: auth(Storage, Capabilities) &Account) { + let d = ExampleNFT2.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - if acct.borrow<&ExampleNFT2.Collection>(from: d.storagePath) == nil { - acct.save(<- ExampleNFT2.createEmptyCollection(), to: ExampleNFT2.CollectionStoragePath) + if acct.storage.borrow<&ExampleNFT2.Collection>(from: d.storagePath) == nil { + acct.storage.save(<- ExampleNFT2.createEmptyCollection(), to: ExampleNFT2.CollectionStoragePath) } - acct.unlink(d.publicPath) - acct.link<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic, NonFungibleToken.CollectionPublic}>(d.publicPath, target: d.storagePath) + acct.capabilities.unpublish(d.publicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{ExampleNFT2.ExampleNFT2CollectionPublic, NonFungibleToken.CollectionPublic}>(d.storagePath), + at: d.publicPath + ) - acct.unlink(d.providerPath) - acct.link<&ExampleNFT2.Collection{ExampleNFT2.ExampleNFT2CollectionPublic, NonFungibleToken.CollectionPublic, NonFungibleToken.Provider}>(d.providerPath, target: d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } diff --git a/transactions/example-token/mint_tokens.cdc b/transactions/example-token/mint_tokens.cdc index 4e90306..49600ec 100644 --- a/transactions/example-token/mint_tokens.cdc +++ b/transactions/example-token/mint_tokens.cdc @@ -1,4 +1,5 @@ import "FungibleToken" +import "FungibleTokenMetadataViews" import "ExampleToken" //EMULATOR transaction only! Emulator contract does not require admin resource @@ -8,21 +9,20 @@ import "ExampleToken" /// are transferred to the address after minting transaction(recipient: Address, amount: UFix64) { - - /// Reference to the Fungible Token Receiver of the recipient let tokenReceiver: &{FungibleToken.Receiver} /// The total supply of tokens before the burn let supplyBefore: UFix64 - prepare(signer: AuthAccount) { + prepare(signer: auth(Storage, Capabilities) &Account) { self.supplyBefore = ExampleToken.totalSupply + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + // Get the account of the recipient and borrow a reference to their receiver - self.tokenReceiver = getAccount(recipient) - .getCapability(ExampleToken.ReceiverPublicPath) - .borrow<&{FungibleToken.Receiver}>() + self.tokenReceiver = getAccount(recipient).capabilities.get<&{FungibleToken.Receiver}>(vaultData.receiverPath)!.borrow() ?? panic("Unable to borrow receiver reference") } diff --git a/transactions/example-token/setup_provider.cdc b/transactions/example-token/setup_provider.cdc index 764cf4f..e8b7185 100644 --- a/transactions/example-token/setup_provider.cdc +++ b/transactions/example-token/setup_provider.cdc @@ -1,13 +1,13 @@ import "FungibleToken" import "ExampleToken" +import "FungibleTokenMetadataViews" transaction { - prepare(acct: AuthAccount) { - // Create Provider capability that can be used by parent to access the child's vault and transfer tokens - let providerPath = /private/exampleTokenProvider - - acct.unlink(providerPath) - acct.link<&{FungibleToken.Provider}>(providerPath, target: ExampleToken.VaultStoragePath) + prepare(acct: auth(Capabilities) &Account) { + let vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + + acct.capabilities.storage.issue(vaultData.storagePath) } } \ No newline at end of file diff --git a/transactions/filter/allow/add_type_to_list.cdc b/transactions/filter/allow/add_type_to_list.cdc index 34a846e..ec955ad 100644 --- a/transactions/filter/allow/add_type_to_list.cdc +++ b/transactions/filter/allow/add_type_to_list.cdc @@ -1,8 +1,8 @@ import "CapabilityFilter" transaction(identifier: String) { - prepare(acct: AuthAccount) { - let filter = acct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage) &Account) { + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/allow/remove_all_types.cdc b/transactions/filter/allow/remove_all_types.cdc index eebce22..b35c520 100644 --- a/transactions/filter/allow/remove_all_types.cdc +++ b/transactions/filter/allow/remove_all_types.cdc @@ -1,8 +1,8 @@ import "CapabilityFilter" transaction() { - prepare(acct: AuthAccount) { - let filter = acct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage) &Account) { + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/filter/allow/setup.cdc b/transactions/filter/allow/setup.cdc index 9c575dd..f6e2e57 100644 --- a/transactions/filter/allow/setup.cdc +++ b/transactions/filter/allow/setup.cdc @@ -1,12 +1,17 @@ import "CapabilityFilter" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) == nil { - acct.save(<-CapabilityFilter.create(Type<@CapabilityFilter.AllowlistFilter>()), to: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFilter.StoragePath) == nil { + acct.storage.save(<-CapabilityFilter.createFilter(Type<@CapabilityFilter.AllowlistFilter>()), to: CapabilityFilter.StoragePath) } - acct.unlink(CapabilityFilter.PublicPath) - acct.link<&CapabilityFilter.AllowlistFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath, target: CapabilityFilter.StoragePath) + acct.capabilities.unpublish(CapabilityFilter.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFilter.Filter}>(CapabilityFilter.StoragePath), + at: CapabilityFilter.PublicPath + ) + + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/filter/deny/add_type_to_list.cdc b/transactions/filter/deny/add_type_to_list.cdc index 77ba5b7..aeb94c1 100644 --- a/transactions/filter/deny/add_type_to_list.cdc +++ b/transactions/filter/deny/add_type_to_list.cdc @@ -1,8 +1,8 @@ import "CapabilityFilter" transaction(identifier: String) { - prepare(acct: AuthAccount) { - let filter = acct.borrow<&CapabilityFilter.DenylistFilter>(from: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage) &Account) { + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/deny/remove_all_types.cdc b/transactions/filter/deny/remove_all_types.cdc index eb273f3..7c46253 100644 --- a/transactions/filter/deny/remove_all_types.cdc +++ b/transactions/filter/deny/remove_all_types.cdc @@ -1,8 +1,8 @@ import "CapabilityFilter" transaction() { - prepare(acct: AuthAccount) { - let filter = acct.borrow<&CapabilityFilter.DenylistFilter>(from: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage) &Account) { + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/filter/deny/setup.cdc b/transactions/filter/deny/setup.cdc index 1e48b79..c4760e8 100644 --- a/transactions/filter/deny/setup.cdc +++ b/transactions/filter/deny/setup.cdc @@ -1,12 +1,17 @@ import "CapabilityFilter" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&CapabilityFilter.DenylistFilter>(from: CapabilityFilter.StoragePath) == nil { - acct.save(<- CapabilityFilter.create(Type<@CapabilityFilter.DenylistFilter>()), to: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFilter.StoragePath) == nil { + acct.storage.save(<- CapabilityFilter.createFilter(Type<@CapabilityFilter.DenylistFilter>()), to: CapabilityFilter.StoragePath) } - acct.unlink(CapabilityFilter.PublicPath) - acct.link<&CapabilityFilter.DenylistFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath, target: CapabilityFilter.StoragePath) + acct.capabilities.unpublish(CapabilityFilter.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFilter.Filter}>(CapabilityFilter.StoragePath), + at: CapabilityFilter.PublicPath + ) + + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/filter/setup_allow_all.cdc b/transactions/filter/setup_allow_all.cdc index 1761e82..0a8b0b5 100644 --- a/transactions/filter/setup_allow_all.cdc +++ b/transactions/filter/setup_allow_all.cdc @@ -1,14 +1,17 @@ import "CapabilityFilter" transaction { - prepare(acct: AuthAccount) { - if acct.borrow<&CapabilityFilter.AllowAllFilter>(from: CapabilityFilter.StoragePath) == nil { - acct.save(<- CapabilityFilter.create(Type<@CapabilityFilter.AllowAllFilter>()), to: CapabilityFilter.StoragePath) + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&CapabilityFilter.AllowAllFilter>(from: CapabilityFilter.StoragePath) == nil { + acct.storage.save(<- CapabilityFilter.createFilter(Type<@CapabilityFilter.AllowAllFilter>()), to: CapabilityFilter.StoragePath) } - acct.unlink(CapabilityFilter.PublicPath) - let linkRes = acct.link<&CapabilityFilter.AllowAllFilter{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath, target: CapabilityFilter.StoragePath) - ?? panic("link failed") - assert(linkRes.check(), message: "failed to setup filter") + acct.capabilities.unpublish(CapabilityFilter.PublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{CapabilityFilter.Filter}>(CapabilityFilter.StoragePath), + at: CapabilityFilter.PublicPath + ) + + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/hybrid-custody/accept_ownership.cdc b/transactions/hybrid-custody/accept_ownership.cdc index 0d3026d..8225d57 100644 --- a/transactions/hybrid-custody/accept_ownership.cdc +++ b/transactions/hybrid-custody/accept_ownership.cdc @@ -2,33 +2,42 @@ import "HybridCustody" import "CapabilityFilter" -import "MetadataViews" +import "ViewResolver" transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPath?) { - prepare(acct: AuthAccount) { + prepare(acct: auth(Storage, Capabilities, Inbox) &Account) { var filter: Capability<&{CapabilityFilter.Filter}>? = nil if filterAddress != nil && filterPath != nil { - filter = getAccount(filterAddress!).getCapability<&{CapabilityFilter.Filter}>(filterPath!) + filter = getAccount(filterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(filterPath!) + ?? panic("filter address given but capability was not found") } - if acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { + if acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { let m <- HybridCustody.createManager(filter: filter) - acct.save(<- m, to: HybridCustody.ManagerStoragePath) + acct.storage.save(<- m, to: HybridCustody.ManagerStoragePath) - acct.unlink(HybridCustody.ManagerPublicPath) - acct.unlink(HybridCustody.ManagerPrivatePath) + for c in acct.capabilities.storage.getControllers(forPath: HybridCustody.ManagerStoragePath) { + c.delete() + } - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.ManagerPrivatePath, target: HybridCustody.ManagerStoragePath) - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath, target: HybridCustody.ManagerStoragePath) + acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) + + acct.capabilities.storage.issue(HybridCustody.ManagerStoragePath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath), + at: HybridCustody.ManagerPublicPath + ) } let inboxName = HybridCustody.getOwnerIdentifier(acct.address) - let cap = acct.inbox.claim<&AnyResource{HybridCustody.OwnedAccountPrivate, HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(inboxName, provider: childAddress) + let cap = acct.inbox.claim(inboxName, provider: childAddress) ?? panic("owned account cap not found") - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager no found") + let ownedAcct = cap.borrow() ?? panic("could not borrow owned account capability") + manager.addOwnedAccount(cap: cap) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc index 56592c0..558091c 100644 --- a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc +++ b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc @@ -5,16 +5,13 @@ import "NonFungibleToken" import "ExampleNFT2" transaction(parent: Address, isPublic: Bool) { - prepare(acct: AuthAccount) { - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage, Capabilities) &Account) { + let o = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") let child = o.borrowChildAccount(parent: parent) ?? panic("child account not found") - let path = /private/exampleNFT2FullCollection - acct.link<&ExampleNFT2.Collection>(path, target: ExampleNFT2.CollectionStoragePath) - let cap = acct.getCapability<&ExampleNFT2.Collection>(path) - + let cap = acct.capabilities.storage.issue(ExampleNFT2.CollectionStoragePath) o.addCapabilityToDelegator(parent: parent, cap: cap, isPublic: isPublic) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/add_example_nft_collection_to_delegator.cdc b/transactions/hybrid-custody/add_example_nft_collection_to_delegator.cdc index c4ca454..da1e78f 100644 --- a/transactions/hybrid-custody/add_example_nft_collection_to_delegator.cdc +++ b/transactions/hybrid-custody/add_example_nft_collection_to_delegator.cdc @@ -5,16 +5,13 @@ import "NonFungibleToken" import "ExampleNFT" transaction(parent: Address, isPublic: Bool) { - prepare(acct: AuthAccount) { - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage, Capabilities) &Account) { + let o = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") let child: &HybridCustody.ChildAccount = o.borrowChildAccount(parent: parent) ?? panic("child account not found") - let path = /private/exampleNFTFullCollection - acct.link<&ExampleNFT.Collection>(path, target: ExampleNFT.CollectionStoragePath) - let cap = acct.getCapability<&ExampleNFT.Collection>(path) - + let cap = acct.capabilities.storage.issue<&ExampleNFT.Collection>(ExampleNFT.CollectionStoragePath) o.addCapabilityToDelegator(parent: parent, cap: cap, isPublic: isPublic) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/metadata/set_child_account_display.cdc b/transactions/hybrid-custody/metadata/set_child_account_display.cdc index ef66cc7..0f74afa 100644 --- a/transactions/hybrid-custody/metadata/set_child_account_display.cdc +++ b/transactions/hybrid-custody/metadata/set_child_account_display.cdc @@ -2,8 +2,8 @@ import "HybridCustody" import "MetadataViews" transaction(childAddress: Address, name: String, description: String, thumbnail: String) { - prepare(acct: AuthAccount) { - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + prepare(acct: auth(Storage) &Account) { + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") let d = MetadataViews.Display( diff --git a/transactions/hybrid-custody/metadata/set_owned_account_display.cdc b/transactions/hybrid-custody/metadata/set_owned_account_display.cdc index 67d1dc8..7f264ed 100644 --- a/transactions/hybrid-custody/metadata/set_owned_account_display.cdc +++ b/transactions/hybrid-custody/metadata/set_owned_account_display.cdc @@ -2,8 +2,8 @@ import "HybridCustody" import "MetadataViews" transaction(name: String, description: String, thumbnail: String) { - prepare(acct: AuthAccount) { - let o = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage) &Account) { + let o = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("account not found") let d = MetadataViews.Display( diff --git a/transactions/hybrid-custody/misc/save_resource_to_parent_child_storage_slot.cdc b/transactions/hybrid-custody/misc/save_resource_to_parent_child_storage_slot.cdc index 35c1f87..81063ce 100644 --- a/transactions/hybrid-custody/misc/save_resource_to_parent_child_storage_slot.cdc +++ b/transactions/hybrid-custody/misc/save_resource_to_parent_child_storage_slot.cdc @@ -2,10 +2,10 @@ import "ExampleToken" import "HybridCustody" transaction(parent: Address) { - prepare(acct: AuthAccount) { - let v <- ExampleToken.createEmptyVault() + prepare(acct: auth(Storage) &Account) { + let v <- ExampleToken.createEmptyVault(vaultType: Type<@ExampleToken.Vault>()) let identifier = HybridCustody.getChildAccountIdentifier(parent) let storagePath = StoragePath(identifier: identifier)! - acct.save(<-v, to: storagePath) + acct.storage.save(<-v, to: storagePath) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/onboarding/blockchain_native.cdc b/transactions/hybrid-custody/onboarding/blockchain_native.cdc index 422a45b..7f6613c 100644 --- a/transactions/hybrid-custody/onboarding/blockchain_native.cdc +++ b/transactions/hybrid-custody/onboarding/blockchain_native.cdc @@ -3,6 +3,7 @@ import "FungibleToken" import "FlowToken" import "MetadataViews" +import "ViewResolver" import "HybridCustody" import "CapabilityFactory" @@ -16,11 +17,11 @@ transaction( filterAddress: Address ) { - prepare(parent: AuthAccount, app: AuthAccount) { + prepare(parent: auth(Storage, Capabilities, Inbox) &Account, app: auth(Storage, Capabilities) &Account) { /* --- Account Creation --- */ // // Create the child account, funding via the signing app account - let newAccount = AuthAccount(payer: app) + let newAccount = Account(payer: app) // Create a public key for the child account from string value in the provided arg // **NOTE:** You may want to specify a different signature algo for your use case let key = PublicKey( @@ -40,11 +41,9 @@ transaction( // Fund the new account if specified if initialFundingAmt > 0.0 { // Get a vault to fund the new account - let fundingProvider = app.borrow<&FlowToken.Vault{FungibleToken.Provider}>( - from: /storage/flowTokenVault - )! + let fundingProvider = app.storage.borrow(from: /storage/flowTokenVault)! // Fund the new account with the initialFundingAmount specified - newAccount.getCapability<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver) + newAccount.capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)! .borrow()! .deposit( from: <-fundingProvider.withdraw( @@ -61,35 +60,29 @@ transaction( /* --- Link the AuthAccount Capability --- */ // - var acctCap = newAccount.linkAccount(HybridCustody.LinkedAccountPrivatePath) - ?? panic("problem linking account Capability for new account") + let acctCap = newAccount.capabilities.account.issue() // Create a OwnedAccount & link Capabilities let ownedAccount <- HybridCustody.createOwnedAccount(acct: acctCap) - newAccount.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) - newAccount - .link<&HybridCustody.OwnedAccount{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>( - HybridCustody.OwnedAccountPrivatePath, - target: HybridCustody.OwnedAccountStoragePath - ) - newAccount - .link<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>( - HybridCustody.OwnedAccountPublicPath, - target: HybridCustody.OwnedAccountStoragePath - ) + newAccount.storage.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + + newAccount.capabilities.storage.issue<&{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) + newAccount.capabilities.publish( + newAccount.capabilities.storage.issue<&{HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath), + at: HybridCustody.OwnedAccountPublicPath + ) // Get a reference to the OwnedAccount resource - let owned = newAccount.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath)! + let owned = newAccount.storage.borrow(from: HybridCustody.OwnedAccountStoragePath)! // Get the CapabilityFactory.Manager Capability - let factory = getAccount(factoryAddress) - .getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>( - CapabilityFactory.PublicPath - ) + let factory = getAccount(factoryAddress).capabilities + .get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! assert(factory.check(), message: "factory address is not configured properly") // Get the CapabilityFilter.Filter Capability - let filter = getAccount(filterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("filter capability was not valid") assert(filter.check(), message: "capability filter is not configured properly") // Configure access for the delegatee parent account @@ -98,34 +91,34 @@ transaction( /* --- Add delegation to parent account --- */ // // Configure HybridCustody.Manager if needed - if parent.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { + if parent.storage.borrow<&AnyResource>(from: HybridCustody.ManagerStoragePath) == nil { let m <- HybridCustody.createManager(filter: filter) - parent.save(<- m, to: HybridCustody.ManagerStoragePath) + parent.storage.save(<- m, to: HybridCustody.ManagerStoragePath) + + for c in parent.capabilities.storage.getControllers(forPath: HybridCustody.ManagerStoragePath) { + c.delete() + } + + // configure Capabilities + parent.capabilities.storage.issue<&{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath) + parent.capabilities.publish( + parent.capabilities.storage.issue<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath), + at: HybridCustody.ManagerPublicPath + ) } - // Link Capabilities - parent.unlink(HybridCustody.ManagerPublicPath) - parent.unlink(HybridCustody.ManagerPrivatePath) - parent.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>( - HybridCustody.ManagerPrivatePath, - target: HybridCustody.ManagerStoragePath - ) - parent.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>( - HybridCustody.ManagerPublicPath, - target: HybridCustody.ManagerStoragePath - ) // Claim the ChildAccount Capability let inboxName = HybridCustody.getChildAccountIdentifier(parent.address) let cap = parent .inbox - .claim<&HybridCustody.ChildAccount{HybridCustody.AccountPrivate, HybridCustody.AccountPublic, MetadataViews.Resolver}>( + .claim( inboxName, provider: newAccount.address ) ?? panic("child account cap not found") // Get a reference to the Manager and add the account - let managerRef = parent.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + let managerRef = parent.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager no found") managerRef.addAccount(cap: cap) } diff --git a/transactions/hybrid-custody/publish_to_parent.cdc b/transactions/hybrid-custody/publish_to_parent.cdc index d9948c3..6f0612d 100644 --- a/transactions/hybrid-custody/publish_to_parent.cdc +++ b/transactions/hybrid-custody/publish_to_parent.cdc @@ -4,14 +4,14 @@ import "CapabilityFilter" import "CapabilityDelegator" transaction(parent: Address, factoryAddress: Address, filterAddress: Address) { - prepare(acct: AuthAccount) { - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage) &Account) { + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(factoryAddress).getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! assert(factory.check(), message: "factory address is not configured properly") - let filter = getAccount(filterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)! assert(filter.check(), message: "capability filter is not configured properly") owned.publishToParent(parentAddress: parent, factory: factory, filter: filter) diff --git a/transactions/hybrid-custody/redeem_account.cdc b/transactions/hybrid-custody/redeem_account.cdc index 70016db..b28a49a 100644 --- a/transactions/hybrid-custody/redeem_account.cdc +++ b/transactions/hybrid-custody/redeem_account.cdc @@ -1,31 +1,40 @@ import "MetadataViews" +import "ViewResolver" import "HybridCustody" import "CapabilityFilter" transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPath?) { - prepare(acct: AuthAccount) { + prepare(acct: auth(Storage, Capabilities, Inbox) &Account) { var filter: Capability<&{CapabilityFilter.Filter}>? = nil if filterAddress != nil && filterPath != nil { - filter = getAccount(filterAddress!).getCapability<&{CapabilityFilter.Filter}>(filterPath!) + filter = getAccount(filterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(filterPath!) + ?? panic("filter path provided but capability was not found") } - if acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { + if acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { let m <- HybridCustody.createManager(filter: filter) - acct.save(<- m, to: HybridCustody.ManagerStoragePath) + acct.storage.save(<- m, to: HybridCustody.ManagerStoragePath) - acct.unlink(HybridCustody.ManagerPublicPath) - acct.unlink(HybridCustody.ManagerPrivatePath) + for c in acct.capabilities.storage.getControllers(forPath: HybridCustody.ManagerStoragePath) { + c.delete() + } - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.ManagerPrivatePath, target: HybridCustody.ManagerStoragePath) - acct.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath, target: HybridCustody.ManagerStoragePath) + acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) + + acct.capabilities.publish( + acct.capabilities.storage.issue<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath), + at: HybridCustody.ManagerPublicPath + ) + + acct.capabilities.storage.issue(HybridCustody.ManagerStoragePath) } let inboxName = HybridCustody.getChildAccountIdentifier(acct.address) - let cap = acct.inbox.claim<&HybridCustody.ChildAccount{HybridCustody.AccountPrivate, HybridCustody.AccountPublic, MetadataViews.Resolver}>(inboxName, provider: childAddress) + let cap = acct.inbox.claim(inboxName, provider: childAddress) ?? panic("child account cap not found") - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager no found") manager.addAccount(cap: cap) diff --git a/transactions/hybrid-custody/relinquish_ownership.cdc b/transactions/hybrid-custody/relinquish_ownership.cdc index fcbba96..289304c 100644 --- a/transactions/hybrid-custody/relinquish_ownership.cdc +++ b/transactions/hybrid-custody/relinquish_ownership.cdc @@ -3,8 +3,8 @@ import "HybridCustody" transaction { - prepare(acct: AuthAccount) { - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage) &Account) { + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned not found") owned.seal() } diff --git a/transactions/hybrid-custody/remove_child_account.cdc b/transactions/hybrid-custody/remove_child_account.cdc index 872b84a..36de1c7 100644 --- a/transactions/hybrid-custody/remove_child_account.cdc +++ b/transactions/hybrid-custody/remove_child_account.cdc @@ -1,8 +1,8 @@ import "HybridCustody" transaction(child: Address) { - prepare (acct: AuthAccount) { - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + prepare (acct: auth(Storage) &Account) { + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") manager.removeChild(addr: child) } diff --git a/transactions/hybrid-custody/remove_parent_from_child.cdc b/transactions/hybrid-custody/remove_parent_from_child.cdc index fcbe875..f073054 100644 --- a/transactions/hybrid-custody/remove_parent_from_child.cdc +++ b/transactions/hybrid-custody/remove_parent_from_child.cdc @@ -1,13 +1,13 @@ import "HybridCustody" transaction(parent: Address) { - prepare(acct: AuthAccount) { - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage) &Account) { + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned not found") owned.removeParent(parent: parent) - let manager = getAccount(parent).getCapability<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) + let manager = getAccount(parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath)! .borrow() ?? panic("manager not found") let children = manager.getChildAddresses() assert(!children.contains(acct.address), message: "removed child is still in manager resource") diff --git a/transactions/hybrid-custody/send_child_ft_with_parent.cdc b/transactions/hybrid-custody/send_child_ft_with_parent.cdc index b2a5626..6a20b6e 100644 --- a/transactions/hybrid-custody/send_child_ft_with_parent.cdc +++ b/transactions/hybrid-custody/send_child_ft_with_parent.cdc @@ -2,22 +2,31 @@ import "FungibleToken" import "ExampleToken" import "HybridCustody" +import "FungibleTokenMetadataViews" transaction(amount: UFix64, to: Address, child: Address) { // The Vault resource that holds the tokens that are being transferred - let paymentVault: @FungibleToken.Vault + let paymentVault: @{FungibleToken.Vault} + let vaultData: FungibleTokenMetadataViews.FTVaultData - prepare(signer: AuthAccount) { + prepare(signer: auth(Storage) &Account) { // signer is the parent account // get the manager resource and borrow childAccount - let m = signer.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + let m = signer.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager does not exist") let childAcct = m.borrowAccount(addr: child) ?? panic("child account not found") + self.vaultData = ExampleToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not get the vault data view for ExampleToken") + //get Ft cap from child account - let cap = childAcct.getCapability(path: /private/exampleTokenProvider, type: Type<&{FungibleToken.Provider}>()) ?? panic("no cap found") - let providerCap = cap as! Capability<&{FungibleToken.Provider}> + let capType = Type() + let controllerID = childAcct.getControllerIDForType(type: capType, forPath: self.vaultData.storagePath) + ?? panic("no controller found for capType") + + let cap = childAcct.getCapability(controllerID: controllerID, type: capType) ?? panic("no cap found") + let providerCap = cap as! Capability assert(providerCap.check(), message: "invalid provider capability") // Get a reference to the child's stored vault @@ -33,8 +42,7 @@ transaction(amount: UFix64, to: Address, child: Address) { let recipient = getAccount(to) // Get a reference to the recipient's Receiver - let receiverRef = recipient.getCapability(/public/exampleTokenReceiver) - .borrow<&{FungibleToken.Receiver}>() + let receiverRef = recipient.capabilities.get<&{FungibleToken.Receiver}>(self.vaultData.receiverPath)!.borrow() ?? panic("Could not borrow receiver reference to the recipient's Vault") // Deposit the withdrawn tokens in the recipient's receiver diff --git a/transactions/hybrid-custody/set_default_manager_cap.cdc b/transactions/hybrid-custody/set_default_manager_cap.cdc index 360557b..d54e2f5 100644 --- a/transactions/hybrid-custody/set_default_manager_cap.cdc +++ b/transactions/hybrid-custody/set_default_manager_cap.cdc @@ -4,11 +4,12 @@ import "CapabilityFilter" // Sets the signing account's HybridCustody.Manager.filter capability to // the filter which exists at the given address's public path transaction(addr: Address) { - prepare(acct: AuthAccount) { - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + prepare(acct: auth(Storage) &Account) { + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") - let cap = getAccount(addr).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let cap = getAccount(addr).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("invalid capability filter address found") manager.setDefaultManagerCapabilityFilter(cap: cap) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/set_manager_filter_cap.cdc b/transactions/hybrid-custody/set_manager_filter_cap.cdc index 401fd92..4ea9fc7 100644 --- a/transactions/hybrid-custody/set_manager_filter_cap.cdc +++ b/transactions/hybrid-custody/set_manager_filter_cap.cdc @@ -2,11 +2,12 @@ import "HybridCustody" import "CapabilityFilter" transaction(filterAddress: Address, childAddress: Address) { - prepare(acct: AuthAccount) { - let m = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + prepare(acct: auth(Storage) &Account) { + let m = acct.storage.borrow(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("failed to get filter capability") 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 746d2a9..4771ec2 100644 --- a/transactions/hybrid-custody/setup_manager.cdc +++ b/transactions/hybrid-custody/setup_manager.cdc @@ -2,22 +2,29 @@ import "HybridCustody" import "CapabilityFilter" transaction(filterAddress: Address?, filterPath: PublicPath?) { - prepare(acct: AuthAccount) { + prepare(acct: auth(Storage, Capabilities) &Account) { var filter: Capability<&{CapabilityFilter.Filter}>? = nil if filterAddress != nil && filterPath != nil { - filter = getAccount(filterAddress!).getCapability<&{CapabilityFilter.Filter}>(filterPath!) + filter = getAccount(filterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(filterPath!) } - if acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { + if acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { let m <- HybridCustody.createManager(filter: filter) - acct.save(<- m, to: HybridCustody.ManagerStoragePath) + acct.storage.save(<- m, to: HybridCustody.ManagerStoragePath) } + + for c in acct.capabilities.storage.getControllers(forPath: HybridCustody.ManagerStoragePath) { + c.delete() + } + + acct.capabilities.unpublish(HybridCustody.ManagerPublicPath) - acct.unlink(HybridCustody.ManagerPublicPath) - acct.unlink(HybridCustody.ManagerPrivatePath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath), + at: 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) + acct.capabilities.storage.issue(HybridCustody.ManagerStoragePath) } } \ 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..35aba71 100644 --- a/transactions/hybrid-custody/setup_multi_sig.cdc +++ b/transactions/hybrid-custody/setup_multi_sig.cdc @@ -7,64 +7,87 @@ import "CapabilityDelegator" import "CapabilityFilter" import "MetadataViews" +import "ViewResolver" transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, childAccountFilterAddress: Address) { - prepare(childAcct: AuthAccount, parentAcct: AuthAccount) { + prepare(childAcct: auth(Storage, Capabilities) &Account, parentAcct: auth(Storage, Capabilities, Inbox) &Account) { // --------------------- Begin setup of child account --------------------- - var acctCap = childAcct.getCapability<&AuthAccount>(HybridCustody.LinkedAccountPrivatePath) - if !acctCap.check() { - acctCap = childAcct.linkAccount(HybridCustody.LinkedAccountPrivatePath)! + var optCap: Capability? = nil + let t = Type() + for c in childAcct.capabilities.account.getControllers() { + if c.borrowType.isSubtype(of: t) { + optCap = c.capability as! Capability + break + } } - if childAcct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { + if optCap == nil { + optCap = childAcct.capabilities.account.issue() + } + let acctCap = optCap ?? panic("failed to get account capability") + + if childAcct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { let ownedAccount <- HybridCustody.createOwnedAccount(acct: acctCap) - childAcct.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + childAcct.storage.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + } + + for c in childAcct.capabilities.storage.getControllers(forPath: HybridCustody.OwnedAccountStoragePath) { + c.delete() } - // 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) + // configure capabilities + childAcct.capabilities.storage.issue<&{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) + childAcct.capabilities.publish( + childAcct.capabilities.storage.issue<&{HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath), + at: HybridCustody.OwnedAccountPublicPath + ) - childAcct.unlink(HybridCustody.OwnedAccountPublicPath) - childAcct.link<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPublicPath, target: HybridCustody.OwnedAccountStoragePath) // --------------------- 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) + ?? panic("parent filter address provided but it was not valid") } - if parentAcct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { + if parentAcct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { let m <- HybridCustody.createManager(filter: filter) - parentAcct.save(<- m, to: HybridCustody.ManagerStoragePath) + parentAcct.storage.save(<- m, to: HybridCustody.ManagerStoragePath) + } + + for c in parentAcct.capabilities.storage.getControllers(forPath: HybridCustody.ManagerStoragePath) { + c.delete() } - parentAcct.unlink(HybridCustody.ManagerPublicPath) - parentAcct.unlink(HybridCustody.ManagerPrivatePath) + parentAcct.capabilities.publish( + parentAcct.capabilities.storage.issue<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerStoragePath), + at: HybridCustody.ManagerPublicPath + ) + parentAcct.capabilities.storage.issue(HybridCustody.ManagerStoragePath) - parentAcct.link<&HybridCustody.Manager{HybridCustody.ManagerPrivate, HybridCustody.ManagerPublic}>(HybridCustody.OwnedAccountPrivatePath, target: HybridCustody.ManagerStoragePath) - parentAcct.link<&HybridCustody.Manager{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath, target: HybridCustody.ManagerStoragePath) // --------------------- End setup of parent account --------------------- // Publish account to parent - let owned = childAcct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + let owned = childAcct.storage.borrow(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.Getter}>(CapabilityFactory.PublicPath) + ?? panic("child account factory capability was nil") 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("child account filter capability was nil") assert(filterForChild.check(), message: "capability filter is not configured properly") owned.publishToParent(parentAddress: parentAcct.address, factory: factory, filter: filterForChild) // claim the account on the parent let inboxName = HybridCustody.getChildAccountIdentifier(parentAcct.address) - let cap = parentAcct.inbox.claim<&HybridCustody.ChildAccount{HybridCustody.AccountPrivate, HybridCustody.AccountPublic, MetadataViews.Resolver}>(inboxName, provider: childAcct.address) + let cap = parentAcct.inbox.claim(inboxName, provider: childAcct.address) ?? panic("child account cap not found") - let manager = parentAcct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + let manager = parentAcct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager no found") manager.addAccount(cap: cap) diff --git a/transactions/hybrid-custody/setup_owned_account.cdc b/transactions/hybrid-custody/setup_owned_account.cdc index cab6708..63815b5 100644 --- a/transactions/hybrid-custody/setup_owned_account.cdc +++ b/transactions/hybrid-custody/setup_owned_account.cdc @@ -1,7 +1,7 @@ #allowAccountLinking +import "ViewResolver" import "MetadataViews" - import "HybridCustody" /// This transaction configures an OwnedAccount in the signer if needed and configures its Capabilities per @@ -9,33 +9,34 @@ import "HybridCustody" /// signer's OwnedAccount. /// transaction(name: String?, desc: String?, thumbnailURL: String?) { - prepare(acct: AuthAccount) { - var acctCap = acct.getCapability<&AuthAccount>(HybridCustody.LinkedAccountPrivatePath) - if !acctCap.check() { - acctCap = acct.linkAccount(HybridCustody.LinkedAccountPrivatePath)! - } + prepare(acct: auth(Storage, Capabilities) &Account) { + let acctCap = acct.capabilities.account.issue() - if acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { + if acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { let ownedAccount <- HybridCustody.createOwnedAccount(acct: acctCap) - acct.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + acct.storage.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) } - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") // Set the display metadata for the OwnedAccount if name != nil && desc != nil && thumbnailURL != nil { let thumbnail = MetadataViews.HTTPFile(url: thumbnailURL!) - let display = MetadataViews.Display(name: name!, description: desc!, thumbnail: thumbnail!) + let display = MetadataViews.Display(name: name!, description: desc!, thumbnail: thumbnail) owned.setDisplay(display) } // check that paths are all configured properly - acct.unlink(HybridCustody.OwnedAccountPrivatePath) - acct.link<&HybridCustody.OwnedAccount{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPrivatePath, target: HybridCustody.OwnedAccountStoragePath) + for c in acct.capabilities.storage.getControllers(forPath: HybridCustody.OwnedAccountStoragePath) { + c.delete() + } - acct.unlink(HybridCustody.OwnedAccountPublicPath) - acct.link<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPublicPath, target: HybridCustody.OwnedAccountStoragePath) + acct.capabilities.storage.issue<&{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath), + at: HybridCustody.OwnedAccountPublicPath + ) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc index 2349962..6f03619 100644 --- a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc +++ b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc @@ -1,6 +1,7 @@ #allowAccountLinking import "MetadataViews" +import "ViewResolver" import "HybridCustody" import "CapabilityFactory" @@ -12,47 +13,49 @@ import "CapabilityDelegator" /// Capability on the ChildAccount is then published to the specified parent account. /// transaction( - parent: Address, - factoryAddress: Address, - filterAddress: Address, - name: String?, - desc: String?, - thumbnailURL: String? - ) { - - prepare(acct: AuthAccount) { + parent: Address, + factoryAddress: Address, + filterAddress: Address, + name: String?, + desc: String?, + thumbnailURL: String? +) { + prepare(acct: auth(Storage, Capabilities) &Account) { // Configure OwnedAccount if it doesn't exist - if acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { - var acctCap = acct.getCapability<&AuthAccount>(HybridCustody.LinkedAccountPrivatePath) - if !acctCap.check() { - acctCap = acct.linkAccount(HybridCustody.LinkedAccountPrivatePath)! - } + if acct.storage.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) == nil { + var acctCap = acct.capabilities.account.issue() let ownedAccount <- HybridCustody.createOwnedAccount(acct: acctCap) - acct.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + acct.storage.save(<-ownedAccount, to: HybridCustody.OwnedAccountStoragePath) + } + + for c in acct.capabilities.storage.getControllers(forPath: HybridCustody.OwnedAccountStoragePath) { + c.delete() } - // check that paths are all configured properly - acct.unlink(HybridCustody.OwnedAccountPrivatePath) - acct.link<&HybridCustody.OwnedAccount{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPrivatePath, target: HybridCustody.OwnedAccountStoragePath) - acct.unlink(HybridCustody.OwnedAccountPublicPath) - acct.link<&HybridCustody.OwnedAccount{HybridCustody.OwnedAccountPublic, MetadataViews.Resolver}>(HybridCustody.OwnedAccountPublicPath, target: HybridCustody.OwnedAccountStoragePath) + acct.capabilities.storage.issue<&{HybridCustody.BorrowableAccount, HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&{HybridCustody.OwnedAccountPublic, ViewResolver.Resolver}>(HybridCustody.OwnedAccountStoragePath), + at: HybridCustody.OwnedAccountPublicPath + ) - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") // Set the display metadata for the OwnedAccount if name != nil && desc != nil && thumbnailURL != nil { let thumbnail = MetadataViews.HTTPFile(url: thumbnailURL!) - let display = MetadataViews.Display(name: name!, description: desc!, thumbnail: thumbnail!) + let display = MetadataViews.Display(name: name!, description: desc!, thumbnail: thumbnail) owned.setDisplay(display) } // Get CapabilityFactory & CapabilityFilter Capabilities - let factory = getAccount(factoryAddress).getCapability<&CapabilityFactory.Manager{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + ?? panic("failed to get factory capability") assert(factory.check(), message: "factory address is not configured properly") - let filter = getAccount(filterAddress).getCapability<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("failed to get filter capability") assert(filter.check(), message: "capability filter is not configured properly") // Finally publish a ChildAccount capability on the signing account to the specified parent diff --git a/transactions/hybrid-custody/transfer_ownership.cdc b/transactions/hybrid-custody/transfer_ownership.cdc index 2be0ee1..34f1a30 100644 --- a/transactions/hybrid-custody/transfer_ownership.cdc +++ b/transactions/hybrid-custody/transfer_ownership.cdc @@ -3,8 +3,8 @@ import "HybridCustody" transaction(owner: Address) { - prepare(acct: AuthAccount) { - let owned = acct.borrow<&HybridCustody.OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) + prepare(acct: auth(Storage) &Account) { + let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned not found") owned.giveOwnership(to: owner) } diff --git a/transactions/hybrid-custody/transfer_ownership_from_manager.cdc b/transactions/hybrid-custody/transfer_ownership_from_manager.cdc index 45e35c6..45a0e3d 100644 --- a/transactions/hybrid-custody/transfer_ownership_from_manager.cdc +++ b/transactions/hybrid-custody/transfer_ownership_from_manager.cdc @@ -3,8 +3,8 @@ import "HybridCustody" transaction(ownedAddress: Address, owner: Address) { - prepare(acct: AuthAccount) { - let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + prepare(acct: auth(Storage) &Account) { + let manager = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) ?? panic("manager not found") manager.giveOwnership(addr: ownedAddress, to: owner) } diff --git a/transactions/misc/unlink_from_storage_paths.cdc b/transactions/misc/unlink_from_storage_paths.cdc new file mode 100644 index 0000000..ff8c533 --- /dev/null +++ b/transactions/misc/unlink_from_storage_paths.cdc @@ -0,0 +1,10 @@ +transaction(storagePaths: [StoragePath]) { + prepare(acct: auth(Capabilities) &Account) { + for storagePath in storagePaths { + let controllers = acct.capabilities.storage.getControllers(forPath: storagePath) + for con in controllers { + acct.capabilities.storage.getController(byCapabilityID: con.capabilityID)?.delete() + } + } + } +} \ No newline at end of file diff --git a/transactions/misc/unlink_paths.cdc b/transactions/misc/unlink_paths.cdc deleted file mode 100644 index dbe5bc8..0000000 --- a/transactions/misc/unlink_paths.cdc +++ /dev/null @@ -1,7 +0,0 @@ -transaction(paths: [CapabilityPath]) { - prepare(acct: AuthAccount) { - for p in paths { - acct.unlink(p) - } - } -} \ No newline at end of file From 1731fe65c63942a67d150f18c4fa36da2a75c583 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 2 Apr 2024 18:38:53 -0700 Subject: [PATCH 09/34] configure tests with flow-c1 --- .github/workflows/integration-tests.yml | 4 +--- codecov.yml | 4 ++++ test.sh | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 codecov.yml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 1af3875..7fec93b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -20,11 +20,9 @@ jobs: with: go-version: 1.18 - name: Install Flow CLI - run: bash -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.5.0 + run: bash -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)" - name: Run tests run: sh ./test.sh - - name: Normalize coverage report filepaths - run : sh ./normalize_coverage_report.sh - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..5a60395 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,4 @@ +ignore: + - "contracts/standard/ExampleNFT.cdc" + - "contracts/standard/ExampleNFT2.cdc" + - "contracts/standard/ExampleToken.cdc" \ No newline at end of file diff --git a/test.sh b/test.sh index acc7741..03faee0 100755 --- a/test.sh +++ b/test.sh @@ -2,4 +2,4 @@ set -e -flow test --cover --covercode="contracts" --coverprofile="coverage.lcov" test/*_tests.cdc \ No newline at end of file +flow-c1 test --cover --covercode="contracts" --coverprofile="coverage.lcov" test/*_tests.cdc \ No newline at end of file From 317016a869d235e1e1659e17bad85a451547d3ef Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 2 Apr 2024 18:41:43 -0700 Subject: [PATCH 10/34] add exclusions to code coverage --- codecov.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 5a60395..d65792d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,9 @@ ignore: - "contracts/standard/ExampleNFT.cdc" - "contracts/standard/ExampleNFT2.cdc" - - "contracts/standard/ExampleToken.cdc" \ No newline at end of file + - "contracts/standard/ExampleToken.cdc" + - "contracts/factories/FTBalanceFactory.cdc" + - "contracts/factories/FTProviderFactory.cdc" + - "contracts/factories/FTReceiverFactory.cdc" + - "contracts/factories/NFTCollectionPublicFactory.cdc" + - "contracts/factories/NFTProviderFactory.cdc" \ No newline at end of file From ed1253890b4b4cd0e4b223de128fb5a594948a5a Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 2 Apr 2024 21:52:52 -0700 Subject: [PATCH 11/34] add Burnable Interface --- contracts/HybridCustody.cdc | 50 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 4bc851f..a8ed0e4 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -1,6 +1,7 @@ // Third-party imports import "MetadataViews" import "ViewResolver" +import "Burner" // HC-owned imports import "CapabilityFactory" @@ -204,7 +205,6 @@ access(all) contract HybridCustody { /// necessarily the same. /// access(all) resource interface AccountPublic { - // TODO: This has been disabled because you cannot get a capability without providing a type T anymore in Cadence 1.0 access(all) view fun getPublicCapability(path: PublicPath, type: Type): Capability? access(all) view fun getPublicCapFromDelegator(type: Type): Capability? access(all) view fun getAddress(): Address @@ -267,7 +267,8 @@ access(all) contract HybridCustody { /// A resource for an account which fills the Parent role of the Child-Parent account management Model. A Manager /// can redeem or remove child accounts, and obtain any capabilities exposed by the child account to them. /// - access(all) resource Manager: ManagerPrivate, ManagerPublic, ViewResolver.Resolver { + access(all) resource Manager: ManagerPrivate, ManagerPublic, ViewResolver.Resolver, Burner.Burnable { + access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid) /// Mapping of restricted access child account Capabilities indexed by their address access(self) let childAccounts: {Address: Capability} @@ -498,10 +499,13 @@ access(all) contract HybridCustody { self.resources <- {} } - // TODO: burnCallback and ResourceDestroyed event - // destroy () { - // destroy self.resources - // } + access(all) fun burnCallback() { + let keys = self.resources.keys + for k in keys { + let r <- self.resources.remove(key: k)! + Burner.burn(<-r) + } + } } /// The ChildAccount resource sits between a child account and a parent and is stored on the same account as the @@ -513,7 +517,9 @@ access(all) contract HybridCustody { /// able to manage all ChildAccount resources it shares, without worrying about whether the upstream parent can do /// anything to prevent it. /// - access(all) resource ChildAccount: AccountPrivate, AccountPublic, ViewResolver.Resolver { + access(all) resource ChildAccount: AccountPrivate, AccountPublic, ViewResolver.Resolver, Burner.Burnable { + access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, address: Address = self.childCap.address, parent: Address = self.parent) + /// A Capability providing access to the underlying child account access(self) let childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}> @@ -767,10 +773,13 @@ access(all) contract HybridCustody { return child!.getControllerIDForType(type: type, forPath: forPath) } - // TODO: burnCallback and ResourceDestoryed event - // destroy () { - // destroy <- self.resources - // } + access(contract) fun burnCallback() { + let keys = self.resources.keys + for k in keys { + let r <- self.resources.remove(key: k)! + Burner.burn(<- r) + } + } } /// A resource which sits on the account it manages to make it easier for apps to configure the behavior they want @@ -782,7 +791,8 @@ access(all) contract HybridCustody { /// accounts would still exist, allowing a form of Hybrid Custody which has no true owner over an account, but /// shared partial ownership. /// - access(all) resource OwnedAccount: OwnedAccountPrivate, BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver { + access(all) resource OwnedAccount: OwnedAccountPrivate, BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver, Burner.Burnable { + access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, addr: Address = self.acct.address) /// Capability on the underlying account object access(self) var acct: Capability @@ -1015,12 +1025,6 @@ access(all) contract HybridCustody { self.seal() let acct = self.borrowAccount() - // Unlink existing owner's Capability if owner exists - // TODO: is this still needed? Sealing the account should revoke and rotate all - // existing account links which should mean this one is already gone. - // if self.acctOwner != nil { - // acct.capabilities.account.getController(byCapabilityID: self.acct.id)?.delete() - // } // Link a Capability for the new owner, retrieve & publish let identifier = HybridCustody.getOwnerIdentifier(to) @@ -1192,10 +1196,12 @@ access(all) contract HybridCustody { self.display = nil } - // TODO: Use the burner interface - // destroy () { - // destroy <- self.resources - // } + access(all) fun burnCallback() { + for k in self.resources.keys { + let r <- self.resources.remove(key: k)! + Burner.burn(<-r) + } + } } /// Utility function to get the path identifier for a parent address when interacting with a ChildAccount and its From b075ab006108493499b712afa3b33d8a28941e39 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 3 Apr 2024 08:59:07 -0700 Subject: [PATCH 12/34] fix access level for burn callback --- contracts/HybridCustody.cdc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index a8ed0e4..ef7f127 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -499,12 +499,21 @@ access(all) contract HybridCustody { self.resources <- {} } - access(all) fun burnCallback() { + access(contract) fun burnCallback() { + pre { + // Prevent accidental burning of a resource that has ownership of other accounts + self.ownedAccounts.length == 0: "cannot destroy a manager with owned accounts" + } + let keys = self.resources.keys for k in keys { let r <- self.resources.remove(key: k)! Burner.burn(<-r) } + + for c in self.childAccounts.keys { + self.removeChild(addr: c) + } } } @@ -969,14 +978,14 @@ access(all) contract HybridCustody { for c in childAccountControllers { c.delete() } - destroy <- acct.storage.load<@AnyResource>(from: storagePath) + Burner.burn(<- acct.storage.load<@AnyResource>(from: storagePath)) let delegatorStoragePath = StoragePath(identifier: capDelegatorIdentifier)! let delegatorControllers = acct.capabilities.storage.getControllers(forPath: delegatorStoragePath) for c in delegatorControllers { c.delete() } - destroy <- acct.storage.load<@AnyResource>(from: delegatorStoragePath) + Burner.burn(<- acct.storage.load<@AnyResource>(from: delegatorStoragePath)) self.parents.remove(key: parent) emit AccountUpdated(id: self.uuid, child: self.acct.address, parent: parent, active: false) @@ -1196,11 +1205,15 @@ access(all) contract HybridCustody { self.display = nil } - access(all) fun burnCallback() { + access(contract) fun burnCallback() { for k in self.resources.keys { let r <- self.resources.remove(key: k)! Burner.burn(<-r) } + + for p in self.parents.keys { + self.removeParent(parent: p) + } } } From 96fbbbf5f3156199d0bdfd7fcc9cfead1ce2479a Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 3 Apr 2024 10:06:14 -0700 Subject: [PATCH 13/34] add missing tests, make a new _borrowAccount method for internal use and give borrowAccount the Owner entitlement --- contracts/HybridCustody.cdc | 25 +-- .../hybrid-custody/borrow_owned_account.cdc | 11 ++ .../get_account_public_address.cdc | 13 ++ .../metadata/resolve_child_display_name.cdc | 4 +- test/HybridCustody_tests.cdc | 148 ++++++++++++++++++ transactions/factory/setup_empty_factory.cdc | 25 +++ .../set_child_account_display_to_nil.cdc | 10 ++ .../hybrid-custody/remove_owned_account.cdc | 10 ++ .../set_capability_factory_for_parent.cdc | 13 ++ .../set_capability_filter_for_parent.cdc | 13 ++ .../unlink_child_capability.cdc | 10 ++ 11 files changed, 271 insertions(+), 11 deletions(-) create mode 100644 scripts/hybrid-custody/borrow_owned_account.cdc create mode 100644 scripts/hybrid-custody/get_account_public_address.cdc create mode 100644 transactions/factory/setup_empty_factory.cdc create mode 100644 transactions/hybrid-custody/metadata/set_child_account_display_to_nil.cdc create mode 100644 transactions/hybrid-custody/remove_owned_account.cdc create mode 100644 transactions/hybrid-custody/set_capability_factory_for_parent.cdc create mode 100644 transactions/hybrid-custody/set_capability_filter_for_parent.cdc create mode 100644 transactions/hybrid-custody/unlink_child_capability.cdc diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index ef7f127..bb8fb97 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -84,7 +84,7 @@ access(all) contract HybridCustody { /// An OwnedAccount shares the BorrowableAccount capability to itelf with ChildAccount resources /// access(all) resource interface BorrowableAccount { - access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account + access(contract) view fun _borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account access(all) view fun check(): Bool } @@ -182,7 +182,7 @@ access(all) contract HybridCustody { access(all) view fun getParentAddresses(): [Address] /// Borrows this OwnedAccount's AuthAccount Capability - access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account + access(Owner) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account /// Returns the current owner of this account, if there is one access(all) view fun getOwner(): Address? @@ -245,7 +245,7 @@ access(all) contract HybridCustody { access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? access(Manage) fun removeChild(addr: Address) access(Manage) fun addOwnedAccount(cap: Capability) - access(Manage) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? + access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? access(Manage) fun removeOwned(addr: Address) access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { pre { @@ -418,7 +418,7 @@ access(all) contract HybridCustody { /// Returns a reference to an owned account /// - access(Manage) fun borrowOwnedAccount(addr: Address): &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { + access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { if let cap = self.ownedAccounts[addr] { return cap.borrow() } @@ -612,7 +612,7 @@ access(all) contract HybridCustody { return nil } - let acct = child.borrowAccount() + let acct = child._borrowAccount() let tmp = f!.getCapability(acct: acct, controllerID: controllerID) if tmp == nil { return nil @@ -660,7 +660,7 @@ access(all) contract HybridCustody { return nil } - let acct = child.borrowAccount() + let acct = child._borrowAccount() return f!.getPublicCapability(acct: acct, path: path) } @@ -673,7 +673,7 @@ access(all) contract HybridCustody { /// Sets the child account as redeemed by the given Address /// access(contract) fun setRedeemed(_ addr: Address) { - let acct = self.childCap.borrow()!.borrowAccount() + let acct = self.childCap.borrow()!._borrowAccount() if let o = acct.storage.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) { o.setRedeemed(addr) } @@ -683,7 +683,7 @@ access(all) contract HybridCustody { /// access(Owner) fun borrowCapabilityDelegator(): auth(Capabilities) &CapabilityDelegator.Delegator? { let path = HybridCustody.getCapabilityDelegatorIdentifier(self.parent) - return self.childCap.borrow()!.borrowAccount().storage.borrow( + return self.childCap.borrow()!._borrowAccount().storage.borrow( from: StoragePath(identifier: path)! ) } @@ -731,7 +731,7 @@ access(all) contract HybridCustody { return } - let acct = child.borrowAccount() + let acct = child._borrowAccount() if let ownedAcct = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) { ownedAcct.removeParent(parent: parent) } @@ -930,10 +930,15 @@ access(all) contract HybridCustody { /// Returns a reference to the encapsulated account object /// - access(contract) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account { + access(Owner) view fun borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account { return self.acct.borrow() ?? panic("unable to borrow Account Capability") } + // Used internally so that child account resources are able to borrow their underlying Account reference + access(contract) view fun _borrowAccount(): auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account { + return self.borrowAccount() + } + /// Returns the addresses of all associated parents pending and active /// access(all) view fun getParentAddresses(): [Address] { diff --git a/scripts/hybrid-custody/borrow_owned_account.cdc b/scripts/hybrid-custody/borrow_owned_account.cdc new file mode 100644 index 0000000..0fde2bf --- /dev/null +++ b/scripts/hybrid-custody/borrow_owned_account.cdc @@ -0,0 +1,11 @@ +import "HybridCustody" + +access(all) fun main(owner: Address, child: Address): Address { + let m = getAuthAccount(owner).storage.borrow(from: HybridCustody.ManagerStoragePath) + ?? panic("manager could not be borrowed") + let ownedAcct = m.borrowOwnedAccount(addr: child) + ?? panic("could not borrow owned account") + + let acct = ownedAcct.borrowAccount() + return acct.address +} \ No newline at end of file diff --git a/scripts/hybrid-custody/get_account_public_address.cdc b/scripts/hybrid-custody/get_account_public_address.cdc new file mode 100644 index 0000000..aed9558 --- /dev/null +++ b/scripts/hybrid-custody/get_account_public_address.cdc @@ -0,0 +1,13 @@ +import "HybridCustody" + +access(all) fun main(parent: Address, child: Address): Address { + let cap = getAccount(parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) + ?? panic("manager not found") + let manager = cap.borrow() + ?? panic("unable to borrow manager") + + let acct = manager.borrowAccountPublic(addr: child) + ?? panic("child account not found") + + return acct.getAddress() +} \ No newline at end of file diff --git a/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc b/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc index 2cec87f..f67dadd 100644 --- a/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc +++ b/scripts/hybrid-custody/metadata/resolve_child_display_name.cdc @@ -7,7 +7,9 @@ access(all) fun main(parent: Address, child: Address): String { ?? panic("manager not found") let c = m.borrowAccount(addr: child) ?? panic("child not found") + + let tmp = c.resolveView(Type()) ?? panic("unable to resolve metadata display") - let d = c.resolveView(Type())! as! MetadataViews.Display + let d = tmp as! MetadataViews.Display return d.name } \ No newline at end of file diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index 8522089..4a7219f 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -1,5 +1,6 @@ import Test import "test_helpers.cdc" +import "HybridCustody" access(all) let adminAccount = Test.getAccount(0x0000000000000007) access(all) let accounts: {String: Test.TestAccount} = {} @@ -964,6 +965,148 @@ fun testGetChildAccountCapabilityFilterAndFactory() { scriptExecutor("test/can_get_child_factory_and_filter_caps.cdc", [child.address, parent.address]) } +access(all) +fun testSetCapabilityFactoryForParent() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + let newFactory = Test.createAccount() + setupEmptyFactory(newFactory) + + txExecutor("hybrid-custody/set_capability_factory_for_parent.cdc", [child], [parent.address, newFactory.address], nil) + + expectScriptFailure( + "hybrid-custody/get_nft_provider_capability.cdc", + [parent.address, child.address], + "capability not found" + ) +} + +access(all) +fun testSetCapabilityFilterForParent() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + let newFilter = Test.createAccount() + setupFilter(newFilter, FilterKindAllowList) + + txExecutor("hybrid-custody/set_capability_filter_for_parent.cdc", [child], [parent.address, newFilter.address], nil) + + expectScriptFailure( + "hybrid-custody/get_nft_provider_capability.cdc", + [parent.address, child.address], + "capability not found" + ) +} + +access(all) +fun testSetChildAccountDisplay_toNil() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + txExecutor("hybrid-custody/metadata/set_child_account_display_to_nil.cdc", [parent], [child.address], nil) + + expectScriptFailure( + "hybrid-custody/metadata/resolve_child_display_name.cdc", + [parent.address, child.address], + "unable to resolve metadata display" + ) +} + +access(all) +fun testRemoveChild_invalidChildAccountCapability() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + txExecutor("hybrid-custody/unlink_child_capability.cdc", [child], [parent.address], nil) + + txExecutor("hybrid-custody/remove_child_account.cdc", [parent], [child.address], nil) + + let e = Test.eventsOfType(Type()).removeLast() as! HybridCustody.AccountUpdated + Test.assert(e.child == child.address, message: "unexpected AccountUpdated value") +} + +access(all) +fun testBorrowAccount_nilCapability() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + txExecutor("hybrid-custody/unlink_child_capability.cdc", [child], [parent.address], nil) + + expectScriptFailure( + "hybrid-custody/metadata/resolve_child_display_name.cdc", + [parent.address, child.address], + "child not found" + ) +} + +access(all) +fun testBorrowAccountPublic() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + let res = scriptExecutor("hybrid-custody/get_account_public_address.cdc", [parent.address, child.address])! as! Address + Test.assertEqual(child.address, res) + + txExecutor("hybrid-custody/remove_child_account.cdc", [parent], [child.address], nil) + + expectScriptFailure("hybrid-custody/get_account_public_address.cdc", [parent.address, child.address], "child account not found") +} + +access(all) fun testBorrowOwnedAccount() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + let owner = Test.createAccount() + setupAccountManager(owner) + + txExecutor("hybrid-custody/transfer_ownership.cdc", [child], [owner.address], nil) + Test.assert(getPendingOwner(child: child)! == owner.address, message: "child account pending ownership was not updated correctly") + + txExecutor("hybrid-custody/accept_ownership.cdc", [owner], [child.address, nil, nil], nil) + + let res = scriptExecutor("hybrid-custody/borrow_owned_account.cdc", [owner.address, child.address])! as! Address + Test.assertEqual(child.address, res) + + expectScriptFailure("hybrid-custody/borrow_owned_account.cdc", [owner.address, parent.address], "could not borrow owned account") +} + +access(all) +fun testRemoveOwned() { + let child = Test.createAccount() + let owner = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: Test.createAccount()) + setupAccountManager(owner) + + txExecutor("hybrid-custody/transfer_ownership.cdc", [child], [owner.address], nil) + Test.assert(getPendingOwner(child: child)! == owner.address, message: "child account pending ownership was not updated correctly") + + txExecutor("hybrid-custody/accept_ownership.cdc", [owner], [child.address, nil, nil], nil) + + // remove the owned account + txExecutor("hybrid-custody/remove_owned_account.cdc", [owner], [child.address], nil) + + let sealEvent = Test.eventsOfType(Type()).removeLast() as! HybridCustody.AccountSealed + Test.assertEqual(child.address, sealEvent.address) + + let ownershipEvent = Test.eventsOfType(Type()).removeLast() as! HybridCustody.OwnershipUpdated + Test.assertEqual(owner.address, ownershipEvent.previousOwner!) + Test.assertEqual(nil, ownershipEvent.owner) +} + // --------------- End Test Cases --------------- @@ -1018,6 +1161,11 @@ fun setupFactoryManager(_ acct: Test.TestAccount) { txExecutor("factory/setup_nft_ft_manager.cdc", [acct], [], nil) } +access(all) +fun setupEmptyFactory(_ acct: Test.TestAccount) { + txExecutor("factory/setup_empty_factory.cdc", [acct], [], nil) +} + access(all) fun setupNFTCollection(_ acct: Test.TestAccount) { txExecutor("example-nft/setup_full.cdc", [acct], [], nil) diff --git a/transactions/factory/setup_empty_factory.cdc b/transactions/factory/setup_empty_factory.cdc new file mode 100644 index 0000000..4a49b8c --- /dev/null +++ b/transactions/factory/setup_empty_factory.cdc @@ -0,0 +1,25 @@ +import "NonFungibleToken" +import "FungibleToken" + +import "CapabilityFactory" + +transaction { + prepare(acct: auth(Storage, Capabilities) &Account) { + if acct.storage.borrow<&AnyResource>(from: CapabilityFactory.StoragePath) == nil { + let f <- CapabilityFactory.createFactoryManager() + acct.storage.save(<-f, to: CapabilityFactory.StoragePath) + } + + if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + acct.capabilities.unpublish(CapabilityFactory.PublicPath) + + let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) + acct.capabilities.publish(cap, at: CapabilityFactory.PublicPath) + } + + assert( + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), + message: "CapabilityFactory is not setup properly" + ) + } +} diff --git a/transactions/hybrid-custody/metadata/set_child_account_display_to_nil.cdc b/transactions/hybrid-custody/metadata/set_child_account_display_to_nil.cdc new file mode 100644 index 0000000..e9168b7 --- /dev/null +++ b/transactions/hybrid-custody/metadata/set_child_account_display_to_nil.cdc @@ -0,0 +1,10 @@ +import "HybridCustody" + +transaction(childAddress: Address) { + prepare(acct: auth(Storage) &Account) { + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) + ?? panic("manager not found") + + m.setChildAccountDisplay(address: childAddress, nil) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/remove_owned_account.cdc b/transactions/hybrid-custody/remove_owned_account.cdc new file mode 100644 index 0000000..ced74ee --- /dev/null +++ b/transactions/hybrid-custody/remove_owned_account.cdc @@ -0,0 +1,10 @@ +import "HybridCustody" + +transaction(addr: Address) { + prepare(acct: auth(Storage) &Account) { + let m = acct.storage.borrow(from: HybridCustody.ManagerStoragePath) + ?? panic("manager not found") + + m.removeOwned(addr: addr) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/set_capability_factory_for_parent.cdc b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc new file mode 100644 index 0000000..cf1bc8a --- /dev/null +++ b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc @@ -0,0 +1,13 @@ +import "HybridCustody" +import "CapabilityFactory" + +transaction(parent: Address, factoryAddress: Address) { + prepare(acct: auth(Storage) &Account) { + let cap = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + ?? panic("capability factory was nil") + + let ownedAccount = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) + ?? panic("owned account not found") + ownedAccount.setCapabilityFactoryForParent(parent: parent, cap: cap) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/set_capability_filter_for_parent.cdc b/transactions/hybrid-custody/set_capability_filter_for_parent.cdc new file mode 100644 index 0000000..3fdf350 --- /dev/null +++ b/transactions/hybrid-custody/set_capability_filter_for_parent.cdc @@ -0,0 +1,13 @@ +import "HybridCustody" +import "CapabilityFilter" + +transaction(parent: Address, factoryAddress: Address) { + prepare(acct: auth(Storage) &Account) { + let cap = getAccount(factoryAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) + ?? panic("capability filter was nil") + + let ownedAccount = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) + ?? panic("owned account not found") + ownedAccount.setCapabilityFilterForParent(parent: parent, cap: cap) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/unlink_child_capability.cdc b/transactions/hybrid-custody/unlink_child_capability.cdc new file mode 100644 index 0000000..67bd93b --- /dev/null +++ b/transactions/hybrid-custody/unlink_child_capability.cdc @@ -0,0 +1,10 @@ +import "HybridCustody" + +transaction(parent: Address) { + prepare(acct: auth(Storage, Capabilities) &Account) { + let storagePath = StoragePath(identifier: HybridCustody.getChildAccountIdentifier(parent))! + for c in acct.capabilities.storage.getControllers(forPath: storagePath) { + c.delete() + } + } +} \ No newline at end of file From 53ff59549468770b6fcb4af03031152fb70cf23c Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 3 Apr 2024 10:35:42 -0700 Subject: [PATCH 14/34] add tests for burn callback --- contracts/HybridCustody.cdc | 21 +++------ test/HybridCustody_tests.cdc | 46 +++++++++++++++++++ transactions/hybrid-custody/destroy_child.cdc | 11 +++++ .../hybrid-custody/destroy_manager.cdc | 10 ++++ .../hybrid-custody/destroy_owned_account.cdc | 10 ++++ 5 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 transactions/hybrid-custody/destroy_child.cdc create mode 100644 transactions/hybrid-custody/destroy_manager.cdc create mode 100644 transactions/hybrid-custody/destroy_owned_account.cdc diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index bb8fb97..1fbc3b3 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -60,7 +60,7 @@ access(all) contract HybridCustody { /// ChildAccount added/removed from Manager /// active : added to Manager /// !active : removed from Manager - access(all) event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool) + access(all) event AccountUpdated(id: UInt64?, child: Address, parent: Address?, active: Bool) /// OwnedAccount added/removed or sealed /// active && owner != nil : added to Manager /// !active && owner == nil : removed from Manager @@ -359,9 +359,11 @@ access(all) contract HybridCustody { // Get the child account id before removing capability let id: UInt64 = acct.uuid - acct.parentRemoveChildCallback(parent: self.owner!.address) + if self.owner != nil { + acct.parentRemoveChildCallback(parent: self.owner!.address) + } - emit AccountUpdated(id: id, child: cap.address, parent: self.owner!.address, active: false) + emit AccountUpdated(id: id, child: cap.address, parent: self.owner?.address, active: false) } /// Contract callback that removes a child account from the Manager's child accounts in the event a child @@ -783,11 +785,7 @@ access(all) contract HybridCustody { } access(contract) fun burnCallback() { - let keys = self.resources.keys - for k in keys { - let r <- self.resources.remove(key: k)! - Burner.burn(<- r) - } + self.parentRemoveChildCallback(parent: self.parent) } } @@ -997,7 +995,7 @@ access(all) contract HybridCustody { let parentManager = getAccount(parent).capabilities.get<&{ManagerPublic}>(HybridCustody.ManagerPublicPath) if parentManager?.check() == true { - parentManager!.borrow()?.removeParentCallback(child: self.owner!.address) + parentManager!.borrow()?.removeParentCallback(child: acct.address) } return true @@ -1211,11 +1209,6 @@ access(all) contract HybridCustody { } access(contract) fun burnCallback() { - for k in self.resources.keys { - let r <- self.resources.remove(key: k)! - Burner.burn(<-r) - } - for p in self.parents.keys { self.removeParent(parent: p) } diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index 4a7219f..beb3b32 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -1107,6 +1107,52 @@ fun testRemoveOwned() { Test.assertEqual(nil, ownershipEvent.owner) } +access(all) +fun testManager_burnCallback() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + txExecutor("hybrid-custody/destroy_manager.cdc", [parent], [], nil) + + let e = Test.eventsOfType(Type()).removeLast() as! HybridCustody.AccountUpdated + Test.assertEqual(e.child, child.address) +} + +access(all) +fun testChildAccount_burnCallback() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + let beforeChildren = (scriptExecutor("hybrid-custody/get_child_addresses.cdc", [parent.address]))! as! [Address] + Test.assert(beforeChildren.contains(child.address), message: "missing child address") + + txExecutor("hybrid-custody/destroy_child.cdc", [child], [parent.address], nil) + + let e = Test.eventsOfType(Type()).removeLast() as! HybridCustody.ChildAccount.ResourceDestroyed + Test.assertEqual(child.address, e.address) + Test.assertEqual(parent.address, e.parent) + + // make sure that the parent no longer has the child account (burn callback should have removed it) + let afterChildren: [Address] = (scriptExecutor("hybrid-custody/get_child_addresses.cdc", [parent.address]))! as! [Address] + Test.assert(!afterChildren.contains(child.address), message: "child address found but should not have been") +} + +access(all) +fun testOwnedAccount_burnCallback() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + txExecutor("hybrid-custody/destroy_owned_account.cdc", [child], [], nil) + + let children = (scriptExecutor("hybrid-custody/get_child_addresses.cdc", [parent.address]))! as! [Address] + Test.assert(!children.contains(child.address), message: "child account found when it should not have been") +} + // --------------- End Test Cases --------------- diff --git a/transactions/hybrid-custody/destroy_child.cdc b/transactions/hybrid-custody/destroy_child.cdc new file mode 100644 index 0000000..a5e8ba6 --- /dev/null +++ b/transactions/hybrid-custody/destroy_child.cdc @@ -0,0 +1,11 @@ +import "HybridCustody" +import "Burner" + +transaction(parent: Address) { + prepare(acct: auth(Storage) &Account) { + let s = StoragePath(identifier: HybridCustody.getChildAccountIdentifier(parent))! + let m <- acct.storage.load<@AnyResource>(from: s) + ?? panic("no resource found in child account storage path") + Burner.burn(<- m) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/destroy_manager.cdc b/transactions/hybrid-custody/destroy_manager.cdc new file mode 100644 index 0000000..9749e73 --- /dev/null +++ b/transactions/hybrid-custody/destroy_manager.cdc @@ -0,0 +1,10 @@ +import "HybridCustody" +import "Burner" + +transaction { + prepare(acct: auth(Storage) &Account) { + let m <- acct.storage.load<@AnyResource>(from: HybridCustody.ManagerStoragePath) + ?? panic("no resource found in manager storage path") + Burner.burn(<- m) + } +} \ No newline at end of file diff --git a/transactions/hybrid-custody/destroy_owned_account.cdc b/transactions/hybrid-custody/destroy_owned_account.cdc new file mode 100644 index 0000000..14d2a81 --- /dev/null +++ b/transactions/hybrid-custody/destroy_owned_account.cdc @@ -0,0 +1,10 @@ +import "HybridCustody" +import "Burner" + +transaction { + prepare(acct: auth(Storage) &Account) { + let m <- acct.storage.load<@AnyResource>(from: HybridCustody.OwnedAccountStoragePath) + ?? panic("no resource found in owned account storage path") + Burner.burn(<- m) + } +} \ No newline at end of file From 2d12790c7cf6f595c425a2de9ab4cdeeb4e95e4e Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 3 Apr 2024 11:07:27 -0700 Subject: [PATCH 15/34] add test for public capabilities --- contracts/HybridCustody.cdc | 10 +------ .../get_collection_public_from_child.cdc | 14 ++++++++++ test/HybridCustody_tests.cdc | 27 +++++++++++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 scripts/hybrid-custody/get_collection_public_from_child.cdc diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 1fbc3b3..2fa7cd7 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -507,12 +507,6 @@ access(all) contract HybridCustody { self.ownedAccounts.length == 0: "cannot destroy a manager with owned accounts" } - let keys = self.resources.keys - for k in keys { - let r <- self.resources.remove(key: k)! - Burner.burn(<-r) - } - for c in self.childAccounts.keys { self.removeChild(addr: c) } @@ -676,9 +670,7 @@ access(all) contract HybridCustody { /// access(contract) fun setRedeemed(_ addr: Address) { let acct = self.childCap.borrow()!._borrowAccount() - if let o = acct.storage.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath) { - o.setRedeemed(addr) - } + acct.storage.borrow<&OwnedAccount>(from: HybridCustody.OwnedAccountStoragePath)?.setRedeemed(addr) } /// Returns a reference to the stored delegator, generally used for arbitrary Capability retrieval diff --git a/scripts/hybrid-custody/get_collection_public_from_child.cdc b/scripts/hybrid-custody/get_collection_public_from_child.cdc new file mode 100644 index 0000000..ab9d113 --- /dev/null +++ b/scripts/hybrid-custody/get_collection_public_from_child.cdc @@ -0,0 +1,14 @@ +import "HybridCustody" +import "NonFungibleToken" + +access(all) fun main(parent: Address, child: Address, path: PublicPath, type: Type): [UInt64] { + let parentAcct = getAuthAccount(parent) + let manager = parentAcct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) + ?? panic("manager not found") + let child = manager.borrowAccountPublic(addr: child) ?? panic("child account not found") + let cap = child.getPublicCapability(path: path, type: type) + ?? panic("could not get capability") + let collection = cap.borrow<&{NonFungibleToken.CollectionPublic}>() + ?? panic("failed to borrow collection") + return collection.getIDs() +} \ No newline at end of file diff --git a/test/HybridCustody_tests.cdc b/test/HybridCustody_tests.cdc index beb3b32..c9b1584 100644 --- a/test/HybridCustody_tests.cdc +++ b/test/HybridCustody_tests.cdc @@ -1,6 +1,8 @@ import Test import "test_helpers.cdc" import "HybridCustody" +import "NonFungibleToken" +import "ExampleNFT" access(all) let adminAccount = Test.getAccount(0x0000000000000007) access(all) let accounts: {String: Test.TestAccount} = {} @@ -1153,6 +1155,31 @@ fun testOwnedAccount_burnCallback() { Test.assert(!children.contains(child.address), message: "child account found when it should not have been") } +access(all) +fun testGetPublicCapability() { + let child = Test.createAccount() + let parent = Test.createAccount() + + setupChildAndParent_FilterKindAll(child: child, parent: parent) + + setupNFTCollection(child) + mintNFTDefault(accounts[exampleNFT]!, receiver: child) + + let ids = scriptExecutor( + "hybrid-custody/get_collection_public_from_child.cdc", + [parent.address, child.address, PublicPath(identifier: exampleNFTPublicIdentifier)!, Type<&{NonFungibleToken.CollectionPublic}>()] + )! as! [UInt64] + Test.assert(ids.length > 0, message: "unexpected number of nfts in collection") + + // now try with a type that doesn't have a factory configured for it + Test.expectFailure(fun() { + scriptExecutor( + "hybrid-custody/get_collection_public_from_child.cdc", + [parent.address, child.address, PublicPath(identifier: exampleNFTPublicIdentifier)!, Type<&ExampleNFT.Collection>()] + )! as! [UInt64] + }, errorMessageSubstring: "could not get capability") +} + // --------------- End Test Cases --------------- From 0336192a6f874d4ced17decb0105c69fff549f45 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 3 Apr 2024 12:08:47 -0700 Subject: [PATCH 16/34] add comments to burnCallback methods --- contracts/HybridCustody.cdc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 2fa7cd7..ee5c302 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -30,7 +30,6 @@ import "CapabilityFilter" /// Repo reference: https://github.com/onflow/hybrid-custody /// access(all) contract HybridCustody { - access(all) entitlement Owner access(all) entitlement Child access(all) entitlement Publish @@ -330,7 +329,7 @@ access(all) contract HybridCustody { self.filter = cap } - + /// Sets the Filter Capability for this Manager, propagating to the specified child account /// access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { @@ -501,6 +500,10 @@ access(all) contract HybridCustody { self.resources <- {} } + // When a manager resource is destroyed, attempt to remove this parent from every + // child account it currently has + // + // Destruction will fail if there are any owned account to prevent loss of access to an account access(contract) fun burnCallback() { pre { // Prevent accidental burning of a resource that has ownership of other accounts @@ -776,6 +779,7 @@ access(all) contract HybridCustody { return child!.getControllerIDForType(type: type, forPath: forPath) } + // When a ChildAccount is destroyed, attempt to remove it from the parent account as well access(contract) fun burnCallback() { self.parentRemoveChildCallback(parent: self.parent) } @@ -1200,6 +1204,7 @@ access(all) contract HybridCustody { self.display = nil } + // When an OwnedAccount is destroyed, remove it from every configured parent account access(contract) fun burnCallback() { for p in self.parents.keys { self.removeParent(parent: p) From da1071234f4fb82cbc39ac2ba20c1ff92e823be6 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Fri, 12 Apr 2024 08:03:18 -0700 Subject: [PATCH 17/34] remove all variables and references to private paths --- contracts/HybridCustody.cdc | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index ee5c302..5366a19 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -41,14 +41,9 @@ access(all) contract HybridCustody { // access(all) let OwnedAccountStoragePath: StoragePath access(all) let OwnedAccountPublicPath: PublicPath - access(all) let OwnedAccountPrivatePath: PrivatePath access(all) let ManagerStoragePath: StoragePath access(all) let ManagerPublicPath: PublicPath - access(all) let ManagerPrivatePath: PrivatePath - - access(all) let LinkedAccountPrivatePath: PrivatePath - access(all) let BorrowableAccountPrivatePath: PrivatePath /* --- Events --- */ // @@ -153,7 +148,7 @@ access(all) contract HybridCustody { } /// Override the existing CapabilityFilter Capability for a given parent. This will allow the owner of the - /// account to start managing their own filter for retrieving Capabilities on Private Paths + /// account to start managing their own filter for retrieving Capabilities access(Owner) fun setCapabilityFilterForParent(parent: Address, cap: Capability<&{CapabilityFilter.Filter}>) { pre { cap.check(): "Invalid CapabilityFilter Capability provided" @@ -596,8 +591,8 @@ access(all) contract HybridCustody { self.filter = cap } - /// The main function to a child account's capabilities from a parent account. When a PrivatePath type is used, - /// the CapabilityFilter will be borrowed and the Capability being returned will be checked against it to + /// The main function to a child account's capabilities from a parent account. When getting a capability, the CapabilityFilter will be borrowed and + /// the Capability being returned will be checked against it to /// ensure that borrowing is permitted. If not allowed, nil is returned. /// Also know that this method retrieves Capabilities via the CapabilityFactory path. To retrieve arbitrary /// Capabilities, see `getPrivateCapFromDelegator()` and `getPublicCapFromDelegator()` which use the @@ -882,7 +877,6 @@ access(all) contract HybridCustody { } let capDelegatorPublic = PublicPath(identifier: capDelegatorIdentifier)! - // let capDelegatorPrivate = PrivatePath(identifier: capDelegatorIdentifier)! let pubCap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(capDelegatorStorage) acct.capabilities.publish(pubCap, at: capDelegatorPublic) @@ -895,7 +889,6 @@ access(all) contract HybridCustody { ) let childAcct <- create ChildAccount(borrowableCap, factory, filter, delegator, parentAddress) - let childAccountPrivatePath = PrivatePath(identifier: identifier)! acct.storage.save(<-childAcct, to: childAccountStorage) let delegatorCap = acct.capabilities.storage.issue(childAccountStorage) @@ -1261,15 +1254,10 @@ access(all) contract HybridCustody { init() { let identifier = "HybridCustodyChild_".concat(self.account.address.toString()) self.OwnedAccountStoragePath = StoragePath(identifier: identifier)! - self.OwnedAccountPrivatePath = PrivatePath(identifier: identifier)! self.OwnedAccountPublicPath = PublicPath(identifier: identifier)! - self.LinkedAccountPrivatePath = PrivatePath(identifier: "LinkedAccountPrivatePath_".concat(identifier))! - self.BorrowableAccountPrivatePath = PrivatePath(identifier: "BorrowableAccountPrivatePath_".concat(identifier))! - let managerIdentifier = "HybridCustodyManager_".concat(self.account.address.toString()) self.ManagerStoragePath = StoragePath(identifier: managerIdentifier)! self.ManagerPublicPath = PublicPath(identifier: managerIdentifier)! - self.ManagerPrivatePath = PrivatePath(identifier: managerIdentifier)! } } From 419deeaef2fa2b87c8034b9da5844247afa869bf Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Fri, 12 Apr 2024 09:02:57 -0700 Subject: [PATCH 18/34] update entitlements --- contracts/CapabilityDelegator.cdc | 16 ++++++++-------- contracts/CapabilityFactory.cdc | 10 ++++------ contracts/CapabilityFilter.cdc | 12 ++++++------ contracts/HybridCustody.cdc | 15 +++++++-------- contracts/factories/FTAllFactory.cdc | 2 +- contracts/factories/FTBalanceFactory.cdc | 2 +- contracts/factories/FTProviderFactory.cdc | 2 +- contracts/factories/FTReceiverBalanceFactory.cdc | 2 +- contracts/factories/FTReceiverFactory.cdc | 2 +- .../factories/NFTCollectionPublicFactory.cdc | 2 +- .../NFTProviderAndCollectionFactory.cdc | 2 +- contracts/factories/NFTProviderFactory.cdc | 2 +- scripts/delegator/find_nft_provider_cap.cdc | 2 +- scripts/delegator/get_all_private_caps.cdc | 2 +- scripts/delegator/get_nft_provider.cdc | 2 +- 15 files changed, 36 insertions(+), 39 deletions(-) diff --git a/contracts/CapabilityDelegator.cdc b/contracts/CapabilityDelegator.cdc index b574456..9a4eae1 100644 --- a/contracts/CapabilityDelegator.cdc +++ b/contracts/CapabilityDelegator.cdc @@ -12,8 +12,9 @@ access(all) contract CapabilityDelegator { /* --- Canonical Paths --- */ // access(all) let StoragePath: StoragePath - access(all) let PrivatePath: PrivatePath access(all) let PublicPath: PublicPath + + access(all) entitlement Get /* --- Events --- */ // @@ -23,13 +24,13 @@ access(all) contract CapabilityDelegator { /// Private interface for Capability retrieval /// access(all) resource interface GetterPrivate { - access(Capabilities) view fun getPrivateCapability(_ type: Type): Capability? { + access(Get) view fun getPrivateCapability(_ type: Type): Capability? { post { result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type" } } access(all) view fun findFirstPrivateType(_ type: Type): Type? - access(Capabilities) fun getAllPrivate(): [Capability] + access(Get) fun getAllPrivate(): [Capability] } /// Exposes public Capability retrieval @@ -66,7 +67,7 @@ access(all) contract CapabilityDelegator { /// @param type: Type of the Capability to retrieve /// @return Capability of the given Type if it exists, nil otherwise /// - access(Capabilities) view fun getPrivateCapability(_ type: Type): Capability? { + access(Get) view fun getPrivateCapability(_ type: Type): Capability? { return self.privateCapabilities[type] } @@ -82,7 +83,7 @@ access(all) contract CapabilityDelegator { /// /// @return List of all private Capabilities /// - access(Capabilities) fun getAllPrivate(): [Capability] { + access(Get) fun getAllPrivate(): [Capability] { return self.privateCapabilities.values } @@ -122,7 +123,7 @@ access(all) contract CapabilityDelegator { /// @param cap: Capability to add /// @param isPublic: Whether the Capability should be public or private /// - access(Mutate) fun addCapability(cap: Capability, isPublic: Bool) { + access(Mutate | Insert) fun addCapability(cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } @@ -138,7 +139,7 @@ access(all) contract CapabilityDelegator { /// /// @param cap: Capability to remove /// - access(Mutate) fun removeCapability(cap: Capability) { + access(Mutate | Remove) fun removeCapability(cap: Capability) { if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) { emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false) } @@ -167,7 +168,6 @@ access(all) contract CapabilityDelegator { init() { let identifier = "CapabilityDelegator_".concat(self.account.address.toString()) self.StoragePath = StoragePath(identifier: identifier)! - self.PrivatePath = PrivatePath(identifier: identifier)! self.PublicPath = PublicPath(identifier: identifier)! } } diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index e986e2b..1b6a07b 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -16,13 +16,12 @@ access(all) contract CapabilityFactory { access(all) let StoragePath: StoragePath - access(all) let PrivatePath: PrivatePath access(all) let PublicPath: PublicPath /// Factory structures a common interface for Capability retrieval from a given account at a specified path /// access(all) struct interface Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? } @@ -61,7 +60,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to add /// - access(Mutate) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Mutate | Insert) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { pre { !self.factories.containsKey(t): "Factory of given type already exists" } @@ -73,7 +72,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to replace existing Factory /// - access(Mutate) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Mutate | Insert) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { self.factories[t] = f } @@ -81,7 +80,7 @@ access(all) contract CapabilityFactory { /// /// @param t: Type the Factory is indexed on /// - access(Mutate) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { + access(Mutate | Remove) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { return self.factories.remove(key: t) } @@ -100,7 +99,6 @@ access(all) contract CapabilityFactory { init() { let identifier = "CapabilityFactory_".concat(self.account.address.toString()) self.StoragePath = StoragePath(identifier: identifier)! - self.PrivatePath = PrivatePath(identifier: identifier)! self.PublicPath = PublicPath(identifier: identifier)! } } \ No newline at end of file diff --git a/contracts/CapabilityFilter.cdc b/contracts/CapabilityFilter.cdc index 07f08c8..3ecd248 100644 --- a/contracts/CapabilityFilter.cdc +++ b/contracts/CapabilityFilter.cdc @@ -39,7 +39,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the denied types mapping /// - access(Mutate) fun addType(_ type: Type) { + access(Mutate | Insert) fun addType(_ type: Type) { self.deniedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -48,7 +48,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Mutate) fun removeType(_ type: Type) { + access(Mutate | Remove) fun removeType(_ type: Type) { if let removed = self.deniedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -56,7 +56,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Mutate) fun removeAllTypes() { + access(Mutate | Remove) fun removeAllTypes() { for type in self.deniedTypes.keys { self.removeType(type) } @@ -106,7 +106,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the allowed types mapping /// - access(Mutate) fun addType(_ type: Type) { + access(Mutate | Insert) fun addType(_ type: Type) { self.allowedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -115,7 +115,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Mutate) fun removeType(_ type: Type) { + access(Mutate | Remove) fun removeType(_ type: Type) { if let removed = self.allowedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -123,7 +123,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Mutate) fun removeAllTypes() { + access(Mutate | Remove) fun removeAllTypes() { for type in self.allowedTypes.keys { self.removeType(type) } diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 5366a19..a094199 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -32,7 +32,6 @@ import "CapabilityFilter" access(all) contract HybridCustody { access(all) entitlement Owner access(all) entitlement Child - access(all) entitlement Publish access(all) entitlement Manage /* --- Canonical Paths --- */ @@ -114,7 +113,7 @@ access(all) contract HybridCustody { /// supplied factory and filter to manage what can be obtained from the child account, and a new /// CapabilityDelegator resource is created for the sharing of one-off capabilities. Each of these pieces of /// access control are managed through the child account. - access(Publish | Owner) fun publishToParent( + access(Owner) fun publishToParent( parentAddress: Address, factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> @@ -542,7 +541,7 @@ access(all) contract HybridCustody { /// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a /// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot /// collection, but only to the path that the collection exists in. - access(self) let delegator: Capability + access(self) let delegator: Capability /// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If /// this filter is not nil, any Capability returned through the `getCapability` function checks that the @@ -673,9 +672,9 @@ access(all) contract HybridCustody { /// Returns a reference to the stored delegator, generally used for arbitrary Capability retrieval /// - access(Owner) fun borrowCapabilityDelegator(): auth(Capabilities) &CapabilityDelegator.Delegator? { + access(Owner) fun borrowCapabilityDelegator(): auth(CapabilityDelegator.Get) &CapabilityDelegator.Delegator? { let path = HybridCustody.getCapabilityDelegatorIdentifier(self.parent) - return self.childCap.borrow()!._borrowAccount().storage.borrow( + return self.childCap.borrow()!._borrowAccount().storage.borrow( from: StoragePath(identifier: path)! ) } @@ -733,7 +732,7 @@ access(all) contract HybridCustody { _ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>, _ factory: Capability<&{CapabilityFactory.Getter}>, _ filter: Capability<&{CapabilityFilter.Filter}>, - _ delegator: Capability, + _ delegator: Capability, _ parent: Address ) { pre { @@ -852,7 +851,7 @@ access(all) contract HybridCustody { /// 4. Publish the newly made private link to the designated parent's inbox for them to claim on their @Manager /// resource. /// - access(Publish | Owner) fun publishToParent( + access(Owner) fun publishToParent( parentAddress: Address, factory: Capability<&{CapabilityFactory.Getter}>, filter: Capability<&{CapabilityFilter.Filter}> @@ -881,7 +880,7 @@ access(all) contract HybridCustody { let pubCap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(capDelegatorStorage) acct.capabilities.publish(pubCap, at: capDelegatorPublic) - let delegator = acct.capabilities.storage.issue(capDelegatorStorage) + let delegator = acct.capabilities.storage.issue(capDelegatorStorage) assert(delegator.check(), message: "failed to setup capability delegator for parent address") let borrowableCap = self.borrowAccount().capabilities.storage.issue<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>( diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index db4ee1e..85eced8 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -3,7 +3,7 @@ import "FungibleToken" access(all) contract FTAllFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check() { return nil diff --git a/contracts/factories/FTBalanceFactory.cdc b/contracts/factories/FTBalanceFactory.cdc index 7d96926..ae4342d 100644 --- a/contracts/factories/FTBalanceFactory.cdc +++ b/contracts/factories/FTBalanceFactory.cdc @@ -3,7 +3,7 @@ import "FungibleToken" access(all) contract FTBalanceFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check<&{FungibleToken.Balance}>() { return nil diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index b81ee13..7b7504e 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -3,7 +3,7 @@ import "FungibleToken" access(all) contract FTProviderFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check() { return nil diff --git a/contracts/factories/FTReceiverBalanceFactory.cdc b/contracts/factories/FTReceiverBalanceFactory.cdc index 067eaa4..8ce95ad 100644 --- a/contracts/factories/FTReceiverBalanceFactory.cdc +++ b/contracts/factories/FTReceiverBalanceFactory.cdc @@ -3,7 +3,7 @@ import "FungibleToken" access(all) contract FTReceiverBalanceFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check<&{FungibleToken.Receiver, FungibleToken.Balance}>() { return nil diff --git a/contracts/factories/FTReceiverFactory.cdc b/contracts/factories/FTReceiverFactory.cdc index c1e9a59..d0ddb3f 100644 --- a/contracts/factories/FTReceiverFactory.cdc +++ b/contracts/factories/FTReceiverFactory.cdc @@ -3,7 +3,7 @@ import "FungibleToken" access(all) contract FTReceiverFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check<&{FungibleToken.Receiver}>() { return nil diff --git a/contracts/factories/NFTCollectionPublicFactory.cdc b/contracts/factories/NFTCollectionPublicFactory.cdc index 5902360..0d7be05 100644 --- a/contracts/factories/NFTCollectionPublicFactory.cdc +++ b/contracts/factories/NFTCollectionPublicFactory.cdc @@ -3,7 +3,7 @@ import "NonFungibleToken" access(all) contract NFTCollectionPublicFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check<&{NonFungibleToken.CollectionPublic}>() { return nil diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index 028adf4..423fdc4 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -3,7 +3,7 @@ import "NonFungibleToken" access(all) contract NFTProviderAndCollectionFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check() { return nil diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index 48d07b6..990cf06 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -3,7 +3,7 @@ import "NonFungibleToken" access(all) contract NFTProviderFactory { access(all) struct Factory: CapabilityFactory.Factory { - access(Capabilities) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { if !con.capability.check() { return nil diff --git a/scripts/delegator/find_nft_provider_cap.cdc b/scripts/delegator/find_nft_provider_cap.cdc index 95c4cb2..2916183 100644 --- a/scripts/delegator/find_nft_provider_cap.cdc +++ b/scripts/delegator/find_nft_provider_cap.cdc @@ -7,7 +7,7 @@ access(all) fun main(addr: Address): Bool { let acct = getAuthAccount(addr) let delegator = - acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() + acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") let desiredType = Type>() diff --git a/scripts/delegator/get_all_private_caps.cdc b/scripts/delegator/get_all_private_caps.cdc index 2d0ebd6..8c0b48c 100644 --- a/scripts/delegator/get_all_private_caps.cdc +++ b/scripts/delegator/get_all_private_caps.cdc @@ -4,7 +4,7 @@ import "NonFungibleToken" import "ExampleNFT" access(all) fun main(address: Address): Bool { - let privateCaps: [Capability] = getAuthAccount(address).capabilities.storage.issue(CapabilityDelegator.StoragePath) + let privateCaps: [Capability] = getAuthAccount(address).capabilities.storage.issue(CapabilityDelegator.StoragePath) .borrow() ?.getAllPrivate() ?? panic("could not borrow delegator") diff --git a/scripts/delegator/get_nft_provider.cdc b/scripts/delegator/get_nft_provider.cdc index 1e20416..0753b65 100644 --- a/scripts/delegator/get_nft_provider.cdc +++ b/scripts/delegator/get_nft_provider.cdc @@ -7,7 +7,7 @@ access(all) fun main(addr: Address): Bool { let acct = getAuthAccount(addr) let delegator = - acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() + acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") let capType = Type>() From ce76340324ea0927c8379076eeb7ac9bddf27ab6 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Fri, 12 Apr 2024 15:31:00 -0700 Subject: [PATCH 19/34] more entitlements changes --- contracts/CapabilityFactory.cdc | 2 +- contracts/CapabilityFilter.cdc | 2 - contracts/HybridCustody.cdc | 41 ++++++++++--------- contracts/factories/FTAllFactory.cdc | 2 +- contracts/factories/FTBalanceFactory.cdc | 2 +- contracts/factories/FTProviderFactory.cdc | 2 +- .../factories/FTReceiverBalanceFactory.cdc | 2 +- contracts/factories/FTReceiverFactory.cdc | 2 +- .../factories/NFTCollectionPublicFactory.cdc | 2 +- .../NFTProviderAndCollectionFactory.cdc | 2 +- contracts/factories/NFTProviderFactory.cdc | 2 +- package.json | 2 +- 12 files changed, 31 insertions(+), 32 deletions(-) diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index 1b6a07b..ef61a5d 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -22,7 +22,7 @@ access(all) contract CapabilityFactory { /// access(all) struct interface Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? } /// Getter defines an interface for retrieval of a Factory if contained within the implementing resource diff --git a/contracts/CapabilityFilter.cdc b/contracts/CapabilityFilter.cdc index 3ecd248..1cd1883 100644 --- a/contracts/CapabilityFilter.cdc +++ b/contracts/CapabilityFilter.cdc @@ -12,7 +12,6 @@ access(all) contract CapabilityFilter { // access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath - access(all) let PrivatePath: PrivatePath /* --- Events --- */ // @@ -210,6 +209,5 @@ access(all) contract CapabilityFilter { self.StoragePath = StoragePath(identifier: identifier)! self.PublicPath = PublicPath(identifier: identifier)! - self.PrivatePath = PrivatePath(identifier: identifier)! } } diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index a094199..6383fa5 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -107,7 +107,7 @@ access(all) contract HybridCustody { access(all) resource interface OwnedAccountPrivate { /// Deletes the ChildAccount resource being used to share access to this OwnedAccount with the supplied parent /// address, and unlinks the paths it was using to reach the underlying account. - access(Owner | Remove) fun removeParent(parent: Address): Bool + access(Owner) fun removeParent(parent: Address): Bool /// Sets up a new ChildAccount resource for the given parentAddress to redeem. This child account uses the /// supplied factory and filter to manage what can be obtained from the child account, and a new @@ -234,13 +234,13 @@ access(all) contract HybridCustody { /// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts /// access(all) resource interface ManagerPrivate { - access(Manage) fun addAccount(cap: Capability) + access(Manage | Insert) fun addAccount(cap: Capability) access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? - access(Manage) fun removeChild(addr: Address) - access(Manage) fun addOwnedAccount(cap: Capability) + access(Manage | Remove) fun removeChild(addr: Address) + access(Manage | Insert) fun addOwnedAccount(cap: Capability) access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? - access(Manage) fun removeOwned(addr: Address) - access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage | Remove) fun removeOwned(addr: Address) + access(Manage | Mutate) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { pre { cap == nil || cap!.check(): "Invalid Manager Capability Filter" } @@ -250,10 +250,10 @@ access(all) contract HybridCustody { /// Functions anyone can call on a manager to get information about an account such as What child accounts it has /// Functions anyone can call on a manager to get information about an account such as what child accounts it has access(all) resource interface ManagerPublic { - access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? - access(all) fun getChildAddresses(): [Address] - access(all) fun getOwnedAddresses(): [Address] - access(all) fun getChildAccountDisplay(address: Address): MetadataViews.Display? + access(all) view fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? + access(all) view fun getChildAddresses(): [Address] + access(all) view fun getOwnedAddresses(): [Address] + access(all) view fun getChildAccountDisplay(address: Address): MetadataViews.Display? access(contract) fun removeParentCallback(child: Address) } @@ -282,7 +282,7 @@ access(all) contract HybridCustody { /// Sets the Display on the ChildAccount. If nil, the display is removed. /// - access(Manage) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { + access(Manage | Mutate) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { pre { self.childAccounts[address] != nil: "There is no child account with this address" } @@ -298,7 +298,7 @@ access(all) contract HybridCustody { /// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be /// added to the ChildAccount /// - access(Manage) fun addAccount(cap: Capability) { + access(Manage | Insert) fun addAccount(cap: Capability) { pre { self.childAccounts[cap.address] == nil: "There is already a child account with this address" } @@ -316,7 +316,7 @@ access(all) contract HybridCustody { /// Sets the default Filter Capability for this Manager. Does not propagate to child accounts. /// - access(Manage) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { + access(Manage | Mutate) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { pre { cap == nil || cap!.check(): "supplied capability must be nil or check must pass" } @@ -326,7 +326,7 @@ access(all) contract HybridCustody { /// Sets the Filter Capability for this Manager, propagating to the specified child account /// - access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage | Mutate) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { let acct = self.borrowAccount(addr: childAddress) ?? panic("child account not found") @@ -336,7 +336,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Manage) fun removeChild(addr: Address) { + access(Manage | Remove) fun removeChild(addr: Address) { let cap = self.childAccounts.remove(key: addr) ?? panic("child account not found") @@ -370,7 +370,7 @@ access(all) contract HybridCustody { /// Adds an owned account to the Manager's list of owned accounts, setting the Manager account as the owner of /// the given account /// - access(Manage) fun addOwnedAccount(cap: Capability) { + access(Manage | Insert) fun addOwnedAccount(cap: Capability) { pre { self.ownedAccounts[cap.address] == nil: "There is already an owned account with this address" } @@ -402,7 +402,7 @@ access(all) contract HybridCustody { /// Returns a reference to a child account's public AccountPublic interface /// - access(all) fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? { + access(all) view fun borrowAccountPublic(addr: Address): &{AccountPublic, ViewResolver.Resolver}? { let cap = self.childAccounts[addr] if cap == nil { return nil @@ -413,7 +413,7 @@ access(all) contract HybridCustody { /// Returns a reference to an owned account /// - access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { + access(Manage) view fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? { if let cap = self.ownedAccounts[addr] { return cap.borrow() } @@ -424,7 +424,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Manage) fun removeOwned(addr: Address) { + access(Manage | Remove) fun removeOwned(addr: Address) { if let acct = self.ownedAccounts.remove(key: addr) { if acct.check() { acct.borrow()!.seal() @@ -958,6 +958,7 @@ access(all) contract HybridCustody { if self.parents[parent] == nil { return false } + let identifier = HybridCustody.getChildAccountIdentifier(parent) let capDelegatorIdentifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) @@ -1031,7 +1032,7 @@ access(all) contract HybridCustody { let cap = acct.capabilities.storage.issue(HybridCustody.OwnedAccountStoragePath) // make sure we can borrow the newly issued owned account - cap.borrow()!.borrowAccount() + cap.borrow()?.borrowAccount() ?? panic("can not borrow the Hybrid Custody Owned Account") acct.inbox.publish(cap, name: identifier, recipient: to) diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index 85eced8..cdaf53d 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -15,7 +15,7 @@ access(all) contract FTAllFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return nil } } diff --git a/contracts/factories/FTBalanceFactory.cdc b/contracts/factories/FTBalanceFactory.cdc index ae4342d..f4b70c1 100644 --- a/contracts/factories/FTBalanceFactory.cdc +++ b/contracts/factories/FTBalanceFactory.cdc @@ -15,7 +15,7 @@ access(all) contract FTBalanceFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return acct.capabilities.get<&{FungibleToken.Balance}>(path) } } diff --git a/contracts/factories/FTProviderFactory.cdc b/contracts/factories/FTProviderFactory.cdc index 7b7504e..bff3175 100644 --- a/contracts/factories/FTProviderFactory.cdc +++ b/contracts/factories/FTProviderFactory.cdc @@ -15,7 +15,7 @@ access(all) contract FTProviderFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return nil } } diff --git a/contracts/factories/FTReceiverBalanceFactory.cdc b/contracts/factories/FTReceiverBalanceFactory.cdc index 8ce95ad..dd87c1c 100644 --- a/contracts/factories/FTReceiverBalanceFactory.cdc +++ b/contracts/factories/FTReceiverBalanceFactory.cdc @@ -15,7 +15,7 @@ access(all) contract FTReceiverBalanceFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return acct.capabilities.get<&{FungibleToken.Receiver, FungibleToken.Balance}>(path) } } diff --git a/contracts/factories/FTReceiverFactory.cdc b/contracts/factories/FTReceiverFactory.cdc index d0ddb3f..815a244 100644 --- a/contracts/factories/FTReceiverFactory.cdc +++ b/contracts/factories/FTReceiverFactory.cdc @@ -15,7 +15,7 @@ access(all) contract FTReceiverFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return acct.capabilities.get<&{FungibleToken.Receiver}>(path) } } diff --git a/contracts/factories/NFTCollectionPublicFactory.cdc b/contracts/factories/NFTCollectionPublicFactory.cdc index 0d7be05..16edaad 100644 --- a/contracts/factories/NFTCollectionPublicFactory.cdc +++ b/contracts/factories/NFTCollectionPublicFactory.cdc @@ -15,7 +15,7 @@ access(all) contract NFTCollectionPublicFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return acct.capabilities.get<&{NonFungibleToken.CollectionPublic}>(path) } } diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index 423fdc4..ebeb4e4 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -15,7 +15,7 @@ access(all) contract NFTProviderAndCollectionFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return nil } } diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index 990cf06..a2214dc 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -15,7 +15,7 @@ access(all) contract NFTProviderFactory { return nil } - access(all) view fun getPublicCapability(acct: auth(Capabilities) &Account, path: PublicPath): Capability? { + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { return nil } } diff --git a/package.json b/package.json index 6ec1b14..31de31f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "./test.sh" }, "author": "", "license": "ISC", From 3e923b535360bd55c1f6e3644b828e3e247c501b Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 17 Apr 2024 10:21:02 -0700 Subject: [PATCH 20/34] add {Collection} and {Vault} factories --- codecov.yml | 4 +- contracts/factories/FTAllFactory.cdc | 4 +- contracts/factories/FTVaultFactory.cdc | 48 ++++++++++++++++++++ contracts/factories/NFTCollectionFactory.cdc | 48 ++++++++++++++++++++ flow.json | 19 +++++++- 5 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 contracts/factories/FTVaultFactory.cdc create mode 100644 contracts/factories/NFTCollectionFactory.cdc diff --git a/codecov.yml b/codecov.yml index d65792d..5ffe41a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,4 +6,6 @@ ignore: - "contracts/factories/FTProviderFactory.cdc" - "contracts/factories/FTReceiverFactory.cdc" - "contracts/factories/NFTCollectionPublicFactory.cdc" - - "contracts/factories/NFTProviderFactory.cdc" \ No newline at end of file + - "contracts/factories/NFTProviderFactory.cdc" + - "contracts/factories/FTVaultFactory.cdc" + - "contracts/factories/NFTCollectionFactory.cdc" \ No newline at end of file diff --git a/contracts/factories/FTAllFactory.cdc b/contracts/factories/FTAllFactory.cdc index cdaf53d..046991e 100644 --- a/contracts/factories/FTAllFactory.cdc +++ b/contracts/factories/FTAllFactory.cdc @@ -5,11 +5,11 @@ access(all) contract FTAllFactory { access(all) struct Factory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/contracts/factories/FTVaultFactory.cdc b/contracts/factories/FTVaultFactory.cdc new file mode 100644 index 0000000..82e5e93 --- /dev/null +++ b/contracts/factories/FTVaultFactory.cdc @@ -0,0 +1,48 @@ +import "CapabilityFactory" +import "FungibleToken" + +access(all) contract FTVaultFactory { + access(all) struct WithdrawFactory: CapabilityFactory.Factory { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability + } + + return nil + } + + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { + return nil + } + } + + access(all) struct Factory: CapabilityFactory.Factory { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{FungibleToken.Vault}>() { + return nil + } + + return con.capability as! Capability<&{FungibleToken.Vault}> + } + + return nil + } + + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { + if let cap = acct.capabilities.get<&{FungibleToken.Vault}>(path) { + if !cap.check() { + return nil + } + + return cap + } + + return nil + } + } +} \ No newline at end of file diff --git a/contracts/factories/NFTCollectionFactory.cdc b/contracts/factories/NFTCollectionFactory.cdc new file mode 100644 index 0000000..9508c23 --- /dev/null +++ b/contracts/factories/NFTCollectionFactory.cdc @@ -0,0 +1,48 @@ +import "CapabilityFactory" +import "NonFungibleToken" + +access(all) contract NFTProviderAndCollectionFactory { + access(all) struct WithdrawFactory: CapabilityFactory.Factory { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check() { + return nil + } + + return con.capability as! Capability + } + + return nil + } + + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { + return nil + } + } + + access(all) struct Factory: CapabilityFactory.Factory { + access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { + if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { + if !con.capability.check<&{NonFungibleToken.Collection}>() { + return nil + } + + return con.capability as! Capability<&{NonFungibleToken.Collection}> + } + + return nil + } + + access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { + if let cap = acct.capabilities.get<&{NonFungibleToken.Collection}>(path) { + if !cap.check() { + return nil + } + + return cap + } + + return nil + } + } +} \ No newline at end of file diff --git a/flow.json b/flow.json index b062ee8..ca3cc70 100644 --- a/flow.json +++ b/flow.json @@ -54,6 +54,15 @@ "mainnet": "d8a7e05a7ac670c0" } }, + "FTVaultFactory": { + "source": "./contracts/factories/FTVaultFactory.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007", + "testnet": "294e44e1ec6993c6", + "mainnet": "d8a7e05a7ac670c0" + } + }, "FTBalanceFactory": { "source": "./contracts/factories/FTBalanceFactory.cdc", "aliases": { @@ -328,6 +337,8 @@ "NFTProviderFactory", "NFTProviderAndCollectionFactory", "NFTCollectionPublicFactory", + "FTVaultFactory", + "NFTCollectionFactory", "ExampleNFT", "ExampleNFT2", "ExampleToken", @@ -354,7 +365,9 @@ "FTAllFactory", "FTBalanceFactory", "FTReceiverBalanceFactory", - "FTReceiverFactory" + "FTReceiverFactory", + "FTVaultFactory", + "NFTCollectionFactory" ] }, "mainnet": { @@ -370,7 +383,9 @@ "FTAllFactory", "FTBalanceFactory", "FTReceiverBalanceFactory", - "FTReceiverFactory" + "FTReceiverFactory", + "FTVaultFactory", + "NFTCollectionFactory" ] } } From 83b7571705bb73fd4689e7a71b3f60d8c2101dc3 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 17 Apr 2024 10:25:38 -0700 Subject: [PATCH 21/34] add missing contract in config --- flow.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flow.json b/flow.json index ca3cc70..33ab5b8 100644 --- a/flow.json +++ b/flow.json @@ -134,6 +134,14 @@ "testnet": "294e44e1ec6993c6" } }, + "NFTCollectionFactory": { + "source": "./contracts/factories/NFTCollectionFactory.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007", + "testnet": "294e44e1ec6993c6" + } + }, "FungibleToken": { "source": "./node_modules/@flowtyio/flow-contracts/contracts/FungibleToken.cdc", "aliases": { From 0c8ef753fa27209de7d16da2c191e37399126e22 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Mon, 22 Apr 2024 11:27:42 -0700 Subject: [PATCH 22/34] remove incorrect entitlement usage --- contracts/HybridCustody.cdc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 6383fa5..0de05c9 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -1100,9 +1100,9 @@ access(all) contract HybridCustody { /// Retrieves a reference to the ChildAccount associated with the given parent account if one exists. /// - access(Owner) fun borrowChildAccount(parent: Address): auth(Capabilities) &ChildAccount? { + access(Owner) fun borrowChildAccount(parent: Address): auth(Child) &ChildAccount? { let identifier = HybridCustody.getChildAccountIdentifier(parent) - return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Sets the CapabilityFactory Manager for the specified parent in the associated ChildAccount. From 547abbedf5bb771777c9bd56fde6d727885ceb04 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 24 Apr 2024 09:18:27 -0700 Subject: [PATCH 23/34] remove built-in entitlements --- contracts/CapabilityDelegator.cdc | 7 +++++-- contracts/CapabilityFactory.cdc | 10 +++++++--- contracts/CapabilityFilter.cdc | 16 +++++++++------ contracts/HybridCustody.cdc | 20 +++++++++---------- .../add_type_for_nft_provider_factory.cdc | 2 +- scripts/test/remove_nft_provider_factory.cdc | 2 +- scripts/test/update_nft_provider_factory.cdc | 2 +- .../delegator/add_private_nft_collection.cdc | 2 +- .../delegator/add_public_nft_collection.cdc | 2 +- .../remove_private_nft_collection.cdc | 2 +- .../remove_public_nft_collection.cdc | 2 +- .../setup_nft_filter_and_factory_manager.cdc | 4 ++-- transactions/factory/setup_ft_manager.cdc | 2 +- transactions/factory/setup_nft_ft_manager.cdc | 2 +- transactions/factory/setup_nft_manager.cdc | 2 +- .../filter/allow/add_type_to_list.cdc | 2 +- .../filter/allow/remove_all_types.cdc | 2 +- transactions/filter/deny/add_type_to_list.cdc | 2 +- transactions/filter/deny/remove_all_types.cdc | 2 +- .../add_type_for_nft_provider_factory.cdc | 2 +- 20 files changed, 49 insertions(+), 38 deletions(-) diff --git a/contracts/CapabilityDelegator.cdc b/contracts/CapabilityDelegator.cdc index 9a4eae1..f83e375 100644 --- a/contracts/CapabilityDelegator.cdc +++ b/contracts/CapabilityDelegator.cdc @@ -15,6 +15,9 @@ access(all) contract CapabilityDelegator { access(all) let PublicPath: PublicPath access(all) entitlement Get + access(all) entitlement Owner + access(all) entitlement Add + access(all) entitlement Delete /* --- Events --- */ // @@ -123,7 +126,7 @@ access(all) contract CapabilityDelegator { /// @param cap: Capability to add /// @param isPublic: Whether the Capability should be public or private /// - access(Mutate | Insert) fun addCapability(cap: Capability, isPublic: Bool) { + access(Owner | Add) fun addCapability(cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } @@ -139,7 +142,7 @@ access(all) contract CapabilityDelegator { /// /// @param cap: Capability to remove /// - access(Mutate | Remove) fun removeCapability(cap: Capability) { + access(Owner | Delete) fun removeCapability(cap: Capability) { if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) { emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false) } diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index ef61a5d..d8d7e74 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -17,6 +17,10 @@ access(all) contract CapabilityFactory { access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath + + access(all) entitlement Owner + access(all) entitlement Add + access(all) entitlement Delete /// Factory structures a common interface for Capability retrieval from a given account at a specified path /// @@ -60,7 +64,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to add /// - access(Mutate | Insert) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Owner | Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { pre { !self.factories.containsKey(t): "Factory of given type already exists" } @@ -72,7 +76,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to replace existing Factory /// - access(Mutate | Insert) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Owner | Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { self.factories[t] = f } @@ -80,7 +84,7 @@ access(all) contract CapabilityFactory { /// /// @param t: Type the Factory is indexed on /// - access(Mutate | Remove) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { + access(Owner | Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { return self.factories.remove(key: t) } diff --git a/contracts/CapabilityFilter.cdc b/contracts/CapabilityFilter.cdc index 1cd1883..9ffe645 100644 --- a/contracts/CapabilityFilter.cdc +++ b/contracts/CapabilityFilter.cdc @@ -13,6 +13,10 @@ access(all) contract CapabilityFilter { access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath + access(all) entitlement Owner + access(all) entitlement Add + access(all) entitlement Delete + /* --- Events --- */ // access(all) event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool) @@ -38,7 +42,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the denied types mapping /// - access(Mutate | Insert) fun addType(_ type: Type) { + access(Owner | Add) fun addType(_ type: Type) { self.deniedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -47,7 +51,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Mutate | Remove) fun removeType(_ type: Type) { + access(Owner | Delete) fun removeType(_ type: Type) { if let removed = self.deniedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -55,7 +59,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Mutate | Remove) fun removeAllTypes() { + access(Owner | Delete) fun removeAllTypes() { for type in self.deniedTypes.keys { self.removeType(type) } @@ -105,7 +109,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the allowed types mapping /// - access(Mutate | Insert) fun addType(_ type: Type) { + access(Owner | Add) fun addType(_ type: Type) { self.allowedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -114,7 +118,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Mutate | Remove) fun removeType(_ type: Type) { + access(Owner | Delete) fun removeType(_ type: Type) { if let removed = self.allowedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -122,7 +126,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Mutate | Remove) fun removeAllTypes() { + access(Owner | Delete) fun removeAllTypes() { for type in self.allowedTypes.keys { self.removeType(type) } diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 0de05c9..7866c64 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -234,13 +234,13 @@ access(all) contract HybridCustody { /// Entry point for a parent to obtain, maintain and access Capabilities or perform other actions on child accounts /// access(all) resource interface ManagerPrivate { - access(Manage | Insert) fun addAccount(cap: Capability) + access(Manage) fun addAccount(cap: Capability) access(Manage) fun borrowAccount(addr: Address): auth(Child) &{AccountPrivate, AccountPublic, ViewResolver.Resolver}? - access(Manage | Remove) fun removeChild(addr: Address) - access(Manage | Insert) fun addOwnedAccount(cap: Capability) + access(Manage) fun removeChild(addr: Address) + access(Manage) fun addOwnedAccount(cap: Capability) access(Manage) fun borrowOwnedAccount(addr: Address): auth(Owner) &{OwnedAccountPrivate, OwnedAccountPublic, ViewResolver.Resolver}? - access(Manage | Remove) fun removeOwned(addr: Address) - access(Manage | Mutate) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage) fun removeOwned(addr: Address) + access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { pre { cap == nil || cap!.check(): "Invalid Manager Capability Filter" } @@ -282,7 +282,7 @@ access(all) contract HybridCustody { /// Sets the Display on the ChildAccount. If nil, the display is removed. /// - access(Manage | Mutate) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { + access(Manage) fun setChildAccountDisplay(address: Address, _ d: MetadataViews.Display?) { pre { self.childAccounts[address] != nil: "There is no child account with this address" } @@ -316,7 +316,7 @@ access(all) contract HybridCustody { /// Sets the default Filter Capability for this Manager. Does not propagate to child accounts. /// - access(Manage | Mutate) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { + access(Manage) fun setDefaultManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?) { pre { cap == nil || cap!.check(): "supplied capability must be nil or check must pass" } @@ -326,7 +326,7 @@ access(all) contract HybridCustody { /// Sets the Filter Capability for this Manager, propagating to the specified child account /// - access(Manage | Mutate) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { + access(Manage) fun setManagerCapabilityFilter(cap: Capability<&{CapabilityFilter.Filter}>?, childAddress: Address) { let acct = self.borrowAccount(addr: childAddress) ?? panic("child account not found") @@ -1124,9 +1124,9 @@ access(all) contract HybridCustody { /// Retrieves a reference to the Delegator associated with the given parent account if one exists. /// - access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(Mutate) &CapabilityDelegator.Delegator? { + access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(CapabilityDelegator.Owner) &CapabilityDelegator.Delegator? { let identifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) - return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Adds the provided Capability to the Delegator associated with the given parent account. diff --git a/scripts/test/add_type_for_nft_provider_factory.cdc b/scripts/test/add_type_for_nft_provider_factory.cdc index 4ebab4e..8a2da57 100644 --- a/scripts/test/add_type_for_nft_provider_factory.cdc +++ b/scripts/test/add_type_for_nft_provider_factory.cdc @@ -4,7 +4,7 @@ import "NFTProviderFactory" import "NonFungibleToken" access(all) fun main(address: Address, type: Type): Bool { - let managerRef = getAuthAccount(address).storage.borrow( + let managerRef = getAuthAccount(address).storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") diff --git a/scripts/test/remove_nft_provider_factory.cdc b/scripts/test/remove_nft_provider_factory.cdc index 793c658..566b778 100644 --- a/scripts/test/remove_nft_provider_factory.cdc +++ b/scripts/test/remove_nft_provider_factory.cdc @@ -5,7 +5,7 @@ import "NonFungibleToken" access(all) fun main(address: Address): Bool { - let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let expectedType = Type() diff --git a/scripts/test/update_nft_provider_factory.cdc b/scripts/test/update_nft_provider_factory.cdc index 748b938..93f50a3 100644 --- a/scripts/test/update_nft_provider_factory.cdc +++ b/scripts/test/update_nft_provider_factory.cdc @@ -4,7 +4,7 @@ import "NFTProviderFactory" import "NonFungibleToken" access(all) fun main(address: Address) { - let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let nftProviderFactory = NFTProviderFactory.Factory() diff --git a/transactions/delegator/add_private_nft_collection.cdc b/transactions/delegator/add_private_nft_collection.cdc index cb32068..e24a49c 100644 --- a/transactions/delegator/add_private_nft_collection.cdc +++ b/transactions/delegator/add_private_nft_collection.cdc @@ -6,7 +6,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData diff --git a/transactions/delegator/add_public_nft_collection.cdc b/transactions/delegator/add_public_nft_collection.cdc index 9c71b61..79d3d5d 100644 --- a/transactions/delegator/add_public_nft_collection.cdc +++ b/transactions/delegator/add_public_nft_collection.cdc @@ -5,7 +5,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap diff --git a/transactions/delegator/remove_private_nft_collection.cdc b/transactions/delegator/remove_private_nft_collection.cdc index a870848..82d2ada 100644 --- a/transactions/delegator/remove_private_nft_collection.cdc +++ b/transactions/delegator/remove_private_nft_collection.cdc @@ -6,7 +6,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData diff --git a/transactions/delegator/remove_public_nft_collection.cdc b/transactions/delegator/remove_public_nft_collection.cdc index 8b14546..be157f5 100644 --- a/transactions/delegator/remove_public_nft_collection.cdc +++ b/transactions/delegator/remove_public_nft_collection.cdc @@ -5,7 +5,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index 0cc267c..92acfc4 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -67,7 +67,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { message: "CapabilityFactory is not setup properly" ) - let factoryManager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let factoryManager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") // Add NFT-related Factories to the Manager @@ -95,7 +95,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { message: "AllowlistFilter is not setup properly" ) - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("AllowlistFilter does not exist") // Construct an NFT Collection Type from the provided args & add to the AllowlistFilter diff --git a/transactions/factory/setup_ft_manager.cdc b/transactions/factory/setup_ft_manager.cdc index 1806525..287affe 100644 --- a/transactions/factory/setup_ft_manager.cdc +++ b/transactions/factory/setup_ft_manager.cdc @@ -27,7 +27,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type(), FTProviderFactory.Factory()) diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 703a478..8a53858 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -30,7 +30,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index 3472d18..2c3526d 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -24,7 +24,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) diff --git a/transactions/filter/allow/add_type_to_list.cdc b/transactions/filter/allow/add_type_to_list.cdc index ec955ad..5424d62 100644 --- a/transactions/filter/allow/add_type_to_list.cdc +++ b/transactions/filter/allow/add_type_to_list.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction(identifier: String) { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/allow/remove_all_types.cdc b/transactions/filter/allow/remove_all_types.cdc index b35c520..03de0fd 100644 --- a/transactions/filter/allow/remove_all_types.cdc +++ b/transactions/filter/allow/remove_all_types.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction() { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/filter/deny/add_type_to_list.cdc b/transactions/filter/deny/add_type_to_list.cdc index aeb94c1..c4cde7d 100644 --- a/transactions/filter/deny/add_type_to_list.cdc +++ b/transactions/filter/deny/add_type_to_list.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction(identifier: String) { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/deny/remove_all_types.cdc b/transactions/filter/deny/remove_all_types.cdc index 7c46253..2aac0e7 100644 --- a/transactions/filter/deny/remove_all_types.cdc +++ b/transactions/filter/deny/remove_all_types.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction() { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/test/add_type_for_nft_provider_factory.cdc b/transactions/test/add_type_for_nft_provider_factory.cdc index af6d6da..101127e 100644 --- a/transactions/test/add_type_for_nft_provider_factory.cdc +++ b/transactions/test/add_type_for_nft_provider_factory.cdc @@ -5,7 +5,7 @@ import "NonFungibleToken" transaction(type: Type) { prepare(account: auth(Storage) &Account) { - let managerRef = account.storage.borrow( + let managerRef = account.storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") From 2b229352231eb7cc1f944f9704605c1ebf7be945 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 24 Apr 2024 09:29:43 -0700 Subject: [PATCH 24/34] correct entitlements for NFT.Withdraw because migrations also need the Owner entitlement --- contracts/factories/NFTCollectionFactory.cdc | 4 ++-- .../NFTProviderAndCollectionFactory.cdc | 4 ++-- contracts/factories/NFTProviderFactory.cdc | 4 ++-- scripts/delegator/find_nft_provider_cap.cdc | 2 +- scripts/delegator/get_all_private_caps.cdc | 2 +- scripts/delegator/get_nft_provider.cdc | 4 ++-- .../factory/get_nft_provider_from_factory.cdc | 4 ++-- .../get_nft_provider_from_factory_allowed.cdc | 6 +++--- .../get_child_account_nft_capabilities.cdc | 4 ++-- .../get_nft_provider_capability.cdc | 2 +- .../get_nft_provider_capability_optional.cdc | 2 +- scripts/test/remove_nft_provider_factory.cdc | 2 +- .../test/test_get_accessible_child_nfts.cdc | 2 +- test/CapabilityDelegator_tests.cdc | 4 ++-- test/CapabilityFactory_tests.cdc | 18 +++++++++--------- .../delegator/add_private_nft_collection.cdc | 2 +- .../remove_private_nft_collection.cdc | 2 +- .../setup_nft_filter_and_factory_manager.cdc | 4 ++-- transactions/example-nft-2/setup_full.cdc | 2 +- transactions/example-nft/setup_full.cdc | 2 +- transactions/factory/setup_nft_ft_manager.cdc | 4 ++-- transactions/factory/setup_nft_manager.cdc | 4 ++-- ...dd_example_nft2_collection_to_delegator.cdc | 2 +- 23 files changed, 43 insertions(+), 43 deletions(-) diff --git a/contracts/factories/NFTCollectionFactory.cdc b/contracts/factories/NFTCollectionFactory.cdc index 9508c23..5b006bf 100644 --- a/contracts/factories/NFTCollectionFactory.cdc +++ b/contracts/factories/NFTCollectionFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderAndCollectionFactory { access(all) struct WithdrawFactory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index ebeb4e4..cf02cf2 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderAndCollectionFactory { access(all) struct Factory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index a2214dc..fcb8486 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderFactory { access(all) struct Factory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/scripts/delegator/find_nft_provider_cap.cdc b/scripts/delegator/find_nft_provider_cap.cdc index 2916183..5a60b9e 100644 --- a/scripts/delegator/find_nft_provider_cap.cdc +++ b/scripts/delegator/find_nft_provider_cap.cdc @@ -10,7 +10,7 @@ access(all) fun main(addr: Address): Bool { acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let desiredType = Type>() + let desiredType = Type>() let foundType = delegator.findFirstPrivateType(desiredType) ?? panic("no type found") let nakedCap = delegator.getPrivateCapability(foundType) ?? panic("requested capability type was not found") diff --git a/scripts/delegator/get_all_private_caps.cdc b/scripts/delegator/get_all_private_caps.cdc index 8c0b48c..12ab8ee 100644 --- a/scripts/delegator/get_all_private_caps.cdc +++ b/scripts/delegator/get_all_private_caps.cdc @@ -9,7 +9,7 @@ access(all) fun main(address: Address): Bool { ?.getAllPrivate() ?? panic("could not borrow delegator") - let desiredType: Type = Type>() + let desiredType: Type = Type>() return privateCaps.length == 1 && privateCaps[0].getType() == desiredType } \ No newline at end of file diff --git a/scripts/delegator/get_nft_provider.cdc b/scripts/delegator/get_nft_provider.cdc index 0753b65..ab4bbd0 100644 --- a/scripts/delegator/get_nft_provider.cdc +++ b/scripts/delegator/get_nft_provider.cdc @@ -10,12 +10,12 @@ access(all) fun main(addr: Address): Bool { acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let capType = Type>() + let capType = Type>() let nakedCap = delegator.getPrivateCapability(capType) ?? panic("requested capability type was not found") // we don't need to do anything with this cap, being able to cast here is enough to know // that this works - let cap = nakedCap as! Capability + let cap = nakedCap as! Capability return true } \ No newline at end of file diff --git a/scripts/factory/get_nft_provider_from_factory.cdc b/scripts/factory/get_nft_provider_from_factory.cdc index c49019c..794037a 100644 --- a/scripts/factory/get_nft_provider_from_factory.cdc +++ b/scripts/factory/get_nft_provider_from_factory.cdc @@ -13,8 +13,8 @@ access(all) fun main(addr: Address) { let controllers = acct.capabilities.storage.getControllers(forPath: d.storagePath) for c in controllers { - if c.borrowType.isSubtype(of: Type()) { - factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability + if c.borrowType.isSubtype(of: Type()) { + factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability return } } diff --git a/scripts/factory/get_nft_provider_from_factory_allowed.cdc b/scripts/factory/get_nft_provider_from_factory_allowed.cdc index 4c963da..7b8e646 100644 --- a/scripts/factory/get_nft_provider_from_factory_allowed.cdc +++ b/scripts/factory/get_nft_provider_from_factory_allowed.cdc @@ -15,14 +15,14 @@ access(all) fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { let factoryManager = ruleAcct.storage.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) ?? panic("Problem borrowing CapabilityFactory Manager") - let factory = factoryManager.getFactory(Type()) + let factory = factoryManager.getFactory(Type()) ?? panic("No factory for NFT Provider found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData var controllerID: UInt64? = nil for c in providerAcct.capabilities.storage.getControllers(forPath: d.storagePath) { - if c.borrowType.isSubtype(of: Type()) { + if c.borrowType.isSubtype(of: Type()) { controllerID = c.capabilityID break } @@ -30,7 +30,7 @@ access(all) fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { assert(controllerID != nil, message: "could not find existing provider capcon") - let provider = factory.getCapability(acct: providerAcct, controllerID: controllerID!)! as! Capability + let provider = factory.getCapability(acct: providerAcct, controllerID: controllerID!)! as! Capability let filter = ruleAcct.storage.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) ?? panic("Problem borrowing CapabilityFilter AllowlistFilter") diff --git a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc index 85978f4..0f76545 100644 --- a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc +++ b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc @@ -9,7 +9,7 @@ access(all) fun main(addr: Address): AnyStruct { var typeIdsWithProvider: {Address: [String]} = {} - let providerType = Type() + let providerType = Type() // Iterate through child accounts for address in manager.getChildAddresses() { @@ -26,7 +26,7 @@ access(all) fun main(addr: Address): AnyStruct { } if let cap = childAcct.getCapability(controllerID: c.capabilityID, type: providerType) { - let providerCap = cap as! Capability + let providerCap = cap as! Capability if !providerCap.check(){ continue diff --git a/scripts/hybrid-custody/get_nft_provider_capability.cdc b/scripts/hybrid-custody/get_nft_provider_capability.cdc index d80c390..6ab97b6 100644 --- a/scripts/hybrid-custody/get_nft_provider_capability.cdc +++ b/scripts/hybrid-custody/get_nft_provider_capability.cdc @@ -14,7 +14,7 @@ access(all) fun main(parent: Address, child: Address) { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let desiredType = Type() + let desiredType = Type() let controllerID = childAcct.getControllerIDForType(type: desiredType, forPath: d.storagePath) ?? panic("no capability found for desired type") diff --git a/scripts/test/get_nft_provider_capability_optional.cdc b/scripts/test/get_nft_provider_capability_optional.cdc index 635cb9d..065258c 100644 --- a/scripts/test/get_nft_provider_capability_optional.cdc +++ b/scripts/test/get_nft_provider_capability_optional.cdc @@ -14,7 +14,7 @@ access(all) fun main(parent: Address, child: Address, returnsNil: Bool): Bool { let collectionData = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let type = Type() + let type = Type() let controllerID = childAcct.getControllerIDForType(type: type, forPath: collectionData.storagePath) ?? panic("could not find controller for desired type") diff --git a/scripts/test/remove_nft_provider_factory.cdc b/scripts/test/remove_nft_provider_factory.cdc index 566b778..92537d1 100644 --- a/scripts/test/remove_nft_provider_factory.cdc +++ b/scripts/test/remove_nft_provider_factory.cdc @@ -10,7 +10,7 @@ access(all) fun main(address: Address): Bool { let expectedType = Type() - if let removed = managerRef.removeFactory(Type()) { + if let removed = managerRef.removeFactory(Type()) { return removed.getType() == expectedType } diff --git a/scripts/test/test_get_accessible_child_nfts.cdc b/scripts/test/test_get_accessible_child_nfts.cdc index 587dc6b..54f3043 100644 --- a/scripts/test/test_get_accessible_child_nfts.cdc +++ b/scripts/test/test_get_accessible_child_nfts.cdc @@ -29,7 +29,7 @@ access(all) fun main(addr: Address, expectedAddressToIDs: {Address: [UInt64]}){ var typeIdsWithProvider: {Address: [String]} = {} var nftViews: {Address: {UInt64: MetadataViews.Display}} = {} - let providerType = Type() + let providerType = Type() let collectionType: Type = Type<@{NonFungibleToken.CollectionPublic}>() for address in manager.getChildAddresses() { diff --git a/test/CapabilityDelegator_tests.cdc b/test/CapabilityDelegator_tests.cdc index 0fd099e..1c481d3 100644 --- a/test/CapabilityDelegator_tests.cdc +++ b/test/CapabilityDelegator_tests.cdc @@ -60,7 +60,7 @@ fun testShareExampleNFTCollectionPrivate() { Test.assert(e.isPublic == false) Test.assert(e.active) - let capabilityType = Type>() + let capabilityType = Type>() Test.assertEqual(capabilityType, e.capabilityType) } @@ -101,7 +101,7 @@ fun testRemoveExampleNFTCollectionPrivate() { Test.assert(e.isPublic == false) Test.assert(e.active == false) - let capabilityType = Type>() + let capabilityType = Type>() Test.assertEqual(capabilityType, e.capabilityType) let scriptCode = loadCode("delegator/find_nft_provider_cap.cdc", "scripts") diff --git a/test/CapabilityFactory_tests.cdc b/test/CapabilityFactory_tests.cdc index 2180c30..4227078 100644 --- a/test/CapabilityFactory_tests.cdc +++ b/test/CapabilityFactory_tests.cdc @@ -38,9 +38,9 @@ fun testGetSupportedTypesFromManager() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { Test.assert(supportedTypes.contains(e), message: "missing expected type in supported types") @@ -51,7 +51,7 @@ access(all) fun testAddFactoryFails() { expectScriptFailure( "test/add_type_for_nft_provider_factory.cdc", - [creator.address, Type()], + [creator.address, Type()], "Factory of given type already exists" ) } @@ -71,9 +71,9 @@ fun testAddFactorySucceeds() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type(), + Type(), Type<&{NonFungibleToken.Receiver}>() ] @@ -121,9 +121,9 @@ fun testSetupNFTManager() { let supportedTypes = scriptExecutor("factory/get_supported_types_from_manager.cdc", [tmp.address])! as! [Type] let expectedTypes = [ - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { @@ -180,9 +180,9 @@ fun testSetupNFTFTManager() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { diff --git a/transactions/delegator/add_private_nft_collection.cdc b/transactions/delegator/add_private_nft_collection.cdc index e24a49c..e023565 100644 --- a/transactions/delegator/add_private_nft_collection.cdc +++ b/transactions/delegator/add_private_nft_collection.cdc @@ -11,7 +11,7 @@ transaction { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.capabilities.storage.issue(d.storagePath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.addCapability(cap: sharedCap, isPublic: false) } diff --git a/transactions/delegator/remove_private_nft_collection.cdc b/transactions/delegator/remove_private_nft_collection.cdc index 82d2ada..6eb0924 100644 --- a/transactions/delegator/remove_private_nft_collection.cdc +++ b/transactions/delegator/remove_private_nft_collection.cdc @@ -11,7 +11,7 @@ transaction { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.capabilities.storage.issue(d.storagePath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.removeCapability(cap: sharedCap) diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index 92acfc4..23035d6 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -72,8 +72,8 @@ transaction(nftContractAddress: Address, nftContractName: String) { // Add NFT-related Factories to the Manager factoryManager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - factoryManager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - factoryManager.updateFactory(Type(), NFTProviderFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderFactory.Factory()) /* --- AllowlistFilter configuration --- */ // diff --git a/transactions/example-nft-2/setup_full.cdc b/transactions/example-nft-2/setup_full.cdc index b72b7a1..16049f1 100644 --- a/transactions/example-nft-2/setup_full.cdc +++ b/transactions/example-nft-2/setup_full.cdc @@ -17,6 +17,6 @@ transaction { at: d.publicPath ) - acct.capabilities.storage.issue(d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } diff --git a/transactions/example-nft/setup_full.cdc b/transactions/example-nft/setup_full.cdc index c20ad67..550e50a 100644 --- a/transactions/example-nft/setup_full.cdc +++ b/transactions/example-nft/setup_full.cdc @@ -15,6 +15,6 @@ transaction { let cap = acct.capabilities.storage.issue<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(d.storagePath) acct.capabilities.publish(cap, at: d.publicPath) - acct.capabilities.storage.issue(d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 8a53858..976eb87 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -33,8 +33,8 @@ transaction { let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) manager.updateFactory(Type(), FTProviderFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Balance}>(), FTBalanceFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver}>(), FTReceiverFactory.Factory()) diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index 2c3526d..fb1ba73 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -28,7 +28,7 @@ transaction { ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) } } diff --git a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc index 558091c..ce420e3 100644 --- a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc +++ b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc @@ -11,7 +11,7 @@ transaction(parent: Address, isPublic: Bool) { let child = o.borrowChildAccount(parent: parent) ?? panic("child account not found") - let cap = acct.capabilities.storage.issue(ExampleNFT2.CollectionStoragePath) + let cap = acct.capabilities.storage.issue(ExampleNFT2.CollectionStoragePath) o.addCapabilityToDelegator(parent: parent, cap: cap, isPublic: isPublic) } } \ No newline at end of file From 0c0243b8d29304db556763e001601d5e2c72d26f Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:43:20 -0500 Subject: [PATCH 25/34] update Burner testnet alias --- flow.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flow.json b/flow.json index 33ab5b8..6f36e87 100644 --- a/flow.json +++ b/flow.json @@ -162,8 +162,8 @@ "source": "./node_modules/@flowtyio/flow-contracts/contracts/Burner.cdc", "aliases": { "emulator": "0xf8d6e0586b0a20c7", - "testnet": "0x631e88ae7f1d7c20", - "mainnet": "0x1d7e57aa55817448" + "testnet": "0x9a0766d93b6608b7", + "mainnet": "0xf233dcee88fe0abe" } }, "FlowToken": { From 1346ae114f4af393f3ed80d188f1469192c0da9a Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Sat, 4 May 2024 06:55:21 -0700 Subject: [PATCH 26/34] sync new nft standard and public capability retrieval changes --- contracts/HybridCustody.cdc | 14 +++++++------- contracts/factories/NFTCollectionFactory.cdc | 17 +++++++---------- .../NFTProviderAndCollectionFactory.cdc | 4 ++-- contracts/factories/NFTProviderFactory.cdc | 4 ++-- contracts/standard/ExampleNFT.cdc | 2 +- contracts/standard/ExampleNFT2.cdc | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- scripts/delegator/find_nft_provider_cap.cdc | 2 +- scripts/delegator/get_all_private_caps.cdc | 2 +- scripts/delegator/get_nft_provider.cdc | 4 ++-- .../factory/get_nft_provider_from_factory.cdc | 4 ++-- .../get_nft_provider_from_factory_allowed.cdc | 6 +++--- .../get_account_public_address.cdc | 1 - .../get_child_account_nft_capabilities.cdc | 4 ++-- .../get_nft_provider_capability.cdc | 2 +- .../get_nft_provider_capability_optional.cdc | 2 +- scripts/test/remove_nft_provider_factory.cdc | 2 +- .../test/test_get_accessible_child_nfts.cdc | 2 +- test/CapabilityDelegator_tests.cdc | 4 ++-- test/CapabilityFactory_tests.cdc | 18 +++++++++--------- .../delegator/add_private_nft_collection.cdc | 2 +- .../remove_private_nft_collection.cdc | 2 +- .../setup_nft_filter_and_factory_manager.cdc | 12 ++++++------ transactions/example-nft-2/mint_to_account.cdc | 2 +- transactions/example-nft-2/setup_full.cdc | 2 +- transactions/example-nft/mint_to_account.cdc | 2 +- transactions/example-nft/setup_full.cdc | 2 +- transactions/factory/setup_empty_factory.cdc | 4 ++-- transactions/factory/setup_ft_manager.cdc | 4 ++-- transactions/factory/setup_nft_ft_manager.cdc | 8 ++++---- transactions/factory/setup_nft_manager.cdc | 6 +++--- transactions/filter/allow/setup.cdc | 2 +- transactions/filter/deny/setup.cdc | 2 +- transactions/filter/setup_allow_all.cdc | 2 +- .../hybrid-custody/accept_ownership.cdc | 1 - ...dd_example_nft2_collection_to_delegator.cdc | 2 +- .../onboarding/blockchain_native.cdc | 1 - .../hybrid-custody/publish_to_parent.cdc | 4 ++-- transactions/hybrid-custody/redeem_account.cdc | 1 - .../remove_parent_from_child.cdc | 2 +- .../set_capability_factory_for_parent.cdc | 1 - .../set_capability_filter_for_parent.cdc | 1 - .../hybrid-custody/set_default_manager_cap.cdc | 1 - .../hybrid-custody/set_manager_filter_cap.cdc | 1 - .../hybrid-custody/setup_multi_sig.cdc | 3 --- ...tup_owned_account_and_publish_to_parent.cdc | 2 -- 47 files changed, 81 insertions(+), 97 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 7866c64..1c0a026 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -298,7 +298,7 @@ access(all) contract HybridCustody { /// Adds a ChildAccount Capability to this Manager. If a default Filter is set in the manager, it will also be /// added to the ChildAccount /// - access(Manage | Insert) fun addAccount(cap: Capability) { + access(Manage) fun addAccount(cap: Capability) { pre { self.childAccounts[cap.address] == nil: "There is already a child account with this address" } @@ -336,7 +336,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Manage | Remove) fun removeChild(addr: Address) { + access(Manage) fun removeChild(addr: Address) { let cap = self.childAccounts.remove(key: addr) ?? panic("child account not found") @@ -370,7 +370,7 @@ access(all) contract HybridCustody { /// Adds an owned account to the Manager's list of owned accounts, setting the Manager account as the owner of /// the given account /// - access(Manage | Insert) fun addOwnedAccount(cap: Capability) { + access(Manage) fun addOwnedAccount(cap: Capability) { pre { self.ownedAccounts[cap.address] == nil: "There is already an owned account with this address" } @@ -424,7 +424,7 @@ access(all) contract HybridCustody { /// Removes specified child account from the Manager's child accounts. Callbacks to the child account remove /// any associated resources and Capabilities /// - access(Manage | Remove) fun removeOwned(addr: Address) { + access(Manage) fun removeOwned(addr: Address) { if let acct = self.ownedAccounts.remove(key: addr) { if acct.check() { acct.borrow()!.seal() @@ -954,7 +954,7 @@ access(all) contract HybridCustody { /// configured for the provided parent address. Once done, the parent will not have any valid capabilities with /// which to access the child account. /// - access(Owner | Remove) fun removeParent(parent: Address): Bool { + access(Owner) fun removeParent(parent: Address): Bool { if self.parents[parent] == nil { return false } @@ -983,8 +983,8 @@ access(all) contract HybridCustody { emit AccountUpdated(id: self.uuid, child: self.acct.address, parent: parent, active: false) let parentManager = getAccount(parent).capabilities.get<&{ManagerPublic}>(HybridCustody.ManagerPublicPath) - if parentManager?.check() == true { - parentManager!.borrow()?.removeParentCallback(child: acct.address) + if parentManager.check() { + parentManager.borrow()?.removeParentCallback(child: acct.address) } return true diff --git a/contracts/factories/NFTCollectionFactory.cdc b/contracts/factories/NFTCollectionFactory.cdc index 5b006bf..caf4dec 100644 --- a/contracts/factories/NFTCollectionFactory.cdc +++ b/contracts/factories/NFTCollectionFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderAndCollectionFactory { access(all) struct WithdrawFactory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil @@ -34,15 +34,12 @@ access(all) contract NFTProviderAndCollectionFactory { } access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { - if let cap = acct.capabilities.get<&{NonFungibleToken.Collection}>(path) { - if !cap.check() { - return nil - } - - return cap + let cap = acct.capabilities.get<&{NonFungibleToken.Collection}>(path) + if !cap.check() { + return nil } - - return nil + + return cap } } } \ No newline at end of file diff --git a/contracts/factories/NFTProviderAndCollectionFactory.cdc b/contracts/factories/NFTProviderAndCollectionFactory.cdc index cf02cf2..ebeb4e4 100644 --- a/contracts/factories/NFTProviderAndCollectionFactory.cdc +++ b/contracts/factories/NFTProviderAndCollectionFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderAndCollectionFactory { access(all) struct Factory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/contracts/factories/NFTProviderFactory.cdc b/contracts/factories/NFTProviderFactory.cdc index fcb8486..a2214dc 100644 --- a/contracts/factories/NFTProviderFactory.cdc +++ b/contracts/factories/NFTProviderFactory.cdc @@ -5,11 +5,11 @@ access(all) contract NFTProviderFactory { access(all) struct Factory: CapabilityFactory.Factory { access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability? { if let con = acct.capabilities.storage.getController(byCapabilityID: controllerID) { - if !con.capability.check() { + if !con.capability.check() { return nil } - return con.capability as! Capability + return con.capability as! Capability } return nil diff --git a/contracts/standard/ExampleNFT.cdc b/contracts/standard/ExampleNFT.cdc index 60e1d77..b80e993 100644 --- a/contracts/standard/ExampleNFT.cdc +++ b/contracts/standard/ExampleNFT.cdc @@ -155,7 +155,7 @@ access(all) contract ExampleNFT: ViewResolver { } // withdraw removes an NFT from the collection and moves it to the caller - access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { + access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) diff --git a/contracts/standard/ExampleNFT2.cdc b/contracts/standard/ExampleNFT2.cdc index 21f417c..cc65ad7 100644 --- a/contracts/standard/ExampleNFT2.cdc +++ b/contracts/standard/ExampleNFT2.cdc @@ -155,7 +155,7 @@ access(all) contract ExampleNFT2: ViewResolver { } // withdraw removes an NFT from the collection and moves it to the caller - access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { + access(NonFungibleToken.Withdraw ) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) diff --git a/package-lock.json b/package-lock.json index adba3c5..d8f1faa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@flowtyio/flow-contracts": "^0.1.0-beta.11" + "@flowtyio/flow-contracts": "^0.1.0-beta.19" } }, "node_modules/@flowtyio/flow-contracts": { - "version": "0.1.0-beta.11", - "resolved": "https://registry.npmjs.org/@flowtyio/flow-contracts/-/flow-contracts-0.1.0-beta.11.tgz", - "integrity": "sha512-4D1JHCrV6KxRgKEsfGxzVxAYrEjq51N0tlVy7gi+Ne7YhWQ+Jp7ha+QwPxuLIYkjMZjMzoM/dD6WedZQERgFSg==", + "version": "0.1.0-beta.19", + "resolved": "https://registry.npmjs.org/@flowtyio/flow-contracts/-/flow-contracts-0.1.0-beta.19.tgz", + "integrity": "sha512-s88ttcc+BYwgR+eXyIAtL8bXPaSj2lVQgbpD+7huadfst8N8gri3g4uaS8KxXkHZw4WQojJmaoc16Fkvlp93gQ==", "dependencies": { "commander": "^11.0.0" }, diff --git a/package.json b/package.json index 31de31f..350d7f7 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,6 @@ "author": "", "license": "ISC", "dependencies": { - "@flowtyio/flow-contracts": "^0.1.0-beta.11" + "@flowtyio/flow-contracts": "^0.1.0-beta.19" } } diff --git a/scripts/delegator/find_nft_provider_cap.cdc b/scripts/delegator/find_nft_provider_cap.cdc index 5a60b9e..2916183 100644 --- a/scripts/delegator/find_nft_provider_cap.cdc +++ b/scripts/delegator/find_nft_provider_cap.cdc @@ -10,7 +10,7 @@ access(all) fun main(addr: Address): Bool { acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let desiredType = Type>() + let desiredType = Type>() let foundType = delegator.findFirstPrivateType(desiredType) ?? panic("no type found") let nakedCap = delegator.getPrivateCapability(foundType) ?? panic("requested capability type was not found") diff --git a/scripts/delegator/get_all_private_caps.cdc b/scripts/delegator/get_all_private_caps.cdc index 12ab8ee..8c0b48c 100644 --- a/scripts/delegator/get_all_private_caps.cdc +++ b/scripts/delegator/get_all_private_caps.cdc @@ -9,7 +9,7 @@ access(all) fun main(address: Address): Bool { ?.getAllPrivate() ?? panic("could not borrow delegator") - let desiredType: Type = Type>() + let desiredType: Type = Type>() return privateCaps.length == 1 && privateCaps[0].getType() == desiredType } \ No newline at end of file diff --git a/scripts/delegator/get_nft_provider.cdc b/scripts/delegator/get_nft_provider.cdc index ab4bbd0..0753b65 100644 --- a/scripts/delegator/get_nft_provider.cdc +++ b/scripts/delegator/get_nft_provider.cdc @@ -10,12 +10,12 @@ access(all) fun main(addr: Address): Bool { acct.capabilities.storage.issue(CapabilityDelegator.StoragePath).borrow() ?? panic("could not borrow delegator") - let capType = Type>() + let capType = Type>() let nakedCap = delegator.getPrivateCapability(capType) ?? panic("requested capability type was not found") // we don't need to do anything with this cap, being able to cast here is enough to know // that this works - let cap = nakedCap as! Capability + let cap = nakedCap as! Capability return true } \ No newline at end of file diff --git a/scripts/factory/get_nft_provider_from_factory.cdc b/scripts/factory/get_nft_provider_from_factory.cdc index 794037a..c49019c 100644 --- a/scripts/factory/get_nft_provider_from_factory.cdc +++ b/scripts/factory/get_nft_provider_from_factory.cdc @@ -13,8 +13,8 @@ access(all) fun main(addr: Address) { let controllers = acct.capabilities.storage.getControllers(forPath: d.storagePath) for c in controllers { - if c.borrowType.isSubtype(of: Type()) { - factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability + if c.borrowType.isSubtype(of: Type()) { + factory.getCapability(acct: acct, controllerID: c.capabilityID)! as! Capability return } } diff --git a/scripts/factory/get_nft_provider_from_factory_allowed.cdc b/scripts/factory/get_nft_provider_from_factory_allowed.cdc index 7b8e646..4c963da 100644 --- a/scripts/factory/get_nft_provider_from_factory_allowed.cdc +++ b/scripts/factory/get_nft_provider_from_factory_allowed.cdc @@ -15,14 +15,14 @@ access(all) fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { let factoryManager = ruleAcct.storage.borrow<&CapabilityFactory.Manager>(from: CapabilityFactory.StoragePath) ?? panic("Problem borrowing CapabilityFactory Manager") - let factory = factoryManager.getFactory(Type()) + let factory = factoryManager.getFactory(Type()) ?? panic("No factory for NFT Provider found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData var controllerID: UInt64? = nil for c in providerAcct.capabilities.storage.getControllers(forPath: d.storagePath) { - if c.borrowType.isSubtype(of: Type()) { + if c.borrowType.isSubtype(of: Type()) { controllerID = c.capabilityID break } @@ -30,7 +30,7 @@ access(all) fun main(filterFactoryAddr: Address, providerAddr: Address): Bool { assert(controllerID != nil, message: "could not find existing provider capcon") - let provider = factory.getCapability(acct: providerAcct, controllerID: controllerID!)! as! Capability + let provider = factory.getCapability(acct: providerAcct, controllerID: controllerID!)! as! Capability let filter = ruleAcct.storage.borrow<&CapabilityFilter.AllowlistFilter>(from: CapabilityFilter.StoragePath) ?? panic("Problem borrowing CapabilityFilter AllowlistFilter") diff --git a/scripts/hybrid-custody/get_account_public_address.cdc b/scripts/hybrid-custody/get_account_public_address.cdc index aed9558..330e1d0 100644 --- a/scripts/hybrid-custody/get_account_public_address.cdc +++ b/scripts/hybrid-custody/get_account_public_address.cdc @@ -2,7 +2,6 @@ import "HybridCustody" access(all) fun main(parent: Address, child: Address): Address { let cap = getAccount(parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) - ?? panic("manager not found") let manager = cap.borrow() ?? panic("unable to borrow manager") diff --git a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc index 0f76545..85978f4 100644 --- a/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc +++ b/scripts/hybrid-custody/get_child_account_nft_capabilities.cdc @@ -9,7 +9,7 @@ access(all) fun main(addr: Address): AnyStruct { var typeIdsWithProvider: {Address: [String]} = {} - let providerType = Type() + let providerType = Type() // Iterate through child accounts for address in manager.getChildAddresses() { @@ -26,7 +26,7 @@ access(all) fun main(addr: Address): AnyStruct { } if let cap = childAcct.getCapability(controllerID: c.capabilityID, type: providerType) { - let providerCap = cap as! Capability + let providerCap = cap as! Capability if !providerCap.check(){ continue diff --git a/scripts/hybrid-custody/get_nft_provider_capability.cdc b/scripts/hybrid-custody/get_nft_provider_capability.cdc index 6ab97b6..d80c390 100644 --- a/scripts/hybrid-custody/get_nft_provider_capability.cdc +++ b/scripts/hybrid-custody/get_nft_provider_capability.cdc @@ -14,7 +14,7 @@ access(all) fun main(parent: Address, child: Address) { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let desiredType = Type() + let desiredType = Type() let controllerID = childAcct.getControllerIDForType(type: desiredType, forPath: d.storagePath) ?? panic("no capability found for desired type") diff --git a/scripts/test/get_nft_provider_capability_optional.cdc b/scripts/test/get_nft_provider_capability_optional.cdc index 065258c..635cb9d 100644 --- a/scripts/test/get_nft_provider_capability_optional.cdc +++ b/scripts/test/get_nft_provider_capability_optional.cdc @@ -14,7 +14,7 @@ access(all) fun main(parent: Address, child: Address, returnsNil: Bool): Bool { let collectionData = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let type = Type() + let type = Type() let controllerID = childAcct.getControllerIDForType(type: type, forPath: collectionData.storagePath) ?? panic("could not find controller for desired type") diff --git a/scripts/test/remove_nft_provider_factory.cdc b/scripts/test/remove_nft_provider_factory.cdc index 92537d1..566b778 100644 --- a/scripts/test/remove_nft_provider_factory.cdc +++ b/scripts/test/remove_nft_provider_factory.cdc @@ -10,7 +10,7 @@ access(all) fun main(address: Address): Bool { let expectedType = Type() - if let removed = managerRef.removeFactory(Type()) { + if let removed = managerRef.removeFactory(Type()) { return removed.getType() == expectedType } diff --git a/scripts/test/test_get_accessible_child_nfts.cdc b/scripts/test/test_get_accessible_child_nfts.cdc index 54f3043..587dc6b 100644 --- a/scripts/test/test_get_accessible_child_nfts.cdc +++ b/scripts/test/test_get_accessible_child_nfts.cdc @@ -29,7 +29,7 @@ access(all) fun main(addr: Address, expectedAddressToIDs: {Address: [UInt64]}){ var typeIdsWithProvider: {Address: [String]} = {} var nftViews: {Address: {UInt64: MetadataViews.Display}} = {} - let providerType = Type() + let providerType = Type() let collectionType: Type = Type<@{NonFungibleToken.CollectionPublic}>() for address in manager.getChildAddresses() { diff --git a/test/CapabilityDelegator_tests.cdc b/test/CapabilityDelegator_tests.cdc index 1c481d3..0fd099e 100644 --- a/test/CapabilityDelegator_tests.cdc +++ b/test/CapabilityDelegator_tests.cdc @@ -60,7 +60,7 @@ fun testShareExampleNFTCollectionPrivate() { Test.assert(e.isPublic == false) Test.assert(e.active) - let capabilityType = Type>() + let capabilityType = Type>() Test.assertEqual(capabilityType, e.capabilityType) } @@ -101,7 +101,7 @@ fun testRemoveExampleNFTCollectionPrivate() { Test.assert(e.isPublic == false) Test.assert(e.active == false) - let capabilityType = Type>() + let capabilityType = Type>() Test.assertEqual(capabilityType, e.capabilityType) let scriptCode = loadCode("delegator/find_nft_provider_cap.cdc", "scripts") diff --git a/test/CapabilityFactory_tests.cdc b/test/CapabilityFactory_tests.cdc index 4227078..2180c30 100644 --- a/test/CapabilityFactory_tests.cdc +++ b/test/CapabilityFactory_tests.cdc @@ -38,9 +38,9 @@ fun testGetSupportedTypesFromManager() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { Test.assert(supportedTypes.contains(e), message: "missing expected type in supported types") @@ -51,7 +51,7 @@ access(all) fun testAddFactoryFails() { expectScriptFailure( "test/add_type_for_nft_provider_factory.cdc", - [creator.address, Type()], + [creator.address, Type()], "Factory of given type already exists" ) } @@ -71,9 +71,9 @@ fun testAddFactorySucceeds() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type(), + Type(), Type<&{NonFungibleToken.Receiver}>() ] @@ -121,9 +121,9 @@ fun testSetupNFTManager() { let supportedTypes = scriptExecutor("factory/get_supported_types_from_manager.cdc", [tmp.address])! as! [Type] let expectedTypes = [ - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { @@ -180,9 +180,9 @@ fun testSetupNFTFTManager() { Type<&{FungibleToken.Receiver}>(), Type<&{FungibleToken.Receiver, FungibleToken.Balance}>(), Type(), - Type(), + Type(), Type<&{NonFungibleToken.CollectionPublic}>(), - Type() + Type() ] for e in expectedTypes { diff --git a/transactions/delegator/add_private_nft_collection.cdc b/transactions/delegator/add_private_nft_collection.cdc index e023565..e24a49c 100644 --- a/transactions/delegator/add_private_nft_collection.cdc +++ b/transactions/delegator/add_private_nft_collection.cdc @@ -11,7 +11,7 @@ transaction { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.capabilities.storage.issue(d.storagePath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.addCapability(cap: sharedCap, isPublic: false) } diff --git a/transactions/delegator/remove_private_nft_collection.cdc b/transactions/delegator/remove_private_nft_collection.cdc index 6eb0924..82d2ada 100644 --- a/transactions/delegator/remove_private_nft_collection.cdc +++ b/transactions/delegator/remove_private_nft_collection.cdc @@ -11,7 +11,7 @@ transaction { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let sharedCap = acct.capabilities.storage.issue(d.storagePath) + let sharedCap = acct.capabilities.storage.issue(d.storagePath) delegator.removeCapability(cap: sharedCap) diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index 23035d6..2ec061e 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -54,7 +54,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) acct.capabilities.publish( acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), @@ -63,7 +63,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() == true, + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() == true, message: "CapabilityFactory is not setup properly" ) @@ -72,8 +72,8 @@ transaction(nftContractAddress: Address, nftContractName: String) { // Add NFT-related Factories to the Manager factoryManager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - factoryManager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - factoryManager.updateFactory(Type(), NFTProviderFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + factoryManager.updateFactory(Type(), NFTProviderFactory.Factory()) /* --- AllowlistFilter configuration --- */ // @@ -81,7 +81,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { acct.storage.save(<-CapabilityFilter.createFilter(Type<@CapabilityFilter.AllowlistFilter>()), to: CapabilityFilter.StoragePath) } - if acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() != true { + if !acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(){ acct.capabilities.unpublish(CapabilityFilter.PublicPath) acct.capabilities.publish( @@ -91,7 +91,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { } assert( - acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, + acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(), message: "AllowlistFilter is not setup properly" ) diff --git a/transactions/example-nft-2/mint_to_account.cdc b/transactions/example-nft-2/mint_to_account.cdc index 0be32eb..5d5e61a 100644 --- a/transactions/example-nft-2/mint_to_account.cdc +++ b/transactions/example-nft-2/mint_to_account.cdc @@ -13,7 +13,7 @@ transaction(receiver: Address, name: String, description: String, thumbnail: Str execute { let d = ExampleNFT2.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) ?? panic("receiver capability was nil") + let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) let r = c.borrow() ?? panic("no receiver collection") self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: self.minter.owner!.address) } diff --git a/transactions/example-nft-2/setup_full.cdc b/transactions/example-nft-2/setup_full.cdc index 16049f1..b72b7a1 100644 --- a/transactions/example-nft-2/setup_full.cdc +++ b/transactions/example-nft-2/setup_full.cdc @@ -17,6 +17,6 @@ transaction { at: d.publicPath ) - acct.capabilities.storage.issue(d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } diff --git a/transactions/example-nft/mint_to_account.cdc b/transactions/example-nft/mint_to_account.cdc index 699d022..ac7bd44 100644 --- a/transactions/example-nft/mint_to_account.cdc +++ b/transactions/example-nft/mint_to_account.cdc @@ -13,7 +13,7 @@ transaction(receiver: Address, name: String, description: String, thumbnail: Str execute { let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData - let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) ?? panic("receiver capability was nil") + let c = getAccount(receiver).capabilities.get<&{NonFungibleToken.CollectionPublic}>(d.publicPath) let r = c.borrow() ?? panic("no receiver collection") self.minter.mintNFT(recipient: r, name: name, description: description, thumbnail: thumbnail, royaltyReceipient: self.minter.owner!.address) } diff --git a/transactions/example-nft/setup_full.cdc b/transactions/example-nft/setup_full.cdc index 550e50a..c20ad67 100644 --- a/transactions/example-nft/setup_full.cdc +++ b/transactions/example-nft/setup_full.cdc @@ -15,6 +15,6 @@ transaction { let cap = acct.capabilities.storage.issue<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(d.storagePath) acct.capabilities.publish(cap, at: d.publicPath) - acct.capabilities.storage.issue(d.storagePath) + acct.capabilities.storage.issue(d.storagePath) } } diff --git a/transactions/factory/setup_empty_factory.cdc b/transactions/factory/setup_empty_factory.cdc index 4a49b8c..c6cabe5 100644 --- a/transactions/factory/setup_empty_factory.cdc +++ b/transactions/factory/setup_empty_factory.cdc @@ -10,7 +10,7 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) @@ -18,7 +18,7 @@ transaction { } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) } diff --git a/transactions/factory/setup_ft_manager.cdc b/transactions/factory/setup_ft_manager.cdc index 287affe..ac963df 100644 --- a/transactions/factory/setup_ft_manager.cdc +++ b/transactions/factory/setup_ft_manager.cdc @@ -14,7 +14,7 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) acct.capabilities.publish( acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), @@ -23,7 +23,7 @@ transaction { } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 976eb87..30c373e 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -18,7 +18,7 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)?.check() != true { + if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) @@ -26,15 +26,15 @@ transaction { } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) manager.updateFactory(Type(), FTProviderFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Balance}>(), FTBalanceFactory.Factory()) manager.updateFactory(Type<&{FungibleToken.Receiver}>(), FTReceiverFactory.Factory()) diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index fb1ba73..a87841d 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -20,7 +20,7 @@ transaction { ) assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)!.check(), + acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) @@ -28,7 +28,7 @@ transaction { ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) - manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) - manager.updateFactory(Type(), NFTProviderFactory.Factory()) + manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) + manager.updateFactory(Type(), NFTProviderFactory.Factory()) } } diff --git a/transactions/filter/allow/setup.cdc b/transactions/filter/allow/setup.cdc index f6e2e57..d3765f6 100644 --- a/transactions/filter/allow/setup.cdc +++ b/transactions/filter/allow/setup.cdc @@ -12,6 +12,6 @@ transaction { at: CapabilityFilter.PublicPath ) - assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(), message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/filter/deny/setup.cdc b/transactions/filter/deny/setup.cdc index c4760e8..d5a78b4 100644 --- a/transactions/filter/deny/setup.cdc +++ b/transactions/filter/deny/setup.cdc @@ -12,6 +12,6 @@ transaction { at: CapabilityFilter.PublicPath ) - assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(), message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/filter/setup_allow_all.cdc b/transactions/filter/setup_allow_all.cdc index 0a8b0b5..dfe1e00 100644 --- a/transactions/filter/setup_allow_all.cdc +++ b/transactions/filter/setup_allow_all.cdc @@ -12,6 +12,6 @@ transaction { at: CapabilityFilter.PublicPath ) - assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)?.check() == true, message: "failed to setup filter") + assert(acct.capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath).check(), message: "failed to setup filter") } } \ No newline at end of file diff --git a/transactions/hybrid-custody/accept_ownership.cdc b/transactions/hybrid-custody/accept_ownership.cdc index 8225d57..0ef08c0 100644 --- a/transactions/hybrid-custody/accept_ownership.cdc +++ b/transactions/hybrid-custody/accept_ownership.cdc @@ -9,7 +9,6 @@ transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPa var filter: Capability<&{CapabilityFilter.Filter}>? = nil if filterAddress != nil && filterPath != nil { filter = getAccount(filterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(filterPath!) - ?? panic("filter address given but capability was not found") } if acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { diff --git a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc index ce420e3..558091c 100644 --- a/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc +++ b/transactions/hybrid-custody/add_example_nft2_collection_to_delegator.cdc @@ -11,7 +11,7 @@ transaction(parent: Address, isPublic: Bool) { let child = o.borrowChildAccount(parent: parent) ?? panic("child account not found") - let cap = acct.capabilities.storage.issue(ExampleNFT2.CollectionStoragePath) + let cap = acct.capabilities.storage.issue(ExampleNFT2.CollectionStoragePath) o.addCapabilityToDelegator(parent: parent, cap: cap, isPublic: isPublic) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/onboarding/blockchain_native.cdc b/transactions/hybrid-custody/onboarding/blockchain_native.cdc index 7f6613c..2141803 100644 --- a/transactions/hybrid-custody/onboarding/blockchain_native.cdc +++ b/transactions/hybrid-custody/onboarding/blockchain_native.cdc @@ -82,7 +82,6 @@ transaction( // Get the CapabilityFilter.Filter Capability let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("filter capability was not valid") assert(filter.check(), message: "capability filter is not configured properly") // Configure access for the delegatee parent account diff --git a/transactions/hybrid-custody/publish_to_parent.cdc b/transactions/hybrid-custody/publish_to_parent.cdc index 6f0612d..cfcff26 100644 --- a/transactions/hybrid-custody/publish_to_parent.cdc +++ b/transactions/hybrid-custody/publish_to_parent.cdc @@ -8,10 +8,10 @@ transaction(parent: Address, factoryAddress: Address, filterAddress: Address) { let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! + let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) assert(factory.check(), message: "factory address is not configured properly") - let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath)! + let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) assert(filter.check(), message: "capability filter is not configured properly") owned.publishToParent(parentAddress: parent, factory: factory, filter: filter) diff --git a/transactions/hybrid-custody/redeem_account.cdc b/transactions/hybrid-custody/redeem_account.cdc index b28a49a..82a757e 100644 --- a/transactions/hybrid-custody/redeem_account.cdc +++ b/transactions/hybrid-custody/redeem_account.cdc @@ -9,7 +9,6 @@ transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPa var filter: Capability<&{CapabilityFilter.Filter}>? = nil if filterAddress != nil && filterPath != nil { filter = getAccount(filterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(filterPath!) - ?? panic("filter path provided but capability was not found") } if acct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { diff --git a/transactions/hybrid-custody/remove_parent_from_child.cdc b/transactions/hybrid-custody/remove_parent_from_child.cdc index f073054..5b57b7c 100644 --- a/transactions/hybrid-custody/remove_parent_from_child.cdc +++ b/transactions/hybrid-custody/remove_parent_from_child.cdc @@ -7,7 +7,7 @@ transaction(parent: Address) { owned.removeParent(parent: parent) - let manager = getAccount(parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath)! + let manager = getAccount(parent).capabilities.get<&{HybridCustody.ManagerPublic}>(HybridCustody.ManagerPublicPath) .borrow() ?? panic("manager not found") let children = manager.getChildAddresses() assert(!children.contains(acct.address), message: "removed child is still in manager resource") diff --git a/transactions/hybrid-custody/set_capability_factory_for_parent.cdc b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc index cf1bc8a..86d8b5e 100644 --- a/transactions/hybrid-custody/set_capability_factory_for_parent.cdc +++ b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc @@ -4,7 +4,6 @@ import "CapabilityFactory" transaction(parent: Address, factoryAddress: Address) { prepare(acct: auth(Storage) &Account) { let cap = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) - ?? panic("capability factory was nil") let ownedAccount = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") diff --git a/transactions/hybrid-custody/set_capability_filter_for_parent.cdc b/transactions/hybrid-custody/set_capability_filter_for_parent.cdc index 3fdf350..7446af6 100644 --- a/transactions/hybrid-custody/set_capability_filter_for_parent.cdc +++ b/transactions/hybrid-custody/set_capability_filter_for_parent.cdc @@ -4,7 +4,6 @@ import "CapabilityFilter" transaction(parent: Address, factoryAddress: Address) { prepare(acct: auth(Storage) &Account) { let cap = getAccount(factoryAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("capability filter was nil") let ownedAccount = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") diff --git a/transactions/hybrid-custody/set_default_manager_cap.cdc b/transactions/hybrid-custody/set_default_manager_cap.cdc index d54e2f5..732692d 100644 --- a/transactions/hybrid-custody/set_default_manager_cap.cdc +++ b/transactions/hybrid-custody/set_default_manager_cap.cdc @@ -9,7 +9,6 @@ transaction(addr: Address) { ?? panic("manager not found") let cap = getAccount(addr).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("invalid capability filter address found") manager.setDefaultManagerCapabilityFilter(cap: cap) } } \ No newline at end of file diff --git a/transactions/hybrid-custody/set_manager_filter_cap.cdc b/transactions/hybrid-custody/set_manager_filter_cap.cdc index 4ea9fc7..abadc0b 100644 --- a/transactions/hybrid-custody/set_manager_filter_cap.cdc +++ b/transactions/hybrid-custody/set_manager_filter_cap.cdc @@ -7,7 +7,6 @@ transaction(filterAddress: Address, childAddress: Address) { ?? panic("manager not found") let cap = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("failed to get filter capability") 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 35aba71..f00ae56 100644 --- a/transactions/hybrid-custody/setup_multi_sig.cdc +++ b/transactions/hybrid-custody/setup_multi_sig.cdc @@ -48,7 +48,6 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, var filter: Capability<&{CapabilityFilter.Filter}>? = nil if parentFilterAddress != nil { filter = getAccount(parentFilterAddress!).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("parent filter address provided but it was not valid") } if parentAcct.storage.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath) == nil { @@ -73,11 +72,9 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, ?? panic("owned account not found") let factory = getAccount(childAccountFactoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) - ?? panic("child account factory capability was nil") assert(factory.check(), message: "factory address is not configured properly") let filterForChild = getAccount(childAccountFilterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("child account filter capability was nil") assert(filterForChild.check(), message: "capability filter is not configured properly") owned.publishToParent(parentAddress: parentAcct.address, factory: factory, filter: filterForChild) diff --git a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc index 6f03619..8416271 100644 --- a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc +++ b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc @@ -51,11 +51,9 @@ transaction( // Get CapabilityFactory & CapabilityFilter Capabilities let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) - ?? panic("failed to get factory capability") assert(factory.check(), message: "factory address is not configured properly") let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) - ?? panic("failed to get filter capability") assert(filter.check(), message: "capability filter is not configured properly") // Finally publish a ChildAccount capability on the signing account to the specified parent From 6b46b3bcd10e1f665fc108263ffcb84860ec54b7 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 7 May 2024 11:16:43 -0500 Subject: [PATCH 27/34] add temporary local migration report --- ...-capability-value-migrator_1715098464.json | 1 + ...adence-link-value-migrator_1715098464.json | 1 + .../cadence-value-migration_1715098464.json | 1 + report/contract-checking_1715098464.json | 1 + .../staged-contracts-migrator_1715098464.json | 26 +++++++++++++++++++ .../system-contracts-migrator_1715098464.json | 1 + 6 files changed, 31 insertions(+) create mode 100644 report/cadence-capability-value-migrator_1715098464.json create mode 100644 report/cadence-link-value-migrator_1715098464.json create mode 100644 report/cadence-value-migration_1715098464.json create mode 100644 report/contract-checking_1715098464.json create mode 100644 report/staged-contracts-migrator_1715098464.json create mode 100644 report/system-contracts-migrator_1715098464.json diff --git a/report/cadence-capability-value-migrator_1715098464.json b/report/cadence-capability-value-migrator_1715098464.json new file mode 100644 index 0000000..e5f1ca4 --- /dev/null +++ b/report/cadence-capability-value-migrator_1715098464.json @@ -0,0 +1 @@ +[{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowIDTableStaking.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"CapabilityValueMigration"},{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowClusterQC.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"CapabilityValueMigration"},{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowDKG.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"CapabilityValueMigration"}] \ No newline at end of file diff --git a/report/cadence-link-value-migrator_1715098464.json b/report/cadence-link-value-migrator_1715098464.json new file mode 100644 index 0000000..f4f5314 --- /dev/null +++ b/report/cadence-link-value-migrator_1715098464.json @@ -0,0 +1 @@ +[{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/lockedTokenAdmin","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","capability_id":3},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","capability_id":4},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenBalance","capability_id":5},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenReceiver","capability_id":6},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"}] \ No newline at end of file diff --git a/report/cadence-value-migration_1715098464.json b/report/cadence-value-migration_1715098464.json new file mode 100644 index 0000000..54dd011 --- /dev/null +++ b/report/cadence-value-migration_1715098464.json @@ -0,0 +1 @@ +[{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"}] \ No newline at end of file diff --git a/report/contract-checking_1715098464.json b/report/contract-checking_1715098464.json new file mode 100644 index 0000000..8fe4e68 --- /dev/null +++ b/report/contract-checking_1715098464.json @@ -0,0 +1 @@ +[{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTCollectionPublicFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTCollectionPublicFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTCollectionPublicFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTCollectionPublicFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityFilter","error":"error: error getting program f8d6e0586b0a20c7.CapabilityFilter: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :9:0\n |\n9 | pub contract CapabilityFilter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :13:4\n |\n13 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :14:4\n |\n14 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :15:4\n |\n15 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :19:4\n |\n19 | pub event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :24:4\n |\n24 | pub resource interface Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:8\n |\n25 | pub fun allowed(cap: Capability): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :26:8\n |\n26 | pub fun getDetails(): AnyStruct\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:4\n |\n31 | pub resource DenylistFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:8\n |\n42 | pub fun addType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :51:8\n |\n51 | pub fun removeType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :59:8\n |\n59 | pub fun removeAllTypes() {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :70:8\n |\n70 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :83:8\n |\n83 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :97:4\n |\n97 | pub resource AllowlistFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :109:8\n |\n109 | pub fun addType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :118:8\n |\n118 | pub fun removeType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :126:8\n |\n126 | pub fun removeAllTypes() {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :137:8\n |\n137 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :150:8\n |\n150 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :164:4\n |\n164 | pub resource AllowAllFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :170:8\n |\n170 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :179:8\n |\n179 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :191:4\n |\n191 | pub fun create(_ t: Type): @AnyResource{Filter} {\n | ^^^\n\nerror: expected identifier after start of function declaration, got keyword create\n --\u003e :191:12\n |\n191 | pub fun create(_ t: Type): @AnyResource{Filter} {\n | ^\n\n--\u003e f8d6e0586b0a20c7.CapabilityFilter\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderAndCollectionFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderAndCollectionFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderAndCollectionFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderAndCollectionFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.FTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"HybridCustody","error":"error: error getting program f8d6e0586b0a20c7.HybridCustody: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:0\n |\n30 | pub contract HybridCustody {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :36:4\n |\n36 | pub let OwnedAccountStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub let OwnedAccountPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub let OwnedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:4\n |\n40 | pub let ManagerStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :41:4\n |\n41 | pub let ManagerPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:4\n |\n42 | pub let ManagerPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:4\n |\n44 | pub let LinkedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:4\n |\n45 | pub let BorrowableAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :50:4\n |\n50 | pub event CreatedManager(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :52:4\n |\n52 | pub event CreatedOwnedAccount(id: UInt64, child: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :56:4\n |\n56 | pub event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :60:4\n |\n60 | pub event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :62:4\n |\n62 | pub event ChildAccountPublished(\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :73:4\n |\n73 | pub event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:4\n |\n75 | pub event AccountSealed(id: UInt64, address: Address, parents: [Address])\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :79:4\n |\n79 | pub resource interface BorrowableAccount {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :81:8\n |\n81 | pub fun check(): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :86:4\n |\n86 | pub resource interface OwnedAccountPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :88:8\n |\n88 | pub fun getParentAddresses(): [Address]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :91:8\n |\n91 | pub fun getParentStatuses(): {Address: Bool}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :96:8\n |\n96 | pub fun getRedeemedStatus(addr: Address): Bool?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :104:4\n |\n104 | pub resource interface OwnedAccountPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :107:8\n |\n107 | pub fun removeParent(parent: Address): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :113:8\n |\n113 | pub fun publishToParent(\n | ^^^\n\nerror: restricted types have been removed; replace with the concrete type or an equivalent intersection type\n --\u003e :115:59\n |\n115 | factory: Capability\u003c\u0026CapabilityFactory.Manager{CapabilityFactory.Getter}\u003e,\n | ^^^^^^^^^^^^^^^^^\n\n--\u003e f8d6e0586b0a20c7.HybridCustody\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityDelegator","error":"error: error getting program f8d6e0586b0a20c7.CapabilityDelegator: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :10:0\n |\n10 | pub contract CapabilityDelegator {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :14:4\n |\n14 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :15:4\n |\n15 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :16:4\n |\n16 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :20:4\n |\n20 | pub event DelegatorCreated(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :21:4\n |\n21 | pub event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:4\n |\n25 | pub resource interface GetterPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :26:8\n |\n26 | pub fun getPrivateCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:8\n |\n31 | pub fun findFirstPrivateType(_ type: Type): Type?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :32:8\n |\n32 | pub fun getAllPrivate(): [Capability]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub resource interface GetterPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:8\n |\n38 | pub fun getPublicCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:8\n |\n44 | pub fun findFirstPublicType(_ type: Type): Type?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:8\n |\n45 | pub fun getAllPublic(): [Capability]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :51:4\n |\n51 | pub resource Delegator: GetterPublic, GetterPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :59:8\n |\n59 | pub fun getPublicCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :69:8\n |\n69 | pub fun getPrivateCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :77:8\n |\n77 | pub fun getAllPublic(): [Capability] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :85:8\n |\n85 | pub fun getAllPrivate(): [Capability] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :94:8\n |\n94 | pub fun findFirstPublicType(_ type: Type): Type? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :109:8\n |\n109 | pub fun findFirstPrivateType(_ type: Type): Type? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :125:8\n |\n125 | pub fun addCapability(cap: Capability, isPublic: Bool) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :141:8\n |\n141 | pub fun removeCapability(cap: Capability) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :161:4\n |\n161 | pub fun createDelegator(): @Delegator {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.CapabilityDelegator\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTAllFactory","error":"error: error getting program f8d6e0586b0a20c7.FTAllFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTAllFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTAllFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityFactory","error":"error: error getting program f8d6e0586b0a20c7.CapabilityFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :16:0\n |\n16 | pub contract CapabilityFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :18:4\n |\n18 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :19:4\n |\n19 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :20:4\n |\n20 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :24:4\n |\n24 | pub struct interface Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:8\n |\n25 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:4\n |\n30 | pub resource interface Getter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:8\n |\n31 | pub fun getSupportedTypes(): [Type]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :32:8\n |\n32 | pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub resource Manager: Getter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:8\n |\n40 | pub let factories: {Type: {CapabilityFactory.Factory}}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :46:8\n |\n46 | pub fun getSupportedTypes(): [Type] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :54:8\n |\n54 | pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :63:8\n |\n63 | pub fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:8\n |\n75 | pub fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :83:8\n |\n83 | pub fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :95:4\n |\n95 | pub fun createFactoryManager(): @Manager {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.CapabilityFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverBalanceFactory\n"}] \ No newline at end of file diff --git a/report/staged-contracts-migrator_1715098464.json b/report/staged-contracts-migrator_1715098464.json new file mode 100644 index 0000000..821830e --- /dev/null +++ b/report/staged-contracts-migrator_1715098464.json @@ -0,0 +1,26 @@ +[ + { + "kind": "contract-update-failure", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "HybridCustody", + "error": "error: mismatching field `factory` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:532:34\n |\n532 | access(self) var factory: Capability<&{CapabilityFactory.Getter}>\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityFactory.Manager`, found `{CapabilityFactory.Getter}`\n\nerror: mismatching field `delegator` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:544:36\n |\n544 | access(self) let delegator: Capability\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityDelegator.Delegator`, found `{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}`\n" + }, + { + "kind": "contract-update-failure", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityFactory", + "error": "error: unsafe access modifiers on CapabilityFactory.Manager: the entitlements migration would grant references to this type CapabilityFactory.Owner, CapabilityFactory.Add, CapabilityFactory.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFactory:42:4\n |\n42 | access(all) resource Manager: Getter {\n43 | /// Mapping of Factories indexed on Type of Capability they retrieve\n44 | access(all) let factories: {Type: {CapabilityFactory.Factory}}\n45 | \n46 | /// Retrieves a list of Types supported by contained Factories\n47 | ///\n48 | /// @return List of Types supported by the Manager\n49 | ///\n50 | access(all) view fun getSupportedTypes(): [Type] {\n51 | return self.factories.keys\n52 | }\n53 | \n54 | /// Retrieves a Factory from the Manager, returning it or nil if it doesn't exist\n55 | ///\n56 | /// @param t: Type the Factory is indexed on\n57 | ///\n58 | access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {\n59 | return self.factories[t]\n60 | }\n61 | \n62 | /// Adds a Factory to the Manager, conditioned on the Factory not already existing\n63 | ///\n64 | /// @param t: Type of Capability the Factory retrieves\n65 | /// @param f: Factory to add\n66 | ///\n67 | access(Owner | Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n68 | pre {\n69 | !self.factories.containsKey(t): \"Factory of given type already exists\"\n70 | }\n71 | self.factories[t] = f\n72 | }\n73 | \n74 | /// Updates a Factory in the Manager, adding if it didn't already exist\n75 | ///\n76 | /// @param t: Type of Capability the Factory retrieves\n77 | /// @param f: Factory to replace existing Factory\n78 | ///\n79 | access(Owner | Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n80 | self.factories[t] = f\n81 | }\n82 | \n83 | /// Removes a Factory from the Manager, returning it or nil if it didn't exist\n84 | ///\n85 | /// @param t: Type the Factory is indexed on\n86 | ///\n87 | access(Owner | Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {\n88 | return self.factories.remove(key: t)\n89 | }\n90 | \n91 | init () {\n92 | self.factories = {}\n93 | }\n94 | }\n | ^ Consider removing any disjunction access modifiers\n" + }, + { + "kind": "contract-update-failure", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityFilter", + "error": "error: unsafe access modifiers on CapabilityFilter.DenylistFilter: the entitlements migration would grant references to this type CapabilityFilter.Owner, CapabilityFilter.Add, CapabilityFilter.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFilter:34:4\n |\n34 | access(all) resource DenylistFilter: Filter {\n35 | \n36 | /// Represents the underlying types which should not ever be returned by a RestrictedChildAccount. The filter\n37 | /// will borrow a requested capability, and make sure that the type it gets back is not in the list of denied\n38 | /// types\n39 | access(self) let deniedTypes: {Type: Bool}\n40 | \n41 | /// Adds a type to the mapping of denied types with a value of true\n42 | /// \n43 | /// @param type: The type to add to the denied types mapping\n44 | ///\n45 | access(Owner | Add) fun addType(_ type: Type) {\n46 | self.deniedTypes.insert(key: type, true)\n47 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)\n48 | }\n49 | \n50 | /// Removes a type from the mapping of denied types\n51 | ///\n52 | /// @param type: The type to remove from the denied types mapping\n53 | ///\n54 | access(Owner | Delete) fun removeType(_ type: Type) {\n55 | if let removed = self.deniedTypes.remove(key: type) {\n56 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)\n57 | }\n58 | }\n59 | \n60 | /// Removes all types from the mapping of denied types\n61 | ///\n62 | access(Owner | Delete) fun removeAllTypes() {\n63 | for type in self.deniedTypes.keys {\n64 | self.removeType(type)\n65 | }\n66 | }\n67 | \n68 | /// Determines if a requested capability is allowed by this `Filter`\n69 | ///\n70 | /// @param cap: The capability to check\n71 | /// @return: true if the capability is allowed, false otherwise\n72 | ///\n73 | access(all) view fun allowed(cap: Capability): Bool {\n74 | if let item = cap.borrow<&AnyResource>() {\n75 | return !self.deniedTypes.containsKey(item.getType())\n76 | }\n77 | \n78 | return false\n79 | }\n80 | \n81 | /// Returns details about this filter\n82 | ///\n83 | /// @return A struct containing details about this filter including this Filter's Type indexed on the `type`\n84 | /// key as well as types denied indexed on the `deniedTypes` key\n85 | ///\n86 | access(all) view fun getDetails(): AnyStruct {\n87 | return {\n88 | \"type\": self.getType(),\n89 | \"deniedTypes\": self.deniedTypes.keys\n90 | }\n91 | }\n92 | \n93 | init() {\n94 | self.deniedTypes = {}\n95 | }\n96 | }\n | ^ Consider removing any disjunction access modifiers\n\nerror: unsafe access modifiers on CapabilityFilter.AllowlistFilter: the entitlements migration would grant references to this type CapabilityFilter.Owner, CapabilityFilter.Add, CapabilityFilter.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFilter:100:4\n |\n100 | access(all) resource AllowlistFilter: Filter {\n101 | // allowedTypes\n102 | // Represents the set of underlying types which are allowed to be \n103 | // returned by a RestrictedChildAccount. The filter will borrow\n104 | // a requested capability, and make sure that the type it gets back is\n105 | // in the list of allowed types\n106 | access(self) let allowedTypes: {Type: Bool}\n107 | \n108 | /// Adds a type to the mapping of allowed types with a value of true\n109 | /// \n110 | /// @param type: The type to add to the allowed types mapping\n111 | ///\n112 | access(Owner | Add) fun addType(_ type: Type) {\n113 | self.allowedTypes.insert(key: type, true)\n114 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)\n115 | }\n116 | \n117 | /// Removes a type from the mapping of allowed types\n118 | ///\n119 | /// @param type: The type to remove from the denied types mapping\n120 | ///\n121 | access(Owner | Delete) fun removeType(_ type: Type) {\n122 | if let removed = self.allowedTypes.remove(key: type) {\n123 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)\n124 | }\n125 | }\n126 | \n127 | /// Removes all types from the mapping of denied types\n128 | ///\n129 | access(Owner | Delete) fun removeAllTypes() {\n130 | for type in self.allowedTypes.keys {\n131 | self.removeType(type)\n132 | }\n133 | }\n134 | \n135 | /// Determines if a requested capability is allowed by this `Filter`\n136 | ///\n137 | /// @param cap: The capability to check\n138 | /// @return: true if the capability is allowed, false otherwise\n139 | ///\n140 | access(all) view fun allowed(cap: Capability): Bool {\n141 | if let item = cap.borrow<&AnyResource>() {\n142 | return self.allowedTypes.containsKey(item.getType())\n143 | }\n144 | \n145 | return false\n146 | }\n147 | \n148 | /// Returns details about this filter\n149 | ///\n150 | /// @return A struct containing details about this filter including this Filter's Type indexed on the `type`\n151 | /// key as well as types allowed indexed on the `allowedTypes` key\n152 | ///\n153 | access(all) view fun getDetails(): AnyStruct {\n154 | return {\n155 | \"type\": self.getType(),\n156 | \"allowedTypes\": self.allowedTypes.keys\n157 | }\n158 | }\n159 | \n160 | init() {\n161 | self.allowedTypes = {}\n162 | }\n163 | }\n | ^ Consider removing any disjunction access modifiers\n" + }, + { + "kind": "contract-update-failure", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityDelegator", + "error": "error: unsafe access modifiers on CapabilityDelegator.Delegator: the entitlements migration would grant references to this type CapabilityDelegator.Get, CapabilityDelegator.Owner, CapabilityDelegator.Add, CapabilityDelegator.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityDelegator:55:4\n |\n 55 | access(all) resource Delegator: GetterPublic, GetterPrivate {\n 56 | access(self) let privateCapabilities: {Type: Capability}\n 57 | access(self) let publicCapabilities: {Type: Capability}\n 58 | \n 59 | // ------ Begin Getter methods\n 60 | //\n 61 | /// Returns the public Capability of the given Type if it exists\n 62 | ///\n 63 | access(all) view fun getPublicCapability(_ type: Type): Capability? {\n 64 | return self.publicCapabilities[type]\n 65 | }\n 66 | \n 67 | /// Returns the private Capability of the given Type if it exists\n 68 | ///\n 69 | ///\n 70 | /// @param type: Type of the Capability to retrieve\n 71 | /// @return Capability of the given Type if it exists, nil otherwise\n 72 | ///\n 73 | access(Get) view fun getPrivateCapability(_ type: Type): Capability? {\n 74 | return self.privateCapabilities[type]\n 75 | }\n 76 | \n 77 | /// Returns all public Capabilities\n 78 | ///\n 79 | /// @return List of all public Capabilities\n 80 | ///\n 81 | access(all) view fun getAllPublic(): [Capability] {\n 82 | return self.publicCapabilities.values\n 83 | }\n 84 | \n 85 | /// Returns all private Capabilities\n 86 | ///\n 87 | /// @return List of all private Capabilities\n 88 | ///\n 89 | access(Get) fun getAllPrivate(): [Capability] {\n 90 | return self.privateCapabilities.values\n 91 | }\n 92 | \n 93 | /// Returns the first public Type that is a subtype of the given Type\n 94 | ///\n 95 | /// @param type: Type to check for subtypes\n 96 | /// @return First public Type that is a subtype of the given Type, nil otherwise\n 97 | ///\n 98 | access(all) view fun findFirstPublicType(_ type: Type): Type? {\n 99 | for t in self.publicCapabilities.keys {\n100 | if t.isSubtype(of: type) {\n101 | return t\n102 | }\n103 | }\n104 | \n105 | return nil\n106 | }\n107 | \n108 | /// Returns the first private Type that is a subtype of the given Type\n109 | ///\n110 | /// @param type: Type to check for subtypes\n111 | /// @return First private Type that is a subtype of the given Type, nil otherwise\n112 | ///\n113 | access(all) view fun findFirstPrivateType(_ type: Type): Type? {\n114 | for t in self.privateCapabilities.keys {\n115 | if t.isSubtype(of: type) {\n116 | return t\n117 | }\n118 | }\n119 | \n120 | return nil\n121 | }\n122 | // ------- End Getter methods\n123 | \n124 | /// Adds a Capability to the Delegator\n125 | ///\n126 | /// @param cap: Capability to add\n127 | /// @param isPublic: Whether the Capability should be public or private\n128 | ///\n129 | access(Owner | Add) fun addCapability(cap: Capability, isPublic: Bool) {\n130 | pre {\n131 | cap.check<&AnyResource>(): \"Invalid Capability provided\"\n132 | }\n133 | if isPublic {\n134 | self.publicCapabilities.insert(key: cap.getType(), cap)\n135 | } else {\n136 | self.privateCapabilities.insert(key: cap.getType(), cap)\n137 | }\n138 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: isPublic, active: true)\n139 | }\n140 | \n141 | /// Removes a Capability from the Delegator\n142 | ///\n143 | /// @param cap: Capability to remove\n144 | ///\n145 | access(Owner | Delete) fun removeCapability(cap: Capability) {\n146 | if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) {\n147 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false)\n148 | }\n149 | \n150 | if let removedPrivate = self.privateCapabilities.remove(key: cap.getType()) {\n151 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: false, active: false)\n152 | }\n153 | }\n154 | \n155 | init() {\n156 | self.privateCapabilities = {}\n157 | self.publicCapabilities = {}\n158 | }\n159 | }\n | ^ Consider removing any disjunction access modifiers\n" + } +] \ No newline at end of file diff --git a/report/system-contracts-migrator_1715098464.json b/report/system-contracts-migrator_1715098464.json new file mode 100644 index 0000000..5ac3e1b --- /dev/null +++ b/report/system-contracts-migrator_1715098464.json @@ -0,0 +1 @@ +[{"kind":"contract-update-success","account_address":"0xee82856bf20e2aa6","contract_name":"FungibleTokenMetadataViews"},{"kind":"contract-update-success","account_address":"0xee82856bf20e2aa6","contract_name":"FungibleToken"},{"kind":"contract-update-success","account_address":"0xe5a8b7f23e8b548f","contract_name":"FlowFees"},{"kind":"contract-update-success","account_address":"0x0ae53cb6e3f42a79","contract_name":"FlowToken"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"NonFungibleToken"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"MetadataViews"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"ViewResolver"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"RandomBeaconHistory"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowIDTableStaking"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowServiceAccount"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"NodeVersionBeacon"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowEpoch"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowClusterQC"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowStorageFees"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowStakingCollection"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"StakingProxy"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"LockedTokens"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowDKG"}] \ No newline at end of file From 8ae4eeea14e3e805218d0516423e2aad15dc5a6f Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 7 May 2024 16:05:12 -0700 Subject: [PATCH 28/34] remove all conjunctions from function acess modifiers --- contracts/CapabilityDelegator.cdc | 5 ++--- contracts/CapabilityFactory.cdc | 7 +++---- contracts/CapabilityFilter.cdc | 13 ++++++------- contracts/HybridCustody.cdc | 4 ++-- scripts/test/add_type_for_nft_provider_factory.cdc | 2 +- scripts/test/remove_nft_provider_factory.cdc | 2 +- scripts/test/update_nft_provider_factory.cdc | 2 +- .../delegator/add_private_nft_collection.cdc | 2 +- .../delegator/add_public_nft_collection.cdc | 4 ++-- .../delegator/remove_private_nft_collection.cdc | 2 +- .../delegator/remove_public_nft_collection.cdc | 4 ++-- .../setup_nft_filter_and_factory_manager.cdc | 4 ++-- transactions/factory/setup_ft_manager.cdc | 2 +- transactions/factory/setup_nft_ft_manager.cdc | 2 +- transactions/factory/setup_nft_manager.cdc | 2 +- transactions/filter/allow/add_type_to_list.cdc | 2 +- transactions/filter/allow/remove_all_types.cdc | 2 +- transactions/filter/deny/add_type_to_list.cdc | 2 +- transactions/filter/deny/remove_all_types.cdc | 2 +- .../test/add_type_for_nft_provider_factory.cdc | 2 +- 20 files changed, 32 insertions(+), 35 deletions(-) diff --git a/contracts/CapabilityDelegator.cdc b/contracts/CapabilityDelegator.cdc index f83e375..796002b 100644 --- a/contracts/CapabilityDelegator.cdc +++ b/contracts/CapabilityDelegator.cdc @@ -15,7 +15,6 @@ access(all) contract CapabilityDelegator { access(all) let PublicPath: PublicPath access(all) entitlement Get - access(all) entitlement Owner access(all) entitlement Add access(all) entitlement Delete @@ -126,7 +125,7 @@ access(all) contract CapabilityDelegator { /// @param cap: Capability to add /// @param isPublic: Whether the Capability should be public or private /// - access(Owner | Add) fun addCapability(cap: Capability, isPublic: Bool) { + access(Add) fun addCapability(cap: Capability, isPublic: Bool) { pre { cap.check<&AnyResource>(): "Invalid Capability provided" } @@ -142,7 +141,7 @@ access(all) contract CapabilityDelegator { /// /// @param cap: Capability to remove /// - access(Owner | Delete) fun removeCapability(cap: Capability) { + access(Delete) fun removeCapability(cap: Capability) { if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) { emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false) } diff --git a/contracts/CapabilityFactory.cdc b/contracts/CapabilityFactory.cdc index d8d7e74..f4b62ac 100644 --- a/contracts/CapabilityFactory.cdc +++ b/contracts/CapabilityFactory.cdc @@ -18,7 +18,6 @@ access(all) contract CapabilityFactory { access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath - access(all) entitlement Owner access(all) entitlement Add access(all) entitlement Delete @@ -64,7 +63,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to add /// - access(Owner | Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { pre { !self.factories.containsKey(t): "Factory of given type already exists" } @@ -76,7 +75,7 @@ access(all) contract CapabilityFactory { /// @param t: Type of Capability the Factory retrieves /// @param f: Factory to replace existing Factory /// - access(Owner | Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { + access(Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) { self.factories[t] = f } @@ -84,7 +83,7 @@ access(all) contract CapabilityFactory { /// /// @param t: Type the Factory is indexed on /// - access(Owner | Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { + access(Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? { return self.factories.remove(key: t) } diff --git a/contracts/CapabilityFilter.cdc b/contracts/CapabilityFilter.cdc index 9ffe645..efd8487 100644 --- a/contracts/CapabilityFilter.cdc +++ b/contracts/CapabilityFilter.cdc @@ -13,7 +13,6 @@ access(all) contract CapabilityFilter { access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath - access(all) entitlement Owner access(all) entitlement Add access(all) entitlement Delete @@ -42,7 +41,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the denied types mapping /// - access(Owner | Add) fun addType(_ type: Type) { + access(Add) fun addType(_ type: Type) { self.deniedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -51,7 +50,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Owner | Delete) fun removeType(_ type: Type) { + access(Delete) fun removeType(_ type: Type) { if let removed = self.deniedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -59,7 +58,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Owner | Delete) fun removeAllTypes() { + access(Delete) fun removeAllTypes() { for type in self.deniedTypes.keys { self.removeType(type) } @@ -109,7 +108,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to add to the allowed types mapping /// - access(Owner | Add) fun addType(_ type: Type) { + access(Add) fun addType(_ type: Type) { self.allowedTypes.insert(key: type, true) emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true) } @@ -118,7 +117,7 @@ access(all) contract CapabilityFilter { /// /// @param type: The type to remove from the denied types mapping /// - access(Owner | Delete) fun removeType(_ type: Type) { + access(Delete) fun removeType(_ type: Type) { if let removed = self.allowedTypes.remove(key: type) { emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false) } @@ -126,7 +125,7 @@ access(all) contract CapabilityFilter { /// Removes all types from the mapping of denied types /// - access(Owner | Delete) fun removeAllTypes() { + access(Delete) fun removeAllTypes() { for type in self.allowedTypes.keys { self.removeType(type) } diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 1c0a026..7860217 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -1124,9 +1124,9 @@ access(all) contract HybridCustody { /// Retrieves a reference to the Delegator associated with the given parent account if one exists. /// - access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(CapabilityDelegator.Owner) &CapabilityDelegator.Delegator? { + access(Owner) fun borrowCapabilityDelegatorForParent(parent: Address): auth(CapabilityDelegator.Get, CapabilityDelegator.Add, CapabilityDelegator.Delete) &CapabilityDelegator.Delegator? { let identifier = HybridCustody.getCapabilityDelegatorIdentifier(parent) - return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) + return self.borrowAccount().storage.borrow(from: StoragePath(identifier: identifier)!) } /// Adds the provided Capability to the Delegator associated with the given parent account. diff --git a/scripts/test/add_type_for_nft_provider_factory.cdc b/scripts/test/add_type_for_nft_provider_factory.cdc index 8a2da57..e87dc62 100644 --- a/scripts/test/add_type_for_nft_provider_factory.cdc +++ b/scripts/test/add_type_for_nft_provider_factory.cdc @@ -4,7 +4,7 @@ import "NFTProviderFactory" import "NonFungibleToken" access(all) fun main(address: Address, type: Type): Bool { - let managerRef = getAuthAccount(address).storage.borrow( + let managerRef = getAuthAccount(address).storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") diff --git a/scripts/test/remove_nft_provider_factory.cdc b/scripts/test/remove_nft_provider_factory.cdc index 566b778..3dd408d 100644 --- a/scripts/test/remove_nft_provider_factory.cdc +++ b/scripts/test/remove_nft_provider_factory.cdc @@ -5,7 +5,7 @@ import "NonFungibleToken" access(all) fun main(address: Address): Bool { - let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let expectedType = Type() diff --git a/scripts/test/update_nft_provider_factory.cdc b/scripts/test/update_nft_provider_factory.cdc index 93f50a3..e2acdbe 100644 --- a/scripts/test/update_nft_provider_factory.cdc +++ b/scripts/test/update_nft_provider_factory.cdc @@ -4,7 +4,7 @@ import "NFTProviderFactory" import "NonFungibleToken" access(all) fun main(address: Address) { - let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) + let managerRef = getAuthAccount(address).storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") let nftProviderFactory = NFTProviderFactory.Factory() diff --git a/transactions/delegator/add_private_nft_collection.cdc b/transactions/delegator/add_private_nft_collection.cdc index e24a49c..bcb09c5 100644 --- a/transactions/delegator/add_private_nft_collection.cdc +++ b/transactions/delegator/add_private_nft_collection.cdc @@ -6,7 +6,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData diff --git a/transactions/delegator/add_public_nft_collection.cdc b/transactions/delegator/add_public_nft_collection.cdc index 79d3d5d..8dfda2f 100644 --- a/transactions/delegator/add_public_nft_collection.cdc +++ b/transactions/delegator/add_public_nft_collection.cdc @@ -5,11 +5,11 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap - = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath)! + = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) delegator.addCapability(cap: sharedCap, isPublic: true) } } \ No newline at end of file diff --git a/transactions/delegator/remove_private_nft_collection.cdc b/transactions/delegator/remove_private_nft_collection.cdc index 82d2ada..1a8008f 100644 --- a/transactions/delegator/remove_private_nft_collection.cdc +++ b/transactions/delegator/remove_private_nft_collection.cdc @@ -6,7 +6,7 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let d = ExampleNFT.resolveContractView(resourceType: nil, viewType: Type())! as! MetadataViews.NFTCollectionData diff --git a/transactions/delegator/remove_public_nft_collection.cdc b/transactions/delegator/remove_public_nft_collection.cdc index be157f5..faac917 100644 --- a/transactions/delegator/remove_public_nft_collection.cdc +++ b/transactions/delegator/remove_public_nft_collection.cdc @@ -5,11 +5,11 @@ import "ExampleNFT" transaction { prepare(acct: auth(BorrowValue, Capabilities) &Account) { - let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) + let delegator = acct.storage.borrow(from: CapabilityDelegator.StoragePath) ?? panic("delegator not found") let sharedCap - = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath)! + = acct.capabilities.get<&{ExampleNFT.ExampleNFTCollectionPublic, NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) delegator.removeCapability(cap: sharedCap) } } \ No newline at end of file diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index 2ec061e..a47c2c6 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -67,7 +67,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { message: "CapabilityFactory is not setup properly" ) - let factoryManager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let factoryManager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("CapabilityFactory Manager not found") // Add NFT-related Factories to the Manager @@ -95,7 +95,7 @@ transaction(nftContractAddress: Address, nftContractName: String) { message: "AllowlistFilter is not setup properly" ) - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("AllowlistFilter does not exist") // Construct an NFT Collection Type from the provided args & add to the AllowlistFilter diff --git a/transactions/factory/setup_ft_manager.cdc b/transactions/factory/setup_ft_manager.cdc index ac963df..dff5445 100644 --- a/transactions/factory/setup_ft_manager.cdc +++ b/transactions/factory/setup_ft_manager.cdc @@ -27,7 +27,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type(), FTProviderFactory.Factory()) diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 30c373e..9115b2b 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -30,7 +30,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) manager.updateFactory(Type(), NFTProviderAndCollectionFactory.Factory()) diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index a87841d..f60d476 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -24,7 +24,7 @@ transaction { message: "CapabilityFactory is not setup properly" ) - let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) + let manager = acct.storage.borrow(from: CapabilityFactory.StoragePath) ?? panic("manager not found") manager.updateFactory(Type<&{NonFungibleToken.CollectionPublic}>(), NFTCollectionPublicFactory.Factory()) diff --git a/transactions/filter/allow/add_type_to_list.cdc b/transactions/filter/allow/add_type_to_list.cdc index 5424d62..1acb657 100644 --- a/transactions/filter/allow/add_type_to_list.cdc +++ b/transactions/filter/allow/add_type_to_list.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction(identifier: String) { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/allow/remove_all_types.cdc b/transactions/filter/allow/remove_all_types.cdc index 03de0fd..71df876 100644 --- a/transactions/filter/allow/remove_all_types.cdc +++ b/transactions/filter/allow/remove_all_types.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction() { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/filter/deny/add_type_to_list.cdc b/transactions/filter/deny/add_type_to_list.cdc index c4cde7d..71974f1 100644 --- a/transactions/filter/deny/add_type_to_list.cdc +++ b/transactions/filter/deny/add_type_to_list.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction(identifier: String) { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") let c = CompositeType(identifier)! diff --git a/transactions/filter/deny/remove_all_types.cdc b/transactions/filter/deny/remove_all_types.cdc index 2aac0e7..d24cfa8 100644 --- a/transactions/filter/deny/remove_all_types.cdc +++ b/transactions/filter/deny/remove_all_types.cdc @@ -2,7 +2,7 @@ import "CapabilityFilter" transaction() { prepare(acct: auth(Storage) &Account) { - let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) + let filter = acct.storage.borrow(from: CapabilityFilter.StoragePath) ?? panic("filter does not exist") filter.removeAllTypes() diff --git a/transactions/test/add_type_for_nft_provider_factory.cdc b/transactions/test/add_type_for_nft_provider_factory.cdc index 101127e..8bb0166 100644 --- a/transactions/test/add_type_for_nft_provider_factory.cdc +++ b/transactions/test/add_type_for_nft_provider_factory.cdc @@ -5,7 +5,7 @@ import "NonFungibleToken" transaction(type: Type) { prepare(account: auth(Storage) &Account) { - let managerRef = account.storage.borrow( + let managerRef = account.storage.borrow( from: CapabilityFactory.StoragePath ) ?? panic("CapabilityFactory Manager not found") From 2671d5d65dd6fb899c8247c4e64109743760bb86 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 7 May 2024 18:11:57 -0500 Subject: [PATCH 29/34] update local migration report --- ...capability-value-migrator_1715123315.json} | 0 ...adence-link-value-migrator_1715098464.json | 1 - ...adence-link-value-migrator_1715123315.json | 1 + ...> cadence-value-migration_1715123315.json} | 2 +- report/contract-checking_1715098464.json | 1 - report/contract-checking_1715123315.json | 1 + .../staged-contracts-migrator_1715098464.json | 26 ------ .../staged-contracts-migrator_1715123315.json | 23 +++++ .../system-contracts-migrator_1715098464.json | 1 - .../system-contracts-migrator_1715123315.json | 92 +++++++++++++++++++ 10 files changed, 118 insertions(+), 30 deletions(-) rename report/{cadence-capability-value-migrator_1715098464.json => cadence-capability-value-migrator_1715123315.json} (100%) delete mode 100644 report/cadence-link-value-migrator_1715098464.json create mode 100644 report/cadence-link-value-migrator_1715123315.json rename report/{cadence-value-migration_1715098464.json => cadence-value-migration_1715123315.json} (79%) delete mode 100644 report/contract-checking_1715098464.json create mode 100644 report/contract-checking_1715123315.json delete mode 100644 report/staged-contracts-migrator_1715098464.json create mode 100644 report/staged-contracts-migrator_1715123315.json delete mode 100644 report/system-contracts-migrator_1715098464.json create mode 100644 report/system-contracts-migrator_1715123315.json diff --git a/report/cadence-capability-value-migrator_1715098464.json b/report/cadence-capability-value-migrator_1715123315.json similarity index 100% rename from report/cadence-capability-value-migrator_1715098464.json rename to report/cadence-capability-value-migrator_1715123315.json diff --git a/report/cadence-link-value-migrator_1715098464.json b/report/cadence-link-value-migrator_1715098464.json deleted file mode 100644 index f4f5314..0000000 --- a/report/cadence-link-value-migrator_1715098464.json +++ /dev/null @@ -1 +0,0 @@ -[{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/lockedTokenAdmin","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","capability_id":3},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","capability_id":4},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenBalance","capability_id":5},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenReceiver","capability_id":6},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"}] \ No newline at end of file diff --git a/report/cadence-link-value-migrator_1715123315.json b/report/cadence-link-value-migrator_1715123315.json new file mode 100644 index 0000000..33b576b --- /dev/null +++ b/report/cadence-link-value-migrator_1715123315.json @@ -0,0 +1 @@ +[{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","capability_id":1},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/lockedTokenAdmin","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","capability_id":3},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","capability_id":4},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenBalance","capability_id":5},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenReceiver","capability_id":6},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"}] \ No newline at end of file diff --git a/report/cadence-value-migration_1715098464.json b/report/cadence-value-migration_1715123315.json similarity index 79% rename from report/cadence-value-migration_1715098464.json rename to report/cadence-value-migration_1715123315.json index 54dd011..d5e7219 100644 --- a/report/cadence-value-migration_1715098464.json +++ b/report/cadence-value-migration_1715123315.json @@ -1 +1 @@ -[{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"}] \ No newline at end of file +[{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"}] \ No newline at end of file diff --git a/report/contract-checking_1715098464.json b/report/contract-checking_1715098464.json deleted file mode 100644 index 8fe4e68..0000000 --- a/report/contract-checking_1715098464.json +++ /dev/null @@ -1 +0,0 @@ -[{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTCollectionPublicFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTCollectionPublicFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTCollectionPublicFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTCollectionPublicFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityFilter","error":"error: error getting program f8d6e0586b0a20c7.CapabilityFilter: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :9:0\n |\n9 | pub contract CapabilityFilter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :13:4\n |\n13 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :14:4\n |\n14 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :15:4\n |\n15 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :19:4\n |\n19 | pub event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :24:4\n |\n24 | pub resource interface Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:8\n |\n25 | pub fun allowed(cap: Capability): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :26:8\n |\n26 | pub fun getDetails(): AnyStruct\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:4\n |\n31 | pub resource DenylistFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:8\n |\n42 | pub fun addType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :51:8\n |\n51 | pub fun removeType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :59:8\n |\n59 | pub fun removeAllTypes() {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :70:8\n |\n70 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :83:8\n |\n83 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :97:4\n |\n97 | pub resource AllowlistFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :109:8\n |\n109 | pub fun addType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :118:8\n |\n118 | pub fun removeType(_ type: Type) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :126:8\n |\n126 | pub fun removeAllTypes() {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :137:8\n |\n137 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :150:8\n |\n150 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :164:4\n |\n164 | pub resource AllowAllFilter: Filter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :170:8\n |\n170 | pub fun allowed(cap: Capability): Bool {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :179:8\n |\n179 | pub fun getDetails(): AnyStruct {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :191:4\n |\n191 | pub fun create(_ t: Type): @AnyResource{Filter} {\n | ^^^\n\nerror: expected identifier after start of function declaration, got keyword create\n --\u003e :191:12\n |\n191 | pub fun create(_ t: Type): @AnyResource{Filter} {\n | ^\n\n--\u003e f8d6e0586b0a20c7.CapabilityFilter\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderAndCollectionFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderAndCollectionFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderAndCollectionFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderAndCollectionFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.FTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"HybridCustody","error":"error: error getting program f8d6e0586b0a20c7.HybridCustody: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:0\n |\n30 | pub contract HybridCustody {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :36:4\n |\n36 | pub let OwnedAccountStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub let OwnedAccountPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub let OwnedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:4\n |\n40 | pub let ManagerStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :41:4\n |\n41 | pub let ManagerPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:4\n |\n42 | pub let ManagerPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:4\n |\n44 | pub let LinkedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:4\n |\n45 | pub let BorrowableAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :50:4\n |\n50 | pub event CreatedManager(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :52:4\n |\n52 | pub event CreatedOwnedAccount(id: UInt64, child: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :56:4\n |\n56 | pub event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :60:4\n |\n60 | pub event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :62:4\n |\n62 | pub event ChildAccountPublished(\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :73:4\n |\n73 | pub event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:4\n |\n75 | pub event AccountSealed(id: UInt64, address: Address, parents: [Address])\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :79:4\n |\n79 | pub resource interface BorrowableAccount {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :81:8\n |\n81 | pub fun check(): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :86:4\n |\n86 | pub resource interface OwnedAccountPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :88:8\n |\n88 | pub fun getParentAddresses(): [Address]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :91:8\n |\n91 | pub fun getParentStatuses(): {Address: Bool}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :96:8\n |\n96 | pub fun getRedeemedStatus(addr: Address): Bool?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :104:4\n |\n104 | pub resource interface OwnedAccountPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :107:8\n |\n107 | pub fun removeParent(parent: Address): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :113:8\n |\n113 | pub fun publishToParent(\n | ^^^\n\nerror: restricted types have been removed; replace with the concrete type or an equivalent intersection type\n --\u003e :115:59\n |\n115 | factory: Capability\u003c\u0026CapabilityFactory.Manager{CapabilityFactory.Getter}\u003e,\n | ^^^^^^^^^^^^^^^^^\n\n--\u003e f8d6e0586b0a20c7.HybridCustody\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityDelegator","error":"error: error getting program f8d6e0586b0a20c7.CapabilityDelegator: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :10:0\n |\n10 | pub contract CapabilityDelegator {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :14:4\n |\n14 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :15:4\n |\n15 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :16:4\n |\n16 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :20:4\n |\n20 | pub event DelegatorCreated(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :21:4\n |\n21 | pub event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:4\n |\n25 | pub resource interface GetterPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :26:8\n |\n26 | pub fun getPrivateCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:8\n |\n31 | pub fun findFirstPrivateType(_ type: Type): Type?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :32:8\n |\n32 | pub fun getAllPrivate(): [Capability]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub resource interface GetterPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:8\n |\n38 | pub fun getPublicCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:8\n |\n44 | pub fun findFirstPublicType(_ type: Type): Type?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:8\n |\n45 | pub fun getAllPublic(): [Capability]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :51:4\n |\n51 | pub resource Delegator: GetterPublic, GetterPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :59:8\n |\n59 | pub fun getPublicCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :69:8\n |\n69 | pub fun getPrivateCapability(_ type: Type): Capability? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :77:8\n |\n77 | pub fun getAllPublic(): [Capability] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :85:8\n |\n85 | pub fun getAllPrivate(): [Capability] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :94:8\n |\n94 | pub fun findFirstPublicType(_ type: Type): Type? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :109:8\n |\n109 | pub fun findFirstPrivateType(_ type: Type): Type? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :125:8\n |\n125 | pub fun addCapability(cap: Capability, isPublic: Bool) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :141:8\n |\n141 | pub fun removeCapability(cap: Capability) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :161:4\n |\n161 | pub fun createDelegator(): @Delegator {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.CapabilityDelegator\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTAllFactory","error":"error: error getting program f8d6e0586b0a20c7.FTAllFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTAllFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTAllFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"CapabilityFactory","error":"error: error getting program f8d6e0586b0a20c7.CapabilityFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :16:0\n |\n16 | pub contract CapabilityFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :18:4\n |\n18 | pub let StoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :19:4\n |\n19 | pub let PrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :20:4\n |\n20 | pub let PublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :24:4\n |\n24 | pub struct interface Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :25:8\n |\n25 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:4\n |\n30 | pub resource interface Getter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :31:8\n |\n31 | pub fun getSupportedTypes(): [Type]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :32:8\n |\n32 | pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub resource Manager: Getter {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:8\n |\n40 | pub let factories: {Type: {CapabilityFactory.Factory}}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :46:8\n |\n46 | pub fun getSupportedTypes(): [Type] {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :54:8\n |\n54 | pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :63:8\n |\n63 | pub fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:8\n |\n75 | pub fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :83:8\n |\n83 | pub fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :95:4\n |\n95 | pub fun createFactoryManager(): @Manager {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.CapabilityFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverBalanceFactory\n"}] \ No newline at end of file diff --git a/report/contract-checking_1715123315.json b/report/contract-checking_1715123315.json new file mode 100644 index 0000000..fd1cfe3 --- /dev/null +++ b/report/contract-checking_1715123315.json @@ -0,0 +1 @@ +[{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTAllFactory","error":"error: error getting program f8d6e0586b0a20c7.FTAllFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTAllFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTAllFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderAndCollectionFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderAndCollectionFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderAndCollectionFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderAndCollectionFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"HybridCustody","error":"error: error getting program f8d6e0586b0a20c7.HybridCustody: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:0\n |\n30 | pub contract HybridCustody {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :36:4\n |\n36 | pub let OwnedAccountStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub let OwnedAccountPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub let OwnedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:4\n |\n40 | pub let ManagerStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :41:4\n |\n41 | pub let ManagerPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:4\n |\n42 | pub let ManagerPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:4\n |\n44 | pub let LinkedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:4\n |\n45 | pub let BorrowableAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :50:4\n |\n50 | pub event CreatedManager(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :52:4\n |\n52 | pub event CreatedOwnedAccount(id: UInt64, child: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :56:4\n |\n56 | pub event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :60:4\n |\n60 | pub event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :62:4\n |\n62 | pub event ChildAccountPublished(\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :73:4\n |\n73 | pub event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:4\n |\n75 | pub event AccountSealed(id: UInt64, address: Address, parents: [Address])\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :79:4\n |\n79 | pub resource interface BorrowableAccount {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :81:8\n |\n81 | pub fun check(): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :86:4\n |\n86 | pub resource interface OwnedAccountPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :88:8\n |\n88 | pub fun getParentAddresses(): [Address]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :91:8\n |\n91 | pub fun getParentStatuses(): {Address: Bool}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :96:8\n |\n96 | pub fun getRedeemedStatus(addr: Address): Bool?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :104:4\n |\n104 | pub resource interface OwnedAccountPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :107:8\n |\n107 | pub fun removeParent(parent: Address): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :113:8\n |\n113 | pub fun publishToParent(\n | ^^^\n\nerror: restricted types have been removed; replace with the concrete type or an equivalent intersection type\n --\u003e :115:59\n |\n115 | factory: Capability\u003c\u0026CapabilityFactory.Manager{CapabilityFactory.Getter}\u003e,\n | ^^^^^^^^^^^^^^^^^\n\n--\u003e f8d6e0586b0a20c7.HybridCustody\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.FTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTCollectionPublicFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTCollectionPublicFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTCollectionPublicFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTCollectionPublicFactory\n"}] \ No newline at end of file diff --git a/report/staged-contracts-migrator_1715098464.json b/report/staged-contracts-migrator_1715098464.json deleted file mode 100644 index 821830e..0000000 --- a/report/staged-contracts-migrator_1715098464.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "kind": "contract-update-failure", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "HybridCustody", - "error": "error: mismatching field `factory` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:532:34\n |\n532 | access(self) var factory: Capability<&{CapabilityFactory.Getter}>\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityFactory.Manager`, found `{CapabilityFactory.Getter}`\n\nerror: mismatching field `delegator` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:544:36\n |\n544 | access(self) let delegator: Capability\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityDelegator.Delegator`, found `{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}`\n" - }, - { - "kind": "contract-update-failure", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityFactory", - "error": "error: unsafe access modifiers on CapabilityFactory.Manager: the entitlements migration would grant references to this type CapabilityFactory.Owner, CapabilityFactory.Add, CapabilityFactory.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFactory:42:4\n |\n42 | access(all) resource Manager: Getter {\n43 | /// Mapping of Factories indexed on Type of Capability they retrieve\n44 | access(all) let factories: {Type: {CapabilityFactory.Factory}}\n45 | \n46 | /// Retrieves a list of Types supported by contained Factories\n47 | ///\n48 | /// @return List of Types supported by the Manager\n49 | ///\n50 | access(all) view fun getSupportedTypes(): [Type] {\n51 | return self.factories.keys\n52 | }\n53 | \n54 | /// Retrieves a Factory from the Manager, returning it or nil if it doesn't exist\n55 | ///\n56 | /// @param t: Type the Factory is indexed on\n57 | ///\n58 | access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {\n59 | return self.factories[t]\n60 | }\n61 | \n62 | /// Adds a Factory to the Manager, conditioned on the Factory not already existing\n63 | ///\n64 | /// @param t: Type of Capability the Factory retrieves\n65 | /// @param f: Factory to add\n66 | ///\n67 | access(Owner | Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n68 | pre {\n69 | !self.factories.containsKey(t): \"Factory of given type already exists\"\n70 | }\n71 | self.factories[t] = f\n72 | }\n73 | \n74 | /// Updates a Factory in the Manager, adding if it didn't already exist\n75 | ///\n76 | /// @param t: Type of Capability the Factory retrieves\n77 | /// @param f: Factory to replace existing Factory\n78 | ///\n79 | access(Owner | Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {\n80 | self.factories[t] = f\n81 | }\n82 | \n83 | /// Removes a Factory from the Manager, returning it or nil if it didn't exist\n84 | ///\n85 | /// @param t: Type the Factory is indexed on\n86 | ///\n87 | access(Owner | Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {\n88 | return self.factories.remove(key: t)\n89 | }\n90 | \n91 | init () {\n92 | self.factories = {}\n93 | }\n94 | }\n | ^ Consider removing any disjunction access modifiers\n" - }, - { - "kind": "contract-update-failure", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityFilter", - "error": "error: unsafe access modifiers on CapabilityFilter.DenylistFilter: the entitlements migration would grant references to this type CapabilityFilter.Owner, CapabilityFilter.Add, CapabilityFilter.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFilter:34:4\n |\n34 | access(all) resource DenylistFilter: Filter {\n35 | \n36 | /// Represents the underlying types which should not ever be returned by a RestrictedChildAccount. The filter\n37 | /// will borrow a requested capability, and make sure that the type it gets back is not in the list of denied\n38 | /// types\n39 | access(self) let deniedTypes: {Type: Bool}\n40 | \n41 | /// Adds a type to the mapping of denied types with a value of true\n42 | /// \n43 | /// @param type: The type to add to the denied types mapping\n44 | ///\n45 | access(Owner | Add) fun addType(_ type: Type) {\n46 | self.deniedTypes.insert(key: type, true)\n47 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)\n48 | }\n49 | \n50 | /// Removes a type from the mapping of denied types\n51 | ///\n52 | /// @param type: The type to remove from the denied types mapping\n53 | ///\n54 | access(Owner | Delete) fun removeType(_ type: Type) {\n55 | if let removed = self.deniedTypes.remove(key: type) {\n56 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)\n57 | }\n58 | }\n59 | \n60 | /// Removes all types from the mapping of denied types\n61 | ///\n62 | access(Owner | Delete) fun removeAllTypes() {\n63 | for type in self.deniedTypes.keys {\n64 | self.removeType(type)\n65 | }\n66 | }\n67 | \n68 | /// Determines if a requested capability is allowed by this `Filter`\n69 | ///\n70 | /// @param cap: The capability to check\n71 | /// @return: true if the capability is allowed, false otherwise\n72 | ///\n73 | access(all) view fun allowed(cap: Capability): Bool {\n74 | if let item = cap.borrow<&AnyResource>() {\n75 | return !self.deniedTypes.containsKey(item.getType())\n76 | }\n77 | \n78 | return false\n79 | }\n80 | \n81 | /// Returns details about this filter\n82 | ///\n83 | /// @return A struct containing details about this filter including this Filter's Type indexed on the `type`\n84 | /// key as well as types denied indexed on the `deniedTypes` key\n85 | ///\n86 | access(all) view fun getDetails(): AnyStruct {\n87 | return {\n88 | \"type\": self.getType(),\n89 | \"deniedTypes\": self.deniedTypes.keys\n90 | }\n91 | }\n92 | \n93 | init() {\n94 | self.deniedTypes = {}\n95 | }\n96 | }\n | ^ Consider removing any disjunction access modifiers\n\nerror: unsafe access modifiers on CapabilityFilter.AllowlistFilter: the entitlements migration would grant references to this type CapabilityFilter.Owner, CapabilityFilter.Add, CapabilityFilter.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityFilter:100:4\n |\n100 | access(all) resource AllowlistFilter: Filter {\n101 | // allowedTypes\n102 | // Represents the set of underlying types which are allowed to be \n103 | // returned by a RestrictedChildAccount. The filter will borrow\n104 | // a requested capability, and make sure that the type it gets back is\n105 | // in the list of allowed types\n106 | access(self) let allowedTypes: {Type: Bool}\n107 | \n108 | /// Adds a type to the mapping of allowed types with a value of true\n109 | /// \n110 | /// @param type: The type to add to the allowed types mapping\n111 | ///\n112 | access(Owner | Add) fun addType(_ type: Type) {\n113 | self.allowedTypes.insert(key: type, true)\n114 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)\n115 | }\n116 | \n117 | /// Removes a type from the mapping of allowed types\n118 | ///\n119 | /// @param type: The type to remove from the denied types mapping\n120 | ///\n121 | access(Owner | Delete) fun removeType(_ type: Type) {\n122 | if let removed = self.allowedTypes.remove(key: type) {\n123 | emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)\n124 | }\n125 | }\n126 | \n127 | /// Removes all types from the mapping of denied types\n128 | ///\n129 | access(Owner | Delete) fun removeAllTypes() {\n130 | for type in self.allowedTypes.keys {\n131 | self.removeType(type)\n132 | }\n133 | }\n134 | \n135 | /// Determines if a requested capability is allowed by this `Filter`\n136 | ///\n137 | /// @param cap: The capability to check\n138 | /// @return: true if the capability is allowed, false otherwise\n139 | ///\n140 | access(all) view fun allowed(cap: Capability): Bool {\n141 | if let item = cap.borrow<&AnyResource>() {\n142 | return self.allowedTypes.containsKey(item.getType())\n143 | }\n144 | \n145 | return false\n146 | }\n147 | \n148 | /// Returns details about this filter\n149 | ///\n150 | /// @return A struct containing details about this filter including this Filter's Type indexed on the `type`\n151 | /// key as well as types allowed indexed on the `allowedTypes` key\n152 | ///\n153 | access(all) view fun getDetails(): AnyStruct {\n154 | return {\n155 | \"type\": self.getType(),\n156 | \"allowedTypes\": self.allowedTypes.keys\n157 | }\n158 | }\n159 | \n160 | init() {\n161 | self.allowedTypes = {}\n162 | }\n163 | }\n | ^ Consider removing any disjunction access modifiers\n" - }, - { - "kind": "contract-update-failure", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityDelegator", - "error": "error: unsafe access modifiers on CapabilityDelegator.Delegator: the entitlements migration would grant references to this type CapabilityDelegator.Get, CapabilityDelegator.Owner, CapabilityDelegator.Add, CapabilityDelegator.Delete authorization, which is too permissive.\n --> f8d6e0586b0a20c7.CapabilityDelegator:55:4\n |\n 55 | access(all) resource Delegator: GetterPublic, GetterPrivate {\n 56 | access(self) let privateCapabilities: {Type: Capability}\n 57 | access(self) let publicCapabilities: {Type: Capability}\n 58 | \n 59 | // ------ Begin Getter methods\n 60 | //\n 61 | /// Returns the public Capability of the given Type if it exists\n 62 | ///\n 63 | access(all) view fun getPublicCapability(_ type: Type): Capability? {\n 64 | return self.publicCapabilities[type]\n 65 | }\n 66 | \n 67 | /// Returns the private Capability of the given Type if it exists\n 68 | ///\n 69 | ///\n 70 | /// @param type: Type of the Capability to retrieve\n 71 | /// @return Capability of the given Type if it exists, nil otherwise\n 72 | ///\n 73 | access(Get) view fun getPrivateCapability(_ type: Type): Capability? {\n 74 | return self.privateCapabilities[type]\n 75 | }\n 76 | \n 77 | /// Returns all public Capabilities\n 78 | ///\n 79 | /// @return List of all public Capabilities\n 80 | ///\n 81 | access(all) view fun getAllPublic(): [Capability] {\n 82 | return self.publicCapabilities.values\n 83 | }\n 84 | \n 85 | /// Returns all private Capabilities\n 86 | ///\n 87 | /// @return List of all private Capabilities\n 88 | ///\n 89 | access(Get) fun getAllPrivate(): [Capability] {\n 90 | return self.privateCapabilities.values\n 91 | }\n 92 | \n 93 | /// Returns the first public Type that is a subtype of the given Type\n 94 | ///\n 95 | /// @param type: Type to check for subtypes\n 96 | /// @return First public Type that is a subtype of the given Type, nil otherwise\n 97 | ///\n 98 | access(all) view fun findFirstPublicType(_ type: Type): Type? {\n 99 | for t in self.publicCapabilities.keys {\n100 | if t.isSubtype(of: type) {\n101 | return t\n102 | }\n103 | }\n104 | \n105 | return nil\n106 | }\n107 | \n108 | /// Returns the first private Type that is a subtype of the given Type\n109 | ///\n110 | /// @param type: Type to check for subtypes\n111 | /// @return First private Type that is a subtype of the given Type, nil otherwise\n112 | ///\n113 | access(all) view fun findFirstPrivateType(_ type: Type): Type? {\n114 | for t in self.privateCapabilities.keys {\n115 | if t.isSubtype(of: type) {\n116 | return t\n117 | }\n118 | }\n119 | \n120 | return nil\n121 | }\n122 | // ------- End Getter methods\n123 | \n124 | /// Adds a Capability to the Delegator\n125 | ///\n126 | /// @param cap: Capability to add\n127 | /// @param isPublic: Whether the Capability should be public or private\n128 | ///\n129 | access(Owner | Add) fun addCapability(cap: Capability, isPublic: Bool) {\n130 | pre {\n131 | cap.check<&AnyResource>(): \"Invalid Capability provided\"\n132 | }\n133 | if isPublic {\n134 | self.publicCapabilities.insert(key: cap.getType(), cap)\n135 | } else {\n136 | self.privateCapabilities.insert(key: cap.getType(), cap)\n137 | }\n138 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: isPublic, active: true)\n139 | }\n140 | \n141 | /// Removes a Capability from the Delegator\n142 | ///\n143 | /// @param cap: Capability to remove\n144 | ///\n145 | access(Owner | Delete) fun removeCapability(cap: Capability) {\n146 | if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) {\n147 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false)\n148 | }\n149 | \n150 | if let removedPrivate = self.privateCapabilities.remove(key: cap.getType()) {\n151 | emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: false, active: false)\n152 | }\n153 | }\n154 | \n155 | init() {\n156 | self.privateCapabilities = {}\n157 | self.publicCapabilities = {}\n158 | }\n159 | }\n | ^ Consider removing any disjunction access modifiers\n" - } -] \ No newline at end of file diff --git a/report/staged-contracts-migrator_1715123315.json b/report/staged-contracts-migrator_1715123315.json new file mode 100644 index 0000000..a7448df --- /dev/null +++ b/report/staged-contracts-migrator_1715123315.json @@ -0,0 +1,23 @@ +[ + { + "kind": "contract-update-failure", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "HybridCustody", + "error": "error: mismatching field `factory` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:532:34\n |\n532 | access(self) var factory: Capability<&{CapabilityFactory.Getter}>\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityFactory.Manager`, found `{CapabilityFactory.Getter}`\n\nerror: mismatching field `delegator` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:544:36\n |\n544 | access(self) let delegator: Capability\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityDelegator.Delegator`, found `{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}`\n" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityFactory" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityFilter" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "CapabilityDelegator" + } +] \ No newline at end of file diff --git a/report/system-contracts-migrator_1715098464.json b/report/system-contracts-migrator_1715098464.json deleted file mode 100644 index 5ac3e1b..0000000 --- a/report/system-contracts-migrator_1715098464.json +++ /dev/null @@ -1 +0,0 @@ -[{"kind":"contract-update-success","account_address":"0xee82856bf20e2aa6","contract_name":"FungibleTokenMetadataViews"},{"kind":"contract-update-success","account_address":"0xee82856bf20e2aa6","contract_name":"FungibleToken"},{"kind":"contract-update-success","account_address":"0xe5a8b7f23e8b548f","contract_name":"FlowFees"},{"kind":"contract-update-success","account_address":"0x0ae53cb6e3f42a79","contract_name":"FlowToken"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"NonFungibleToken"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"MetadataViews"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"ViewResolver"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"RandomBeaconHistory"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowIDTableStaking"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowServiceAccount"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"NodeVersionBeacon"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowEpoch"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowClusterQC"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowStorageFees"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowStakingCollection"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"StakingProxy"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"LockedTokens"},{"kind":"contract-update-success","account_address":"0xf8d6e0586b0a20c7","contract_name":"FlowDKG"}] \ No newline at end of file diff --git a/report/system-contracts-migrator_1715123315.json b/report/system-contracts-migrator_1715123315.json new file mode 100644 index 0000000..1f91926 --- /dev/null +++ b/report/system-contracts-migrator_1715123315.json @@ -0,0 +1,92 @@ +[ + { + "kind": "contract-update-success", + "account_address": "0xee82856bf20e2aa6", + "contract_name": "FungibleTokenMetadataViews" + }, + { + "kind": "contract-update-success", + "account_address": "0xee82856bf20e2aa6", + "contract_name": "FungibleToken" + }, + { + "kind": "contract-update-success", + "account_address": "0x0ae53cb6e3f42a79", + "contract_name": "FlowToken" + }, + { + "kind": "contract-update-success", + "account_address": "0xe5a8b7f23e8b548f", + "contract_name": "FlowFees" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowClusterQC" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "NonFungibleToken" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "ViewResolver" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowIDTableStaking" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "RandomBeaconHistory" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "LockedTokens" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "NodeVersionBeacon" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowStakingCollection" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "StakingProxy" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowDKG" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "MetadataViews" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowStorageFees" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowServiceAccount" + }, + { + "kind": "contract-update-success", + "account_address": "0xf8d6e0586b0a20c7", + "contract_name": "FlowEpoch" + } +] \ No newline at end of file From b646f850cec280e2e18aa315ec7952b956c03526 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 7 May 2024 16:17:20 -0700 Subject: [PATCH 30/34] fix FTVaultFactory --- contracts/factories/FTVaultFactory.cdc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/contracts/factories/FTVaultFactory.cdc b/contracts/factories/FTVaultFactory.cdc index 82e5e93..c279af4 100644 --- a/contracts/factories/FTVaultFactory.cdc +++ b/contracts/factories/FTVaultFactory.cdc @@ -34,15 +34,13 @@ access(all) contract FTVaultFactory { } access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability? { - if let cap = acct.capabilities.get<&{FungibleToken.Vault}>(path) { - if !cap.check() { - return nil - } - - return cap + let cap = acct.capabilities.get<&{FungibleToken.Vault}>(path) + if !cap.check() { + return nil } + + return cap - return nil } } } \ No newline at end of file From 051c49c45aa768100a199d4f45991cd40efb26c8 Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 7 May 2024 18:27:14 -0700 Subject: [PATCH 31/34] fix migration types for child account factory and delegator --- contracts/HybridCustody.cdc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 7860217..549ce52 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -529,7 +529,7 @@ access(all) contract HybridCustody { /// account. The CapabilityFactory returns Capabilities which can be casted to their appropriate types once /// obtained, but only if the child account has configured their factory to allow it. For instance, a /// ChildAccount might choose to expose NonFungibleToken.Provider, but not FungibleToken.Provider - access(self) var factory: Capability<&{CapabilityFactory.Getter}> + access(self) var factory: Capability<&CapabilityFactory.Manager> /// The CapabilityFilter is a restriction put at the front of obtaining any non-public Capability. Some wallets /// might want to give access to NonFungibleToken.Provider, but only to **some** of the collections it manages, @@ -541,7 +541,7 @@ access(all) contract HybridCustody { /// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a /// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot /// collection, but only to the path that the collection exists in. - access(self) let delegator: Capability + access(self) let delegator: Capability /// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If /// this filter is not nil, any Capability returned through the `getCapability` function checks that the From 7562ab157512f30bb3ddaeb0dca63f652372f94d Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Tue, 7 May 2024 18:41:49 -0700 Subject: [PATCH 32/34] fix tests --- contracts/HybridCustody.cdc | 18 +++++++++--------- .../get_supported_types_from_manager.cdc | 5 ++--- .../setup_nft_filter_and_factory_manager.cdc | 6 +++--- transactions/factory/setup_empty_factory.cdc | 6 +++--- transactions/factory/setup_ft_manager.cdc | 6 +++--- transactions/factory/setup_nft_ft_manager.cdc | 6 +++--- transactions/factory/setup_nft_manager.cdc | 4 ++-- .../onboarding/blockchain_native.cdc | 3 +-- .../hybrid-custody/publish_to_parent.cdc | 2 +- .../set_capability_factory_for_parent.cdc | 2 +- .../hybrid-custody/setup_multi_sig.cdc | 2 +- ...tup_owned_account_and_publish_to_parent.cdc | 2 +- 12 files changed, 30 insertions(+), 32 deletions(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 549ce52..5e81da2 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -115,7 +115,7 @@ access(all) contract HybridCustody { /// access control are managed through the child account. access(Owner) fun publishToParent( parentAddress: Address, - factory: Capability<&{CapabilityFactory.Getter}>, + factory: Capability<&CapabilityFactory.Manager>, filter: Capability<&{CapabilityFilter.Filter}> ) { pre { @@ -140,7 +140,7 @@ access(all) contract HybridCustody { // setCapabilityFactoryForParent // Override the existing CapabilityFactory Capability for a given parent. This will allow the owner of the // account to start managing their own factory of capabilities to be able to retrieve - access(Owner) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&{CapabilityFactory.Getter}>) { + access(Owner) fun setCapabilityFactoryForParent(parent: Address, cap: Capability<&CapabilityFactory.Manager>) { pre { cap.check(): "Invalid CapabilityFactory.Getter Capability provided" } @@ -541,7 +541,7 @@ access(all) contract HybridCustody { /// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a /// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot /// collection, but only to the path that the collection exists in. - access(self) let delegator: Capability + access(self) let delegator: Capability /// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If /// this filter is not nil, any Capability returned through the `getCapability` function checks that the @@ -580,7 +580,7 @@ access(all) contract HybridCustody { /// Sets the CapabiltyFactory.Manager Capability /// - access(contract) fun setCapabilityFactory(cap: Capability<&{CapabilityFactory.Getter}>) { + access(contract) fun setCapabilityFactory(cap: Capability<&CapabilityFactory.Manager>) { self.factory = cap } @@ -730,9 +730,9 @@ access(all) contract HybridCustody { init( _ childCap: Capability<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>, - _ factory: Capability<&{CapabilityFactory.Getter}>, + _ factory: Capability<&CapabilityFactory.Manager>, _ filter: Capability<&{CapabilityFilter.Filter}>, - _ delegator: Capability, + _ delegator: Capability, _ parent: Address ) { pre { @@ -853,7 +853,7 @@ access(all) contract HybridCustody { /// access(Owner) fun publishToParent( parentAddress: Address, - factory: Capability<&{CapabilityFactory.Getter}>, + factory: Capability<&CapabilityFactory.Manager>, filter: Capability<&{CapabilityFilter.Filter}> ) { pre { @@ -880,7 +880,7 @@ access(all) contract HybridCustody { let pubCap = acct.capabilities.storage.issue<&{CapabilityDelegator.GetterPublic}>(capDelegatorStorage) acct.capabilities.publish(pubCap, at: capDelegatorPublic) - let delegator = acct.capabilities.storage.issue(capDelegatorStorage) + let delegator = acct.capabilities.storage.issue(capDelegatorStorage) assert(delegator.check(), message: "failed to setup capability delegator for parent address") let borrowableCap = self.borrowAccount().capabilities.storage.issue<&{BorrowableAccount, OwnedAccountPublic, ViewResolver.Resolver}>( @@ -1109,7 +1109,7 @@ access(all) contract HybridCustody { /// access(Owner) fun setCapabilityFactoryForParent( parent: Address, - cap: Capability<&{CapabilityFactory.Getter}> + cap: Capability<&CapabilityFactory.Manager> ) { let p = self.borrowChildAccount(parent: parent) ?? panic("could not find parent address") p.setCapabilityFactory(cap: cap) diff --git a/scripts/factory/get_supported_types_from_manager.cdc b/scripts/factory/get_supported_types_from_manager.cdc index 45e4df3..ecf5987 100644 --- a/scripts/factory/get_supported_types_from_manager.cdc +++ b/scripts/factory/get_supported_types_from_manager.cdc @@ -3,8 +3,7 @@ import "CapabilityFactory" import "NonFungibleToken" access(all) fun main(address: Address): [Type] { - let getterRef = getAccount(address).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! - .borrow() - ?? panic("CapabilityFactory Getter not found") + let getterRef = getAccount(address).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) + .borrow() ?? panic("CapabilityFactory Getter not found") return getterRef.getSupportedTypes() } \ No newline at end of file diff --git a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc index a47c2c6..4851fb6 100644 --- a/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc +++ b/transactions/dev-setup/setup_nft_filter_and_factory_manager.cdc @@ -54,16 +54,16 @@ transaction(nftContractAddress: Address, nftContractName: String) { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { + if !acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) acct.capabilities.publish( - acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + acct.capabilities.storage.issue<&CapabilityFactory.Manager>(CapabilityFactory.StoragePath), at: CapabilityFactory.PublicPath ) } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() == true, + acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check() == true, message: "CapabilityFactory is not setup properly" ) diff --git a/transactions/factory/setup_empty_factory.cdc b/transactions/factory/setup_empty_factory.cdc index c6cabe5..f61edee 100644 --- a/transactions/factory/setup_empty_factory.cdc +++ b/transactions/factory/setup_empty_factory.cdc @@ -10,15 +10,15 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { + if !acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) - let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) + let cap = acct.capabilities.storage.issue<&CapabilityFactory.Manager>(CapabilityFactory.StoragePath) acct.capabilities.publish(cap, at: CapabilityFactory.PublicPath) } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) } diff --git a/transactions/factory/setup_ft_manager.cdc b/transactions/factory/setup_ft_manager.cdc index dff5445..5685e32 100644 --- a/transactions/factory/setup_ft_manager.cdc +++ b/transactions/factory/setup_ft_manager.cdc @@ -14,16 +14,16 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { + if !acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) acct.capabilities.publish( - acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + acct.capabilities.storage.issue<&CapabilityFactory.Manager>(CapabilityFactory.StoragePath), at: CapabilityFactory.PublicPath ) } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) diff --git a/transactions/factory/setup_nft_ft_manager.cdc b/transactions/factory/setup_nft_ft_manager.cdc index 9115b2b..a2083f2 100644 --- a/transactions/factory/setup_nft_ft_manager.cdc +++ b/transactions/factory/setup_nft_ft_manager.cdc @@ -18,15 +18,15 @@ transaction { acct.storage.save(<-f, to: CapabilityFactory.StoragePath) } - if !acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check() { + if !acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check() { acct.capabilities.unpublish(CapabilityFactory.PublicPath) - let cap = acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath) + let cap = acct.capabilities.storage.issue<&CapabilityFactory.Manager>(CapabilityFactory.StoragePath) acct.capabilities.publish(cap, at: CapabilityFactory.PublicPath) } assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) diff --git a/transactions/factory/setup_nft_manager.cdc b/transactions/factory/setup_nft_manager.cdc index f60d476..b35cf77 100644 --- a/transactions/factory/setup_nft_manager.cdc +++ b/transactions/factory/setup_nft_manager.cdc @@ -15,12 +15,12 @@ transaction { acct.capabilities.unpublish(CapabilityFactory.PublicPath) acct.capabilities.publish( - acct.capabilities.storage.issue<&{CapabilityFactory.Getter}>(CapabilityFactory.StoragePath), + acct.capabilities.storage.issue<&CapabilityFactory.Manager>(CapabilityFactory.StoragePath), at: CapabilityFactory.PublicPath ) assert( - acct.capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath).check(), + acct.capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath).check(), message: "CapabilityFactory is not setup properly" ) diff --git a/transactions/hybrid-custody/onboarding/blockchain_native.cdc b/transactions/hybrid-custody/onboarding/blockchain_native.cdc index 2141803..3d36102 100644 --- a/transactions/hybrid-custody/onboarding/blockchain_native.cdc +++ b/transactions/hybrid-custody/onboarding/blockchain_native.cdc @@ -76,8 +76,7 @@ transaction( let owned = newAccount.storage.borrow(from: HybridCustody.OwnedAccountStoragePath)! // Get the CapabilityFactory.Manager Capability - let factory = getAccount(factoryAddress).capabilities - .get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath)! + let factory = getAccount(factoryAddress).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) assert(factory.check(), message: "factory address is not configured properly") // Get the CapabilityFilter.Filter Capability diff --git a/transactions/hybrid-custody/publish_to_parent.cdc b/transactions/hybrid-custody/publish_to_parent.cdc index cfcff26..d7e80b1 100644 --- a/transactions/hybrid-custody/publish_to_parent.cdc +++ b/transactions/hybrid-custody/publish_to_parent.cdc @@ -8,7 +8,7 @@ transaction(parent: Address, factoryAddress: Address, filterAddress: Address) { let owned = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(factoryAddress).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) assert(factory.check(), message: "factory address is not configured properly") let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) diff --git a/transactions/hybrid-custody/set_capability_factory_for_parent.cdc b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc index 86d8b5e..b7af73d 100644 --- a/transactions/hybrid-custody/set_capability_factory_for_parent.cdc +++ b/transactions/hybrid-custody/set_capability_factory_for_parent.cdc @@ -3,7 +3,7 @@ import "CapabilityFactory" transaction(parent: Address, factoryAddress: Address) { prepare(acct: auth(Storage) &Account) { - let cap = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let cap = getAccount(factoryAddress).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) let ownedAccount = acct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") diff --git a/transactions/hybrid-custody/setup_multi_sig.cdc b/transactions/hybrid-custody/setup_multi_sig.cdc index f00ae56..9289e74 100644 --- a/transactions/hybrid-custody/setup_multi_sig.cdc +++ b/transactions/hybrid-custody/setup_multi_sig.cdc @@ -71,7 +71,7 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, let owned = childAcct.storage.borrow(from: HybridCustody.OwnedAccountStoragePath) ?? panic("owned account not found") - let factory = getAccount(childAccountFactoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(childAccountFactoryAddress).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) assert(factory.check(), message: "factory address is not configured properly") let filterForChild = getAccount(childAccountFilterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) diff --git a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc index 8416271..6b9f380 100644 --- a/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc +++ b/transactions/hybrid-custody/setup_owned_account_and_publish_to_parent.cdc @@ -50,7 +50,7 @@ transaction( } // Get CapabilityFactory & CapabilityFilter Capabilities - let factory = getAccount(factoryAddress).capabilities.get<&{CapabilityFactory.Getter}>(CapabilityFactory.PublicPath) + let factory = getAccount(factoryAddress).capabilities.get<&CapabilityFactory.Manager>(CapabilityFactory.PublicPath) assert(factory.check(), message: "factory address is not configured properly") let filter = getAccount(filterAddress).capabilities.get<&{CapabilityFilter.Filter}>(CapabilityFilter.PublicPath) From 0b41ec7f848494cd88abe14b7208d4d65ac80adf Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 7 May 2024 21:17:12 -0500 Subject: [PATCH 33/34] update ChildAccount.delegator field to CapabilityDelegator.Delegator --- contracts/HybridCustody.cdc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/HybridCustody.cdc b/contracts/HybridCustody.cdc index 5e81da2..7602830 100644 --- a/contracts/HybridCustody.cdc +++ b/contracts/HybridCustody.cdc @@ -541,7 +541,7 @@ access(all) contract HybridCustody { /// certain type. When using the CapabilityDelegator, you do not have the ability to specify which path a /// capability came from. For instance, Dapper Wallet might choose to expose a Capability to their Full TopShot /// collection, but only to the path that the collection exists in. - access(self) let delegator: Capability + access(self) let delegator: Capability /// managerCapabilityFilter is a component optionally given to a child account when a manager redeems it. If /// this filter is not nil, any Capability returned through the `getCapability` function checks that the From 756be5fa52b118fef07a3713bc0d9d651fc4d23f Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 7 May 2024 21:17:41 -0500 Subject: [PATCH 34/34] remove temp report directory --- ...-capability-value-migrator_1715123315.json | 1 - ...adence-link-value-migrator_1715123315.json | 1 - .../cadence-value-migration_1715123315.json | 1 - report/contract-checking_1715123315.json | 1 - .../staged-contracts-migrator_1715123315.json | 23 ----- .../system-contracts-migrator_1715123315.json | 92 ------------------- 6 files changed, 119 deletions(-) delete mode 100644 report/cadence-capability-value-migrator_1715123315.json delete mode 100644 report/cadence-link-value-migrator_1715123315.json delete mode 100644 report/cadence-value-migration_1715123315.json delete mode 100644 report/contract-checking_1715123315.json delete mode 100644 report/staged-contracts-migrator_1715123315.json delete mode 100644 report/system-contracts-migrator_1715123315.json diff --git a/report/cadence-capability-value-migrator_1715123315.json b/report/cadence-capability-value-migrator_1715123315.json deleted file mode 100644 index e5f1ca4..0000000 --- a/report/cadence-capability-value-migrator_1715123315.json +++ /dev/null @@ -1 +0,0 @@ -[{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowIDTableStaking.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"CapabilityValueMigration"},{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowClusterQC.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"CapabilityValueMigration"},{"kind":"capability-migration-success","account_address":"0xf8d6e0586b0a20c7","address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","borrow_type":"\u0026A.f8d6e0586b0a20c7.FlowDKG.Admin"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"CapabilityValueMigration"}] \ No newline at end of file diff --git a/report/cadence-link-value-migrator_1715123315.json b/report/cadence-link-value-migrator_1715123315.json deleted file mode 100644 index 33b576b..0000000 --- a/report/cadence-link-value-migrator_1715123315.json +++ /dev/null @@ -1 +0,0 @@ -[{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xee82856bf20e2aa6","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowStakingAdminEpochOperations","capability_id":1},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenReceiver","capability_id":1},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0x0ae53cb6e3f42a79","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xe5a8b7f23e8b548f","path":"/public/flowTokenBalance","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/lockedTokenAdmin","capability_id":2},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowDKGAdminEpochOperations","capability_id":3},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/private/flowQCAdminEpochOperations","capability_id":4},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenBalance","capability_id":5},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"LinkValueMigration"},{"kind":"link-migration-success","account_address":"0xf8d6e0586b0a20c7","path":"/public/flowTokenReceiver","capability_id":6},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"LinkValueMigration"}] \ No newline at end of file diff --git a/report/cadence-value-migration_1715123315.json b/report/cadence-value-migration_1715123315.json deleted file mode 100644 index d5e7219..0000000 --- a/report/cadence-value-migration_1715123315.json +++ /dev/null @@ -1 +0,0 @@ -[{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0x0ae53cb6e3f42a79","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xee82856bf20e2aa6","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xe5a8b7f23e8b548f","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"storage","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowStakingAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"lockedTokenAdmin","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowDKGAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"private","key":"flowQCAdminEpochOperations","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenBalance","migration":"EntitlementsMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"StaticTypeMigration"},{"kind":"cadence-value-migration-success","account_address":"0xf8d6e0586b0a20c7","domain":"public","key":"flowTokenReceiver","migration":"EntitlementsMigration"}] \ No newline at end of file diff --git a/report/contract-checking_1715123315.json b/report/contract-checking_1715123315.json deleted file mode 100644 index fd1cfe3..0000000 --- a/report/contract-checking_1715123315.json +++ /dev/null @@ -1 +0,0 @@ -[{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTAllFactory","error":"error: error getting program f8d6e0586b0a20c7.FTAllFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTAllFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTAllFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTProviderAndCollectionFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTProviderAndCollectionFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTProviderAndCollectionFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTProviderAndCollectionFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"HybridCustody","error":"error: error getting program f8d6e0586b0a20c7.HybridCustody: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :30:0\n |\n30 | pub contract HybridCustody {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :36:4\n |\n36 | pub let OwnedAccountStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :37:4\n |\n37 | pub let OwnedAccountPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :38:4\n |\n38 | pub let OwnedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :40:4\n |\n40 | pub let ManagerStoragePath: StoragePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :41:4\n |\n41 | pub let ManagerPublicPath: PublicPath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :42:4\n |\n42 | pub let ManagerPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :44:4\n |\n44 | pub let LinkedAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :45:4\n |\n45 | pub let BorrowableAccountPrivatePath: PrivatePath\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :50:4\n |\n50 | pub event CreatedManager(id: UInt64)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :52:4\n |\n52 | pub event CreatedOwnedAccount(id: UInt64, child: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :56:4\n |\n56 | pub event AccountUpdated(id: UInt64?, child: Address, parent: Address, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :60:4\n |\n60 | pub event OwnershipUpdated(id: UInt64, child: Address, previousOwner: Address?, owner: Address?, active: Bool)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :62:4\n |\n62 | pub event ChildAccountPublished(\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :73:4\n |\n73 | pub event OwnershipGranted(ownedAcctID: UInt64, child: Address, previousOwner: Address?, pendingOwner: Address)\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :75:4\n |\n75 | pub event AccountSealed(id: UInt64, address: Address, parents: [Address])\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :79:4\n |\n79 | pub resource interface BorrowableAccount {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :81:8\n |\n81 | pub fun check(): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :86:4\n |\n86 | pub resource interface OwnedAccountPublic {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :88:8\n |\n88 | pub fun getParentAddresses(): [Address]\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :91:8\n |\n91 | pub fun getParentStatuses(): {Address: Bool}\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :96:8\n |\n96 | pub fun getRedeemedStatus(addr: Address): Bool?\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :104:4\n |\n104 | pub resource interface OwnedAccountPrivate {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :107:8\n |\n107 | pub fun removeParent(parent: Address): Bool\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :113:8\n |\n113 | pub fun publishToParent(\n | ^^^\n\nerror: restricted types have been removed; replace with the concrete type or an equivalent intersection type\n --\u003e :115:59\n |\n115 | factory: Capability\u003c\u0026CapabilityFactory.Manager{CapabilityFactory.Getter}\u003e,\n | ^^^^^^^^^^^^^^^^^\n\n--\u003e f8d6e0586b0a20c7.HybridCustody\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTProviderFactory","error":"error: error getting program f8d6e0586b0a20c7.FTProviderFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTProviderFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTProviderFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"FTReceiverBalanceFactory","error":"error: error getting program f8d6e0586b0a20c7.FTReceiverBalanceFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract FTReceiverBalanceFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.FTReceiverBalanceFactory\n"},{"address":"0xf8d6e0586b0a20c7","name":"NFTCollectionPublicFactory","error":"error: error getting program f8d6e0586b0a20c7.NFTCollectionPublicFactory: failed to derive value: load program failed: Parsing failed:\nerror: `pub` is no longer a valid access keyword\n --\u003e :4:0\n |\n4 | pub contract NFTCollectionPublicFactory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :5:4\n |\n5 | pub struct Factory: CapabilityFactory.Factory {\n | ^^^\n\nerror: `pub` is no longer a valid access keyword\n --\u003e :6:8\n |\n6 | pub fun getCapability(acct: \u0026AuthAccount, path: CapabilityPath): Capability {\n | ^^^\n\n--\u003e f8d6e0586b0a20c7.NFTCollectionPublicFactory\n"}] \ No newline at end of file diff --git a/report/staged-contracts-migrator_1715123315.json b/report/staged-contracts-migrator_1715123315.json deleted file mode 100644 index a7448df..0000000 --- a/report/staged-contracts-migrator_1715123315.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "kind": "contract-update-failure", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "HybridCustody", - "error": "error: mismatching field `factory` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:532:34\n |\n532 | access(self) var factory: Capability<&{CapabilityFactory.Getter}>\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityFactory.Manager`, found `{CapabilityFactory.Getter}`\n\nerror: mismatching field `delegator` in `ChildAccount`\n --> f8d6e0586b0a20c7.HybridCustody:544:36\n |\n544 | access(self) let delegator: Capability\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incompatible type annotations. expected `CapabilityDelegator.Delegator`, found `{CapabilityDelegator.GetterPublic, CapabilityDelegator.GetterPrivate}`\n" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityFactory" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityFilter" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "CapabilityDelegator" - } -] \ No newline at end of file diff --git a/report/system-contracts-migrator_1715123315.json b/report/system-contracts-migrator_1715123315.json deleted file mode 100644 index 1f91926..0000000 --- a/report/system-contracts-migrator_1715123315.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "kind": "contract-update-success", - "account_address": "0xee82856bf20e2aa6", - "contract_name": "FungibleTokenMetadataViews" - }, - { - "kind": "contract-update-success", - "account_address": "0xee82856bf20e2aa6", - "contract_name": "FungibleToken" - }, - { - "kind": "contract-update-success", - "account_address": "0x0ae53cb6e3f42a79", - "contract_name": "FlowToken" - }, - { - "kind": "contract-update-success", - "account_address": "0xe5a8b7f23e8b548f", - "contract_name": "FlowFees" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowClusterQC" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "NonFungibleToken" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "ViewResolver" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowIDTableStaking" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "RandomBeaconHistory" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "LockedTokens" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "NodeVersionBeacon" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowStakingCollection" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "StakingProxy" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowDKG" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "MetadataViews" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowStorageFees" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowServiceAccount" - }, - { - "kind": "contract-update-success", - "account_address": "0xf8d6e0586b0a20c7", - "contract_name": "FlowEpoch" - } -] \ No newline at end of file