Smart Contract

FlowVaultsConnector

A.b2b7a4c7033eaa24.FlowVaultsConnector

Valid From

134,199,131

Deployed

6d ago
Feb 22, 2026, 02:18:54 AM UTC

Dependents

0 imports
1/*
2FlowVaultsConnector - Mainnet Flow Vaults Integration
3
4This connector enables PrizeSavings to deposit funds into Flow Vaults Tides (yield-bearing strategies)
5and implements DeFiActions.Sink and DeFiActions.Source interfaces.
6
7Flow Vaults Contract: mainnet://b1d63873c3cc9f79.FlowVaults
8*/
9
10import FungibleToken from 0xf233dcee88fe0abe
11import FlowVaults from 0xb1d63873c3cc9f79
12import FlowVaultsClosedBeta from 0xb1d63873c3cc9f79
13import DeFiActions from 0x92195d814edf9cb0
14
15access(all) contract FlowVaultsConnector {
16    
17    // Storage paths
18    access(all) let ManagerStoragePath: StoragePath
19    access(all) let ManagerPublicPath: PublicPath
20    
21    // Events
22    access(all) event ConnectorCreated(managerAddress: Address, strategyType: String, vaultType: String)
23    access(all) event DepositedToTide(tideID: UInt64, amount: UFix64, vaultType: String)
24    access(all) event WithdrawnFromTide(tideID: UInt64, amount: UFix64, vaultType: String)
25    access(all) event TideCreated(tideID: UInt64, strategyType: String, initialAmount: UFix64)
26    
27    /// TideManager Resource
28    /// Manages the actual Tide in Flow Vaults with beta badge authentication
29    access(all) resource TideManager {
30        access(self) let tideManagerCap: Capability<auth(FungibleToken.Withdraw) &FlowVaults.TideManager>
31        access(self) let betaBadgeCap: Capability<auth(FlowVaultsClosedBeta.Beta) &FlowVaultsClosedBeta.BetaBadge>
32        access(self) var tideID: UInt64?
33        access(all) let vaultType: Type
34        access(all) let strategyType: Type
35        
36        init(
37            tideManagerCap: Capability<auth(FungibleToken.Withdraw) &FlowVaults.TideManager>,
38            betaBadgeCap: Capability<auth(FlowVaultsClosedBeta.Beta) &FlowVaultsClosedBeta.BetaBadge>,
39            vaultType: Type,
40            strategyType: Type
41        ) {
42            pre {
43                tideManagerCap.check(): "Invalid TideManager capability"
44                betaBadgeCap.check(): "Invalid Beta badge capability"
45            }
46            
47            self.tideManagerCap = tideManagerCap
48            self.betaBadgeCap = betaBadgeCap
49            self.vaultType = vaultType
50            self.strategyType = strategyType
51            self.tideID = nil
52        }
53        
54        access(all) fun depositToTide(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) {
55            pre {
56                from.getType() == self.vaultType: "Vault type mismatch"
57                from.balance > 0.0: "Cannot deposit zero balance"
58            }
59            
60            let amount = from.balance
61            let tideManager = self.tideManagerCap.borrow()
62                ?? panic("Cannot borrow TideManager")
63            let betaBadge = self.betaBadgeCap.borrow()
64                ?? panic("Cannot borrow Beta badge")
65            
66            // If we don't have a Tide yet, create one
67            if self.tideID == nil {
68                let initialVault <- from.withdraw(amount: amount)
69                
70                tideManager.createTide(
71                    betaRef: betaBadge,
72                    strategyType: self.strategyType,
73                    withVault: <- initialVault
74                )
75                
76                let tideIDs = tideManager.getIDs()
77                assert(tideIDs.length > 0, message: "Failed to create Tide")
78                self.tideID = tideIDs[tideIDs.length - 1]
79                
80                emit TideCreated(
81                    tideID: self.tideID!,
82                    strategyType: self.strategyType.identifier,
83                    initialAmount: amount
84                )
85                
86                emit DepositedToTide(
87                    tideID: self.tideID!,
88                    amount: amount,
89                    vaultType: self.vaultType.identifier
90                )
91            } else {
92                let depositVault <- from.withdraw(amount: amount)
93                
94                tideManager.depositToTide(
95                    betaRef: betaBadge,
96                    self.tideID!,
97                    from: <- depositVault
98                )
99                
100                emit DepositedToTide(
101                    tideID: self.tideID!,
102                    amount: amount,
103                    vaultType: self.vaultType.identifier
104                )
105            }
106        }
107        
108        access(all) fun getTideBalance(): UFix64 {
109            if self.tideID == nil {
110                return 0.0
111            }
112            
113            let tideManager = self.tideManagerCap.borrow()
114                ?? panic("Cannot borrow TideManager")
115            
116            let tideRef = tideManager.borrowTide(id: self.tideID!)
117            if tideRef == nil {
118                return 0.0
119            }
120            
121            return tideRef!.getTideBalance()
122        }
123        
124        access(all) fun withdrawFromTide(maxAmount: UFix64): @{FungibleToken.Vault} {
125            pre {
126                self.tideID != nil: "No Tide initialized"
127                maxAmount > 0.0: "Cannot withdraw zero amount"
128            }
129            
130            let tideManager = self.tideManagerCap.borrow()
131                ?? panic("Cannot borrow TideManager")
132            
133            let available = self.getTideBalance()
134            let withdrawAmount = maxAmount < available ? maxAmount : available
135            
136            assert(withdrawAmount > 0.0, message: "Insufficient balance in Tide")
137            
138            let vault <- tideManager.withdrawFromTide(self.tideID!, amount: withdrawAmount)
139            
140            emit WithdrawnFromTide(
141                tideID: self.tideID!,
142                amount: withdrawAmount,
143                vaultType: vault.getType().identifier
144            )
145            
146            return <- vault
147        }
148    }
149    
150    /// Connector Struct
151    /// Implements DeFiActions.Sink and DeFiActions.Source
152    /// References a stored TideManager resource
153    access(all) struct Connector: DeFiActions.Sink, DeFiActions.Source {
154        access(all) let managerAddress: Address
155        access(contract) var uniqueID: DeFiActions.UniqueIdentifier?
156        access(all) let vaultType: Type
157        
158        init(managerAddress: Address, vaultType: Type) {
159            self.managerAddress = managerAddress
160            self.vaultType = vaultType
161            self.uniqueID = nil
162        }
163        
164        /// DeFiActions.Sink Implementation
165        access(all) fun depositCapacity(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) {
166            let managerAccount = getAccount(self.managerAddress)
167            let managerRef = managerAccount.capabilities.borrow<&TideManager>(
168                FlowVaultsConnector.ManagerPublicPath
169            ) ?? panic("Cannot borrow TideManager from address")
170            
171            managerRef.depositToTide(from: from)
172        }
173        
174        access(all) view fun getSinkType(): Type {
175            return self.vaultType
176        }
177        
178        access(all) view fun minimumCapacity(): UFix64 {
179            return 0.0
180        }
181        
182        /// DeFiActions.Source Implementation
183        access(all) fun minimumAvailable(): UFix64 {
184            let managerAccount = getAccount(self.managerAddress)
185            if let managerRef = managerAccount.capabilities.borrow<&TideManager>(
186                FlowVaultsConnector.ManagerPublicPath
187            ) {
188                return managerRef.getTideBalance()
189            }
190            return 0.0
191        }
192        
193        access(FungibleToken.Withdraw) fun withdrawAvailable(maxAmount: UFix64): @{FungibleToken.Vault} {
194            let managerAccount = getAccount(self.managerAddress)
195            let managerRef = managerAccount.capabilities.borrow<&TideManager>(
196                FlowVaultsConnector.ManagerPublicPath
197            ) ?? panic("Cannot borrow TideManager from address")
198            
199            return <- managerRef.withdrawFromTide(maxAmount: maxAmount)
200        }
201        
202        access(all) view fun getSourceType(): Type {
203            return self.vaultType
204        }
205        
206        /// DeFiActions Component Info
207        access(all) fun getComponentInfo(): DeFiActions.ComponentInfo {
208            return DeFiActions.ComponentInfo(
209                type: self.getType(),
210                id: self.uniqueID?.id,
211                innerComponents: []
212            )
213        }
214        
215        access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? {
216            return self.uniqueID
217        }
218        
219        access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) {
220            self.uniqueID = id
221        }
222    }
223    
224    /// Create a new TideManager and store it
225    /// Returns a Connector struct that references it
226    access(all) fun createConnectorAndManager(
227        account: auth(Storage, Capabilities) &Account,
228        tideManagerCap: Capability<auth(FungibleToken.Withdraw) &FlowVaults.TideManager>,
229        betaBadgeCap: Capability<auth(FlowVaultsClosedBeta.Beta) &FlowVaultsClosedBeta.BetaBadge>,
230        vaultType: Type,
231        strategyType: Type
232    ): Connector {
233        // Validate that the strategy supports the vault type
234        let supportedVaults = FlowVaults.getSupportedInitializationVaults(forStrategy: strategyType)
235        assert(
236            supportedVaults[vaultType] == true,
237            message: "Strategy does not support vault type"
238        )
239        
240        // Create and store the TideManager resource
241        let manager <- create TideManager(
242            tideManagerCap: tideManagerCap,
243            betaBadgeCap: betaBadgeCap,
244            vaultType: vaultType,
245            strategyType: strategyType
246        )
247        
248        account.storage.save(<-manager, to: self.ManagerStoragePath)
249        
250        // Create public capability for the manager
251        let managerCap = account.capabilities.storage.issue<&TideManager>(self.ManagerStoragePath)
252        account.capabilities.publish(managerCap, at: self.ManagerPublicPath)
253        
254        emit ConnectorCreated(
255            managerAddress: account.address,
256            strategyType: strategyType.identifier,
257            vaultType: vaultType.identifier
258        )
259        
260        // Return the struct connector that references this manager
261        return Connector(
262            managerAddress: account.address,
263            vaultType: vaultType
264        )
265    }
266    
267    init() {
268        let identifier = "flowVaultsTideManager_\(self.account.address)"
269        self.ManagerStoragePath = StoragePath(identifier: identifier)!
270        self.ManagerPublicPath = PublicPath(identifier: identifier)!
271    }
272}
273