Smart Contract
TSHOT
A.05b67ba314000b2d.TSHOT
1import FungibleToken from 0xf233dcee88fe0abe
2import MetadataViews from 0x1d7e57aa55817448
3import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
4
5access(all) contract TSHOT: FungibleToken {
6
7 // Total supply of TSHOT
8 access(all) var totalSupply: UFix64
9
10 // Paths
11 access(all) let tokenBalancePath: PublicPath
12 access(all) let tokenReceiverPath: PublicPath
13
14 // Event that is emitted when the contract is created
15 access(all) event TokensInitialized(initialSupply: UFix64)
16
17 // Event that is emitted when tokens are withdrawn from a Vault
18 access(all) event TokensWithdrawn(amount: UFix64, from: Address?)
19
20 // Event that is emitted when tokens are deposited to a Vault
21 access(all) event TokensDeposited(amount: UFix64, to: Address?)
22
23 // Event that is emitted when new tokens are minted
24 access(all) event TokensMinted(amount: UFix64)
25
26 // Event that is emitted when tokens are destroyed
27 access(all) event TokensBurned(amount: UFix64)
28
29 // Define Admin Entitlement
30 access(all) entitlement AdminEntitlement
31
32 // =========================================================================
33 // Vault Resource
34 // =========================================================================
35 access(all) resource Vault: FungibleToken.Vault {
36
37 // Holds the balance of a user's tokens
38 access(all) var balance: UFix64
39
40 // Initialize the balance at resource creation time
41 init(balance: UFix64) {
42 self.balance = balance
43 }
44
45 /// Called when this TSHOT vault is burned via the `Burner.burn()` method
46 access(contract) fun burnCallback() {
47 if self.balance > 0.0 {
48 TSHOT.totalSupply = TSHOT.totalSupply - self.balance
49 }
50 self.balance = 0.0
51 }
52
53 /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
54 access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
55 return {self.getType(): true}
56 }
57
58 access(all) view fun isSupportedVaultType(type: Type): Bool {
59 return type == self.getType()
60 }
61
62 /// Asks if the amount can be withdrawn from this vault
63 access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
64 return amount <= self.balance
65 }
66
67 // In fungible tokens, vaults can simply defer calls to the contract views:
68 access(all) view fun getViews(): [Type] {
69 return TSHOT.getContractViews(resourceType: nil)
70 }
71
72 access(all) fun resolveView(_ view: Type): AnyStruct? {
73 return TSHOT.resolveContractView(resourceType: nil, viewType: view)
74 }
75
76 // withdraw
77 //
78 // Function that takes an integer amount as an argument
79 // and withdraws that amount from the Vault.
80 access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
81 self.balance = self.balance - amount
82 emit TokensWithdrawn(amount: amount, from: self.owner?.address)
83 return <-create Vault(balance: amount)
84 }
85
86 // deposit
87 //
88 // Function that takes a Vault object as an argument and adds
89 // its balance to the balance of the owner's Vault.
90 access(all) fun deposit(from: @{FungibleToken.Vault}) {
91 let vault <- from as! @TSHOT.Vault
92 self.balance = self.balance + vault.balance
93 emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
94 vault.balance = 0.0
95 destroy vault
96 }
97
98 access(all) fun createEmptyVault(): @{FungibleToken.Vault} {
99 return <-create Vault(balance: 0.0)
100 }
101 }
102
103 // =========================================================================
104 // Metadata Views for the Contract
105 // =========================================================================
106
107 //
108 // Provide standard views so explorers, wallets, and dApps can query info
109 //
110 access(all) view fun getContractViews(resourceType: Type?): [Type] {
111 return [
112 Type<FungibleTokenMetadataViews.FTView>(),
113 Type<FungibleTokenMetadataViews.FTDisplay>(),
114 Type<FungibleTokenMetadataViews.FTVaultData>(),
115 Type<FungibleTokenMetadataViews.TotalSupply>()
116 ]
117 }
118
119 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
120 switch viewType {
121 case Type<FungibleTokenMetadataViews.FTView>():
122 return FungibleTokenMetadataViews.FTView(
123 ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTDisplay>())
124 as! FungibleTokenMetadataViews.FTDisplay?,
125 ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTVaultData>())
126 as! FungibleTokenMetadataViews.FTVaultData?
127 )
128
129 case Type<FungibleTokenMetadataViews.FTDisplay>():
130
131 let media = MetadataViews.Media(
132 file: MetadataViews.HTTPFile(
133 url: "https://storage.googleapis.com/vaultopolis/TSHOT.png"
134 ),
135 mediaType: "image/png"
136 )
137
138 return FungibleTokenMetadataViews.FTDisplay(
139 name: "TSHOT Token",
140 symbol: "TSHOT",
141 description: "TSHOT is a token minted by exchanging Common or Fandom Top Shot Moments.",
142 externalURL: MetadataViews.ExternalURL("https://vaultopolis.com"),
143 logos: MetadataViews.Medias([media]),
144 socials: {
145 "twitter": MetadataViews.ExternalURL("https://twitter.com/Vaultopolis")
146 }
147 )
148
149 case Type<FungibleTokenMetadataViews.FTVaultData>():
150
151 return FungibleTokenMetadataViews.FTVaultData(
152 storagePath: /storage/TSHOTTokenVault,
153 receiverPath: self.tokenReceiverPath,
154 metadataPath: self.tokenBalancePath,
155 receiverLinkedType: Type<&TSHOT.Vault>(),
156 metadataLinkedType: Type<&TSHOT.Vault>(),
157 createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} {
158 return <-TSHOT.createEmptyVault(vaultType: Type<@TSHOT.Vault>())
159 })
160 )
161
162 case Type<FungibleTokenMetadataViews.TotalSupply>():
163 return FungibleTokenMetadataViews.TotalSupply(
164 totalSupply: TSHOT.totalSupply
165 )
166 }
167
168 return nil
169 }
170
171 // =========================================================================
172 // Create Empty Vault
173 // =========================================================================
174 access(all) fun createEmptyVault(vaultType: Type): @TSHOT.Vault {
175 return <-create Vault(balance: 0.0)
176 }
177
178 // =========================================================================
179 // Admin resource definition and Minter function
180 // =========================================================================
181 access(all) resource Admin {
182 access(AdminEntitlement) fun mintTokens(amount: UFix64): @TSHOT.Vault {
183 TSHOT.totalSupply = TSHOT.totalSupply + amount
184 emit TokensMinted(amount: amount)
185 return <-create Vault(balance: amount)
186 }
187 }
188
189 // =========================================================================
190 // Burn Tokens
191 // =========================================================================
192 access(account) fun burnTokens(from: @TSHOT.Vault) {
193 let amount = from.balance
194 TSHOT.totalSupply = TSHOT.totalSupply - amount
195 destroy from
196 emit TokensBurned(amount: amount)
197 }
198
199 // =========================================================================
200 // Contract Initialization
201 // =========================================================================
202 init() {
203 self.totalSupply = 0.0
204
205 self.tokenReceiverPath = /public/TSHOTTokenReceiver
206 self.tokenBalancePath = /public/TSHOTTokenBalance
207
208 // Put a new Admin in storage
209 self.account.storage.save<@Admin>(<- create Admin(), to: /storage/TSHOTAdmin)
210
211 // Emit an event that shows that the contract was initialized
212 emit TokensInitialized(initialSupply: self.totalSupply)
213 }
214}
215