Smart Contract

TSHOT

A.05b67ba314000b2d.TSHOT

Deployed

2w ago
Feb 11, 2026, 05:28:51 PM UTC

Dependents

180 imports
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