@flowtyio/flow-contracts 0.1.0-beta.9 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/contracts/FungibleTokenSwitchboard.cdc +360 -0
  3. package/contracts/MetadataViews.cdc +79 -6
  4. package/contracts/NonFungibleToken.cdc +17 -10
  5. package/contracts/capability-cache/CapabilityCache.cdc +97 -0
  6. package/contracts/dapper/TopShot.cdc +323 -259
  7. package/contracts/dapper/TopShotLocking.cdc +41 -15
  8. package/contracts/dapper/offers/DapperOffersV2.cdc +46 -43
  9. package/contracts/dapper/offers/OffersV2.cdc +40 -56
  10. package/contracts/dapper/offers/Resolver.cdc +20 -13
  11. package/contracts/emerald-city/FLOAT.cdc +259 -254
  12. package/contracts/evm/CrossVMNFT.cdc +50 -0
  13. package/contracts/evm/EVM.cdc +851 -0
  14. package/contracts/evm/FlowEVMBridgeConfig.cdc +454 -0
  15. package/contracts/evm/FlowEVMBridgeHandlerInterfaces.cdc +163 -0
  16. package/contracts/evm/FlowEVMBridgeHandlers.cdc +230 -0
  17. package/contracts/evm/FlowEVMBridgeUtils.cdc +1303 -0
  18. package/contracts/evm/IBridgePermissions.cdc +19 -0
  19. package/contracts/evm/ICrossVM.cdc +12 -0
  20. package/contracts/evm/ICrossVMAsset.cdc +19 -0
  21. package/contracts/evm/Serialize.cdc +141 -0
  22. package/contracts/evm/SerializeMetadata.cdc +221 -0
  23. package/contracts/example/ExampleNFT.cdc +2 -2
  24. package/contracts/find/FindViews.cdc +357 -353
  25. package/contracts/flow-utils/ScopedFTProviders.cdc +5 -2
  26. package/contracts/flow-utils/ScopedNFTProviders.cdc +6 -2
  27. package/contracts/flowty-drops/ContractManager.cdc +73 -0
  28. package/contracts/flowty-drops/DropFactory.cdc +75 -0
  29. package/contracts/flowty-drops/DropTypes.cdc +282 -0
  30. package/contracts/flowty-drops/FlowtyActiveCheckers.cdc +113 -0
  31. package/contracts/flowty-drops/FlowtyAddressVerifiers.cdc +64 -0
  32. package/contracts/flowty-drops/FlowtyDrops.cdc +461 -0
  33. package/contracts/flowty-drops/FlowtyPricers.cdc +48 -0
  34. package/contracts/flowty-drops/initializers/ContractBorrower.cdc +14 -0
  35. package/contracts/flowty-drops/initializers/ContractInitializer.cdc +7 -0
  36. package/contracts/flowty-drops/initializers/OpenEditionInitializer.cdc +57 -0
  37. package/contracts/flowty-drops/nft/BaseCollection.cdc +97 -0
  38. package/contracts/flowty-drops/nft/BaseNFT.cdc +107 -0
  39. package/contracts/flowty-drops/nft/ContractFactory.cdc +13 -0
  40. package/contracts/flowty-drops/nft/ContractFactoryTemplate.cdc +48 -0
  41. package/contracts/flowty-drops/nft/NFTMetadata.cdc +140 -0
  42. package/contracts/flowty-drops/nft/OpenEditionNFT.cdc +42 -0
  43. package/contracts/flowty-drops/nft/OpenEditionTemplate.cdc +54 -0
  44. package/contracts/flowty-drops/nft/UniversalCollection.cdc +29 -0
  45. package/contracts/fungible-token-router/FungibleTokenRouter.cdc +103 -0
  46. package/contracts/hybrid-custody/CapabilityDelegator.cdc +28 -26
  47. package/contracts/hybrid-custody/CapabilityFactory.cdc +20 -18
  48. package/contracts/hybrid-custody/CapabilityFilter.cdc +41 -24
  49. package/contracts/hybrid-custody/HybridCustody.cdc +303 -242
  50. package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
  51. package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
  52. package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
  53. package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
  54. package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
  55. package/contracts/hybrid-custody/factories/FTVaultFactory.cdc +46 -0
  56. package/contracts/hybrid-custody/factories/NFTCollectionFactory.cdc +45 -0
  57. package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
  58. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionFactory.cdc +22 -0
  59. package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
  60. package/contracts/lost-and-found/LostAndFound.cdc +21 -17
  61. package/contracts/tokens/USDCFlow.cdc +232 -0
  62. package/flow.json +278 -7
  63. package/package.json +1 -1
  64. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +0 -10
@@ -0,0 +1,454 @@
1
+ import "EVM"
2
+
3
+ import "FlowToken"
4
+
5
+ import "FlowEVMBridgeHandlerInterfaces"
6
+
7
+ /// This contract is used to store configuration information shared by FlowEVMBridge contracts
8
+ ///
9
+ access(all)
10
+ contract FlowEVMBridgeConfig {
11
+
12
+ /******************
13
+ Entitlements
14
+ *******************/
15
+
16
+ access(all) entitlement Gas
17
+ access(all) entitlement Fee
18
+ access(all) entitlement Pause
19
+
20
+ /*************
21
+ Fields
22
+ **************/
23
+
24
+ /// Amount of FLOW paid to onboard a Type or EVMAddress to the bridge
25
+ access(all)
26
+ var onboardFee: UFix64
27
+ /// Flat rate fee for all bridge requests
28
+ access(all)
29
+ var baseFee: UFix64
30
+ /// Default ERC20.decimals() value
31
+ access(all)
32
+ let defaultDecimals: UInt8
33
+ /// The gas limit for all EVM calls related to bridge operations
34
+ access(all)
35
+ var gasLimit: UInt64
36
+ /// Flag enabling pausing of bridge operations
37
+ access(self)
38
+ var paused: Bool
39
+ /// Mapping of Type to its associated EVMAddress. The contained struct values also store the operational status of
40
+ /// the association, allowing for pausing of operations by Type
41
+ access(self) let registeredTypes: {Type: TypeEVMAssociation}
42
+ /// Reverse mapping of registeredTypes. Note the EVMAddress is stored as a hex string since the EVMAddress type
43
+ /// as of contract development is not a hashable or equatable type and making it so is not supported by Cadence
44
+ access(self)
45
+ let evmAddressHexToType: {String: Type}
46
+ /// Mapping of Type to its associated EVMAddress as relevant to the bridge
47
+ access(self)
48
+ let typeToTokenHandlers: @{Type: {FlowEVMBridgeHandlerInterfaces.TokenHandler}}
49
+
50
+ /********************
51
+ Path Constants
52
+ *********************/
53
+
54
+ /// StoragePath where bridge Cadence Owned Account is stored
55
+ access(all)
56
+ let coaStoragePath: StoragePath
57
+ /// StoragePath where bridge config Admin is stored
58
+ access(all)
59
+ let adminStoragePath: StoragePath
60
+ /// PublicPath where a public Capability on the bridge config Admin is exposed
61
+ access(all)
62
+ let adminPublicPath: PublicPath
63
+ /// StoragePath to store the Provider capability used as a bridge fee Provider
64
+ access(all)
65
+ let providerCapabilityStoragePath: StoragePath
66
+
67
+ /*************
68
+ Events
69
+ **************/
70
+
71
+ /// Emitted whenever the onboarding fee is updated
72
+ ///
73
+ access(all)
74
+ event BridgeFeeUpdated(old: UFix64, new: UFix64, isOnboarding: Bool)
75
+ /// Emitted whenever a TokenHandler is configured
76
+ ///
77
+ access(all)
78
+ event HandlerConfigured(targetType: String, targetEVMAddress: String?, isEnabled: Bool)
79
+ /// Emitted whenever the bridge is paused or unpaused globally - true for paused, false for unpaused
80
+ ///
81
+ access(all)
82
+ event BridgePauseStatusUpdated(paused: Bool)
83
+ /// Emitted whenever a specific asset is paused or unpaused - true for paused, false for unpaused
84
+ ///
85
+ access(all)
86
+ event AssetPauseStatusUpdated(paused: Bool, type: String, evmAddress: String)
87
+ /// Emitted whenever an association is updated
88
+ ///
89
+ access(all)
90
+ event AssociationUpdated(type: String, evmAddress: String)
91
+
92
+ /*************
93
+ Getters
94
+ *************/
95
+
96
+ /// Returns whether all bridge operations are currently paused or active
97
+ ///
98
+ access(all)
99
+ view fun isPaused(): Bool {
100
+ return self.paused
101
+ }
102
+
103
+ /// Returns whether operations for a given Type are paused. A return value of nil indicates the Type is not yet
104
+ /// onboarded to the bridge.
105
+ ///
106
+ access(all)
107
+ view fun isTypePaused(_ type: Type): Bool? {
108
+ if !self.typeHasTokenHandler(type) {
109
+ // Most all assets will fall into this block - check if the asset is onboarded and paused
110
+ return self.registeredTypes[type]?.isPaused ?? nil
111
+ }
112
+ // If the asset has a TokenHandler, return true if either the Handler is paused or the type is paused
113
+ return self.borrowTokenHandler(type)!.isEnabled() == false || self.registeredTypes[type]?.isPaused == true
114
+ }
115
+
116
+ /// Retrieves the EVMAddress associated with a given Type if it has been onboarded to the bridge
117
+ ///
118
+ access(all)
119
+ view fun getEVMAddressAssociated(with type: Type): EVM.EVMAddress? {
120
+ return self.registeredTypes[type]?.evmAddress
121
+ }
122
+
123
+ /// Retrieves the type associated with a given EVMAddress if it has been onboarded to the bridge
124
+ ///
125
+ access(all)
126
+ view fun getTypeAssociated(with evmAddress: EVM.EVMAddress): Type? {
127
+ let evmAddressHex = evmAddress.toString()
128
+ return self.evmAddressHexToType[evmAddressHex]
129
+ }
130
+
131
+ /****************************
132
+ Bridge Account Methods
133
+ ****************************/
134
+
135
+ /// Enables bridge contracts to add new associations between types and EVM addresses
136
+ ///
137
+ access(account)
138
+ fun associateType(_ type: Type, with evmAddress: EVM.EVMAddress) {
139
+ pre {
140
+ self.getEVMAddressAssociated(with: type) == nil: "Type already associated with an EVMAddress"
141
+ self.getTypeAssociated(with: evmAddress) == nil: "EVMAddress already associated with a Type"
142
+ }
143
+ self.registeredTypes[type] = TypeEVMAssociation(associated: evmAddress)
144
+ let evmAddressHex = evmAddress.toString()
145
+ self.evmAddressHexToType[evmAddressHex] = type
146
+
147
+ emit AssociationUpdated(type: type.identifier, evmAddress: evmAddressHex)
148
+ }
149
+
150
+ /// Returns whether the given Type has a TokenHandler configured
151
+ ///
152
+ access(account)
153
+ view fun typeHasTokenHandler(_ type: Type): Bool {
154
+ return self.typeToTokenHandlers[type] != nil
155
+ }
156
+
157
+ /// Returns whether the given EVMAddress has a TokenHandler configured
158
+ ///
159
+ access(account)
160
+ view fun evmAddressHasTokenHandler(_ evmAddress: EVM.EVMAddress): Bool {
161
+ let associatedType = self.getTypeAssociated(with: evmAddress)
162
+ return associatedType != nil ? self.typeHasTokenHandler(associatedType!) : false
163
+ }
164
+
165
+ /// Adds a TokenHandler to the bridge configuration
166
+ ///
167
+ access(account)
168
+ fun addTokenHandler(_ handler: @{FlowEVMBridgeHandlerInterfaces.TokenHandler}) {
169
+ pre {
170
+ handler.getTargetType() != nil: "Cannot configure Handler without a target Cadence Type set"
171
+ self.getEVMAddressAssociated(with: handler.getTargetType()!) == nil:
172
+ "Cannot configure Handler for Type that has already been onboarded to the bridge"
173
+ self.borrowTokenHandler(handler.getTargetType()!) == nil:
174
+ "Cannot configure Handler for Type that already has a Handler configured"
175
+ }
176
+ let type = handler.getTargetType()!
177
+ var targetEVMAddressHex: String? = nil
178
+ if let targetEVMAddress = handler.getTargetEVMAddress() {
179
+ targetEVMAddressHex = targetEVMAddress.toString()
180
+
181
+ let associatedType = self.getTypeAssociated(with: targetEVMAddress)
182
+ assert(
183
+ associatedType == nil,
184
+ message: "Handler target EVMAddress is already associated with a different Type"
185
+ )
186
+ self.associateType(type, with: targetEVMAddress)
187
+ }
188
+
189
+ emit HandlerConfigured(
190
+ targetType: type.identifier,
191
+ targetEVMAddress: targetEVMAddressHex,
192
+ isEnabled: handler.isEnabled()
193
+ )
194
+
195
+ self.typeToTokenHandlers[type] <-! handler
196
+ }
197
+
198
+ /// Returns an unentitled reference to the TokenHandler associated with the given Type
199
+ ///
200
+ access(account)
201
+ view fun borrowTokenHandler(
202
+ _ type: Type
203
+ ): &{FlowEVMBridgeHandlerInterfaces.TokenHandler}? {
204
+ return &self.typeToTokenHandlers[type]
205
+ }
206
+
207
+ /// Returns an entitled reference to the TokenHandler associated with the given Type
208
+ ///
209
+ access(self)
210
+ view fun borrowTokenHandlerAdmin(
211
+ _ type: Type
212
+ ): auth(FlowEVMBridgeHandlerInterfaces.Admin) &{FlowEVMBridgeHandlerInterfaces.TokenHandler}? {
213
+ return &self.typeToTokenHandlers[type]
214
+ }
215
+
216
+ /*****************
217
+ Constructs
218
+ *****************/
219
+
220
+ /// Entry in the registeredTypes mapping, associating a Type with an EVMAddress and its operational status. Since
221
+ /// the registeredTypes mapping is indexed on Type, this struct does not additionally store the Type to reduce
222
+ /// redundant storage.
223
+ ///
224
+ access(all) struct TypeEVMAssociation {
225
+ /// The EVMAddress associated with the Type
226
+ access(all) let evmAddress: EVM.EVMAddress
227
+ /// Flag indicating whether operations for the associated Type are paused
228
+ access(all) var isPaused: Bool
229
+
230
+ init(associated evmAddress: EVM.EVMAddress) {
231
+ self.evmAddress = evmAddress
232
+ self.isPaused = false
233
+ }
234
+
235
+ /// Pauses operations for this association
236
+ ///
237
+ access(contract) fun pause() {
238
+ self.isPaused = true
239
+ }
240
+
241
+ /// Unpauses operations for this association
242
+ ///
243
+ access(contract) fun unpause() {
244
+ self.isPaused = false
245
+ }
246
+ }
247
+
248
+ /*****************
249
+ Config Admin
250
+ *****************/
251
+
252
+ /// Admin resource enables updates to the bridge fees
253
+ ///
254
+ access(all)
255
+ resource Admin {
256
+
257
+ /// Sets the TokenMinter for the given Type. If a TokenHandler does not exist for the given Type, the operation
258
+ /// reverts. The provided minter must be of the expected type for the TokenHandler and the handler cannot have
259
+ /// a minter already set.
260
+ ///
261
+ /// @param targetType: Cadence type indexing the relevant TokenHandler
262
+ /// @param minter: TokenMinter minter to set for the TokenHandler
263
+ ///
264
+ access(all)
265
+ fun setTokenHandlerMinter(targetType: Type, minter: @{FlowEVMBridgeHandlerInterfaces.TokenMinter}) {
266
+ pre {
267
+ FlowEVMBridgeConfig.typeHasTokenHandler(targetType):
268
+ "Cannot set minter for Type that does not have a TokenHandler configured"
269
+ FlowEVMBridgeConfig.borrowTokenHandlerAdmin(targetType) != nil:
270
+ "No handler found for target Type"
271
+ FlowEVMBridgeConfig.borrowTokenHandlerAdmin(targetType)!.getExpectedMinterType() == minter.getType():
272
+ "Invalid minter type"
273
+ }
274
+ FlowEVMBridgeConfig.borrowTokenHandlerAdmin(targetType)!.setMinter(<-minter)
275
+ }
276
+
277
+ /// Sets the gas limit for all EVM calls related to bridge operations
278
+ ///
279
+ /// @param lim the new gas limit
280
+ ///
281
+ access(Gas)
282
+ fun setGasLimit(_ limit: UInt64) {
283
+ FlowEVMBridgeConfig.gasLimit = limit
284
+ }
285
+
286
+ /// Updates the onboarding fee
287
+ ///
288
+ /// @param new: UFix64 - new onboarding fee
289
+ ///
290
+ /// @emits BridgeFeeUpdated with the old and new rates and isOnboarding set to true
291
+ ///
292
+ access(Fee)
293
+ fun updateOnboardingFee(_ new: UFix64) {
294
+ emit BridgeFeeUpdated(old: FlowEVMBridgeConfig.onboardFee, new: new, isOnboarding: true)
295
+ FlowEVMBridgeConfig.onboardFee = new
296
+ }
297
+
298
+ /// Updates the base fee
299
+ ///
300
+ /// @param new: UFix64 - new base fee
301
+ ///
302
+ /// @emits BridgeFeeUpdated with the old and new rates and isOnboarding set to false
303
+ ///
304
+ access(Fee)
305
+ fun updateBaseFee(_ new: UFix64) {
306
+ emit BridgeFeeUpdated(old: FlowEVMBridgeConfig.baseFee, new: new, isOnboarding: false)
307
+ FlowEVMBridgeConfig.baseFee = new
308
+ }
309
+
310
+ /// Pauses the bridge, preventing all bridge operations
311
+ ///
312
+ access(Pause)
313
+ fun pauseBridge() {
314
+ if FlowEVMBridgeConfig.isPaused() {
315
+ return
316
+ }
317
+ FlowEVMBridgeConfig.paused = true
318
+ emit BridgePauseStatusUpdated(paused: true)
319
+ }
320
+
321
+ /// Unpauses the bridge, allowing bridge operations to resume
322
+ ///
323
+ access(Pause)
324
+ fun unpauseBridge() {
325
+ if !FlowEVMBridgeConfig.isPaused() {
326
+ return
327
+ }
328
+ FlowEVMBridgeConfig.paused = false
329
+ emit BridgePauseStatusUpdated(paused: false)
330
+ }
331
+
332
+ /// Pauses all operations for a given asset type
333
+ ///
334
+ access(Pause)
335
+ fun pauseType(_ type: Type) {
336
+ let association = &FlowEVMBridgeConfig.registeredTypes[type] as &TypeEVMAssociation?
337
+ ?? panic("Type not associated with an EVM Address")
338
+
339
+ if association.isPaused {
340
+ return
341
+ }
342
+
343
+ association.pause()
344
+
345
+ let evmAddress = association.evmAddress.toString()
346
+ emit AssetPauseStatusUpdated(paused: true, type: type.identifier, evmAddress: evmAddress)
347
+ }
348
+
349
+ /// Unpauses all operations for a given asset type
350
+ ///
351
+ access(Pause)
352
+ fun unpauseType(_ type: Type) {
353
+ let association = &FlowEVMBridgeConfig.registeredTypes[type] as &TypeEVMAssociation?
354
+ ?? panic("Type not associated with an EVM Address")
355
+
356
+ if !association.isPaused {
357
+ return
358
+ }
359
+
360
+ association.unpause()
361
+ let evmAddress = association.evmAddress.toString()
362
+ emit AssetPauseStatusUpdated(paused: false, type: type.identifier, evmAddress: evmAddress)
363
+ }
364
+
365
+ /// Sets the target EVM contract address on the handler for a given Type, associating the Cadence type with the
366
+ /// provided EVM address. If a TokenHandler does not exist for the given Type, the operation reverts.
367
+ ///
368
+ /// @param targetType: Cadence type to associate with the target EVM address
369
+ /// @param targetEVMAddress: target EVM address to associate with the Cadence type
370
+ ///
371
+ /// @emits HandlerConfigured with the target Type, target EVM address, and whether the handler is enabled
372
+ ///
373
+ access(FlowEVMBridgeHandlerInterfaces.Admin)
374
+ fun setHandlerTargetEVMAddress(targetType: Type, targetEVMAddress: EVM.EVMAddress) {
375
+ pre {
376
+ FlowEVMBridgeConfig.getEVMAddressAssociated(with: targetType) == nil:
377
+ "Type already associated with an EVM Address"
378
+ FlowEVMBridgeConfig.getTypeAssociated(with: targetEVMAddress) == nil:
379
+ "EVM Address already associated with another Type"
380
+ }
381
+ let handler = FlowEVMBridgeConfig.borrowTokenHandlerAdmin(targetType)
382
+ ?? panic("No handler found for target Type")
383
+ handler.setTargetEVMAddress(targetEVMAddress)
384
+
385
+ // Get the EVM address currently associated with the target Type. If the association does not exist or the
386
+ // EVM address is different, update the association
387
+ FlowEVMBridgeConfig.associateType(targetType, with: targetEVMAddress)
388
+ assert(
389
+ FlowEVMBridgeConfig.getEVMAddressAssociated(with: targetType)!.equals(targetEVMAddress),
390
+ message: "Problem associating target Type and target EVM Address"
391
+ )
392
+
393
+ emit HandlerConfigured(
394
+ targetType: targetType.identifier,
395
+ targetEVMAddress: targetEVMAddress.toString(),
396
+ isEnabled: handler.isEnabled()
397
+ )
398
+ }
399
+
400
+ /// Enables the TokenHandler for the given Type. If a TokenHandler does not exist for the given Type, the
401
+ /// operation reverts.
402
+ ///
403
+ /// @param targetType: Cadence type indexing the relevant TokenHandler
404
+ ///
405
+ /// @emits HandlerConfigured with the target Type, target EVM address, and whether the handler is enabled
406
+ ///
407
+ access(FlowEVMBridgeHandlerInterfaces.Admin)
408
+ fun enableHandler(targetType: Type) {
409
+ let handler = FlowEVMBridgeConfig.borrowTokenHandlerAdmin(targetType)
410
+ ?? panic("No handler found for target Type")
411
+ handler.enableBridging()
412
+
413
+ let targetEVMAddressHex = handler.getTargetEVMAddress()?.toString()
414
+ ?? panic("Handler cannot be enabled without a target EVM Address")
415
+
416
+ emit HandlerConfigured(
417
+ targetType: handler.getTargetType()!.identifier,
418
+ targetEVMAddress: targetEVMAddressHex,
419
+ isEnabled: handler.isEnabled()
420
+ )
421
+ }
422
+ }
423
+
424
+ init() {
425
+ self.onboardFee = 0.0
426
+ self.baseFee = 0.0
427
+ self.defaultDecimals = 18
428
+ self.gasLimit = 15_000_000
429
+ self.paused = true
430
+
431
+ // Although $FLOW does not have ERC20 address, we associate the the Vault with the EVM address from which
432
+ // EVM transfers originate
433
+ // See FLIP #223 - https://github.com/onflow/flips/pull/225
434
+ let flowOriginationAddress = EVM.EVMAddress(
435
+ bytes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
436
+ )
437
+ let flowVaultType = Type<@FlowToken.Vault>()
438
+ let flowOriginationAddressHex = flowOriginationAddress.toString()
439
+ self.registeredTypes = { flowVaultType: TypeEVMAssociation(associated: flowOriginationAddress) }
440
+ self.evmAddressHexToType = { flowOriginationAddressHex: flowVaultType }
441
+
442
+ self.typeToTokenHandlers <- {}
443
+
444
+ self.adminStoragePath = /storage/flowEVMBridgeConfigAdmin
445
+ self.adminPublicPath = /public/flowEVMBridgeConfigAdmin
446
+ self.coaStoragePath = /storage/evm
447
+ self.providerCapabilityStoragePath = /storage/bridgeFlowVaultProvider
448
+
449
+ // Create & save Admin, issuing a public unentitled Admin Capability
450
+ self.account.storage.save(<-create Admin(), to: self.adminStoragePath)
451
+ let adminCap = self.account.capabilities.storage.issue<&Admin>(self.adminStoragePath)
452
+ self.account.capabilities.publish(adminCap, at: self.adminPublicPath)
453
+ }
454
+ }
@@ -0,0 +1,163 @@
1
+ import "FungibleToken"
2
+ import "NonFungibleToken"
3
+
4
+ import "EVM"
5
+
6
+ /// FlowEVMBridgeHandlerInterfaces
7
+ ///
8
+ /// This contract defines the interfaces for the FlowEVM Bridge Handlers. These Handlers are intended to encapsulate
9
+ /// the logic for bridging edge case assets between Cadence and EVM and require configuration by the bridge account to
10
+ /// enable. Contracts implementing these resources should be deployed to the bridge account so that privileged methods,
11
+ /// particularly those related to fulfilling bridge requests remain in the closed loop of bridge contract logic and
12
+ /// defined assets in the custody of the bridge account.
13
+ ///
14
+ access(all) contract FlowEVMBridgeHandlerInterfaces {
15
+
16
+ /******************
17
+ Entitlements
18
+ *******************/
19
+
20
+ /// Entitlement related to administrative setters
21
+ access(all) entitlement Admin
22
+ /// Entitlement related to minting handled assets
23
+ access(all) entitlement Mint
24
+
25
+ /*************
26
+ Events
27
+ **************/
28
+
29
+ /// Event emitted when a handler is enabled between a Cadence type and an EVM address
30
+ access(all) event HandlerEnabled(
31
+ handlerType: String,
32
+ handlerUUID: UInt64,
33
+ targetType: String,
34
+ targetEVMAddress: String
35
+ )
36
+ access(all) event MinterSet(handlerType: String,
37
+ handlerUUID: UInt64,
38
+ targetType: String?,
39
+ targetEVMAddress: String?,
40
+ minterType: String,
41
+ minterUUID: UInt64
42
+ )
43
+
44
+ /****************
45
+ Constructs
46
+ *****************/
47
+
48
+ /// Non-privileged interface for querying handler information
49
+ ///
50
+ access(all) resource interface HandlerInfo {
51
+ /// Returns whether the Handler is enabled
52
+ access(all) view fun isEnabled(): Bool
53
+ /// Returns the Cadence type handled by the Handler, nil if not set
54
+ access(all) view fun getTargetType(): Type?
55
+ /// Returns the EVM address handled by the Handler, nil if not set
56
+ access(all) view fun getTargetEVMAddress(): EVM.EVMAddress?
57
+ /// Returns the Type of the expected minter if the handler utilizes one
58
+ access(all) view fun getExpectedMinterType(): Type?
59
+ }
60
+
61
+ /// Administrative interface for Handler configuration
62
+ ///
63
+ access(all) resource interface HandlerAdmin : HandlerInfo {
64
+ /// Sets the target Cadence Type handled by this resource. Once the targe type is set - whether by this method
65
+ /// or on initialization - this setter will fail.
66
+ access(Admin) fun setTargetType(_ type: Type) {
67
+ pre {
68
+ self.getTargetType() == nil: "Target Type has already been set"
69
+ }
70
+ post {
71
+ self.getTargetType()! == type: "Problem setting target type"
72
+ }
73
+ }
74
+ /// Sets the target EVM address handled by this resource
75
+ access(Admin) fun setTargetEVMAddress(_ address: EVM.EVMAddress) {
76
+ pre {
77
+ self.getTargetEVMAddress() == nil: "Target EVM address has already been set"
78
+ }
79
+ post {
80
+ self.getTargetEVMAddress()!.equals(address!): "Problem setting target EVM address"
81
+ }
82
+ }
83
+ access(Admin) fun setMinter(_ minter: @{FlowEVMBridgeHandlerInterfaces.TokenMinter}) {
84
+ pre {
85
+ self.getExpectedMinterType() == minter.getType(): "Minter is not of the expected type"
86
+ minter.getMintedType() == self.getTargetType(): "Minter does not mint the target type"
87
+ emit MinterSet(
88
+ handlerType: self.getType().identifier,
89
+ handlerUUID: self.uuid,
90
+ targetType: self.getTargetType()?.identifier,
91
+ targetEVMAddress: self.getTargetEVMAddress()?.toString(),
92
+ minterType: minter.getType().identifier,
93
+ minterUUID: minter.uuid
94
+ )
95
+ }
96
+ }
97
+ /// Enables the Handler to fulfill bridge requests for the configured targets. If implementers utilize a minter,
98
+ /// they should additionally ensure the minter is set before enabling.
99
+ access(Admin) fun enableBridging() {
100
+ pre {
101
+ self.getTargetType() != nil && self.getTargetEVMAddress() != nil:
102
+ "Cannot enable before setting bridge targets"
103
+ !self.isEnabled(): "Handler already enabled"
104
+ }
105
+ post {
106
+ self.isEnabled(): "Problem enabling Handler"
107
+ emit HandlerEnabled(
108
+ handlerType: self.getType().identifier,
109
+ handlerUUID: self.uuid,
110
+ targetType: self.getTargetType()!.identifier,
111
+ targetEVMAddress: self.getTargetEVMAddress()!.toString()
112
+ )
113
+ }
114
+ }
115
+ }
116
+
117
+ /// Minter interface for configurations requiring the minting of Cadence fungible tokens
118
+ ///
119
+ access(all) resource interface TokenMinter {
120
+ /// Returns the Cadence type minted by this resource
121
+ access(all) view fun getMintedType(): Type
122
+ /// Mints the specified amount of tokens
123
+ access(Mint) fun mint(amount: UFix64): @{FungibleToken.Vault} {
124
+ pre {
125
+ amount > 0.0: "Amount must be greater than 0"
126
+ }
127
+ post {
128
+ result.getType() == self.getMintedType(): "Invalid Vault type returned"
129
+ result.balance == amount: "Minted amount does not match requested amount"
130
+ }
131
+ }
132
+ }
133
+
134
+ /// Handler interface for bridging FungibleToken assets. Implementations should be stored within the bridge account
135
+ /// and called be the bridge contract for bridging operations on the Handler's target Type and EVM contract.
136
+ ///
137
+ access(all) resource interface TokenHandler : HandlerAdmin {
138
+ /// Fulfills a request to bridge tokens from the Cadence side to the EVM side
139
+ access(account) fun fulfillTokensToEVM(
140
+ tokens: @{FungibleToken.Vault},
141
+ to: EVM.EVMAddress
142
+ ) {
143
+ pre {
144
+ self.isEnabled(): "Handler is not yet enabled"
145
+ tokens.getType() == self.getTargetType(): "Invalid Vault type"
146
+ }
147
+ }
148
+ /// Fulfills a request to bridge tokens from the EVM side to the Cadence side
149
+ access(account) fun fulfillTokensFromEVM(
150
+ owner: EVM.EVMAddress,
151
+ type: Type,
152
+ amount: UInt256,
153
+ protectedTransferCall: fun (): EVM.Result
154
+ ): @{FungibleToken.Vault} {
155
+ pre {
156
+ self.isEnabled(): "Handler is not yet enabled"
157
+ }
158
+ post {
159
+ result.getType() == self.getTargetType(): "Invalid Vault type returned"
160
+ }
161
+ }
162
+ }
163
+ }