Smart Contract

CapabilityFactory

A.d8a7e05a7ac670c0.CapabilityFactory

Deployed

1w ago
Feb 17, 2026, 02:27:56 PM UTC

Dependents

3999 imports
1/// # Capability Factory
2///
3/// This contract defines a Factory interface and a Manager resource to contain Factory implementations, as well as a
4/// Getter interface for retrieval of contained Factories.
5/// 
6/// A Factory is defines a method getCapability() which defines the retrieval pattern of a Capability from a given
7/// account at the specified path. This pattern arose out of a need to retrieve arbitrary & castable Capabilities from
8/// an account under the static typing constraints inherent to Cadence.
9///
10/// The Manager resource is a container for Factories, and implements the Getter interface.
11///
12/// **Note:** It's generally an anti-pattern to pass around AuthAccount references; however, the need for castable
13/// Capabilities is critical to the use case of Hybrid Custody. It's advised to use Factories sparingly and only for
14/// cases where Capabilities must be castable by the caller.
15///
16access(all) contract CapabilityFactory {
17    
18    access(all) let StoragePath: StoragePath
19    access(all) let PublicPath: PublicPath
20
21    access(all) entitlement Add
22    access(all) entitlement Delete
23    
24    /// Factory structures a common interface for Capability retrieval from a given account at a specified path
25    ///
26    access(all) struct interface Factory {
27        access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability?
28        access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability?
29    }
30
31    /// Getter defines an interface for retrieval of a Factory if contained within the implementing resource
32    ///
33    access(all) resource interface Getter {
34        access(all) view fun getSupportedTypes(): [Type]
35        access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}?
36    }
37
38    /// Manager is a resource that contains Factories and implements the Getter interface for retrieval of contained
39    /// Factories
40    ///
41    access(all) resource Manager: Getter {
42        /// Mapping of Factories indexed on Type of Capability they retrieve
43        access(all) let factories: {Type: {CapabilityFactory.Factory}}
44
45        /// Retrieves a list of Types supported by contained Factories
46        ///
47        /// @return List of Types supported by the Manager
48        ///
49        access(all) view fun getSupportedTypes(): [Type] {
50            return self.factories.keys
51        }
52
53        /// Retrieves a Factory from the Manager, returning it or nil if it doesn't exist
54        ///
55        /// @param t: Type the Factory is indexed on
56        ///
57        access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {
58            return self.factories[t]
59        }
60
61        /// Adds a Factory to the Manager, conditioned on the Factory not already existing
62        ///
63        /// @param t: Type of Capability the Factory retrieves
64        /// @param f: Factory to add
65        ///
66        access(Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
67            pre {
68                !self.factories.containsKey(t): "Factory of given type already exists"
69            }
70            self.factories[t] = f
71        }
72
73        /// Updates a Factory in the Manager, adding if it didn't already exist
74        ///
75        /// @param t: Type of Capability the Factory retrieves
76        /// @param f: Factory to replace existing Factory
77        ///
78        access(Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
79            self.factories[t] = f
80        }
81
82        /// Removes a Factory from the Manager, returning it or nil if it didn't exist
83        ///
84        /// @param t: Type the Factory is indexed on
85        ///
86        access(Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {
87            return self.factories.remove(key: t)
88        }
89
90        init () {
91            self.factories = {}
92        }
93    }
94
95    /// Creates a Manager resource
96    ///
97    /// @return Manager resource
98    access(all) fun createFactoryManager(): @Manager {
99        return <- create Manager()
100    }
101
102    init() {
103        let identifier = "CapabilityFactory_".concat(self.account.address.toString())
104        self.StoragePath = StoragePath(identifier: identifier)!
105        self.PublicPath = PublicPath(identifier: identifier)!
106    }
107}