Smart Contract

AuctionV2

A.f5b0eb433389ac3f.AuctionV2

Deployed

12h ago
Feb 28, 2026, 04:34:50 AM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FUSD from 0x3c5959b568896393
3import Collectible from 0xf5b0eb433389ac3f
4import NonFungibleToken from 0x1d7e57aa55817448
5import Edition from 0xf5b0eb433389ac3f
6
7pub contract AuctionV2 {
8
9    pub let CollectionStoragePath: StoragePath
10    pub let CollectionPublicPath: PublicPath
11
12    pub struct AuctionStatus{
13        pub let id: UInt64
14        pub let price : UFix64
15        pub let bidIncrement : UFix64
16        pub let bids : UInt64
17        pub let active: Bool
18        pub let timeRemaining : Fix64
19        pub let endTime : Fix64
20        pub let startTime : Fix64
21        pub let startBidTime : Fix64
22        pub let metadata: Collectible.Metadata?
23        pub let collectibleId: UInt64?     
24        pub let leader: Address?
25        pub let minNextBid: UFix64
26        pub let completed: Bool
27        pub let expired: Bool
28        pub let cancelled: Bool
29        pub let currentLength: UFix64     
30     
31        init(
32            id:UInt64, 
33            currentPrice: UFix64, 
34            bids:UInt64, 
35            active: Bool, 
36            timeRemaining:Fix64, 
37            metadata: Collectible.Metadata?,
38            collectibleId: UInt64?,
39            leader:Address?, 
40            bidIncrement: UFix64,           
41            startTime: Fix64,
42            startBidTime: Fix64,
43            endTime: Fix64,
44            minNextBid:UFix64,
45            completed: Bool,
46            expired:Bool, 
47            cancelled: Bool,
48            currentLength: UFix64       
49        ) {
50            self.id = id
51            self.price = currentPrice
52            self.bids = bids
53            self.active = active
54            self.timeRemaining = timeRemaining
55            self.metadata = metadata
56            self.collectibleId = collectibleId
57            self.leader = leader
58            self.bidIncrement = bidIncrement       
59            self.startTime = startTime
60            self.startBidTime = startBidTime
61            self.endTime = endTime
62            self.minNextBid = minNextBid
63            self.completed = completed
64            self.expired = expired
65            self.cancelled = cancelled
66            self.currentLength = currentLength  
67        }
68    }
69
70    // The total amount of AuctionItems that have been created
71    pub var totalAuctions: UInt64
72
73    // Events
74    pub event CollectionCreated()
75    pub event Created(auctionID: UInt64, owner: Address, startPrice: UFix64, startTime: UFix64, auctionLength: UFix64, startBidTime: UFix64)
76    pub event Bid(auctionID: UInt64, bidderAddress: Address, bidPrice: UFix64, placedAt: Fix64)
77    pub event SetStartTime(auctionID: UInt64, startAuctionTime: UFix64)
78    pub event Settled(auctionID: UInt64, price: UFix64)
79    pub event Canceled(auctionID: UInt64)
80    pub event Earned(nftID: UInt64, amount: UFix64, owner: Address, type: String)
81    pub event FailEarned(nftID: UInt64, amount: UFix64, owner: Address, type: String)
82    pub event Extend(auctionID: UInt64, auctionLengthFrom: UFix64, auctionLengthTo: UFix64) 
83    pub event AddNFT(auctionID: UInt64, nftID: UInt64) 
84    pub event BurnNFT(auctionID: UInt64, nftID: UInt64) 
85    pub event SendNFT(auctionID: UInt64, nftID: UInt64, to: Address)   
86    pub event FailSendNFT(auctionID: UInt64, nftID: UInt64, to: Address) 
87    pub event SendBidTokens(auctionID: UInt64, amount: UFix64, to: Address)   
88    pub event FailSendBidTokens(auctionID: UInt64, amount: UFix64, to: Address) 
89
90    // AuctionItem contains the Resources and metadata for a single auction
91    pub resource AuctionItem {
92        
93        //Number of bids made, that is aggregated to the status struct
94        priv var numberOfBids: UInt64
95
96        //The Item that is sold at this auction
97        priv var NFT: @Collectible.NFT?
98
99        //This is the escrow vault that holds the tokens for the current largest bid
100        priv let bidVault: @FUSD.Vault
101
102        //The id of this individual auction
103        pub let auctionID: UInt64
104
105        //The minimum increment for a bid. This is an english auction style system where bids increase
106        priv let minimumBidIncrement: UFix64
107
108        //the time the auction should start at
109        priv var auctionStartTime: UFix64
110
111        //the start time for bids
112        priv var auctionStartBidTime: UFix64
113
114        //The length in seconds for this auction
115        priv var auctionLength: UFix64
116
117        //The period of time to extend auction
118        priv var extendedLength: UFix64
119
120        //The period of time of rest to extend
121        priv var remainLengthToExtend: UFix64
122
123        //Right now the dropitem is not moved from the collection when it ends, it is just marked here that it has ended 
124        priv var auctionCompleted: Bool
125
126        //Start price
127        access(account) var startPrice: UFix64
128
129        //Current price
130        priv var currentPrice: UFix64
131
132        //the capability that points to the resource where you want the NFT transfered to if you win this bid. 
133        priv var recipientCollectionCap: Capability<&{Collectible.CollectionPublic}>?
134
135        //the capablity to send the escrow bidVault to if you are outbid
136        priv var recipientVaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>?
137
138        //the vault receive FUSD in case of the recipient of commissiona or the previous bidder are unreachable
139        priv let platformVaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>
140
141        //This action was cancelled
142        priv var auctionCancelled: Bool
143
144        // Manage royalty for copies of the same items
145        priv let editionCap: Capability<&{Edition.EditionCollectionPublic}>
146
147        init(          
148            minimumBidIncrement: UFix64,
149            auctionStartTime: UFix64,     
150            startPrice: UFix64, 
151            auctionStartBidTime: UFix64,
152            auctionLength: UFix64,         
153            extendedLength: UFix64, 
154            remainLengthToExtend: UFix64, 
155            platformVaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>,         
156            editionCap: Capability<&{Edition.EditionCollectionPublic}>
157        ) {
158            AuctionV2.totalAuctions = AuctionV2.totalAuctions + (1 as UInt64)
159            self.NFT <- nil
160            self.bidVault <- FUSD.createEmptyVault()
161            self.auctionID = AuctionV2.totalAuctions
162            self.minimumBidIncrement = minimumBidIncrement
163            self.auctionLength = auctionLength            
164            self.extendedLength = extendedLength
165            self.remainLengthToExtend = remainLengthToExtend
166            self.startPrice = startPrice
167            self.currentPrice = 0.0
168            self.auctionStartTime = auctionStartTime
169            self.auctionStartBidTime = auctionStartBidTime
170            self.auctionCompleted = false
171            self.recipientCollectionCap = nil
172            self.recipientVaultCap = nil         
173            self.platformVaultCap = platformVaultCap
174            self.numberOfBids = 0
175            self.auctionCancelled = false
176            self.editionCap = editionCap
177        }
178
179        // sendNFT sends the NFT to the Collection belonging to the provided Capability
180        priv fun sendNFT(_ capability: Capability<&{Collectible.CollectionPublic}>) {
181            let nftId = self.NFT?.id!
182            if let collectionRef = capability.borrow() {                
183                let NFT <- self.NFT <- nil
184                collectionRef.deposit(token: <-NFT!)
185                emit SendNFT(auctionID: self.auctionID, nftID: nftId, to: collectionRef.owner!.address)  
186                return
187            }    
188            emit FailSendNFT(auctionID: self.auctionID, nftID: nftId, to: self.recipientVaultCap!.borrow()!.owner!.address)
189        }
190
191        priv fun burnNFT() {   
192            
193            if(self.NFT == nil) { 
194                return
195            }           
196
197            let nftId = self.NFT?.id!
198
199            let NFT <- self.NFT <- nil
200
201            destroy NFT 
202
203            emit BurnNFT(auctionID: self.auctionID, nftID: nftId)          
204        }
205        
206        // sendBidTokens sends the bid tokens to the previous bidder
207        priv fun sendBidTokens(_ capability: Capability<&FUSD.Vault{FungibleToken.Receiver}>) {
208            // borrow a reference to the prevous bidder's vault
209            if let vaultRef = capability.borrow() {
210                let bidVaultRef = &self.bidVault as &FUSD.Vault
211                let balance = bidVaultRef.balance
212                if(bidVaultRef.balance > 0.0) {
213                    vaultRef.deposit(from: <- bidVaultRef.withdraw(amount: balance))
214                }
215
216                emit SendBidTokens(auctionID: self.auctionID, amount: balance, to: vaultRef.owner!.address)
217                return
218            }
219
220            //  platform vault get money in case the previous bidder vault is unreachable
221            if let ownerRef = self.platformVaultCap.borrow() {
222                let bidVaultRef = &self.bidVault as &FUSD.Vault
223                let balance = bidVaultRef.balance
224                if(bidVaultRef.balance > 0.0) {
225                    ownerRef.deposit(from: <-bidVaultRef.withdraw(amount: balance))
226                }
227                emit FailSendBidTokens(auctionID: self.auctionID, amount: balance, to: ownerRef.owner!.address)
228                return
229            }
230        }
231
232        priv fun releasePreviousBid() {
233            if let vaultCap = self.recipientVaultCap {
234                self.sendBidTokens(self.recipientVaultCap!)
235                return
236            } 
237        }
238
239        pub fun getEditionNumber(id: UInt64): UInt64? {             
240            return self.NFT?.editionNumber
241        }
242
243        priv fun sendCommissionPayment() {
244
245            let editionNumber = self.NFT?.editionNumber!
246
247            let editionRef = self.editionCap.borrow()!   
248
249            let editionStatus = editionRef.getEdition(editionNumber)!  
250
251            for key in editionStatus.royalty.keys {
252                if (editionStatus.royalty[key]!.firstSalePercent > 0.0) {
253                    let commission = self.currentPrice * editionStatus.royalty[key]!.firstSalePercent * 0.01
254
255                    let account = getAccount(key) 
256
257                    let vaultCap = account.getCapability<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver)    
258
259                    if (vaultCap.check()) {
260                        let vault = vaultCap.borrow()!
261                        vault.deposit(from: <- self.bidVault.withdraw(amount: commission))
262                        emit Earned(nftID: self.NFT?.id!, amount: commission, owner: key, type: editionStatus.royalty[key]!.description)
263                    } else {
264                        emit FailEarned(nftID: self.NFT?.id!, amount: commission, owner: key, type: editionStatus.royalty[key]!.description)
265                    }            
266                }                
267            }
268
269            // If commission was not paid, this money get platform
270
271            if (self.bidVault.balance > 0.0) {
272
273                let amount = self.bidVault.balance
274
275                let platformVault = self.platformVaultCap.borrow()!
276
277                platformVault.deposit(from: <- self.bidVault.withdraw(amount: amount))
278
279                emit Earned(nftID: self.NFT?.id!, amount: amount, owner: platformVault.owner!.address, type: "PLATFORM")
280            }
281        }
282
283        pub fun settleAuction()  {
284
285            pre {
286                !self.auctionCancelled : "The auction was cancelled"
287                !self.auctionCompleted : "The auction has been already settled"
288                self.NFT != nil: "NFT in auction does not exist"
289                self.isAuctionExpired() : "Auction has not completed yet"               
290            }
291
292            // burn token if there are no bids to settle
293            if self.currentPrice == 0.0 {
294                self.burnNFT()
295                self.auctionCompleted = true
296                emit Settled(auctionID: self.auctionID, price: self.currentPrice)
297                return
298            }       
299
300            self.sendCommissionPayment()
301           
302            self.sendNFT(self.recipientCollectionCap!)
303         
304            self.auctionCompleted = true
305            
306            emit Settled(auctionID: self.auctionID, price: self.currentPrice)
307        }
308
309        //this can be negative if is expired
310        pub fun timeRemaining() : Fix64 {
311            // Case, when auction time ddi not start, because nobody set the first bid
312            if(self.auctionStartBidTime > 0.0 && self.numberOfBids == 0) {
313              return 0.0
314            }
315
316            let auctionLength = self.auctionLength
317
318            let startTime = self.auctionStartTime
319
320            let currentTime = getCurrentBlock().timestamp
321
322            let remaining = Fix64(startTime + auctionLength) - Fix64(currentTime)
323
324            return remaining
325        }
326
327        pub fun isAuctionExpired(): Bool {
328            let timeRemaining = self.timeRemaining()
329            return timeRemaining < Fix64(0.0)
330        }
331
332        pub fun minNextBid() : UFix64 {
333            //If there are bids then the next min bid is the current price plus the increment
334            if self.currentPrice != 0.0 {
335                return self.currentPrice + self.currentPrice * self.minimumBidIncrement * 0.01
336            }
337
338            //else start Collectible price
339            return self.startPrice
340        }
341
342        priv fun extendAuction() {
343            if (
344                //Auction time left is less than remainLengthToExtend
345                self.timeRemaining() < Fix64(self.remainLengthToExtend) 
346                //This is not the first bid in the reserve auction
347                && (self.auctionStartBidTime == 0.0 || (self.auctionStartBidTime > 0.0 && self.numberOfBids > 1))
348            ) {
349                self.auctionLength = self.auctionLength + self.extendedLength
350                emit Extend(auctionID: self.auctionID, auctionLengthFrom: self.auctionLength - self.extendedLength, auctionLengthTo: self.auctionLength)
351            }            
352        }
353
354        pub fun bidder() : Address? {
355            if let vaultCap = self.recipientVaultCap {
356                // Check possible situation, where vault was unlinked after bid
357                // Test this case in automated test
358                if !vaultCap.check() {
359                    return nil
360                }
361
362                return vaultCap.borrow()!.owner!.address
363            }
364            return nil
365        }
366
367        pub fun currentBidForUser(address:Address): UFix64 {            
368            if(self.bidder() == address) {
369                return self.bidVault.balance
370            }
371            return 0.0
372        }
373
374        // This method should probably use preconditions more
375        pub fun placeBid(bidTokens: @FUSD.Vault, vaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>, collectionCap: Capability<&{Collectible.CollectionPublic}>) {
376
377            pre {
378                vaultCap.check() : "Fungible token storage is not initialized on account"
379                collectionCap.check() : "NFT storage is not initialized on account"
380                !self.auctionCancelled : "Auction was cancelled"
381                self.NFT != nil: "NFT in auction does not exist"
382                self.auctionStartTime < getCurrentBlock().timestamp || self.auctionStartTime == 0.0: "The auction has not started yet"             
383                !self.isAuctionExpired() : "Time expired"
384                bidTokens.balance <= 999999.99 : "Bid should be less than 1 000 000.00" 
385                self.auctionStartBidTime < getCurrentBlock().timestamp || self.auctionStartBidTime == 0.0: "The auction bid time has not started yet"       
386            }
387
388            let bidderAddress = vaultCap.borrow()!.owner!.address
389            let collectionAddress = collectionCap.borrow()!.owner!.address
390
391            if bidderAddress != collectionAddress {
392              panic("you cannot make a bid and send the Collectible to somebody else collection")
393            }
394
395            let amountYouAreBidding = bidTokens.balance + self.currentBidForUser(address: bidderAddress)
396
397            let minNextBid = self.minNextBid()
398
399            if amountYouAreBidding < minNextBid {
400                panic("Bid is less than min acceptable")
401            }
402
403            // The first bid sets start auction time if auctionStartTime is not defined
404            if self.bidVault.balance == 0.0 && self.auctionStartTime == 0.0 {
405               self.auctionStartTime = getCurrentBlock().timestamp
406               emit SetStartTime(auctionID: self.auctionID, startAuctionTime: self.auctionStartTime)
407            }
408
409            if self.bidder() != bidderAddress {
410              if self.bidVault.balance != 0.0 {
411                // Return the previous bid 
412                self.sendBidTokens(self.recipientVaultCap!)
413              }
414            }
415
416            // Update the bidVault to store the current bid
417            self.bidVault.deposit(from: <-bidTokens)
418
419            //update the capability of the wallet for the address with the current highest bid
420            self.recipientVaultCap = vaultCap
421
422            // Update the current price of the token
423            self.currentPrice = self.bidVault.balance
424
425            // Add the bidder's Vault and NFT receiver references
426            self.recipientCollectionCap = collectionCap
427            self.numberOfBids = self.numberOfBids + (1 as UInt64)
428
429            // Extend auction according to time left and extened length
430            self.extendAuction() 
431
432            emit Bid(auctionID: self.auctionID, bidderAddress: bidderAddress, bidPrice: self.currentPrice, placedAt: Fix64(getCurrentBlock().timestamp))
433        }
434
435        pub fun getAuctionStatus() : AuctionStatus {
436
437            var leader : Address? = nil
438            
439            if let recipient = self.recipientVaultCap {
440                leader = recipient.borrow()!.owner!.address
441            }
442
443            return AuctionStatus(
444                id: self.auctionID,
445                currentPrice: self.currentPrice, 
446                bids: self.numberOfBids,
447                active: !self.auctionCompleted && !self.isAuctionExpired(),
448                timeRemaining: self.timeRemaining(),
449                metadata: self.NFT?.metadata,
450                collectibleId: self.NFT?.id,
451                leader: leader,
452                bidIncrement: self.minimumBidIncrement,         
453                startTime: Fix64(self.auctionStartTime),
454                startBidTime: Fix64(self.auctionStartBidTime),
455                endTime: self.auctionStartTime > 0.0 ? Fix64(self.auctionStartTime+self.auctionLength) : Fix64(0.0),
456                minNextBid: self.minNextBid(),
457                completed: self.auctionCompleted,
458                expired: self.isAuctionExpired(),
459                cancelled: self.auctionCancelled,
460                currentLength: self.auctionLength
461            )
462        }
463
464        pub fun cancelAuction() {
465            pre {
466                !self.auctionCancelled : "The auction has been already cancelled"
467                !self.auctionCompleted : "The auction was settled"           
468            }
469            self.releasePreviousBid()
470            self.burnNFT()
471            self.auctionCancelled = true
472        }
473
474        pub fun addNFT(NFT: @Collectible.NFT) {
475            pre {
476                self.NFT == nil : "NFT in auction has already existed"
477            }
478
479            let nftID = NFT.id
480
481            self.NFT <-! NFT
482
483            emit AddNFT(auctionID: self.auctionID, nftID: nftID) 
484        }
485
486        pub fun reclaimSendNFT(collectionCap: Capability<&{Collectible.CollectionPublic}>)  {
487
488            pre {
489                self.auctionCompleted : "The auction has not been settled yet"
490                self.NFT != nil: "NFT in auction does not exist"      
491            }
492
493            self.sendNFT(collectionCap)         
494        }
495
496        destroy() {
497            log("destroy auction")
498                       
499            // if there's a bidder, therefore minumum one bid
500            if let vaultCap = self.recipientVaultCap {
501                // ...send the bid tokens back to the bidder
502                self.sendBidTokens(vaultCap)
503            }
504
505            self.burnNFT()
506
507            destroy self.NFT
508            destroy self.bidVault
509        }
510    }    
511
512    // AuctionCollectionPublic is a resource interface that restricts users to
513    // retreiving the auction price list and placing bids
514    pub resource interface AuctionCollectionPublic {
515
516        pub fun getAuctionStatuses(): {UInt64: AuctionStatus}
517        pub fun getAuctionStatus(_ id:UInt64): AuctionStatus?
518        pub fun getTimeLeft(_ id: UInt64): Fix64?
519     
520        pub fun placeBid(
521            id: UInt64, 
522            bidTokens: @FUSD.Vault, 
523            vaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>, 
524            collectionCap: Capability<&{Collectible.CollectionPublic}>
525        )
526    }
527
528    // AuctionCollection contains a dictionary of AuctionItems and provides
529    // methods for manipulating the AuctionItems
530    pub resource AuctionCollection: AuctionCollectionPublic {
531
532        // Auction Items
533        access(account) var auctionItems: @{UInt64: AuctionItem}       
534
535        init() { 
536            self.auctionItems <- {}
537        }
538
539        pub fun keys() : [UInt64] {
540            return self.auctionItems.keys
541        }
542
543        // addTokenToAuctionItems adds an NFT to the auction items and sets the meta data
544        // for the auction item
545        pub fun createAuction(       
546            minimumBidIncrement: UFix64, 
547            auctionLength: UFix64,           
548            extendedLength: UFix64, 
549            remainLengthToExtend: UFix64,
550            auctionStartTime: UFix64,
551            startPrice: UFix64,           
552            startBidTime: UFix64,      
553            platformVaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>,         
554            editionCap: Capability<&{Edition.EditionCollectionPublic}>
555        ): UInt64 {
556
557            pre {              
558                auctionLength > 0.00 : "Auction lenght should be more than 0.00"
559                auctionStartTime > getCurrentBlock().timestamp || auctionStartTime == 0.0: "Auction start time can't be in the past"
560                startPrice > 0.00 : "Start price should be more than 0.00"
561                startPrice <= 999999.99 : "Start bid should be less than 1 000 000.00"
562                minimumBidIncrement > 0.00 : "Minimum bid increment should be more than 0.00"
563                platformVaultCap.check() : "Platform vault should be reachable"
564                startBidTime > getCurrentBlock().timestamp || startBidTime == 0.0: "Auction start bid time can't be in the past"
565                (startBidTime == 0.0 && auctionStartTime == 0.0) == false: "Start bid time and auction start time can't equal 0.0 both"
566                (startBidTime > 0.0 && auctionStartTime > 0.0) == false: "Start bid time and auction start time can't be more than 0.0 both"
567            }
568            
569            // create a new auction items resource container
570            let item <- create AuctionItem(         
571                minimumBidIncrement: minimumBidIncrement, 
572                auctionStartTime: auctionStartTime,  
573                startPrice: startPrice,
574                auctionStartBidTime: startBidTime,
575                auctionLength: auctionLength,           
576                extendedLength: extendedLength,    
577                remainLengthToExtend:  remainLengthToExtend,                
578                platformVaultCap: platformVaultCap,
579                editionCap: editionCap
580            )
581
582            let id = item.auctionID
583
584            // update the auction items dictionary with the new resources
585            let oldItem <- self.auctionItems[id] <- item
586            
587            destroy oldItem
588
589            let owner = platformVaultCap.borrow()!.owner!.address
590
591            emit Created(auctionID: id, owner: owner, startPrice: startPrice,  startTime: auctionStartTime, auctionLength: auctionLength, startBidTime: startBidTime)
592
593            return id
594        }
595
596        // getAuctionPrices returns a dictionary of available NFT IDs with their current price
597        pub fun getAuctionStatuses(): {UInt64: AuctionStatus} {
598           
599            if self.auctionItems.keys.length == 0 { 
600                return {} 
601            }           
602
603            let priceList: {UInt64: AuctionStatus} = {}
604
605            for id in self.auctionItems.keys {
606                let itemRef = &self.auctionItems[id] as? &AuctionItem?
607                priceList[id] = itemRef!.getAuctionStatus()
608            }
609            
610            return priceList
611        }
612
613        pub fun getAuctionStatus(_ id:UInt64): AuctionStatus? {
614    
615            if  self.auctionItems[id] == nil {
616                return  nil
617            }        
618
619            // Get the auction item resources
620            let itemRef = &self.auctionItems[id] as &AuctionItem?
621            return itemRef!.getAuctionStatus()
622        }
623
624        pub fun getTimeLeft(_ id: UInt64): Fix64? {
625            if(self.auctionItems[id] == nil) {
626                return nil
627            }
628
629            // Get the auction item resources
630            let itemRef = &self.auctionItems[id] as &AuctionItem?
631            return itemRef!.timeRemaining()
632        }
633
634        // settleAuction sends the auction item to the highest bidder
635        // and deposits the FungibleTokens into the auction owner's account
636        pub fun settleAuction(_ id: UInt64) {
637            pre {
638                self.auctionItems[id] != nil: "Auction does not exist"
639            }
640
641            let itemRef = &self.auctionItems[id] as &AuctionItem?
642            itemRef!.settleAuction()
643        }
644
645        pub fun cancelAuction(_ id: UInt64) {
646            pre {
647                self.auctionItems[id] != nil: "Auction does not exist"
648            }
649            let itemRef = &self.auctionItems[id] as &AuctionItem?        
650            itemRef!.cancelAuction()
651            emit Canceled(auctionID: id)
652        }
653
654        // placeBid sends the bidder's tokens to the bid vault and updates the
655        // currentPrice of the current auction item
656        pub fun placeBid(id: UInt64, bidTokens: @FUSD.Vault, vaultCap: Capability<&FUSD.Vault{FungibleToken.Receiver}>, collectionCap: Capability<&{Collectible.CollectionPublic}>) {
657            pre {
658                self.auctionItems[id] != nil:
659                    "Auction does not exist in this drop"
660            }
661
662            // Get the auction item resources
663            let itemRef = &self.auctionItems[id] as &AuctionItem?
664            itemRef!.placeBid(
665                bidTokens: <- bidTokens, 
666                vaultCap : vaultCap, 
667                collectionCap:collectionCap
668            )
669        }
670
671        pub fun addNFT(id: UInt64, NFT: @Collectible.NFT) {
672            pre {
673                self.auctionItems[id] != nil:
674                    "Auction does not exist"
675            }
676            let itemRef = &self.auctionItems[id] as &AuctionItem?
677
678            itemRef!.addNFT(NFT: <- NFT)
679        }
680
681        pub fun reclaimSendNFT(id: UInt64, collectionCap: Capability<&{Collectible.CollectionPublic}>) {
682            pre {
683                self.auctionItems[id] != nil: "Auction does not exist"
684            }
685            let itemRef = &self.auctionItems[id] as &AuctionItem?          
686            itemRef!.reclaimSendNFT(collectionCap: collectionCap)   
687        }
688
689        destroy() {
690            log("destroy auction collection")
691            // destroy the empty resources
692            destroy self.auctionItems
693        }
694    }
695
696    // createAuctionCollection returns a new AuctionCollection resource to the caller
697    priv fun createAuctionCollection(): @AuctionCollection {
698        let auctionCollection <- create AuctionCollection()
699    
700        return <- auctionCollection
701    }
702
703    init() {
704        self.totalAuctions = (10 as UInt64)
705        self.CollectionPublicPath = /public/NFTXtinglesBloctoAuctionV2
706        self.CollectionStoragePath = /storage/NFTXtinglesBloctoAuctionV2
707
708        let sale <- AuctionV2.createAuctionCollection()
709        self.account.save(<-sale, to:AuctionV2.CollectionStoragePath)         
710        self.account.link<&{AuctionV2.AuctionCollectionPublic}>(AuctionV2.CollectionPublicPath, target:AuctionV2.CollectionStoragePath)
711    }   
712}