Smart Contract

FlovatarInbox

A.921ea449dffec68a.FlovatarInbox

Deployed

1w ago
Feb 16, 2026, 11:20:41 PM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import NonFungibleToken from 0x1d7e57aa55817448
3import FlowToken from 0x1654653399040a61
4import FlovatarComponentTemplate from 0x921ea449dffec68a
5import FlovatarComponent from 0x921ea449dffec68a
6import FlovatarPack from 0x921ea449dffec68a
7import FlovatarDustToken from 0x921ea449dffec68a
8import Flovatar from 0x921ea449dffec68a
9import HybridCustody from 0xd8a7e05a7ac670c0
10
11/*
12
13 This contract defines the Inbox for Flovatars and Flovatar owners where they can withdraw their
14 airdrops and rewards and claim the daily DUST distributed for each Flovatar.
15
16 This contract contains also the Admin resource that can be used to manage the different inboxes.
17
18 The following inboxes are provided:
19 - DUST reward vault for each Flovatar
20 - Flobit (FlovatarComponent) airdrop/reward collection for each Flovatar
21 - DUST reward vault for each Flovatar owner wallet
22 - Flobit (FlovatarComponent) airdrop/reward collection for each Flovatar owner wallet
23 - DUST for each Flovatar that can be claimed daily and that is coming from the Community Vault distribution
24
25 */
26
27access(all)
28contract FlovatarInbox{
29
30    access(all) entitlement Withdraw
31	
32	// The withdrawEnabled will allow to put all withdraws on hold while the distribution of new airdrops is happening
33	// So that everyone will be then be able to access his rewards at the same time
34	access(account)
35	var withdrawEnabled: Bool
36	
37	//The communityVault holds the total of the DUST assigned to the community distribution over a period of 10 years
38	access(account)
39	let communityVault: @FlovatarDustToken.Vault
40	
41	//Stores the timestamp when Dust was first release and when the community distribution should start
42	access(all)
43	let dustDistributionStart: UFix64
44	
45	//Defines the amount of Dust to distribute to each Flovatar for each Rarity Score point
46	access(all)
47	var dustPerDayPerScore: UFix64
48	
49	access(all)
50	let CollectionStoragePath: StoragePath
51	
52	access(all)
53	let CollectionPublicPath: PublicPath
54	
55	// Event to notify about the Inbox creation
56	access(all)
57	event ContractInitialized()
58	
59	// Events to notify when Dust or Components are deposited or withdrawn
60	access(all)
61	event FlovatarDepositComponent(flovatarId: UInt64, componentId: UInt64)
62	
63	access(all)
64	event FlovatarDepositDust(id: UInt64, amount: UFix64)
65	
66	access(all)
67	event FlovatarWithdrawComponent(flovatarId: UInt64, componentId: UInt64, to: Address)
68	
69	access(all)
70	event FlovatarWithdrawDust(id: UInt64, amount: UFix64, to: Address)
71	
72	access(all)
73	event WalletDepositComponent(address: Address, componentId: UInt64)
74	
75	access(all)
76	event WalletDepositDust(address: Address, amount: UFix64)
77	
78	access(all)
79	event WalletWithdrawComponent(address: Address, componentId: UInt64)
80	
81	access(all)
82	event WalletWithdrawDust(address: Address, amount: UFix64)
83	
84	access(all)
85	event FlovatarClaimedCommunityDust(id: UInt64, amount: UFix64, to: Address)
86	
87	// This struct contains all the information about the Dust the be claimed for each Flovatar by the user
88	access(all)
89	struct ClaimableDust{ 
90		access(all)
91		let amount: UFix64
92		
93		access(all)
94		let days: UInt64
95		
96		access(all)
97		let rarityScore: UFix64
98		
99		access(all)
100		let flovatarId: UInt64
101		
102		access(all)
103		let wallet: Address
104		
105		init(
106			amount: UFix64,
107			days: UInt64,
108			rarityScore: UFix64,
109			flovatarId: UInt64,
110			wallet: Address
111		){ 
112			self.amount = amount
113			self.days = days
114			self.rarityScore = rarityScore
115			self.flovatarId = flovatarId
116			self.wallet = wallet
117		}
118	}
119	
120	// The Container resounce holds both the FlovatarComponent Dictionary and the DUST Vault
121	access(all)
122	resource Container{ 
123		access(contract)
124		let dustVault: @FlovatarDustToken.Vault
125		
126		access(contract)
127		let flovatarComponents: @{UInt64: FlovatarComponent.NFT}
128		
129		access(self)
130		var blockHeight: UInt64
131		
132		// Initialize a Template with all the necessary data
133		init(){ 
134			self.dustVault <- FlovatarDustToken.createEmptyDustVault()
135			self.flovatarComponents <-{} 
136			self.blockHeight = getCurrentBlock().height
137		}
138		
139		access(all)
140		fun insertComponent(component: @FlovatarComponent.NFT){ 
141			let oldComponent <- self.flovatarComponents[component.id] <- component
142			destroy oldComponent
143			self.blockHeight = getCurrentBlock().height
144		}
145		
146		access(all)
147		fun withdrawComponent(id: UInt64): @FlovatarComponent.NFT{ 
148			pre{ 
149				self.blockHeight <= getCurrentBlock().height:
150					"You need to wait at least one Block to withdraw the NFT"
151			}
152			let token <- self.flovatarComponents.remove(key: id) ?? panic("missing NFT")
153			return <-token
154		}
155
156		access(all)
157		fun withdrawDust(amount: UFix64): @{FungibleToken.Vault}{ 
158			return <-self.dustVault.withdraw(amount: amount)
159		}
160	}
161	
162	access(all)
163	resource interface CollectionPublic{ 
164		access(all)
165		fun depositDustToFlovatar(id: UInt64, vault: @{FungibleToken.Vault})
166		
167		access(all)
168		fun depositDustToWallet(address: Address, vault: @{FungibleToken.Vault})
169		
170		access(all)
171		fun depositComponentToFlovatar(id: UInt64, component: @FlovatarComponent.NFT)
172		
173		access(all)
174		fun depositComponentToWallet(address: Address, component: @FlovatarComponent.NFT)
175		
176		access(all)
177		fun getFlovatarDustBalance(id: UInt64): UFix64
178		
179		access(all)
180		fun getWalletDustBalance(address: Address): UFix64
181		
182		access(all)
183		fun getFlovatarComponentIDs(id: UInt64): [UInt64]
184		
185		access(all)
186		fun getWalletComponentIDs(address: Address): [UInt64]
187		
188		access(all)
189		fun getLastClaimedDust(id: UInt64): UFix64
190	}
191	
192	// The main Collection that manages the Containers
193	access(all)
194	resource Collection: CollectionPublic{ 
195		
196		// Dictionary of Containers for the Flovatars and the Flovatar Owners Wallets
197		access(all)
198		var flovatarContainers: @{UInt64: FlovatarInbox.Container}
199		
200		access(all)
201		var walletContainers: @{Address: FlovatarInbox.Container}
202		
203		// Dictionary to remember the last time that DUST was claimed by each Flovatar
204		// so that it can calculate the right amount to be claimable
205		access(all)
206		var lastClaimedDust:{ UInt64: UFix64}
207		
208		init(){ 
209			self.flovatarContainers <-{} 
210			self.walletContainers <-{} 
211			self.lastClaimedDust ={} 
212		}
213		
214		// Borrows the Container Collection for the Flovatar and if not present it initializes it
215		access(all)
216		fun borrowFlovatarContainer(id: UInt64): &FlovatarInbox.Container{ 
217			if self.flovatarContainers[id] == nil{ 
218				let oldContainer <- self.flovatarContainers[id] <- create Container()
219				destroy oldContainer
220			}
221			return (&self.flovatarContainers[id] as &FlovatarInbox.Container?)!
222		}
223		
224		// Borrows the Container Collection for the Flovatar Owner Wallet and if not present it initializes it
225		access(all)
226		fun borrowWalletContainer(address: Address): &FlovatarInbox.Container{ 
227			if self.walletContainers[address] == nil{ 
228				let oldContainer <- self.walletContainers[address] <- create Container()
229				destroy oldContainer
230			}
231			return (&self.walletContainers[address] as &FlovatarInbox.Container?)!
232		}
233		
234		access(all)
235		fun depositDustToFlovatar(id: UInt64, vault: @{FungibleToken.Vault}){ 
236			pre{ 
237				vault.isInstance(Type<@FlovatarDustToken.Vault>()):
238					"Vault not of the right Token Type"
239			}
240			let ref = self.borrowFlovatarContainer(id: id)
241			emit FlovatarDepositDust(id: id, amount: vault.balance)
242			ref.dustVault.deposit(from: <-vault)
243		}
244		
245		access(all)
246		fun depositDustToWallet(address: Address, vault: @{FungibleToken.Vault}){ 
247			pre{ 
248				vault.isInstance(Type<@FlovatarDustToken.Vault>()):
249					"Vault not of the right Token Type"
250			}
251			let ref = self.borrowWalletContainer(address: address)
252			emit WalletDepositDust(address: address, amount: vault.balance)
253			ref.dustVault.deposit(from: <-vault)
254		}
255		
256		access(all)
257		fun depositComponentToFlovatar(id: UInt64, component: @FlovatarComponent.NFT){ 
258			let ref = self.borrowFlovatarContainer(id: id)
259			emit FlovatarDepositComponent(flovatarId: id, componentId: component.id)
260			ref.insertComponent(component: <-component)
261		}
262		
263		access(all)
264		fun depositComponentToWallet(address: Address, component: @FlovatarComponent.NFT){ 
265			let ref = self.borrowWalletContainer(address: address)
266			emit WalletDepositComponent(address: address, componentId: component.id)
267			ref.insertComponent(component: <-component)
268		}
269		
270		access(all)
271		fun getFlovatarDustBalance(id: UInt64): UFix64{ 
272			let ref = self.borrowFlovatarContainer(id: id)
273			return ref.dustVault.balance
274		}
275		
276		access(all)
277		fun getWalletDustBalance(address: Address): UFix64{ 
278			let ref = self.borrowWalletContainer(address: address)
279			return ref.dustVault.balance
280		}
281		
282		access(all)
283		fun getFlovatarComponentIDs(id: UInt64): [UInt64]{ 
284			let ref = self.borrowFlovatarContainer(id: id)
285			return *ref.flovatarComponents.keys
286		}
287		
288		access(all)
289		fun getWalletComponentIDs(address: Address): [UInt64]{ 
290			let ref = self.borrowWalletContainer(address: address)
291			return *ref.flovatarComponents.keys
292		}
293		
294		access(all)
295		fun getLastClaimedDust(id: UInt64): UFix64{ 
296			if self.lastClaimedDust[id] == nil{ 
297				self.lastClaimedDust[id] = FlovatarInbox.dustDistributionStart
298			}
299			return self.lastClaimedDust[id]!
300		}
301		
302		access(contract)
303		fun setLastClaimedDust(id: UInt64, value: UFix64){ 
304			self.lastClaimedDust[id] = value
305		}
306		
307		access(Withdraw)
308		fun withdrawFlovatarComponent(id: UInt64, withdrawID: UInt64): @{NonFungibleToken.NFT}{ 
309			let ref = self.borrowFlovatarContainer(id: id)
310			return <-ref.withdrawComponent(id: withdrawID)
311		}
312		
313		access(Withdraw)
314		fun withdrawWalletComponent(address: Address, withdrawID: UInt64): @{NonFungibleToken.NFT}{ 
315			let ref = self.borrowWalletContainer(address: address)
316			return <-ref.withdrawComponent(id: withdrawID)
317		}
318		
319		access(Withdraw)
320		fun withdrawFlovatarDust(id: UInt64): @{FungibleToken.Vault}{ 
321			let ref = self.borrowFlovatarContainer(id: id)
322			return <-ref.withdrawDust(amount: ref.dustVault.balance)
323		}
324		
325		access(Withdraw)
326		fun withdrawWalletDust(address: Address): @{FungibleToken.Vault}{ 
327			let ref = self.borrowWalletContainer(address: address)
328			return <-ref.withdrawDust(amount: ref.dustVault.balance)
329		}
330	}
331	
332	// This function can only be called by the account owner to create an empty Collection
333	access(account)
334	fun createEmptyCollection(): @FlovatarInbox.Collection{ 
335		return <-create Collection()
336	}
337	
338	// Returns the amount of DUST received by the Flovatar for additional rewards or activities (not coming from the Community pool)
339	access(all)
340	fun getFlovatarDustBalance(id: UInt64): UFix64{ 
341		if let inboxCollection = self.account.capabilities.borrow<&FlovatarInbox.Collection>(FlovatarInbox.CollectionPublicPath){ 
342			return inboxCollection.getFlovatarDustBalance(id: id)
343		}
344		 
345		return 0.0
346	}
347	
348	// Returns the amount of DUST received by the Flovatar Owner for additional rewards or activities (not coming from the Community pool)
349	access(all)
350	fun getWalletDustBalance(address: Address): UFix64{ 
351		
352		if let inboxCollection = self.account.capabilities.borrow<&FlovatarInbox.Collection>(FlovatarInbox.CollectionPublicPath){ 
353			return inboxCollection.getWalletDustBalance(address: address)
354		}
355		
356		return 0.0
357	}
358	
359	// Returns the IDs of the Components (Flobits) received by the Flovatar
360	access(all)
361	fun getFlovatarComponentIDs(id: UInt64): [UInt64]{ 
362		
363		if let inboxCollection = self.account.capabilities.borrow<auth(Withdraw) &FlovatarInbox.Collection>(FlovatarInbox.CollectionPublicPath){ 
364			return inboxCollection.getFlovatarComponentIDs(id: id)
365		}
366		
367		return []
368	}
369	
370	// Returns the IDs of the Components (Flobits) received by the Flovatar Owner
371	access(all)
372	fun getWalletComponentIDs(address: Address): [UInt64]{ 
373		
374		if let inboxCollection = self.account.capabilities.borrow<&FlovatarInbox.Collection>(FlovatarInbox.CollectionPublicPath){ 
375			return inboxCollection.getWalletComponentIDs(address: address)
376		}
377		
378		return []
379	}
380	
381	// This function withdraws all the Components assigned to a Flovatar and sends them to the Owner's address
382	access(all)
383	fun withdrawFlovatarComponent(id: UInt64, address: Address){ 
384		pre{ 
385			self.withdrawEnabled:
386				"Withdrawal is not enabled!"
387		}
388		if let inboxCollection =
389			self.account.storage.borrow<auth(Withdraw) &FlovatarInbox.Collection>(
390				from: self.CollectionStoragePath
391			){ 
392			if let flovatar = Flovatar.getFlovatar(address: address, flovatarId: id){ 
393				let receiverAccount = getAccount(address)
394				let flovatarComponentReceiverCollection = receiverAccount.capabilities.get<&{FlovatarComponent.CollectionPublic}>(FlovatarComponent.CollectionPublicPath)
395				var i: UInt32 = 0
396				let componentIds = self.getFlovatarComponentIDs(id: id)
397				
398				//set a max of 50 Components to be withdrawn to avoid gas limits
399				while i < UInt32(componentIds.length) && i < UInt32(50){ 
400					let component <- inboxCollection.withdrawFlovatarComponent(id: id, withdrawID: componentIds[i])
401					if component == nil{ 
402						panic("Component not found!")
403					}
404					(flovatarComponentReceiverCollection.borrow()!).deposit(token: <-component)
405					emit FlovatarWithdrawComponent(flovatarId: id, componentId: componentIds[i], to: address)
406					i = i + UInt32(1)
407				}
408			}
409		}
410	}
411	
412	// This function withdraws all the Components assigned to a Flovatar Owner and sends them to his address
413	access(all)
414	fun withdrawWalletComponent(address: Address){ 
415		pre{ 
416			self.withdrawEnabled:
417				"Withdrawal is not enabled!"
418		}
419		if let inboxCollection =
420			self.account.storage.borrow<auth(Withdraw) &FlovatarInbox.Collection>(
421				from: self.CollectionStoragePath
422			){ 
423			let receiverAccount = getAccount(address)
424			let flovatarComponentReceiverCollection =
425				receiverAccount.capabilities.get<&{FlovatarComponent.CollectionPublic}>(
426					FlovatarComponent.CollectionPublicPath
427				)
428			var i: UInt32 = 0
429			let componentIds = self.getWalletComponentIDs(address: address)
430			
431			//set a max of 50 Components to be withdrawn to avoid gas limits
432			while i < UInt32(componentIds.length) && i < UInt32(50){ 
433				let component <- inboxCollection.withdrawWalletComponent(address: address, withdrawID: componentIds[i])
434				if component == nil{ 
435					panic("Component not found!")
436				}
437				(flovatarComponentReceiverCollection.borrow()!).deposit(token: <-component)
438				emit WalletWithdrawComponent(address: address, componentId: componentIds[i])
439				i = i + UInt32(1)
440			}
441		}
442	}
443	
444	// This function withdraws all the DUST assigned to a Flovatar (not from general community pool) and sends it to the Owner's vault
445	access(all)
446	fun withdrawFlovatarDust(id: UInt64, address: Address){ 
447		pre{ 
448			self.withdrawEnabled:
449				"Withdrawal is not enabled!"
450		}
451		if let inboxCollection =
452			self.account.storage.borrow<auth(Withdraw) &FlovatarInbox.Collection>(
453				from: self.CollectionStoragePath
454			){ 
455			if let flovatar = Flovatar.getFlovatar(address: address, flovatarId: id){ 
456				let receiverAccount = getAccount(address)
457				let receiverRef = (receiverAccount.capabilities.get<&{FungibleToken.Receiver}>(FlovatarDustToken.VaultReceiverPath)!).borrow() ?? panic("Could not borrow receiver reference to the recipient's Vault")
458				let vault <- inboxCollection.withdrawFlovatarDust(id: id)
459				emit FlovatarWithdrawDust(id: id, amount: vault.balance, to: address)
460				receiverRef.deposit(from: <-vault)
461			}
462		}
463	}
464	
465	// This function withdraws all the DUST assigned to a Flovatar Owner (not from general community pool) and sends it to his vault
466	access(all)
467	fun withdrawWalletDust(address: Address){ 
468		pre{ 
469			self.withdrawEnabled:
470				"Withdrawal is not enabled!"
471		}
472		if let inboxCollection =
473			self.account.storage.borrow<auth(Withdraw) &FlovatarInbox.Collection>(
474				from: self.CollectionStoragePath
475			){ 
476			let receiverAccount = getAccount(address)
477			let receiverRef =
478				(
479					receiverAccount.capabilities.get<&{FungibleToken.Receiver}>(
480						FlovatarDustToken.VaultReceiverPath
481					)!
482				).borrow()
483				?? panic("Could not borrow receiver reference to the recipient's Vault")
484			let vault <- inboxCollection.withdrawWalletDust(address: address)
485			emit WalletWithdrawDust(address: address, amount: vault.balance)
486			receiverRef.deposit(from: <-vault)
487		}
488	}
489	
490	// Returns the amount of DUST available and yet to be distributed to the community
491	access(all)
492	fun getCommunityDustBalance(): UFix64{ 
493		return self.communityVault.balance
494	}
495	
496	// Calculates how much DUST a Flovatar should be able to claim based on
497	// his rarity score and on the amount of days passed since the last completed claim
498	access(all)
499	fun getClaimableFlovatarCommunityDust(id: UInt64, address: Address): ClaimableDust?{ 
500
501		if let flovatarScore: UFix64 =
502			Flovatar.getFlovatarRarityScore(address: address, flovatarId: id){ 
503			
504			if let inboxCollection = self.account.capabilities.borrow<&FlovatarInbox.Collection>(FlovatarInbox.CollectionPublicPath){ 
505				let lastClaimed: UFix64 = inboxCollection.getLastClaimedDust(id: id)
506				let currentTime: UFix64 = getCurrentBlock().timestamp
507				let timeDiff: UFix64 = currentTime - lastClaimed
508				let dayLength: UFix64 = 86400.0
509				if timeDiff > dayLength{ 
510					let daysDiff: UInt64 = UInt64(timeDiff / dayLength)
511					return ClaimableDust(amount: UFix64(daysDiff) * (3.0 + flovatarScore) * FlovatarInbox.dustPerDayPerScore, days: daysDiff, rarityScore: flovatarScore, flovatarId: id, wallet: address)
512				}
513			}
514		}
515		return nil
516	}
517	
518	// Internal function to update the timestamp of the last time DUST were claimed for a specific Flovatar
519	access(self)
520	fun setLastClaimedDust(id: UInt64, days: UInt64){ 
521		if let inboxCollection =
522			self.account.storage.borrow<&FlovatarInbox.Collection>(
523				from: self.CollectionStoragePath
524			){ 
525			let lastClaimed: UFix64 = inboxCollection.getLastClaimedDust(id: id)
526			inboxCollection.setLastClaimedDust(id: id, value: lastClaimed + UFix64(days * 86400))
527		}
528	}
529	
530	// This function will allow any Flovatar to claim his share of the daily distribution of DUST from the community pool
531	access(all)
532	fun claimFlovatarCommunityDust(id: UInt64, address: Address){ 
533		pre{ 
534			self.withdrawEnabled:
535				"Withdrawal is not enabled!"
536		}
537		if let claimableDust: ClaimableDust =
538			self.getClaimableFlovatarCommunityDust(id: id, address: address){ 
539			if claimableDust.amount > self.communityVault.balance{ 
540				panic("Not enough community DUST left to be claimed")
541			}
542			if claimableDust.amount > UFix64(0.0){ 
543				let receiverAccount = getAccount(address)
544				let receiverRef = (receiverAccount.capabilities.get<&{FungibleToken.Receiver}>(FlovatarDustToken.VaultReceiverPath)!).borrow() ?? panic("Could not borrow receiver reference to the recipient's Vault")
545				let vault <- self.communityVault.withdraw(amount: claimableDust.amount)
546				self.setLastClaimedDust(id: id, days: claimableDust.days)
547				emit FlovatarClaimedCommunityDust(id: id, amount: vault.balance, to: address)
548				receiverRef.deposit(from: <-vault)
549			}
550		}
551	}
552	
553	access(all)
554	fun claimFlovatarCommunityDustFromChild(id: UInt64, parent: Address, child: Address){ 
555
556		pre{ 
557			self.withdrawEnabled:
558				"Withdrawal is not enabled!"
559		}
560		if parent == child{ 
561			self.claimFlovatarCommunityDust(id: id, address: parent)
562			return
563		}
564		let manager =
565			getAccount(parent).capabilities.get<&HybridCustody.Manager>(
566				HybridCustody.ManagerPublicPath
567			).borrow()
568			?? panic("parent account does not have a hybrid custody manager")
569		assert(
570			manager.borrowAccountPublic(addr: child) != nil,
571			message: "parent does not have supplied child account"
572		)
573		if let claimableDust: ClaimableDust =
574			self.getClaimableFlovatarCommunityDust(id: id, address: child){ 
575			if claimableDust.amount > self.communityVault.balance{ 
576				panic("Not enough community DUST left to be claimed")
577			}
578			if claimableDust.amount > 0.0{ 
579				let receiverAccount = getAccount(parent)
580				let receiverRef = (receiverAccount.capabilities.get<&{FungibleToken.Receiver}>(FlovatarDustToken.VaultReceiverPath)!).borrow() ?? panic("Could not borrow receiver reference to the recipient's Vault")
581				let vault <- self.communityVault.withdraw(amount: claimableDust.amount)
582				self.setLastClaimedDust(id: id, days: claimableDust.days)
583				
584				// TODO: not sure who the `to` address should be, here.
585				emit FlovatarClaimedCommunityDust(id: id, amount: vault.balance, to: parent)
586				receiverRef.deposit(from: <-vault)
587			}
588		}
589		
590	}
591	
592	// Admin function to temporarly enable or disable the airdrop and reward withdraw so that
593	// we can distribute them to everyone at the same time
594	access(account)
595	fun setWithdrawEnable(enabled: Bool){ 
596		self.withdrawEnabled = enabled
597	}
598	
599	// Admin function to deposit DUST into the community pool
600	access(all)
601	fun depositCommunityDust(vault: @{FungibleToken.Vault}){ 
602		pre{ 
603			vault.isInstance(Type<@FlovatarDustToken.Vault>()):
604				"Vault not of the right Token Type"
605		}
606		self.communityVault.deposit(from: <-vault)
607	}
608	
609	// Returns the multiplier used to calculate the amount of DUST to distribute for each Rarity Score point per day for each Flovatar
610	access(all)
611	fun getDustPerDayPerScore(): UFix64{ 
612		return self.dustPerDayPerScore
613	}
614	
615	// Admin function to allow potential adjustments for the distribution speed of the community DUST
616	access(account)
617	fun setDustPerDayPerScore(value: UFix64){ 
618		self.dustPerDayPerScore = value
619	}
620	
621	// This is the main Admin resource that will allow the owner
622	// to manage the Inbox
623	access(all)
624	resource Admin{ 
625		access(all)
626		fun setDustPerDayPerScore(value: UFix64){ 
627			FlovatarInbox.setDustPerDayPerScore(value: value)
628		}
629		
630		access(all)
631		fun setWithdrawEnable(enabled: Bool){ 
632			FlovatarInbox.setWithdrawEnable(enabled: enabled)
633		}
634		
635		// With this function you can generate a new Admin resource
636		// and pass it to another user if needed
637		access(all)
638		fun createNewAdmin(): @Admin{ 
639			return <-create Admin()
640		}
641	}
642	
643	init(){ 
644		self.withdrawEnabled = true
645		self.communityVault <- FlovatarDustToken.createEmptyDustVault()
646			
647		self.dustDistributionStart = getCurrentBlock().timestamp - UFix64(86400)
648		self.dustPerDayPerScore = 0.91447
649		self.CollectionPublicPath = /public/FlovatarInboxCollection
650		self.CollectionStoragePath = /storage/FlovatarInboxCollection
651		self.account.storage.save<@FlovatarInbox.Collection>(
652			<-FlovatarInbox.createEmptyCollection(),
653			to: FlovatarInbox.CollectionStoragePath
654		)
655		var capability_1 =
656			self.account.capabilities.storage.issue<&{FlovatarInbox.CollectionPublic}>(
657				FlovatarInbox.CollectionStoragePath
658			)
659		self.account.capabilities.publish(capability_1, at: FlovatarInbox.CollectionPublicPath)
660		
661		// Put the Admin resource in storage
662		self.account.storage.save<@Admin>(<-create Admin(), to: /storage/FlovatarInboxAdmin)
663		emit ContractInitialized()
664	}
665}
666