Smart Contract
ThulToken
A.e3ad6030cbaff1c2.ThulToken
1import FungibleToken from 0xf233dcee88fe0abe
2
3pub contract ThulToken: FungibleToken {
4
5 /// Total supply of ThulTokens in existence
6 pub var totalSupply: UFix64
7
8 /// Storage and Public Paths
9 pub let VaultStoragePath: StoragePath
10 pub let ReceiverPublicPath: PublicPath
11 pub let BalancePublicPath: PublicPath
12 pub let AdminStoragePath: StoragePath
13
14 /// TokensInitialized
15 ///
16 /// The event that is emitted when the contract is created
17 pub event TokensInitialized(initialSupply: UFix64)
18
19 /// TokensWithdrawn
20 ///
21 /// The event that is emitted when tokens are withdrawn from a Vault
22 pub event TokensWithdrawn(amount: UFix64, from: Address?)
23
24 /// TokensDeposited
25 ///
26 /// The event that is emitted when tokens are deposited to a Vault
27 pub event TokensDeposited(amount: UFix64, to: Address?)
28
29 /// TokensMinted
30 ///
31 /// The event that is emitted when new tokens are minted
32 pub event TokensMinted(amount: UFix64)
33
34 /// TokensBurned
35 ///
36 /// The event that is emitted when tokens are destroyed
37 pub event TokensBurned(amount: UFix64)
38
39 /// MinterCreated
40 ///
41 /// The event that is emitted when a new minter resource is created
42 pub event MinterCreated(allowedAmount: UFix64)
43
44 /// BurnerCreated
45 ///
46 /// The event that is emitted when a new burner resource is created
47 pub event BurnerCreated()
48
49 /// Vault
50 ///
51 /// Each user stores an instance of only the Vault in their storage
52 /// The functions in the Vault and governed by the pre and post conditions
53 /// in FungibleToken when they are called.
54 /// The checks happen at runtime whenever a function is called.
55 ///
56 /// Resources can only be created in the context of the contract that they
57 /// are defined in, so there is no way for a malicious user to create Vaults
58 /// out of thin air. A special Minter resource needs to be defined to mint
59 /// new tokens.
60 ///
61 pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
62
63 /// The total balance of this vault
64 pub var balance: UFix64
65
66 // initialize the balance at resource creation time
67 init(balance: UFix64) {
68 self.balance = balance
69 }
70
71 /// withdraw
72 ///
73 /// Function that takes an amount as an argument
74 /// and withdraws that amount from the Vault.
75 ///
76 /// It creates a new temporary Vault that is used to hold
77 /// the money that is being transferred. It returns the newly
78 /// created Vault to the context that called so it can be deposited
79 /// elsewhere.
80 ///
81 pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
82 self.balance = self.balance - amount
83 emit TokensWithdrawn(amount: amount, from: self.owner?.address)
84 return <-create Vault(balance: amount)
85 }
86
87 /// deposit
88 ///
89 /// Function that takes a Vault object as an argument and adds
90 /// its balance to the balance of the owners Vault.
91 ///
92 /// It is allowed to destroy the sent Vault because the Vault
93 /// was a temporary holder of the tokens. The Vault's balance has
94 /// been consumed and therefore can be destroyed.
95 ///
96 pub fun deposit(from: @FungibleToken.Vault) {
97 let vault <- from as! @ThulToken.Vault
98 self.balance = self.balance + vault.balance
99 emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
100 vault.balance = 0.0
101 destroy vault
102 }
103
104 destroy() {
105 ThulToken.totalSupply = ThulToken.totalSupply - self.balance
106 }
107 }
108
109 /// createEmptyVault
110 ///
111 /// Function that creates a new Vault with a balance of zero
112 /// and returns it to the calling context. A user must call this function
113 /// and store the returned Vault in their storage in order to allow their
114 /// account to be able to receive deposits of this token type.
115 ///
116 pub fun createEmptyVault(): @Vault {
117 return <-create Vault(balance: 0.0)
118 }
119
120 pub resource Administrator {
121
122 /// createNewMinter
123 ///
124 /// Function that creates and returns a new minter resource
125 ///
126 pub fun createNewMinter(allowedAmount: UFix64): @Minter {
127 emit MinterCreated(allowedAmount: allowedAmount)
128 return <-create Minter(allowedAmount: allowedAmount)
129 }
130
131 /// createNewBurner
132 ///
133 /// Function that creates and returns a new burner resource
134 ///
135 pub fun createNewBurner(): @Burner {
136 emit BurnerCreated()
137 return <-create Burner()
138 }
139 }
140
141 /// Minter
142 ///
143 /// Resource object that token admin accounts can hold to mint new tokens.
144 ///
145 pub resource Minter {
146
147 /// The amount of tokens that the minter is allowed to mint
148 pub var allowedAmount: UFix64
149
150 /// mintTokens
151 ///
152 /// Function that mints new tokens, adds them to the total supply,
153 /// and returns them to the calling context.
154 ///
155 pub fun mintTokens(amount: UFix64): @ThulToken.Vault {
156 pre {
157 amount > 0.0: "Amount minted must be greater than zero"
158 amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
159 }
160 ThulToken.totalSupply = ThulToken.totalSupply + amount
161 self.allowedAmount = self.allowedAmount - amount
162 emit TokensMinted(amount: amount)
163 return <-create Vault(balance: amount)
164 }
165
166 init(allowedAmount: UFix64) {
167 self.allowedAmount = allowedAmount
168 }
169 }
170
171 /// Burner
172 ///
173 /// Resource object that token admin accounts can hold to burn tokens.
174 ///
175 pub resource Burner {
176
177 /// burnTokens
178 ///
179 /// Function that destroys a Vault instance, effectively burning the tokens.
180 ///
181 /// Note: the burned tokens are automatically subtracted from the
182 /// total supply in the Vault destructor.
183 ///
184 pub fun burnTokens(from: @FungibleToken.Vault) {
185 let vault <- from as! @ThulToken.Vault
186 let amount = vault.balance
187 destroy vault
188 emit TokensBurned(amount: amount)
189 }
190 }
191
192 init() {
193 self.totalSupply = 1000.0
194
195 self.VaultStoragePath = /storage/thulTokenVault
196 self.ReceiverPublicPath = /public/thulTokenReceiver
197 self.BalancePublicPath = /public/thulTokenBalance
198 self.AdminStoragePath = /storage/thulTokenAdmin
199
200 // Create the Vault with the total supply of tokens and save it in storage
201 //
202 let vault <- create Vault(balance: self.totalSupply)
203 self.account.save(<-vault, to: self.VaultStoragePath)
204
205 // Create a public capability to the stored Vault that only exposes
206 // the `deposit` method through the `Receiver` interface
207 //
208 self.account.link<&{FungibleToken.Receiver}>(
209 self.ReceiverPublicPath,
210 target: self.VaultStoragePath
211 )
212
213 // Create a public capability to the stored Vault that only exposes
214 // the `balance` field through the `Balance` interface
215 //
216 self.account.link<&ThulToken.Vault{FungibleToken.Balance}>(
217 self.BalancePublicPath,
218 target: self.VaultStoragePath
219 )
220
221 let admin <- create Administrator()
222 self.account.save(<-admin, to: self.AdminStoragePath)
223
224 // Emit an event that shows that the contract was initialized
225 //
226 emit TokensInitialized(initialSupply: self.totalSupply)
227 }
228}
229