Smart Contract

FlowYieldVaults

A.b1d63873c3cc9f79.FlowYieldVaults

Valid From

143,267,156

Deployed

1w ago
Feb 16, 2026, 01:06:54 AM UTC

Dependents

36 imports
1// standards
2import FungibleToken from 0xf233dcee88fe0abe
3import Burner from 0xf233dcee88fe0abe
4import ViewResolver from 0x1d7e57aa55817448
5// DeFiActions
6import DeFiActions from 0x6d888f175c158410
7import FlowYieldVaultsClosedBeta from 0xb1d63873c3cc9f79
8
9/// THIS CONTRACT IS A MOCK AND IS NOT INTENDED FOR USE IN PRODUCTION
10/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
11///
12access(all) contract FlowYieldVaults {
13
14    /* --- FIELDS --- */
15
16    /// Canonical StoragePath for where YieldVaultManager should be stored
17    access(all) let YieldVaultManagerStoragePath: StoragePath
18    /// Canonical PublicPath for where YieldVaultManager Capability should be published
19    access(all) let YieldVaultManagerPublicPath: PublicPath
20    /// Canonical StoragePath for where StrategyFactory should be stored
21    access(all) let FactoryStoragePath: StoragePath
22    /// Canonical PublicPath for where StrategyFactory Capability should be published
23    access(all) let FactoryPublicPath: PublicPath
24
25    /* --- EVENTS --- */
26
27    access(all) event CreatedYieldVault(
28        id: UInt64,
29        uuid: UInt64,
30        strategyType: String,
31        tokenType: String,
32        initialAmount: UFix64,
33        creator: Address?
34    )
35    access(all) event DepositedToYieldVault(
36        id: UInt64,
37        strategyType: String,
38        tokenType: String,
39        amount: UFix64,
40        owner: Address?,
41        fromUUID: UInt64
42    )
43    access(all) event WithdrawnFromYieldVault(
44        id: UInt64,
45        strategyType: String,
46        tokenType: String,
47        amount: UFix64,
48        owner: Address?,
49        toUUID: UInt64
50    )
51    access(all) event AddedToManager(
52        id: UInt64,
53        strategyType: String,
54        owner: Address?,
55        managerUUID: UInt64,
56        tokenType: String
57    )
58    access(all) event BurnedYieldVault(
59        id: UInt64,
60        strategyType: String,
61        tokenType: String,
62        remainingBalance: UFix64,
63        owner: Address?
64    )
65
66    /* --- CONSTRUCTS --- */
67
68    /// Strategy
69    ///
70    /// A Strategy is meant to encapsulate the Sink/Source entrypoints allowing for flows into and out of stacked
71    /// DeFiActions components. These compositions are intended to capitalize on some yield-bearing opportunity so that
72    /// a Strategy bears yield on that which is deposited into it, albeit not without some risk. A Strategy then can be
73    /// thought of as the top-level of a nesting of DeFiActions connectors & adapters where one can deposit & withdraw
74    /// funds into the composed DeFi workflows.
75    ///
76    /// While two types of strategies may not highly differ with respect to their fields, the stacking of DeFiActions
77    /// components & connections they provide access to likely do. This difference in wiring is why the Strategy is a
78    /// resource - because the Type and uniqueness of composition of a given Strategy must be preserved as that is its
79    /// distinguishing factor. These qualities are preserved by restricting the party who can construct it, which for
80    /// resources is within the contract that defines it.
81    ///
82    /// TODO: Consider making Sink/Source multi-asset - we could then make Strategy a composite Sink, Source & do away
83    ///     with the added layer of abstraction introduced by a StrategyComposer.
84    access(all) resource interface Strategy : DeFiActions.IdentifiableResource, Burner.Burnable {
85        /// Returns the type of Vaults that this Strategy instance can handle
86        access(all) view fun getSupportedCollateralTypes(): {Type: Bool}
87        /// Returns whether the provided Vault type is supported by this Strategy instance
88        access(all) view fun isSupportedCollateralType(_ type: Type): Bool {
89            return self.getSupportedCollateralTypes()[type] ?? false
90        }
91        /// Returns the balance of the given token available for withdrawal. Note that this may be an estimate due to
92        /// the lack of guarantees inherent to DeFiActions Sources
93        access(all) fun availableBalance(ofToken: Type): UFix64
94        /// Deposits up to the balance of the referenced Vault into this Strategy
95        access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) {
96            pre {
97                self.isSupportedCollateralType(from.getType()):
98                "Cannot deposit Vault \(from.getType().identifier) to Strategy \(self.getType().identifier) - unsupported deposit type"
99            }
100        }
101        /// Withdraws from this Strategy and returns the resulting Vault of the requested token Type
102        access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} {
103            post {
104                result.getType() == ofToken:
105                "Invalid Vault returns - requests \(ofToken.identifier) but returned \(result.getType().identifier)"
106            }
107        }
108    }
109
110    /// StrategyComposer
111    ///
112    /// A StrategyComposer is responsible for stacking DeFiActions connectors in a manner that composes a final Strategy.
113    /// Since DeFiActions Sink/Source only support single assets and some Strategies may be multi-asset, we deal with
114    /// building a Strategy distinctly from encapsulating the top-level DFA connectors acting as entrypoints in to the
115    /// DeFiActions stack.
116    ///
117    /// TODO: Consider making Sink/Source multi-asset - we could then make Strategy a composite Sink, Source & do away
118    ///     with the added layer of abstraction introduced by a StrategyComposer.
119    access(all) resource interface StrategyComposer {
120        /// Returns the Types of Strategies composed by this StrategyComposer
121        access(all) view fun getComposedStrategyTypes(): {Type: Bool}
122        /// Returns the Vault types which can be used to initialize a given Strategy
123        access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool}
124        /// Returns the Vault types which can be deposited to a given Strategy instance if it was initialized with the
125        /// provided Vault type
126        access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool}
127        /// Composes a Strategy of the given type with the provided funds
128        access(all) fun createStrategy(
129            _ type: Type,
130            uniqueID: DeFiActions.UniqueIdentifier,
131            withFunds: @{FungibleToken.Vault}
132        ): @{Strategy} {
133            pre {
134                self.getSupportedInitializationVaults(forStrategy: type)[withFunds.getType()] == true:
135                "Cannot initialize Strategy \(type.identifier) with Vault \(withFunds.getType().identifier) - unsupported initialization Vault"
136                self.getComposedStrategyTypes()[type] == true:
137                "Strategy \(type.identifier) is unsupported by StrategyComposer \(self.getType().identifier)"
138            }
139        }
140    }
141
142    /// StrategyFactory
143    ///
144    /// This resource enables the management of StrategyComposers and the construction of the Strategies they compose.
145    ///
146    access(all) resource StrategyFactory {
147        /// A mapping of StrategyComposers indexed on the related Strategies they can compose
148        access(self) let composers: @{Type: {StrategyComposer}}
149
150        init() {
151            self.composers <- {}
152        }
153
154        /// Returns the Strategy types that can be produced by this StrategyFactory
155        access(all) view fun getSupportedStrategies(): [Type] {
156            return self.composers.keys
157        }
158        /// Returns the Vaults that can be used to initialize a Strategy of the given Type
159        access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} {
160            return self.composers[forStrategy]?.getSupportedInitializationVaults(forStrategy: forStrategy) ?? {}
161        }
162        /// Returns the Vaults that can be deposited to a Strategy initialized with the provided Type
163        access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool} {
164            return self.composers[forStrategy]
165                ?.getSupportedInstanceVaults(forStrategy: forStrategy, initializedWith: initializedWith)
166                ?? {}
167        }
168        /// Initializes a new Strategy of the given type with the provided Vault, identifying all associated DeFiActions
169        /// components by the provided UniqueIdentifier
170        access(all)
171        fun createStrategy(_ type: Type, uniqueID: DeFiActions.UniqueIdentifier, withFunds: @{FungibleToken.Vault}): @{Strategy} {
172            pre {
173                self.composers[type] != nil: "Strategy \(type.identifier) is unsupported"
174            }
175            post {
176                result.getType() == type:
177                "Invalid Strategy returned - expected \(type.identifier) but returned \(result.getType().identifier)"
178            }
179            return <- self._borrowComposer(forStrategy: type)
180                .createStrategy(type, uniqueID: uniqueID, withFunds: <-withFunds)
181        }
182        /// Sets the provided Strategy and Composer association in the StrategyFactory
183        access(Mutate) fun addStrategyComposer(_ strategy: Type, composer: @{StrategyComposer}) {
184            pre {
185                strategy.isSubtype(of: Type<@{Strategy}>()):
186                "Invalid Strategy Type \(strategy.identifier) - provided Type does not implement the Strategy interface"
187                composer.getComposedStrategyTypes()[strategy] == true:
188                "Strategy \(strategy.identifier) cannot be composed by StrategyComposer \(composer.getType().identifier)"
189            }
190            let old <- self.composers[strategy] <- composer
191            Burner.burn(<-old)
192        }
193        /// Removes the Strategy from this StrategyFactory and returns whether the value existed or not
194        access(Mutate) fun removeStrategy(_ strategy: Type): Bool {
195            if let removed <- self.composers.remove(key: strategy) {
196                Burner.burn(<-removed)
197                return true
198            }
199            return false
200        }
201        /// Returns a reference to the StrategyComposer for the requested Strategy type, reverting if none exists
202        access(self) view fun _borrowComposer(forStrategy: Type): &{StrategyComposer} {
203            return &self.composers[forStrategy] as &{StrategyComposer}?
204                ?? panic("Could not borrow StrategyComposer for Strategy \(forStrategy.identifier)")
205        }
206    }
207
208    /// StrategyComposerIssuer
209    ///
210    /// This resource enables the issuance of StrategyComposers, thus safeguarding the issuance of Strategies which
211    /// may utilize resource consumption (i.e. account storage). Contracts defining Strategies that do not require
212    /// such protections may wish to expose Strategy creation publicly via public Capabilities.
213    access(all) resource interface StrategyComposerIssuer {
214        /// Returns the StrategyComposer types supported by this issuer
215        access(all) view fun getSupportedComposers(): {Type: Bool}
216        /// Returns the requested StrategyComposer. If the requested type is unsupported, a revert should be expected
217        access(all) fun issueComposer(_ type: Type): @{StrategyComposer} {
218            post {
219                result.getType() == type:
220                "Invalid StrategyComposer returned - requested \(type.identifier) but returned \(result.getType().identifier)"
221            }
222        }
223    }
224
225    /// YieldVault
226    ///
227    /// A YieldVault is a resource enabling the management of a composed Strategy
228    ///
229    access(all) resource YieldVault : Burner.Burnable, FungibleToken.Receiver, ViewResolver.Resolver {
230        /// The UniqueIdentifier that identifies all related DeFiActions connectors used in the encapsulated Strategy
231        access(contract) let uniqueID: DeFiActions.UniqueIdentifier
232        /// The type of Vault this YieldVault can receive as a deposit and provides as a withdrawal
233        access(self) let vaultType: Type
234        /// The Strategy granting top-level access to the yield-bearing DeFiActions stack
235        access(self) var strategy: @{Strategy}?
236
237        init(strategyType: Type, withVault: @{FungibleToken.Vault}) {
238            self.uniqueID = DeFiActions.createUniqueIdentifier()
239            self.vaultType = withVault.getType()
240            let _strategy <- FlowYieldVaults.createStrategy(
241                    type: strategyType,
242                    uniqueID: self.uniqueID,
243                    withFunds: <-withVault
244                )
245            assert(_strategy.isSupportedCollateralType(self.vaultType),
246                message: "Vault type \(self.vaultType.identifier) is not supported by Strategy \(strategyType.identifier)")
247            self.strategy <-_strategy
248        }
249
250        /// Returns the YieldVault's ID as defined by it's DeFiActions.UniqueIdentifier.id
251        access(all) view fun id(): UInt64 {
252            return self.uniqueID.id
253        }
254        /// Returns the type identifier of the Vault this YieldVault operates on
255        access(all) view fun getVaultTypeIdentifier(): String {
256            return self.vaultType.identifier
257        }
258        /// Returns the balance of the YieldVault's vaultType available via the encapsulated Strategy
259        access(all) fun getYieldVaultBalance(): UFix64 {
260            return self._borrowStrategy().availableBalance(ofToken: self.vaultType)
261        }
262        /// Burner.Burnable conformance - emits the BurnedYieldVault event when burned
263        access(contract) fun burnCallback() {
264            emit BurnedYieldVault(
265                id: self.uniqueID.id,
266                strategyType: self.getStrategyType(),
267                tokenType: self.getVaultTypeIdentifier(),
268                remainingBalance: self.getYieldVaultBalance(),
269                owner: self.owner?.address
270            )
271            let _strategy <- self.strategy <- nil
272            // Force unwrap to ensure burnCallback is called on the Strategy
273            Burner.burn(<-_strategy!)
274        }
275        /// TODO: FlowYieldVaults specific views
276        access(all) view fun getViews(): [Type] {
277            return []
278        }
279        /// TODO: FlowYieldVaults specific view resolution
280        access(all) fun resolveView(_ view: Type): AnyStruct? {
281            return nil
282        }
283        /// Deposits the provided Vault to the Strategy
284        access(all) fun deposit(from: @{FungibleToken.Vault}) {
285            pre {
286                self.isSupportedVaultType(type: from.getType()):
287                "Deposited vault of type \(from.getType().identifier) is not supported by this YieldVault"
288            }
289            let amount = from.balance
290            emit DepositedToYieldVault(
291                id: self.uniqueID.id,
292                strategyType: self.getStrategyType(),
293                tokenType: from.getType().identifier,
294                amount: from.balance,
295                owner: self.owner?.address,
296                fromUUID: from.uuid
297            )
298            self._borrowStrategy().deposit(from: &from as auth(FungibleToken.Withdraw) &{FungibleToken.Vault})
299            assert(
300                from.balance == 0.0,
301                message: "Deposit amount \(amount) of \(self.vaultType.identifier) could not be deposited to YieldVault \(self.id())"
302            )
303            Burner.burn(<-from)
304        }
305        /// Returns the Vaults types supported by this YieldVault as a mapping associated with their current support status
306        access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
307            return self._borrowStrategy().getSupportedCollateralTypes()
308        }
309        /// Returns whether the given Vault type is supported by this YieldVault
310        access(all) view fun isSupportedVaultType(type: Type): Bool {
311            return self.getSupportedVaultTypes()[type] ?? false
312        }
313        /// Returns the strategy type identifier for this YieldVault
314        access(all) view fun getStrategyType(): String {
315            return self.strategy.getType().identifier
316        }
317        /// Withdraws the requested amount from the Strategy
318        access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
319            post {
320                result.balance == amount:
321                "Invalid Vault balance returned - requested \(amount) but returned \(result.balance)"
322
323                self.vaultType == result.getType():
324                "Invalid Vault returned - expected \(self.vaultType.identifier) but returned \(result.getType().identifier)"
325            }
326            let available = self._borrowStrategy().availableBalance(ofToken: self.vaultType)
327            assert(amount <= available,
328                message: "Requested amount \(amount) is greater than withdrawable balance of \(available)")
329
330            let res <- self._borrowStrategy().withdraw(maxAmount: amount, ofToken: self.vaultType)
331
332            emit WithdrawnFromYieldVault(
333                id: self.uniqueID.id,
334                strategyType: self.getStrategyType(),
335                tokenType: res.getType().identifier,
336                amount: amount,
337                owner: self.owner?.address,
338                toUUID: res.uuid
339            )
340
341            return <- res
342        }
343        /// Returns an authorized reference to the encapsulated Strategy
344        access(self) view fun _borrowStrategy(): auth(FungibleToken.Withdraw) &{Strategy} {
345            return &self.strategy as auth(FungibleToken.Withdraw) &{Strategy}?
346                ?? panic("Unknown error - could not borrow Strategy for YieldVault #\(self.id())")
347        }
348    }
349
350    /// YieldVaultManager
351    ///
352    /// A YieldVaultManager encapsulates nested YieldVault resources. Through a YieldVaultManager, one can create, manage, and close
353    /// out inner YieldVault resources.
354    ///
355    access(all) resource YieldVaultManager : ViewResolver.ResolverCollection {
356        /// The open YieldVaults managed by this YieldVaultManager
357        access(self) let yieldVaults: @{UInt64: YieldVault}
358
359        init() {
360            self.yieldVaults <- {}
361        }
362
363        /// Borrows the unauthorized YieldVault with the given id, returning `nil` if none exists
364        access(all) view fun borrowYieldVault(id: UInt64): &YieldVault? {
365            return &self.yieldVaults[id]
366        }
367        /// Borrows the YieldVault with the given ID as a ViewResolver.Resolver, returning `nil` if none exists
368        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
369            return &self.yieldVaults[id]
370        }
371        /// Returns the YieldVault IDs managed by this YieldVaultManager
372        access(all) view fun getIDs(): [UInt64] {
373            return self.yieldVaults.keys
374        }
375        /// Returns the number of open YieldVaults currently managed by this YieldVaultManager
376        access(all) view fun getNumberOfYieldVaults(): Int {
377            return self.yieldVaults.length
378        }
379        /// Creates a new YieldVault executing the specified Strategy with the provided funds.
380        /// Returns the newly created YieldVault ID.
381        access(all) fun createYieldVault(
382            betaRef: auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge,
383            strategyType: Type,
384            withVault: @{FungibleToken.Vault}
385        ): UInt64 {
386            pre {
387                FlowYieldVaultsClosedBeta.validateBeta(self.owner?.address!, betaRef):
388                "Invalid Beta Ref"
389            }
390            let balance = withVault.balance
391            let type = withVault.getType()
392            let yieldVault <-create YieldVault(strategyType: strategyType, withVault: <-withVault)
393            let newID = yieldVault.uniqueID.id
394
395            emit CreatedYieldVault(
396                id: newID,
397                uuid: yieldVault.uuid,
398                strategyType: strategyType.identifier,
399                tokenType: type.identifier,
400                initialAmount: balance,
401                creator: self.owner?.address
402            )
403
404            self.addYieldVault(betaRef: betaRef, <-yieldVault)
405
406            return newID
407        }
408        /// Adds an open YieldVault to this YieldVaultManager resource. This effectively transfers ownership of the newly added
409        /// YieldVault to the owner of this YieldVaultManager
410        access(all) fun addYieldVault(betaRef: auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge, _ yieldVault: @YieldVault) {
411            pre {
412                self.yieldVaults[yieldVault.uniqueID.id] == nil:
413                "Collision with YieldVault ID \(yieldVault.uniqueID.id) - a YieldVault with this ID already exists"
414
415                FlowYieldVaultsClosedBeta.validateBeta(self.owner?.address!, betaRef):
416                "Invalid Beta Ref"
417            }
418            emit AddedToManager(
419                id: yieldVault.uniqueID.id,
420                strategyType: yieldVault.getStrategyType(),
421                owner: self.owner?.address,
422                managerUUID: self.uuid,
423                tokenType: yieldVault.getVaultTypeIdentifier()
424            )
425            self.yieldVaults[yieldVault.uniqueID.id] <-! yieldVault
426        }
427        /// Deposits additional funds to the specified YieldVault, reverting if none exists with the provided ID
428        access(all) fun depositToYieldVault(betaRef: auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge, _ id: UInt64, from: @{FungibleToken.Vault}) {
429            pre {
430                self.yieldVaults[id] != nil:
431                "No YieldVault with ID \(id) found"
432
433                FlowYieldVaultsClosedBeta.validateBeta(self.owner?.address!, betaRef):
434                "Invalid Beta Ref"
435            }
436            let yieldVault = (&self.yieldVaults[id] as &YieldVault?)!
437            yieldVault.deposit(from: <-from)
438        }
439        access(self) fun _withdrawYieldVault(id: UInt64): @ YieldVault {
440            pre {
441                self.yieldVaults[id] != nil:
442                "No YieldVault with ID \(id) found"
443            }
444            return <- self.yieldVaults.remove(key: id)!
445        }
446        /// Withdraws the specified YieldVault, reverting if none exists with the provided ID
447        access(FungibleToken.Withdraw) fun withdrawYieldVault(betaRef: auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge, id: UInt64): @ YieldVault {
448            pre {
449                self.yieldVaults[id] != nil:
450                "No YieldVault with ID \(id) found"
451
452                FlowYieldVaultsClosedBeta.validateBeta(self.owner?.address!, betaRef):
453                "Invalid Beta Ref"
454            }
455            return <- self._withdrawYieldVault(id: id)
456        }
457        /// Withdraws funds from the specified YieldVault in the given amount. The resulting Vault Type will be whatever
458        /// denomination is supported by the YieldVault, so callers should examine the YieldVault to know the resulting Vault to
459        /// expect
460        access(FungibleToken.Withdraw) fun withdrawFromYieldVault(_ id: UInt64, amount: UFix64): @{FungibleToken.Vault} {
461            pre {
462                self.yieldVaults[id] != nil:
463                "No YieldVault with ID \(id) found"
464            }
465            let yieldVault = (&self.yieldVaults[id] as auth(FungibleToken.Withdraw) &YieldVault?)!
466            return <- yieldVault.withdraw(amount: amount)
467        }
468        /// Withdraws and returns all available funds from the specified YieldVault, destroying the YieldVault and access to any
469        /// Strategy-related wiring with it
470        access(FungibleToken.Withdraw) fun closeYieldVault(_ id: UInt64): @{FungibleToken.Vault} {
471            pre {
472                self.yieldVaults[id] != nil:
473                "No YieldVault with ID \(id) found"
474            }
475
476            let yieldVault <- self._withdrawYieldVault(id: id)
477            let res <- yieldVault.withdraw(amount: yieldVault.getYieldVaultBalance())
478            Burner.burn(<-yieldVault)
479            return <-res
480        }
481    }
482
483    /* --- PUBLIC METHODS --- */
484
485    /// Returns the Types of Strategies that can be used in YieldVaults
486    access(all) view fun getSupportedStrategies(): [Type] {
487        return self._borrowFactory().getSupportedStrategies()
488    }
489    /// Returns the Vault types which can be used to initialize a given Strategy
490    access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} {
491        return self._borrowFactory().getSupportedInitializationVaults(forStrategy: forStrategy)
492    }
493    /// Returns the Vault types which can be deposited to a given Strategy instance if it was initialized with the
494    /// provided Vault type
495    access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool} {
496        return self._borrowFactory().getSupportedInstanceVaults(forStrategy: forStrategy, initializedWith: initializedWith)
497    }
498    /// Creates a Strategy of the requested Type using the provided Vault as an initial deposit
499    access(all) fun createStrategy(type: Type, uniqueID: DeFiActions.UniqueIdentifier, withFunds: @{FungibleToken.Vault}): @{Strategy} {
500        return <- self._borrowFactory().createStrategy(type, uniqueID: uniqueID, withFunds: <-withFunds)
501    }
502    /// Creates a YieldVaultManager used to create and manage YieldVaults
503    access(all) fun createYieldVaultManager(betaRef: auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge): @ YieldVaultManager {
504        return <-create YieldVaultManager()
505    }
506    /// Creates a StrategyFactory resource
507    access(all) fun createStrategyFactory(): @StrategyFactory {
508        return <- create StrategyFactory()
509    }
510
511    /* --- INTERNAL METHODS --- */
512
513    /// Returns a reference to the StrategyFactory stored in this contract's account storage
514    access(self) view fun _borrowFactory(): &StrategyFactory {
515        return self.account.storage.borrow<&StrategyFactory>(from: self.FactoryStoragePath)
516            ?? panic("Could not borrow reference to StrategyFactory from \(self.FactoryStoragePath)")
517    }
518
519    init() {
520        var pathIdentifier = "FlowYieldVaultsYieldVaultManager_\(self.account.address)"
521        self.YieldVaultManagerStoragePath = StoragePath(identifier: pathIdentifier)!
522        self.YieldVaultManagerPublicPath = PublicPath(identifier: pathIdentifier)!
523
524        pathIdentifier = "FlowYieldVaultsStrategyFactory_\(self.account.address)"
525        self.FactoryStoragePath = StoragePath(identifier: pathIdentifier)!
526        self.FactoryPublicPath = PublicPath(identifier: pathIdentifier)!
527
528        // configure a StrategyFactory in storage and publish a public Capability
529        self.account.storage.save(<-create StrategyFactory(), to: self.FactoryStoragePath)
530        let cap = self.account.capabilities.storage.issue<&StrategyFactory>(self.FactoryStoragePath)
531        self.account.capabilities.publish(cap, at: self.FactoryPublicPath)
532    }
533}
534