Smart Contract

InceptionMinter

A.83ed64a1d4f3833f.InceptionMinter

Deployed

14h ago
Feb 28, 2026, 02:29:56 AM UTC

Dependents

0 imports
1// SPDX-License-Identifier: MIT
2
3import InceptionAvatar from 0x83ed64a1d4f3833f
4import FungibleToken from 0xf233dcee88fe0abe
5import NonFungibleToken from 0x1d7e57aa55817448
6import DapperUtilityCoin from 0xead892083b3e2c6c
7import FlowUtilityToken from 0xead892083b3e2c6c
8import InceptionCrystal from 0x83ed64a1d4f3833f
9import InceptionBlackBox from 0x83ed64a1d4f3833f
10
11pub contract InceptionMinter {
12
13  pub event ContractInitialized()
14
15  pub let AdminStoragePath: StoragePath
16  pub var tipMintPriceInDuc: UFix64
17  pub var tipMintPriceInFlow: UFix64
18
19  pub var preSaleMintLimitPerTx: UInt64
20  pub var tipSaleLimitPerTx: UInt64
21
22  access(self) var whitelistedAccounts: {Address: UInt64}
23  access(self) var publicMintedAccounts: {Address: UInt64}
24  access(self) var tipMintedAccounts: {Address: UInt64}
25  access(self) var usdTipTracker: {Address: UFix64}
26  access(self) var flowTipTracker: {Address: UFix64}
27
28  pub fun tipMintWithDUC(buyer: Address, setID: UInt64, paymentVault: @FungibleToken.Vault, merchantAccount: Address, numberOfTokens: UInt64) {
29    pre {
30      UInt64(self.tipMintedAccounts[buyer] ?? 0) + numberOfTokens <= 5:
31        "You've tipped too much. Please wait for the next tip sale."
32      numberOfTokens <= InceptionMinter.tipSaleLimitPerTx:
33        "purchaseAmount too large"
34      paymentVault.balance >= UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInDuc:
35        "Insufficient payment amount."
36      paymentVault.getType() == Type<@DapperUtilityCoin.Vault>():
37        "payment type not DapperUtilityCoin.Vault."
38    }
39
40    let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
41      ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
42
43    let set = admin.borrowSet(setID: setID)
44    // Check set availability
45    if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
46    // Check set eligibility
47    if (set.locked) { panic("Set is locked") }
48
49    // Get DUC receiver reference of InceptionAvatar merchant account
50    let merchantDUCReceiverRef = getAccount(merchantAccount).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
51      assert(merchantDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed merchant DUC receiver")
52    // Deposit DUC to InceptionAvatar merchant account DUC Vault (it's then forwarded to the main DUC contract afterwards)
53    merchantDUCReceiverRef.borrow()!.deposit(from: <-paymentVault)
54
55    // Get buyer collection public to receive InceptionAvatar
56    let recipient = getAccount(buyer)
57    let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
58      .borrow<&{NonFungibleToken.CollectionPublic}>()
59      ?? panic("Could not get receiver reference to the NFT Collection")
60
61    // Mint InceptionAvatar NFTs per purchaseAmount
62    var mintCounter = numberOfTokens
63    while(mintCounter > 0) {
64      admin.mintNFT(recipient: NFTReceiver, setID: setID)
65      mintCounter = mintCounter - 1
66    }
67
68    // Add number of mints to tipMintedAccounts
69    InceptionMinter.tipMintedAccounts[buyer] = UInt64(InceptionMinter.tipMintedAccounts[buyer] ?? 0) + numberOfTokens
70
71    // Add amount to tipTracker
72    InceptionMinter.usdTipTracker[buyer] = UFix64(InceptionMinter.usdTipTracker[buyer] ?? 0.00) + UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInDuc
73
74    // Hidden gem from the brotherhood of tinkers for your generosity
75    if (InceptionBlackBox.mintLimit >= InceptionBlackBox.totalSupply) {
76      let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
77      ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
78
79      let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
80        .borrow<&{NonFungibleToken.CollectionPublic}>()
81        ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
82
83      var blackBoxMintCounter = numberOfTokens
84      while(blackBoxMintCounter > 0) {
85        InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
86        blackBoxMintCounter = blackBoxMintCounter - 1
87      }
88    }
89  }
90
91  pub fun tipMintWithFUT(buyer: Address, setID: UInt64, paymentVault: @FungibleToken.Vault, merchantAccount: Address, numberOfTokens: UInt64) {
92    pre {
93      UInt64(self.tipMintedAccounts[buyer] ?? 0) + numberOfTokens < 10:
94        "You've tipped too much. Please wait for the next tip sale."
95      numberOfTokens <= InceptionMinter.tipSaleLimitPerTx:
96        "purchaseAmount too large"
97      paymentVault.balance >= UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInFlow:
98        "Insufficient payment amount."
99      paymentVault.getType() == Type<@FlowUtilityToken.Vault>():
100        "payment type not FlowUtilityToken.Vault."
101    }
102
103    let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
104      ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
105
106    let set = admin.borrowSet(setID: setID)
107    // Check set availability
108    if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
109    // Check set eligibility
110    if (set.locked) { panic("Set is locked") }
111    if (set.isPublic) { panic("Cannot mint public set with mintPrivateNFTWithFUT") }
112
113    // Get FUT receiver reference of InceptionAvatar merchant account
114    let merchantFUTReceiverRef = getAccount(merchantAccount).getCapability<&{FungibleToken.Receiver}>(/public/flowUtilityTokenReceiver)
115      assert(merchantFUTReceiverRef.borrow() != nil, message: "Missing or mis-typed merchant FUT receiver")
116    // Deposit FUT to InceptionAvatar merchant account FUT Vault (it's then forwarded to the main FUT contract afterwards)
117    merchantFUTReceiverRef.borrow()!.deposit(from: <-paymentVault)
118
119    // Get buyer collection public to receive InceptionAvatar
120    let recipient = getAccount(buyer)
121    let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
122      .borrow<&{NonFungibleToken.CollectionPublic}>()
123      ?? panic("Could not get receiver reference to the NFT Collection")
124
125    // Mint InceptionAvatar NFTs per purchaseAmount
126    var mintCounter = numberOfTokens
127    while(mintCounter > 0) {
128      admin.mintNFT(recipient: NFTReceiver, setID: setID)
129      mintCounter = mintCounter - 1
130    }
131
132    // Add number of mints to tipMintedAccounts
133    InceptionMinter.tipMintedAccounts[buyer] = UInt64(InceptionMinter.tipMintedAccounts[buyer] ?? 0) + numberOfTokens
134
135    // Add amount to tipTracker
136    InceptionMinter.flowTipTracker[buyer] = UFix64(InceptionMinter.flowTipTracker[buyer] ?? 0.00) + UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInFlow
137
138    // Hidden gem from the brotherhood of tinkers for your generosity
139    if (InceptionBlackBox.mintLimit >= InceptionBlackBox.totalSupply) {
140      let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
141      ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
142
143      let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
144        .borrow<&{NonFungibleToken.CollectionPublic}>()
145        ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
146
147      var blackBoxMintCounter = numberOfTokens
148      while(blackBoxMintCounter > 0) {
149        InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
150        blackBoxMintCounter = blackBoxMintCounter - 1
151      }
152    }
153  }
154
155  pub fun mintInceptionBlackBoxWithInceptionCrystal(buyer: Address, paymentVault: @InceptionCrystal.Collection) {
156    pre {
157      UInt64(paymentVault.getIDs().length) == InceptionBlackBox.crystalPrice:
158        "incorrect crystal payment"
159    }
160
161    let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
162      ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
163
164    let recipient = getAccount(buyer)
165    let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
166      .borrow<&{NonFungibleToken.CollectionPublic}>()
167      ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
168
169    InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
170
171    destroy <- paymentVault
172  }
173
174  pub fun whitelistFreeMint(buyer: Address, setID: UInt64, numberOfTokens: UInt64) {
175    pre {
176      InceptionMinter.whitelistedAccounts[buyer]! >= 1:
177        "Requesting account is not whitelisted"
178      numberOfTokens <= InceptionMinter.preSaleMintLimitPerTx:
179        "purchaseAmount too large"
180      InceptionMinter.whitelistedAccounts[buyer]! >= numberOfTokens:
181        "purchaseAmount exeeds allowed whitelist spots"
182    }
183    
184    let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
185      ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
186
187    let set = admin.borrowSet(setID: setID)
188    // Check set availability
189    if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
190    // Check set eligibility
191    if (set.locked) { panic("Set is locked") }
192
193    // Get buyer collection public to receive InceptionAvatar
194    let recipient = getAccount(buyer)
195    let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
196      .borrow<&{NonFungibleToken.CollectionPublic}>()
197      ?? panic("Could not get receiver reference to the NFT Collection")
198
199    // Validate buyer's DUC receiver
200    let buyerDUCReceiverRef = getAccount(buyer).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
201      assert(buyerDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed buyer DUC receiver")
202
203    // Mint InceptionAvatar NFTs per purchaseAmount
204    var mintCounter = numberOfTokens
205    while(mintCounter > 0) {
206      admin.mintNFT(recipient: NFTReceiver, setID: setID)
207      mintCounter = mintCounter - 1
208    }
209
210    // Empty whitelist spot
211    if (InceptionMinter.whitelistedAccounts[buyer]! - numberOfTokens == 0) {
212      InceptionMinter.whitelistedAccounts.remove(key: buyer)
213    } else {
214      InceptionMinter.whitelistedAccounts[buyer] = InceptionMinter.whitelistedAccounts[buyer]! - numberOfTokens
215    }
216  }
217
218  // 1 for each outcast
219  pub fun publicFreeMint(buyer: Address, setID: UInt64) {
220    pre {
221      !self.publicMintedAccounts.containsKey(buyer):
222        "Requesting account has already minted"
223
224      getCurrentBlock().timestamp >= 1663797540.00:
225        "Not time yet"
226    }
227
228    let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
229      ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
230
231    let set = admin.borrowSet(setID: setID)
232    // Check set availability
233    if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
234    // Check set eligibility
235    if (set.locked) { panic("Set is locked") }
236
237    // Get buyer collection public to receive InceptionAvatar
238    let recipient = getAccount(buyer)
239    let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
240      .borrow<&{NonFungibleToken.CollectionPublic}>()
241      ?? panic("Could not get receiver reference to the NFT Collection")
242
243    // Validate buyer's DUC receiver
244    let buyerDUCReceiverRef = getAccount(buyer).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
245      assert(buyerDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed buyer DUC receiver")
246
247    // Mint InceptionAvatar NFT to recipient
248    admin.mintNFT(recipient: NFTReceiver, setID: setID)
249
250    // Add wallet address to minted list
251    self.publicMintedAccounts[buyer] = 1
252  }
253
254  pub resource Admin {
255    pub fun addWhiteListAddress(address: Address, amount: UInt64) {
256      pre {
257        amount <= 10:
258          "Unable to allocate more than 10 whitelist spots"
259        InceptionMinter.whitelistedAccounts[address] == nil:
260          "Provided Address is already whitelisted"
261      }
262      InceptionMinter.whitelistedAccounts[address] = amount
263    }
264
265    pub fun removeWhiteListAddress(address: Address) {
266      pre {
267        InceptionMinter.whitelistedAccounts[address] != nil:
268          "Provided Address is not whitelisted"
269      }
270      InceptionMinter.whitelistedAccounts.remove(key: address)
271    }
272
273    pub fun pruneWhitelist() {
274      InceptionMinter.whitelistedAccounts = {}
275    }
276
277    pub fun updateWhiteListAddressAmount(address: Address, amount: UInt64) {
278      pre {
279        InceptionMinter.whitelistedAccounts[address] != nil:
280          "Provided Address is not whitelisted"
281      }
282      InceptionMinter.whitelistedAccounts[address] = amount
283    }
284
285    pub fun updateTipSalePriceInDUC(price: UFix64) {
286      InceptionMinter.tipMintPriceInDuc = price
287    }
288
289    pub fun updateTipSalePriceInFlow(price: UFix64) {
290      InceptionMinter.tipMintPriceInFlow = price
291    }
292
293    pub fun getDucTipJar(): {Address: UFix64} {
294      return InceptionMinter.usdTipTracker
295    }
296
297    pub fun getFlowTipJar(): {Address: UFix64} {
298      return InceptionMinter.flowTipTracker
299    }
300
301    pub fun pruneAccount(address: Address) {
302      if InceptionMinter.tipMintedAccounts.containsKey(address) {
303        InceptionMinter.tipMintedAccounts.remove(key: address)
304      }
305
306      if InceptionMinter.whitelistedAccounts.containsKey(address) {
307        InceptionMinter.whitelistedAccounts.remove(key: address)
308      }
309
310      if InceptionMinter.publicMintedAccounts.containsKey(address) {
311        InceptionMinter.publicMintedAccounts.remove(key: address)
312      }
313    }
314  }
315
316  pub fun getWhitelistedAccounts(): {Address: UInt64} {
317    return InceptionMinter.whitelistedAccounts
318  }
319
320  pub fun getWhitelistedEntriesByAddress(address: Address): UInt64 {
321    return InceptionMinter.whitelistedAccounts[address] ?? 0
322  }
323
324  pub fun getTipMintAccounts(): {Address: UInt64} {
325    return InceptionMinter.tipMintedAccounts
326  }
327
328  pub fun getTipMintCountPerAccount(address: Address): UInt64 {
329    return InceptionMinter.tipMintedAccounts[address] ?? 0
330  }
331
332  pub fun getPublicMintCountPerAccount(address: Address): UInt64 {
333    return InceptionMinter.publicMintedAccounts[address] ?? 0
334  }
335
336  init() {
337    self.AdminStoragePath = /storage/InceptionAvatarWhitelistMinterAdmin
338
339    self.preSaleMintLimitPerTx = 4
340    self.tipSaleLimitPerTx = 5
341
342    self.tipMintPriceInDuc = 20.00
343    self.tipMintPriceInFlow = 12.00
344
345    self.whitelistedAccounts = {}
346    self.publicMintedAccounts = {}
347
348    self.tipMintedAccounts = {}
349    self.usdTipTracker = {}
350    self.flowTipTracker = {}
351
352    let admin <- create Admin()
353    self.account.save(<-admin, to: self.AdminStoragePath)
354
355    emit ContractInitialized()
356  }
357}