Smart Contract
MoxyToken
A.123cb47fe122f6e3.MoxyToken
1import FungibleToken from 0xf233dcee88fe0abe
2import MoxyVaultToken from 0x123cb47fe122f6e3
3
4pub contract MoxyToken: FungibleToken {
5
6 /// Total supply of MoxyTokens in existence
7 pub var totalSupply: UFix64
8
9 /// TokensInitialized
10 ///
11 /// The event that is emitted when the contract is created
12 pub event TokensInitialized(initialSupply: UFix64)
13
14 /// TokensWithdrawn
15 ///
16 /// The event that is emitted when tokens are withdrawn from a Vault
17 pub event TokensWithdrawn(amount: UFix64, from: Address?)
18
19 /// TokensDeposited
20 ///
21 /// The event that is emitted when tokens are deposited to a Vault
22 pub event TokensDeposited(amount: UFix64, to: Address?)
23
24 /// TokensMinted
25 ///
26 /// The event that is emitted when new tokens are minted
27 pub event TokensMinted(amount: UFix64)
28
29 /// TokensBurned
30 ///
31 /// The event that is emitted when tokens are destroyed
32 pub event TokensBurned(amount: UFix64)
33
34 /// MinterCreated
35 ///
36 /// The event that is emitted when a new minter resource is created
37 pub event MinterCreated(allowedAmount: UFix64)
38
39 /// BurnerCreated
40 ///
41 /// The event that is emitted when a new burner resource is created
42 pub event BurnerCreated()
43
44 pub event MOXtoMVConvertionRequested(address: Address, amount: UFix64)
45
46 /// Vault
47 ///
48 /// Each user stores an instance of only the Vault in their storage
49 /// The functions in the Vault and governed by the pre and post conditions
50 /// in FungibleToken when they are called.
51 /// The checks happen at runtime whenever a function is called.
52 ///
53 /// Resources can only be created in the context of the contract that they
54 /// are defined in, so there is no way for a malicious user to create Vaults
55 /// out of thin air. A special Minter resource needs to be defined to mint
56 /// new tokens.
57 ///
58 pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
59
60 /// The total balance of this vault
61 pub var balance: UFix64
62
63 // initialize the balance at resource creation time
64 init(balance: UFix64) {
65 self.balance = balance
66 }
67
68 /// withdraw
69 ///
70 /// Function that takes an amount as an argument
71 /// and withdraws that amount from the Vault.
72 ///
73 /// It creates a new temporary Vault that is used to hold
74 /// the money that is being transferred. It returns the newly
75 /// created Vault to the context that called so it can be deposited
76 /// elsewhere.
77 ///
78 pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
79 self.balance = self.balance - amount
80 emit TokensWithdrawn(amount: amount, from: self.owner?.address)
81 return <-create Vault(balance: amount)
82 }
83
84 /// deposit
85 ///
86 /// Function that takes a Vault object as an argument and adds
87 /// its balance to the balance of the owners Vault.
88 ///
89 /// It is allowed to destroy the sent Vault because the Vault
90 /// was a temporary holder of the tokens. The Vault's balance has
91 /// been consumed and therefore can be destroyed.
92 ///
93 pub fun deposit(from: @FungibleToken.Vault) {
94 let vault <- from as! @MoxyToken.Vault
95 self.balance = self.balance + vault.balance
96 emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
97 vault.balance = 0.0
98 destroy vault
99 }
100
101 access(account) fun depositLocked(from: @FungibleToken.Vault) {
102 return self.deposit(from: <-from)
103 }
104
105 destroy() {
106 MoxyToken.totalSupply = MoxyToken.totalSupply - self.balance
107 }
108 }
109
110 /// createEmptyVault
111 ///
112 /// Function that creates a new Vault with a balance of zero
113 /// and returns it to the calling context. A user must call this function
114 /// and store the returned Vault in their storage in order to allow their
115 /// account to be able to receive deposits of this token type.
116 ///
117 pub fun createEmptyVault(): @Vault {
118 return <-create Vault(balance: 0.0)
119 }
120
121 pub resource Administrator {
122
123 /// createNewMinter
124 ///
125 /// Function that creates and returns a new minter resource
126 ///
127
128 pub fun createNewMinter(allowedAmount: UFix64): @Minter {
129 emit MinterCreated(allowedAmount: allowedAmount)
130 return <-create Minter(allowedAmount: allowedAmount)
131 }
132
133 /// createNewBurner
134 ///
135 /// Function that creates and returns a new burner resource
136 ///
137
138 pub fun createNewBurner(): @Burner {
139 emit BurnerCreated()
140 return <-create Burner()
141 }
142
143 }
144
145 /// Minter
146 ///
147 /// Resource object that token admin accounts can hold to mint new tokens.
148 ///
149 pub resource Minter {
150
151 /// The amount of tokens that the minter is allowed to mint
152 pub var allowedAmount: UFix64
153
154 /// mintTokens
155 ///
156 /// Function that mints new tokens, adds them to the total supply,
157 /// and returns them to the calling context.
158 ///
159
160 pub fun mintTokens(amount: UFix64): @MoxyToken.Vault {
161 pre {
162 amount > 0.0: "Amount mined must be greater than zero ".concat(amount.toString())
163 amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
164 }
165 MoxyToken.totalSupply = MoxyToken.totalSupply + amount
166 self.allowedAmount = self.allowedAmount - amount
167 emit TokensMinted(amount: amount)
168 return <-create Vault(balance: amount)
169 }
170
171 init(allowedAmount: UFix64) {
172 self.allowedAmount = allowedAmount
173 }
174 }
175
176 /// Burner
177 ///
178 /// Resource object that token admin accounts can hold to burn tokens.
179 ///
180 pub resource Burner {
181
182 /// burnTokens
183 ///
184 /// Function that destroys a Vault instance, effectively burning the tokens.
185 ///
186 /// Note: the burned tokens are automatically subtracted from the
187 /// total supply in the Vault destructor.
188 ///
189 pub fun burnTokens(from: @FungibleToken.Vault) {
190 let vault <- from as! @MoxyToken.Vault
191 let amount = vault.balance
192 destroy vault
193 emit TokensBurned(amount: amount)
194 }
195 }
196
197 pub let moxyTokenVaultStorage: StoragePath
198 pub let moxyTokenLockedVaultStorage: StoragePath
199 pub let moxyTokenLockedVaultPrivate: PrivatePath
200 pub let moxyTokenAdminStorage: StoragePath
201 pub let moxyTokenReceiverPath: PublicPath
202 pub let moxyTokenBalancePath: PublicPath
203 pub let moxyTokenLockedBalancePath: PublicPath
204 pub let moxyTokenLockedReceiverPath: PublicPath
205 // Paths for Locked tonkens due MOX to MV conversion
206 pub let moxyTokenLockedMVVaultStorage: StoragePath
207 pub let moxyTokenLockedMVBalancePath: PublicPath
208 pub let moxyTokenLockedMVReceiverPath: PublicPath
209 // Play and Earn Paths
210 pub let moxyTokenPlayAndEarnVaultStorage: StoragePath
211 pub let moxyTokenPlayAndEarnVaultPrivate: PrivatePath
212 pub let moxyTokenPlayAndEarnBalancePath: PublicPath
213
214 init() {
215 // The initial total supply corresponds with the total amount
216 // to release in the different Token allocations rounds
217 self.totalSupply = 0.0
218
219 self.moxyTokenVaultStorage = /storage/moxyTokenVault
220 self.moxyTokenLockedVaultStorage = /storage/moxyTokenLockedVault
221 self.moxyTokenLockedVaultPrivate = /private/moxyTokenLockedVault
222 self.moxyTokenAdminStorage = /storage/moxyTokenAdmin
223 self.moxyTokenReceiverPath = /public/moxyTokenReceiver
224 self.moxyTokenBalancePath = /public/moxyTokenBalance
225 self.moxyTokenLockedBalancePath = /public/moxyTokenLockedBalance
226 self.moxyTokenLockedReceiverPath = /public/moxyTokenLockedReceiver
227 // Locked vaults due to MOX to MV conversion
228 self.moxyTokenLockedMVVaultStorage = /storage/moxyTokenLockedMVVault
229 self.moxyTokenLockedMVBalancePath = /public/moxyTokenLockedMVBalance
230 self.moxyTokenLockedMVReceiverPath = /public/moxyTokenLockedMVReceiver
231 //Play and Earn Storage
232 self.moxyTokenPlayAndEarnVaultStorage = /storage/moxyTokenPlayAndEarnVault
233 self.moxyTokenPlayAndEarnVaultPrivate = /private/moxyTokenPlayAndEarnVault
234 self.moxyTokenPlayAndEarnBalancePath = /public/moxyTokenPlayAndEarnBalance
235
236 // Create the Vault with the total supply of tokens and save it in storage
237 //
238 let vault <- create Vault(balance: self.totalSupply)
239 self.account.save(<-vault, to: self.moxyTokenVaultStorage)
240
241 // Create a public capability to the stored Vault that only exposes
242 // the `deposit` method through the `Receiver` interface
243 //
244 self.account.link<&{FungibleToken.Receiver}>(
245 self.moxyTokenReceiverPath,
246 target: self.moxyTokenVaultStorage
247 )
248
249 // Create a public capability to the stored Vault that only exposes
250 // the `balance` field through the `Balance` interface
251 //
252 self.account.link<&MoxyToken.Vault{FungibleToken.Balance}>(
253 self.moxyTokenBalancePath,
254 target: self.moxyTokenVaultStorage
255 )
256
257 // Create Play & Earn resource
258 let playAndEarnvault <- self.createEmptyVault()
259 self.account.save(<-playAndEarnvault, to: self.moxyTokenPlayAndEarnVaultStorage)
260
261 self.account.link<&FungibleToken.Vault>(
262 self.moxyTokenPlayAndEarnVaultPrivate,
263 target: self.moxyTokenPlayAndEarnVaultStorage
264 )
265 self.account.link<&FungibleToken.Vault{FungibleToken.Balance}>(
266 self.moxyTokenPlayAndEarnBalancePath,
267 target: self.moxyTokenPlayAndEarnVaultStorage
268 )
269
270
271 // Create admin resource
272 let admin <- create Administrator()
273 self.account.save(<-admin, to: self.moxyTokenAdminStorage)
274
275 // Emit an event that shows that the contract was initialized
276 //
277 emit TokensInitialized(initialSupply: self.totalSupply)
278 }
279}
280
281