Smart Contract
KARATZ1XR82W
A.82ed1b9cba5bb1b3.KARATZ1XR82W
1import MetadataViews from 0x1d7e57aa55817448
2import FungibleToken from 0xf233dcee88fe0abe
3import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
4
5access(all) contract KARATZ1XR82W: FungibleToken {
6 // TokensInitialized
7 //
8 // The event that is emitted when the contract is created
9 access(all) event TokensInitialized(initialSupply: UFix64)
10
11 // TokensWithdrawn
12 //
13 // The event that is emitted when tokens are withdrawn from a Vault
14 access(all) event TokensWithdrawn(amount: UFix64, from: Address?)
15
16 // TokensDeposited
17 //
18 // The event that is emitted when tokens are deposited to a Vault
19 access(all) event TokensDeposited(amount: UFix64, to: Address?)
20
21 // TokensBurned
22 //
23 // The event that is emitted when tokens are destroyed
24 access(all) event TokensBurned(amount: UFix64)
25
26 /// The event that is emitted when new tokens are minted
27 access(all) event TokensMinted(amount: UFix64, type: String)
28
29 /// Total supply of ExampleTokens in existence
30 access(all) var totalSupply: UFix64
31
32 /// Storage and Public Paths
33 access(all) let VaultStoragePath: StoragePath
34 access(all) let BalancePublicPath: PublicPath
35 access(all) let ReceiverPublicPath: PublicPath
36 access(all) let AdminStoragePath: StoragePath
37
38 access(all) view fun getContractViews(resourceType: Type?): [Type] {
39 return [
40 Type<FungibleTokenMetadataViews.FTView>(),
41 Type<FungibleTokenMetadataViews.FTDisplay>(),
42 Type<FungibleTokenMetadataViews.FTVaultData>(),
43 Type<FungibleTokenMetadataViews.TotalSupply>()
44 ]
45 }
46
47 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
48 switch viewType {
49 case Type<FungibleTokenMetadataViews.FTView>():
50 return FungibleTokenMetadataViews.FTView(
51 ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTDisplay>()) as! FungibleTokenMetadataViews.FTDisplay?,
52 ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTVaultData>()) as! FungibleTokenMetadataViews.FTVaultData?
53 )
54 case Type<FungibleTokenMetadataViews.FTDisplay>():
55 let media = MetadataViews.Media(
56 file: MetadataViews.HTTPFile(
57 url: "https://apps.24karat.io/tokens/KARATZ1XR82W/thumbnail.png"
58 ),
59 mediaType: "image/png"
60 )
61 let medias = MetadataViews.Medias([media])
62 return FungibleTokenMetadataViews.FTDisplay(
63 name: "GKT",
64 symbol: "KARATZ1XR82W",
65 description: "",
66 externalURL: MetadataViews.ExternalURL("https://24karat.io"),
67 logos: medias,
68 socials: {}
69 )
70 case Type<FungibleTokenMetadataViews.FTVaultData>():
71 return FungibleTokenMetadataViews.FTVaultData(
72 storagePath: self.VaultStoragePath,
73 receiverPath: self.ReceiverPublicPath,
74 metadataPath: self.BalancePublicPath,
75 receiverLinkedType: Type<&KARATZ1XR82W.Vault>(),
76 metadataLinkedType: Type<&KARATZ1XR82W.Vault>(),
77 createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} {
78 return <-KARATZ1XR82W.createEmptyVault(vaultType: Type<@KARATZ1XR82W.Vault>())
79 })
80 )
81 case Type<FungibleTokenMetadataViews.TotalSupply>():
82 return FungibleTokenMetadataViews.TotalSupply(
83 totalSupply: KARATZ1XR82W.totalSupply
84 )
85 }
86 return nil
87 }
88
89 /// Vault
90 ///
91 /// Each user stores an instance of only the Vault in their storage
92 /// The functions in the Vault and governed by the pre and post conditions
93 /// in FungibleToken when they are called.
94 /// The checks happen at runtime whenever a function is called.
95 ///
96 /// Resources can only be created in the context of the contract that they
97 /// are defined in, so there is no way for a malicious user to create Vaults
98 /// out of thin air. A special Minter resource needs to be defined to mint
99 /// new tokens.
100 ///
101 access(all) resource Vault: FungibleToken.Vault {
102
103 /// The total balance of this vault
104 access(all) var balance: UFix64
105
106 // initialize the balance at resource creation time
107 init(balance: UFix64) {
108 self.balance = balance
109 }
110
111 /// Called when a fungible token is burned via the `Burner.burn()` method
112 access(contract) fun burnCallback() {
113 if self.balance > 0.0 {
114 KARATZ1XR82W.totalSupply = KARATZ1XR82W.totalSupply - self.balance
115 }
116 self.balance = 0.0
117 }
118
119 access(all) view fun getViews(): [Type] {
120 return KARATZ1XR82W.getContractViews(resourceType: nil)
121 }
122
123 access(all) fun resolveView(_ view: Type): AnyStruct? {
124 return KARATZ1XR82W.resolveContractView(resourceType: nil, viewType: view)
125 }
126
127 /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
128 access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
129 let supportedTypes: {Type: Bool} = {}
130 supportedTypes[self.getType()] = true
131 return supportedTypes
132 }
133
134 access(all) view fun isSupportedVaultType(type: Type): Bool {
135 return self.getSupportedVaultTypes()[type] ?? false
136 }
137
138 /// Asks if the amount can be withdrawn from this vault
139 access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
140 return amount <= self.balance
141 }
142
143 /// withdraw
144 ///
145 /// Function that takes an amount as an argument
146 /// and withdraws that amount from the Vault.
147 ///
148 /// It creates a new temporary Vault that is used to hold
149 /// the tokens that are being transferred. It returns the newly
150 /// created Vault to the context that called so it can be deposited
151 /// elsewhere.
152 ///
153 access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @KARATZ1XR82W.Vault {
154 self.balance = self.balance - amount
155 return <-create Vault(balance: amount)
156 }
157
158 /// deposit
159 ///
160 /// Function that takes a Vault object as an argument and adds
161 /// its balance to the balance of the owners Vault.
162 ///
163 /// It is allowed to destroy the sent Vault because the Vault
164 /// was a temporary holder of the tokens. The Vault's balance has
165 /// been consumed and therefore can be destroyed.
166 ///
167 access(all) fun deposit(from: @{FungibleToken.Vault}) {
168 let vault <- from as! @KARATZ1XR82W.Vault
169 self.balance = self.balance + vault.balance
170 vault.balance = 0.0
171 destroy vault
172 }
173
174 /// createEmptyVault
175 ///
176 /// Function that creates a new Vault with a balance of zero
177 /// and returns it to the calling context. A user must call this function
178 /// and store the returned Vault in their storage in order to allow their
179 /// account to be able to receive deposits of this token type.
180 ///
181 access(all) fun createEmptyVault(): @KARATZ1XR82W.Vault {
182 return <-create Vault(balance: 0.0)
183 }
184 }
185
186 /// createEmptyVault
187 ///
188 /// Function that creates a new Vault with a balance of zero
189 /// and returns it to the calling context. A user must call this function
190 /// and store the returned Vault in their storage in order to allow their
191 /// account to be able to receive deposits of this token type.
192 ///
193 access(all) fun createEmptyVault(vaultType: Type): @KARATZ1XR82W.Vault {
194 return <- create Vault(balance: 0.0)
195 }
196
197 access(all) resource Administrator {
198 // createNewMinter
199 //
200 // Function that creates and returns a new minter resource
201 //
202 access(all) fun createNewMinter(): @Minter {
203 return <-create Minter()
204 }
205 }
206
207 /// Minter
208 ///
209 /// Resource object that token admin accounts can hold to mint new tokens.
210 ///
211 access(all) resource Minter {
212 /// mintTokens
213 ///
214 /// Function that mints new tokens, adds them to the total supply,
215 /// and returns them to the calling context.
216 ///
217 access(all) fun mintTokens(amount: UFix64): @KARATZ1XR82W.Vault {
218 KARATZ1XR82W.totalSupply = KARATZ1XR82W.totalSupply + amount
219 emit TokensMinted(amount: amount, type: self.getType().identifier)
220 return <-create Vault(balance: amount)
221 }
222 }
223
224 init() {
225 // Set our named paths.
226 self.VaultStoragePath = /storage/KARATZ1XR82WVault
227 self.ReceiverPublicPath = /public/KARATZ1XR82WReceiver
228 self.BalancePublicPath = /public/KARATZ1XR82WBalance
229 self.AdminStoragePath = /storage/KARATZ1XR82WAdmin
230
231 // Initialize contract state.
232 self.totalSupply = 0.0
233
234 // Create the Vault with the total supply of tokens and save it in storage
235 //
236 let vault <- create Vault(balance: self.totalSupply)
237
238 // Create a public capability to the stored Vault that exposes
239 // the `deposit` method and getAcceptedTypes method through the `Receiver` interface
240 // and the `balance` method through the `Balance` interface
241 //
242 let tokenCap = self.account.capabilities.storage.issue<&KARATZ1XR82W.Vault>(self.VaultStoragePath)
243 self.account.capabilities.publish(tokenCap, at: self.BalancePublicPath)
244 let receiverCap = self.account.capabilities.storage.issue<&KARATZ1XR82W.Vault>(self.VaultStoragePath)
245 self.account.capabilities.publish(receiverCap, at: self.ReceiverPublicPath)
246
247 self.account.storage.save(<-vault, to: self.VaultStoragePath)
248
249 let admin <- create Administrator()
250 self.account.storage.save(<-admin, to: self.AdminStoragePath)
251 }
252}