@flowtyio/flow-contracts 0.1.0-beta.1 → 0.1.0-beta.3

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.
@@ -3,6 +3,7 @@ import "FlowStorageFees"
3
3
  import "FlowToken"
4
4
  import "NonFungibleToken"
5
5
  import "MetadataViews"
6
+
6
7
  import "FeeEstimator"
7
8
 
8
9
  // LostAndFound
@@ -26,49 +27,44 @@ import "FeeEstimator"
26
27
  // - NonFunigibleToken.Receiver
27
28
  // - FungibleToken.Receiver
28
29
  // - LostAndFound.ResourceReceiver (This is a placeholder so that non NFT and FT resources can be utilized here)
29
- pub contract LostAndFound {
30
+ access(all) contract LostAndFound {
30
31
  access(contract) let storageFees: {UInt64: UFix64}
31
32
 
32
- pub let LostAndFoundPublicPath: PublicPath
33
- pub let LostAndFoundStoragePath: StoragePath
34
- pub let DepositorPublicPath: PublicPath
35
- pub let DepositorStoragePath: StoragePath
33
+ access(all) let LostAndFoundPublicPath: PublicPath
34
+ access(all) let LostAndFoundStoragePath: StoragePath
35
+ access(all) let DepositorPublicPath: PublicPath
36
+ access(all) let DepositorStoragePath: StoragePath
37
+
38
+ access(all) event TicketDeposited(redeemer: Address, ticketID: UInt64, type: Type, memo: String?, name: String?, description: String?, thumbnail: String?)
39
+ access(all) event TicketRedeemed(redeemer: Address, ticketID: UInt64, type: Type)
40
+ access(all) event BinDestroyed(redeemer: Address, type: Type)
41
+ access(all) event ShelfDestroyed(redeemer: Address)
36
42
 
37
- pub event TicketDeposited(redeemer: Address, ticketID: UInt64, type: Type, memo: String?, name: String?, description: String?, thumbnail: String?)
38
- pub event TicketRedeemed(redeemer: Address, ticketID: UInt64, type: Type)
39
- pub event BinDestroyed(redeemer: Address, type: Type)
40
- pub event ShelfDestroyed(redeemer: Address)
43
+ access(all) event DepositorCreated(uuid: UInt64)
44
+ access(all) event DepositorBalanceLow(uuid: UInt64, threshold: UFix64, balance: UFix64)
45
+ access(all) event DepositorTokensAdded(uuid: UInt64, tokens: UFix64, balance: UFix64)
46
+ access(all) event DepositorTokensWithdrawn(uuid: UInt64, tokens: UFix64, balance: UFix64)
41
47
 
42
- pub event DepositorCreated(uuid: UInt64)
43
- pub event DepositorBalanceLow(uuid: UInt64, threshold: UFix64, balance: UFix64)
44
- pub event DepositorTokensAdded(uuid: UInt64, tokens: UFix64, balance: UFix64)
45
- pub event DepositorTokensWithdrawn(uuid: UInt64, tokens: UFix64, balance: UFix64)
48
+ access(all) entitlement Deposit
49
+ access(all) entitlement Withdraw
46
50
 
47
51
  // Placeholder receiver so that any resource can be supported, not just FT and NFT Receivers
48
- pub resource interface AnyResourceReceiver {
49
- pub fun deposit(resource: @AnyResource)
52
+ access(all) resource interface AnyResourceReceiver {
53
+ access(Deposit) fun deposit(item: @AnyResource)
50
54
  }
51
55
 
52
- pub resource DepositEstimate {
53
- pub var item: @AnyResource?
54
- pub let storageFee: UFix64
56
+ access(all) resource DepositEstimate {
57
+ access(Withdraw) var item: @AnyResource?
58
+ access(all) let storageFee: UFix64
55
59
 
56
60
  init(item: @AnyResource, storageFee: UFix64) {
57
61
  self.item <- item
58
62
  self.storageFee = storageFee
59
63
  }
60
64
 
61
- pub fun withdraw(): @AnyResource {
62
- let resource <- self.item <- nil
63
- return <-resource!
64
- }
65
-
66
- destroy() {
67
- pre {
68
- self.item == nil: "cannot destroy with non-null item"
69
- }
70
-
71
- destroy self.item
65
+ access(Withdraw) fun withdraw(): @AnyResource {
66
+ let item <- self.item <- nil
67
+ return <-item!
72
68
  }
73
69
  }
74
70
 
@@ -77,24 +73,30 @@ pub contract LostAndFound {
77
73
  // - memo: An optional message to attach to this ticket
78
74
  // - redeemer: The address which is allowed to withdraw the item from this ticket
79
75
  // - redeemed: Whether the ticket has been redeemed. This can only be set by the LostAndFound contract
80
- pub resource Ticket {
76
+ access(all) resource Ticket {
81
77
  // The item to be redeemed
82
78
  access(contract) var item: @AnyResource?
83
79
  // An optional message to attach to this item.
84
- pub let memo: String?
80
+ access(all) let memo: String?
85
81
  // an optional Display view so that frontend's that borrow this ticket know how to show it
86
- pub let display: MetadataViews.Display?
82
+ access(all) let display: MetadataViews.Display?
87
83
  // The address that it allowed to withdraw the item fromt this ticket
88
- pub let redeemer: Address
84
+ access(all) let redeemer: Address
89
85
  //The type of the resource (non-optional) so that bins can represent the true type of an item
90
- pub let type: Type
86
+ access(all) let type: Type
91
87
  // State maintained by LostAndFound
92
- pub var redeemed: Bool
88
+ access(all) var redeemed: Bool
93
89
 
94
90
  // flow token amount used to store this ticket is returned when the ticket is redeemed
95
- access(contract) let flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>?
91
+ access(contract) let flowTokenRepayment: Capability<&FlowToken.Vault>?
96
92
 
97
- init (item: @AnyResource, memo: String?, display: MetadataViews.Display?, redeemer: Address, flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>?) {
93
+ init (
94
+ item: @AnyResource,
95
+ memo: String?,
96
+ display: MetadataViews.Display?,
97
+ redeemer: Address,
98
+ flowTokenRepayment: Capability<&FlowToken.Vault>?
99
+ ) {
98
100
  self.type = item.getType()
99
101
  self.item <- item
100
102
  self.memo = memo
@@ -105,40 +107,40 @@ pub contract LostAndFound {
105
107
  self.flowTokenRepayment = flowTokenRepayment
106
108
  }
107
109
 
108
- pub fun itemType(): Type {
110
+ access(all) view fun itemType(): Type {
109
111
  return self.type
110
112
  }
111
113
 
112
- pub fun checkItem(): Bool {
114
+ access(all) fun checkItem(): Bool {
113
115
  return self.item != nil
114
116
  }
115
117
 
116
118
  // A function to get depositor address / flow Repayment address
117
- pub fun getFlowRepaymentAddress() : Address? {
119
+ access(all) fun getFlowRepaymentAddress() : Address? {
118
120
  return self.flowTokenRepayment?.address
119
121
  }
120
122
 
121
123
  // If this is an instance of NFT, return the id , otherwise return nil
122
- pub fun getNonFungibleTokenID() : UInt64? {
123
- if self.type.isSubtype(of: Type<@NonFungibleToken.NFT>()) {
124
- let ref = (&self.item as auth &AnyResource?)!
125
- let nft = ref as! &NonFungibleToken.NFT
126
- return nft.id
124
+ access(all) fun getNonFungibleTokenID() : UInt64? {
125
+ if self.type.isSubtype(of: Type<@{NonFungibleToken.NFT}>()) {
126
+ let ref = (&self.item as &AnyResource?)!
127
+ let nft = ref as! &{NonFungibleToken.NFT}
128
+ return nft.getID()
127
129
  }
128
130
  return nil
129
131
  }
130
132
 
131
133
  // If this is an instance of FT, return the vault balance , otherwise return nil
132
- pub fun getFungibleTokenBalance() : UFix64? {
133
- if self.type.isSubtype(of: Type<@FungibleToken.Vault>()) {
134
- let ref = (&self.item as auth &AnyResource?)!
135
- let ft = ref as! &FungibleToken.Vault
136
- return ft.balance
134
+ access(all) fun getFungibleTokenBalance() : UFix64? {
135
+ if self.type.isSubtype(of: Type<@{FungibleToken.Vault}>()) {
136
+ let ref = (&self.item as &AnyResource?)!
137
+ let ft = ref as! &{FungibleToken.Vault}
138
+ return ft.getBalance()
137
139
  }
138
140
  return nil
139
141
  }
140
142
 
141
- pub fun withdraw(receiver: Capability) {
143
+ access(Withdraw) fun withdraw(receiver: Capability) {
142
144
  pre {
143
145
  receiver.address == self.redeemer: "receiver address and redeemer must match"
144
146
  !self.redeemed: "already redeemed"
@@ -147,25 +149,25 @@ pub contract LostAndFound {
147
149
  var redeemableItem <- self.item <- nil
148
150
  let cap = receiver.borrow<&AnyResource>()!
149
151
 
150
- if cap.isInstance(Type<@NonFungibleToken.Collection>()) {
151
- let target = receiver.borrow<&AnyResource{NonFungibleToken.CollectionPublic}>()!
152
- let token <- redeemableItem as! @NonFungibleToken.NFT?
152
+ if cap.isInstance(Type<@{NonFungibleToken.Collection}>()) {
153
+ let target = receiver.borrow<&{NonFungibleToken.Collection}>()!
154
+ let token <- redeemableItem as! @{NonFungibleToken.NFT}?
153
155
  self.redeemed = true
154
156
  emit TicketRedeemed(redeemer: self.redeemer, ticketID: self.uuid, type: token.getType())
155
157
  target.deposit(token: <- token!)
156
158
  return
157
- } else if cap.isInstance(Type<@FungibleToken.Vault>()) {
158
- let target = receiver.borrow<&AnyResource{FungibleToken.Receiver}>()!
159
- let token <- redeemableItem as! @FungibleToken.Vault?
159
+ } else if cap.isInstance(Type<@{FungibleToken.Vault}>()) {
160
+ let target = receiver.borrow<&{FungibleToken.Receiver}>()!
161
+ let token <- redeemableItem as! @{FungibleToken.Vault}?
160
162
  self.redeemed = true
161
163
  emit TicketRedeemed(redeemer: self.redeemer, ticketID: self.uuid, type: token.getType())
162
164
  target.deposit(from: <- token!)
163
165
  return
164
- } else if cap.isInstance(Type<@AnyResource{LostAndFound.AnyResourceReceiver}>()) {
165
- let target = receiver.borrow<&{LostAndFound.AnyResourceReceiver}>()!
166
+ } else if cap.isInstance(Type<@{LostAndFound.AnyResourceReceiver}>()) {
167
+ let target = receiver.borrow<auth(Deposit) &{LostAndFound.AnyResourceReceiver}>()!
166
168
  self.redeemed = true
167
169
  emit TicketRedeemed(redeemer: self.redeemer, ticketID: self.uuid, type: redeemableItem.getType())
168
- target.deposit(resource: <- redeemableItem)
170
+ target.deposit(item: <- redeemableItem)
169
171
  return
170
172
  } else{
171
173
  panic("cannot redeem resource to receiver")
@@ -180,15 +182,13 @@ pub contract LostAndFound {
180
182
  return <-redeemableItem!
181
183
  }
182
184
 
183
- // destructon is only allowed if the ticket has been redeemed and the underlying item is a our dummy resource
184
- destroy () {
185
+ access(contract) fun safeDestroy() {
185
186
  pre {
186
187
  self.redeemed: "Ticket has not been redeemed"
187
188
  self.item == nil: "can only destroy if not holding any item"
188
189
  }
189
190
 
190
191
  LostAndFound.storageFees.remove(key: self.uuid)
191
- destroy <-self.item
192
192
  }
193
193
  }
194
194
 
@@ -196,11 +196,11 @@ pub contract LostAndFound {
196
196
  // A Bin is a resource that gathers tickets whos item have the same type.
197
197
  // For instance, if two TopShot Moments are deposited to the same redeemer, only one bin
198
198
  // will be made which will contain both tickets to redeem each individual moment.
199
- pub resource Bin {
199
+ access(all) resource Bin {
200
200
  access(contract) let tickets: @{UInt64:Ticket}
201
201
  access(contract) let type: Type
202
202
 
203
- pub let flowTokenRepayment: Capability<&{FungibleToken.Receiver}>?
203
+ access(all) let flowTokenRepayment: Capability<&{FungibleToken.Receiver}>?
204
204
 
205
205
  init (type: Type, flowTokenRepayment: Capability<&{FungibleToken.Receiver}>?) {
206
206
  self.tickets <- {}
@@ -208,11 +208,11 @@ pub contract LostAndFound {
208
208
  self.flowTokenRepayment = flowTokenRepayment
209
209
  }
210
210
 
211
- pub fun borrowTicket(id: UInt64): &LostAndFound.Ticket? {
212
- return &self.tickets[id] as &LostAndFound.Ticket?
211
+ access(all) fun borrowTicket(id: UInt64): &LostAndFound.Ticket? {
212
+ return &self.tickets[id]
213
213
  }
214
214
 
215
- pub fun borrowAllTicketsByType(): [&LostAndFound.Ticket] {
215
+ access(all) fun borrowAllTicketsByType(): [&LostAndFound.Ticket] {
216
216
  let tickets: [&LostAndFound.Ticket] = []
217
217
  let ids = self.tickets.keys
218
218
  for id in ids {
@@ -243,7 +243,7 @@ pub contract LostAndFound {
243
243
  emit TicketDeposited(redeemer: redeemer, ticketID: ticketID, type: self.type, memo: memo, name: name, description: description, thumbnail: thumbnail)
244
244
  }
245
245
 
246
- pub fun getTicketIDs(): [UInt64] {
246
+ access(all) fun getTicketIDs(): [UInt64] {
247
247
  return self.tickets.keys
248
248
  }
249
249
 
@@ -252,16 +252,17 @@ pub contract LostAndFound {
252
252
  return <- ticket!
253
253
  }
254
254
 
255
- destroy () {
256
- destroy <-self.tickets
257
- LostAndFound.storageFees.remove(key: self.uuid)
255
+ access(contract) fun safeDestroy() {
256
+ pre {
257
+ self.tickets.length == 0: "cannot destroy bin with tickets in it"
258
+ }
258
259
  }
259
260
  }
260
261
 
261
262
  // A shelf is our top-level organization resource.
262
263
  // It groups bins by type to help make discovery of the assets that a
263
264
  // redeeming address can claim.
264
- pub resource Shelf {
265
+ access(all) resource Shelf {
265
266
  access(self) let bins: @{String: Bin}
266
267
  access(self) let identifierToType: {String: Type}
267
268
  access(self) let redeemer: Address
@@ -274,11 +275,11 @@ pub contract LostAndFound {
274
275
  self.flowTokenRepayment = flowTokenRepayment
275
276
  }
276
277
 
277
- pub fun getOwner(): Address {
278
+ access(all) fun getOwner(): Address {
278
279
  return self.owner!.address
279
280
  }
280
281
 
281
- pub fun getRedeemableTypes(): [Type] {
282
+ access(all) fun getRedeemableTypes(): [Type] {
282
283
  let types: [Type] = []
283
284
  for k in self.bins.keys {
284
285
  let t = self.identifierToType[k]!
@@ -289,26 +290,26 @@ pub contract LostAndFound {
289
290
  return types
290
291
  }
291
292
 
292
- pub fun hasType(type: Type): Bool {
293
+ access(all) fun hasType(type: Type): Bool {
293
294
  return self.bins[type.identifier] != nil
294
295
  }
295
296
 
296
- pub fun borrowBin(type: Type): &LostAndFound.Bin? {
297
- return &self.bins[type.identifier] as &LostAndFound.Bin?
297
+ access(all) fun borrowBin(type: Type): &LostAndFound.Bin? {
298
+ return &self.bins[type.identifier]
298
299
  }
299
300
 
300
301
  access(contract) fun ensureBin(type: Type, flowTokenRepayment: Capability<&{FungibleToken.Receiver}>?): &Bin {
301
302
  if !self.bins.containsKey(type.identifier) {
302
- let storageBefore = LostAndFound.account.storageUsed
303
+ let storageBefore = LostAndFound.account.storage.used
303
304
  let bin <- create Bin(type: type, flowTokenRepayment: flowTokenRepayment)
304
305
  let uuid = bin.uuid
305
306
  let oldValue <- self.bins.insert(key: type.identifier, <-bin)
306
- LostAndFound.storageFees[uuid] = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storageUsed - storageBefore)
307
+ LostAndFound.storageFees[uuid] = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storage.used - storageBefore)
307
308
  self.identifierToType[type.identifier] = type
308
309
  destroy oldValue
309
310
  }
310
311
 
311
- return (&self.bins[type.identifier] as &LostAndFound.Bin?)!
312
+ return (&self.bins[type.identifier])!
312
313
  }
313
314
 
314
315
  access(contract) fun deposit(ticket: @LostAndFound.Ticket, flowTokenRepayment: Capability<&{FungibleToken.Receiver}>?) {
@@ -324,7 +325,7 @@ pub contract LostAndFound {
324
325
  // Only one of the three receiver options can be specified, and an optional maximum number of tickets
325
326
  // to redeem can be picked to prevent gas issues in case there are large numbers of tickets to be
326
327
  // redeemed at once.
327
- pub fun redeemAll(type: Type, max: Int?, receiver: Capability) {
328
+ access(all) fun redeemAll(type: Type, max: Int?, receiver: Capability) {
328
329
  pre {
329
330
  receiver.address == self.redeemer: "receiver must match the redeemer of this shelf"
330
331
  self.bins.containsKey(type.identifier): "no bin for provided type"
@@ -343,7 +344,7 @@ pub contract LostAndFound {
343
344
  }
344
345
 
345
346
  // Redeem a specific ticket instead of all of a certain type.
346
- pub fun redeem(type: Type, ticketID: UInt64, receiver: Capability) {
347
+ access(Withdraw) fun redeem(type: Type, ticketID: UInt64, receiver: Capability) {
347
348
  pre {
348
349
  receiver.address == self.redeemer: "receiver must match the redeemer of this shelf"
349
350
  self.bins.containsKey(type.identifier): "no bin for provided type"
@@ -360,6 +361,8 @@ pub contract LostAndFound {
360
361
  let repaymentVault <- refundProvider.withdraw(amount: LostAndFound.storageFees[uuid]!)
361
362
  refundCap!.borrow()!.deposit(from: <-repaymentVault)
362
363
  }
364
+
365
+ ticket.safeDestroy()
363
366
  destroy ticket
364
367
 
365
368
  if borrowedBin.getTicketIDs().length == 0 {
@@ -374,77 +377,81 @@ pub contract LostAndFound {
374
377
  let vault <- provider.withdraw(amount: LostAndFound.storageFees[uuid]!)
375
378
  flowTokenRepayment!.borrow()!.deposit(from: <-vault)
376
379
  }
380
+
381
+ bin.safeDestroy()
377
382
  destroy bin
378
383
  }
379
384
  }
380
385
 
381
- destroy () {
382
- destroy <- self.bins
386
+ access(contract) fun safeDestroy() {
387
+ pre {
388
+ self.bins.length == 0: "cannot destroy a shelf with bins in it"
389
+ }
383
390
  LostAndFound.storageFees.remove(key: self.uuid)
384
391
  }
385
392
  }
386
393
 
387
- access(contract) fun getFlowProvider(): &FlowToken.Vault{FungibleToken.Provider} {
388
- return self.account.borrow<&FlowToken.Vault{FungibleToken.Provider}>(from: /storage/flowTokenVault)!
394
+ access(contract) fun getFlowProvider(): auth(FungibleToken.Withdrawable) &FlowToken.Vault {
395
+ return self.account.storage.borrow<auth(FungibleToken.Withdrawable) &FlowToken.Vault>(from: /storage/flowTokenVault)!
389
396
  }
390
397
 
391
398
  // ShelfManager is a light-weight wrapper to get our shelves into storage.
392
- pub resource ShelfManager {
399
+ access(all) resource ShelfManager {
393
400
  access(self) let shelves: @{Address: Shelf}
394
401
 
395
402
  init() {
396
403
  self.shelves <- {}
397
404
  }
398
405
 
399
- access(contract) fun ensureShelf(_ addr: Address, flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>?): &LostAndFound.Shelf {
406
+ access(contract) fun ensureShelf(_ addr: Address, flowTokenRepayment: Capability<&FlowToken.Vault>?): &LostAndFound.Shelf {
400
407
  if !self.shelves.containsKey(addr) {
401
- let storageBefore = LostAndFound.account.storageUsed
408
+ let storageBefore = LostAndFound.account.storage.used
402
409
  let shelf <- create Shelf(redeemer: addr, flowTokenRepayment: flowTokenRepayment)
403
410
  let uuid = shelf.uuid
404
411
  let oldValue <- self.shelves.insert(key: addr, <-shelf)
405
412
 
406
- LostAndFound.storageFees[uuid] = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storageUsed - storageBefore)
413
+ LostAndFound.storageFees[uuid] = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storage.used - storageBefore)
407
414
  destroy oldValue
408
415
  }
409
416
 
410
- return (&self.shelves[addr] as &LostAndFound.Shelf?)!
417
+ return (&self.shelves[addr])!
411
418
  }
412
419
 
413
- pub fun deposit(
420
+ access(all) fun deposit(
414
421
  redeemer: Address,
415
422
  item: @AnyResource,
416
423
  memo: String?,
417
424
  display: MetadataViews.Display?,
418
- storagePayment: &FungibleToken.Vault,
419
- flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>?
425
+ storagePayment: auth(FungibleToken.Withdrawable) &{FungibleToken.Vault},
426
+ flowTokenRepayment: Capability<&FlowToken.Vault>?
420
427
  ) : UInt64 {
421
428
  pre {
422
429
  flowTokenRepayment == nil || flowTokenRepayment!.check(): "flowTokenRepayment is not valid"
423
430
  storagePayment.getType() == Type<@FlowToken.Vault>(): "storage payment must be in flow tokens"
424
431
  }
425
432
  let receiver = LostAndFound.account
426
- .getCapability<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver)
433
+ .capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver)!
427
434
  .borrow()!
428
435
 
429
436
 
430
- let storageBeforeShelf = LostAndFound.account.storageUsed
437
+ let storageBeforeShelf = LostAndFound.account.storage.used
431
438
  let shelf = self.ensureShelf(redeemer, flowTokenRepayment: flowTokenRepayment)
432
- if LostAndFound.account.storageUsed != storageBeforeShelf && LostAndFound.storageFees[shelf.uuid] != nil {
439
+ if LostAndFound.account.storage.used != storageBeforeShelf && LostAndFound.storageFees[shelf.uuid] != nil {
433
440
  receiver.deposit(from: <-storagePayment.withdraw(amount: LostAndFound.storageFees[shelf.uuid]!))
434
441
  }
435
442
 
436
- let storageBeforeBin = LostAndFound.account.storageUsed
443
+ let storageBeforeBin = LostAndFound.account.storage.used
437
444
  let bin = shelf.ensureBin(type: item.getType(), flowTokenRepayment: flowTokenRepayment)
438
- if LostAndFound.account.storageUsed != storageBeforeBin {
445
+ if LostAndFound.account.storage.used != storageBeforeBin {
439
446
  receiver.deposit(from: <-storagePayment.withdraw(amount: LostAndFound.storageFees[bin.uuid]!))
440
447
  }
441
448
 
442
- let storageBefore = LostAndFound.account.storageUsed
449
+ let storageBefore = LostAndFound.account.storage.used
443
450
  let ticket <- create Ticket(item: <-item, memo: memo, display: display, redeemer: redeemer, flowTokenRepayment: flowTokenRepayment)
444
451
  let uuid = ticket.uuid
445
452
  let flowTokenRepayment = ticket.flowTokenRepayment
446
453
  shelf.deposit(ticket: <-ticket, flowTokenRepayment: flowTokenRepayment)
447
- let storageUsedAfter = LostAndFound.account.storageUsed
454
+ let storageUsedAfter = LostAndFound.account.storage.used
448
455
  let storageFee = FeeEstimator.storageUsedToFlowAmount(storageUsedAfter - storageBefore)
449
456
  LostAndFound.storageFees[uuid] = storageFee
450
457
 
@@ -453,20 +460,20 @@ pub contract LostAndFound {
453
460
  return uuid
454
461
  }
455
462
 
456
- pub fun borrowShelf(redeemer: Address): &LostAndFound.Shelf? {
457
- return &self.shelves[redeemer] as &LostAndFound.Shelf?
463
+ access(all) fun borrowShelf(redeemer: Address): &LostAndFound.Shelf? {
464
+ return &self.shelves[redeemer]
458
465
  }
459
466
 
460
467
  // deleteShelf
461
468
  //
462
469
  // delete a shelf if it has no redeemable types
463
- pub fun deleteShelf(_ addr: Address) {
464
- let storageBefore = LostAndFound.account.storageUsed
470
+ access(all) fun deleteShelf(_ addr: Address) {
471
+ let storageBefore = LostAndFound.account.storage.used
465
472
  assert(self.shelves.containsKey(addr), message: "shelf does not exist")
466
473
  let tmp <- self.shelves[addr] <- nil
467
474
  let shelf <-! tmp!
468
475
 
469
- assert(shelf.getRedeemableTypes().length! == 0, message: "shelf still has redeemable types")
476
+ assert(shelf.getRedeemableTypes().length == 0, message: "shelf still has redeemable types")
470
477
  let flowTokenRepayment = shelf.flowTokenRepayment
471
478
  let uuid = shelf.uuid
472
479
  if flowTokenRepayment != nil && flowTokenRepayment!.check() && LostAndFound.storageFees[uuid] != nil {
@@ -474,23 +481,27 @@ pub contract LostAndFound {
474
481
  let vault <- provider.withdraw(amount: LostAndFound.storageFees[uuid]!)
475
482
  flowTokenRepayment!.borrow()!.deposit(from: <-vault)
476
483
  }
484
+
485
+ shelf.safeDestroy()
477
486
  destroy shelf
478
487
  emit ShelfDestroyed(redeemer: addr)
479
488
  }
480
-
481
- destroy () {
482
- destroy <-self.shelves
489
+
490
+ access(contract) fun safeDestroy() {
491
+ pre {
492
+ self.shelves.length == 0: "cannot destroy shelf manager when it has shelves"
493
+ }
483
494
  }
484
495
  }
485
496
 
486
- pub resource interface DepositorPublic {
487
- pub fun balance(): UFix64
488
- pub fun addFlowTokens(vault: @FlowToken.Vault)
497
+ access(all) resource interface DepositorPublic {
498
+ access(all) fun balance(): UFix64
499
+ access(all) fun addFlowTokens(vault: @FlowToken.Vault)
489
500
  }
490
501
 
491
- pub resource Depositor: DepositorPublic {
502
+ access(all) resource Depositor: DepositorPublic {
492
503
  access(self) let flowTokenVault: @FlowToken.Vault
493
- pub let flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>
504
+ access(all) let flowTokenRepayment: Capability<&FlowToken.Vault>
494
505
  access(self) var lowBalanceThreshold: UFix64?
495
506
 
496
507
  access(self) fun checkForLowBalance(): Bool {
@@ -502,45 +513,45 @@ pub contract LostAndFound {
502
513
  return false
503
514
  }
504
515
 
505
- pub fun setLowBalanceThreshold(threshold: UFix64?) {
516
+ access(Mutate) fun setLowBalanceThreshold(threshold: UFix64?) {
506
517
  self.lowBalanceThreshold = threshold
507
518
  }
508
519
 
509
- pub fun getLowBalanceThreshold(): UFix64? {
520
+ access(Mutate) fun getLowBalanceThreshold(): UFix64? {
510
521
  return self.lowBalanceThreshold
511
522
  }
512
523
 
513
- pub fun deposit(
524
+ access(Deposit) fun deposit(
514
525
  redeemer: Address,
515
526
  item: @AnyResource,
516
527
  memo: String?,
517
528
  display: MetadataViews.Display?
518
529
  ) : UInt64 {
519
530
  let receiver = LostAndFound.account
520
- .getCapability<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver)
531
+ .capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver)!
521
532
  .borrow()!
522
533
 
523
- let storageBeforeShelf = LostAndFound.account.storageUsed
534
+ let storageBeforeShelf = LostAndFound.account.storage.used
524
535
  let shelfManager = LostAndFound.borrowShelfManager()
525
536
  let shelf = shelfManager.ensureShelf(redeemer, flowTokenRepayment: self.flowTokenRepayment)
526
- if LostAndFound.account.storageUsed != storageBeforeShelf && LostAndFound.storageFees[shelf.uuid] != nil {
537
+ if LostAndFound.account.storage.used != storageBeforeShelf && LostAndFound.storageFees[shelf.uuid] != nil {
527
538
  receiver.deposit(from: <-self.withdrawTokens(amount: LostAndFound.storageFees[shelf.uuid]!))
528
539
  }
529
540
 
530
- let storageBeforeBin = LostAndFound.account.storageUsed
541
+ let storageBeforeBin = LostAndFound.account.storage.used
531
542
  let bin = shelf.ensureBin(type: item.getType(), flowTokenRepayment: self.flowTokenRepayment)
532
- if storageBeforeBin != LostAndFound.account.storageUsed {
543
+ if storageBeforeBin != LostAndFound.account.storage.used {
533
544
  receiver.deposit(from: <-self.withdrawTokens(amount: LostAndFound.storageFees[bin.uuid]!))
534
545
  }
535
546
 
536
- let storageBefore = LostAndFound.account.storageUsed
547
+ let storageBefore = LostAndFound.account.storage.used
537
548
  let ticket <- create Ticket(item: <-item, memo: memo, display: display, redeemer: redeemer, flowTokenRepayment: self.flowTokenRepayment)
538
549
 
539
550
  let flowTokenRepayment = ticket.flowTokenRepayment
540
551
  let uuid = ticket.uuid
541
- shelf!.deposit(ticket: <-ticket, flowTokenRepayment: flowTokenRepayment)
552
+ shelf.deposit(ticket: <-ticket, flowTokenRepayment: flowTokenRepayment)
542
553
 
543
- let storageFee = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storageUsed - storageBefore)
554
+ let storageFee = FeeEstimator.storageUsedToFlowAmount(LostAndFound.account.storage.used - storageBefore)
544
555
  LostAndFound.storageFees[uuid] = storageFee
545
556
 
546
557
  let storagePaymentVault <- self.withdrawTokens(amount: storageFee)
@@ -549,69 +560,67 @@ pub contract LostAndFound {
549
560
  return uuid
550
561
  }
551
562
 
552
- pub fun trySendResource(
553
- item: @AnyResource,
554
- cap: Capability,
555
- memo: String?,
556
- display: MetadataViews.Display?
563
+ access(Deposit) fun trySendResource(
564
+ item: @AnyResource,
565
+ cap: Capability,
566
+ memo: String?,
567
+ display: MetadataViews.Display?
557
568
  ) {
558
-
559
- if cap.check<&{NonFungibleToken.CollectionPublic}>() {
560
- let nft <- item as! @NonFungibleToken.NFT
561
- cap.borrow<&{NonFungibleToken.CollectionPublic}>()!.deposit(token: <-nft)
562
- } else if cap.check<&{NonFungibleToken.Receiver}>() {
563
- let nft <- item as! @NonFungibleToken.NFT
564
- cap.borrow<&{NonFungibleToken.Receiver}>()!.deposit(token: <-nft)
569
+ if cap.check<&{NonFungibleToken.Collection}>() {
570
+ let nft <- item as! @{NonFungibleToken.NFT}
571
+ cap.borrow<&{NonFungibleToken.Collection}>()!.deposit(token: <-nft)
565
572
  } else if cap.check<&{FungibleToken.Receiver}>() {
566
- let vault <- item as! @FungibleToken.Vault
573
+ let vault <- item as! @{FungibleToken.Vault}
567
574
  cap.borrow<&{FungibleToken.Receiver}>()!.deposit(from: <-vault)
568
575
  } else {
569
576
  self.deposit(redeemer: cap.address, item: <-item, memo: memo, display: display)
570
577
  }
571
578
  }
572
579
 
573
- pub fun withdrawTokens(amount: UFix64): @FungibleToken.Vault {
580
+ access(Mutate) fun withdrawTokens(amount: UFix64): @{FungibleToken.Vault} {
574
581
  let tokens <-self.flowTokenVault.withdraw(amount: amount)
575
582
  emit DepositorTokensWithdrawn(uuid: self.uuid, tokens: amount, balance: self.flowTokenVault.balance)
576
583
  self.checkForLowBalance()
577
584
  return <-tokens
578
585
  }
579
586
 
580
- pub fun addFlowTokens(vault: @FlowToken.Vault) {
587
+ access(all) fun addFlowTokens(vault: @FlowToken.Vault) {
581
588
  let tokensAdded = vault.balance
582
589
  self.flowTokenVault.deposit(from: <-vault)
583
590
  emit DepositorTokensAdded(uuid: self.uuid, tokens: tokensAdded, balance: self.flowTokenVault.balance)
584
591
  self.checkForLowBalance()
585
592
  }
586
593
 
587
- pub fun balance(): UFix64 {
594
+ access(all) fun balance(): UFix64 {
588
595
  return self.flowTokenVault.balance
589
596
  }
590
597
 
591
- init(_ flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>, lowBalanceThreshold: UFix64?) {
598
+ init(_ flowTokenRepayment: Capability<&FlowToken.Vault>, lowBalanceThreshold: UFix64?) {
592
599
  self.flowTokenRepayment = flowTokenRepayment
593
600
 
594
601
  let vault <- FlowToken.createEmptyVault()
595
- self.flowTokenVault <- vault as! @FlowToken.Vault
602
+ self.flowTokenVault <- vault
596
603
  self.lowBalanceThreshold = lowBalanceThreshold
597
604
  }
598
605
 
599
- destroy() {
600
- self.flowTokenRepayment.borrow()!.deposit(from: <-self.flowTokenVault)
606
+ access(contract) fun safeDestroy() {
607
+ pre {
608
+ self.flowTokenVault.balance == 0.0: "depositor still has flow tokens to be withdrawn"
609
+ }
601
610
  }
602
611
  }
603
612
 
604
- pub fun createDepositor(_ flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>, lowBalanceThreshold: UFix64?): @Depositor {
613
+ access(all) fun createDepositor(_ flowTokenRepayment: Capability<&FlowToken.Vault>, lowBalanceThreshold: UFix64?): @Depositor {
605
614
  let depositor <- create Depositor(flowTokenRepayment, lowBalanceThreshold: lowBalanceThreshold)
606
615
  emit DepositorCreated(uuid: depositor.uuid)
607
616
  return <- depositor
608
617
  }
609
618
 
610
- pub fun borrowShelfManager(): &LostAndFound.ShelfManager {
611
- return self.account.getCapability<&LostAndFound.ShelfManager>(LostAndFound.LostAndFoundPublicPath).borrow()!
619
+ access(all) fun borrowShelfManager(): &LostAndFound.ShelfManager {
620
+ return self.account.capabilities.get<&LostAndFound.ShelfManager>(LostAndFound.LostAndFoundPublicPath)!.borrow()!
612
621
  }
613
622
 
614
- pub fun borrowAllTicketsByType(addr: Address, type: Type): [&LostAndFound.Ticket] {
623
+ access(all) fun borrowAllTicketsByType(addr: Address, type: Type): [&LostAndFound.Ticket] {
615
624
  let manager = LostAndFound.borrowShelfManager()
616
625
  let shelf = manager.borrowShelf(redeemer: addr)
617
626
  if shelf == nil {
@@ -626,7 +635,7 @@ pub contract LostAndFound {
626
635
  return bin!.borrowAllTicketsByType()
627
636
  }
628
637
 
629
- pub fun borrowAllTickets(addr: Address): [&LostAndFound.Ticket] {
638
+ access(all) fun borrowAllTickets(addr: Address): [&LostAndFound.Ticket] {
630
639
  let manager = LostAndFound.borrowShelfManager()
631
640
  let shelf = manager.borrowShelf(redeemer: addr)
632
641
  if shelf == nil {
@@ -634,7 +643,7 @@ pub contract LostAndFound {
634
643
  }
635
644
 
636
645
  let types = shelf!.getRedeemableTypes()
637
- let allTickets = [] as [&LostAndFound.Ticket]
646
+ let allTickets: [&Ticket] = []
638
647
 
639
648
  for type in types {
640
649
  let tickets = LostAndFound.borrowAllTicketsByType(addr: addr, type: type)
@@ -644,19 +653,19 @@ pub contract LostAndFound {
644
653
  return allTickets
645
654
  }
646
655
 
647
- pub fun redeemAll(type: Type, max: Int?, receiver: Capability) {
656
+ access(all) fun redeemAll(type: Type, max: Int?, receiver: Capability) {
648
657
  let manager = LostAndFound.borrowShelfManager()
649
- let shelf = manager.borrowShelf(redeemer: receiver.address)
658
+ let shelf = manager.borrowShelf(redeemer: receiver.address)!
650
659
  assert(shelf != nil, message: "shelf not found")
651
660
 
652
- shelf!.redeemAll(type: type, max: max, receiver: receiver)
653
- let remainingTypes = shelf!.getRedeemableTypes()
661
+ shelf.redeemAll(type: type, max: max, receiver: receiver)
662
+ let remainingTypes = shelf.getRedeemableTypes()
654
663
  if remainingTypes.length == 0 {
655
664
  manager.deleteShelf(receiver.address)
656
665
  }
657
666
  }
658
667
 
659
- pub fun estimateDeposit(
668
+ access(all) fun estimateDeposit(
660
669
  redeemer: Address,
661
670
  item: @AnyResource,
662
671
  memo: String?,
@@ -677,7 +686,7 @@ pub contract LostAndFound {
677
686
  }
678
687
  }
679
688
 
680
- let ftReceiver = LostAndFound.account.getCapability<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver)
689
+ let ftReceiver = LostAndFound.account.capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver)
681
690
  let ticket <- create LostAndFound.Ticket(item: <-item, memo: memo, display: display, redeemer: redeemer, flowTokenRepayment: ftReceiver)
682
691
  let tmpEstimate <- FeeEstimator.estimateDeposit(item: <-ticket)
683
692
  let tmpItem <- tmpEstimate.withdraw() as! @LostAndFound.Ticket
@@ -689,7 +698,7 @@ pub contract LostAndFound {
689
698
  return <- estimate
690
699
  }
691
700
 
692
- pub fun getRedeemableTypes(_ addr: Address): [Type] {
701
+ access(all) fun getRedeemableTypes(_ addr: Address): [Type] {
693
702
  let manager = LostAndFound.borrowShelfManager()
694
703
  let shelf = manager.borrowShelf(redeemer: addr)
695
704
  if shelf == nil {
@@ -699,13 +708,13 @@ pub contract LostAndFound {
699
708
  return shelf!.getRedeemableTypes()
700
709
  }
701
710
 
702
- pub fun deposit(
711
+ access(all) fun deposit(
703
712
  redeemer: Address,
704
713
  item: @AnyResource,
705
714
  memo: String?,
706
715
  display: MetadataViews.Display?,
707
- storagePayment: &FungibleToken.Vault,
708
- flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>?
716
+ storagePayment: auth(FungibleToken.Withdrawable) &{FungibleToken.Vault},
717
+ flowTokenRepayment: Capability<&FlowToken.Vault>?
709
718
  ) : UInt64 {
710
719
  pre {
711
720
  flowTokenRepayment == nil || flowTokenRepayment!.check(): "flowTokenRepayment is not valid"
@@ -716,29 +725,26 @@ pub contract LostAndFound {
716
725
  return shelfManager.deposit(redeemer: redeemer, item: <-item, memo: memo, display: display, storagePayment: storagePayment, flowTokenRepayment: flowTokenRepayment)
717
726
  }
718
727
 
719
- pub fun trySendResource(
720
- resource: @AnyResource,
728
+ access(all) fun trySendResource(
729
+ item: @AnyResource,
721
730
  cap: Capability,
722
731
  memo: String?,
723
732
  display: MetadataViews.Display?,
724
- storagePayment: &FungibleToken.Vault,
725
- flowTokenRepayment: Capability<&FlowToken.Vault{FungibleToken.Receiver}>
733
+ storagePayment: auth(FungibleToken.Withdrawable) &{FungibleToken.Vault},
734
+ flowTokenRepayment: Capability<&FlowToken.Vault>
726
735
  ) {
727
- if cap.check<&{NonFungibleToken.CollectionPublic}>() {
728
- let nft <- resource as! @NonFungibleToken.NFT
729
- cap.borrow<&{NonFungibleToken.CollectionPublic}>()!.deposit(token: <-nft)
730
- } else if cap.check<&{NonFungibleToken.Receiver}>() {
731
- let nft <- resource as! @NonFungibleToken.NFT
732
- cap.borrow<&{NonFungibleToken.Receiver}>()!.deposit(token: <-nft)
736
+ if cap.check<&{NonFungibleToken.Collection}>() {
737
+ let nft <- item as! @{NonFungibleToken.NFT}
738
+ cap.borrow<&{NonFungibleToken.Collection}>()!.deposit(token: <-nft)
733
739
  } else if cap.check<&{FungibleToken.Receiver}>() {
734
- let vault <- resource as! @FungibleToken.Vault
740
+ let vault <- item as! @{FungibleToken.Vault}
735
741
  cap.borrow<&{FungibleToken.Receiver}>()!.deposit(from: <-vault)
736
742
  } else {
737
- LostAndFound.deposit(redeemer: cap.address, item: <-resource, memo: memo, display: display, storagePayment: storagePayment, flowTokenRepayment: flowTokenRepayment)
743
+ LostAndFound.deposit(redeemer: cap.address, item: <-item, memo: memo, display: display, storagePayment: storagePayment, flowTokenRepayment: flowTokenRepayment)
738
744
  }
739
745
  }
740
746
 
741
- pub fun getAddress(): Address {
747
+ access(all) fun getAddress(): Address {
742
748
  return self.account.address
743
749
  }
744
750
 
@@ -751,8 +757,10 @@ pub contract LostAndFound {
751
757
  self.DepositorStoragePath = /storage/lostAndFoundDepositor
752
758
 
753
759
  let manager <- create ShelfManager()
754
- self.account.save(<-manager, to: self.LostAndFoundStoragePath)
755
- self.account.link<&LostAndFound.ShelfManager>(self.LostAndFoundPublicPath, target: self.LostAndFoundStoragePath)
760
+ self.account.storage.save(<-manager, to: self.LostAndFoundStoragePath)
761
+
762
+ let cap = self.account.capabilities.storage.issue<&LostAndFound.ShelfManager>(self.LostAndFoundStoragePath)
763
+ self.account.capabilities.publish(cap, at: self.LostAndFoundPublicPath)
756
764
  }
757
765
  }
758
766