Smart Contract

FooToken

A.e58d1d0c518dbaea.FooToken

Valid From

86,132,854

Deployed

3d ago
Feb 24, 2026, 11:54:04 PM UTC

Dependents

0 imports
1//testnet
2import FungibleToken from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
5
6access(all) contract FooToken {
7
8    access(all) var totalSupply: UFix64
9
10    access(all) let VaultStoragePath: StoragePath
11    access(all) let VaultPublicPath: PublicPath
12    access(all) let MinterStoragePath: StoragePath
13
14    access(all) event TokensMinted(amount: UFix64, type: String)
15
16    access(all) resource Vault: FungibleToken.Vault {
17
18        access(all) var balance: UFix64
19
20        init(balance: UFix64) {
21            self.balance = balance
22        }
23
24        /// Called when a fungible token is burned via the `Burner.burn()` method
25        access(contract) fun burnCallback() {
26            if self.balance > 0.0 {
27                FooToken.totalSupply = FooToken.totalSupply - self.balance
28            }
29            self.balance = 0.0
30        }
31
32        access(all) fun deposit(from: @{FungibleToken.Vault}) {
33            let vault <- from as! @FooToken.Vault
34            self.balance = self.balance + vault.balance
35            destroy vault
36        }
37
38        access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @FooToken.Vault {
39            self.balance = self.balance - amount
40            return <-create Vault(balance: amount)
41        }
42
43        /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
44        access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
45            let supportedTypes: {Type: Bool} = {}
46            supportedTypes[self.getType()] = true
47            return supportedTypes
48        }
49
50        /// Says if the Vault can receive the provided type in the deposit method
51        access(all) view fun isSupportedVaultType(type: Type): Bool {
52            return self.getSupportedVaultTypes()[type] ?? false
53        }
54
55        /// Asks if the amount can be withdrawn from this vault
56        access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
57            return amount <= self.balance
58        }
59
60        access(all) view fun getViews(): [Type] {
61            return FooToken.getContractViews(resourceType: nil)
62        }
63
64        access(all) fun resolveView(_ view: Type): AnyStruct? {
65            return FooToken.resolveContractView(resourceType: nil, viewType: view)
66        }
67
68        access(all) fun createEmptyVault(): @FooToken.Vault {
69            return <-create Vault(balance: 0.0)
70        }
71    }
72
73    access(all) fun createEmptyVault(vaultType: Type): @FooToken.Vault {
74        return <- create Vault(balance: 0.0)
75    }
76
77    access(all) view fun getContractViews(resourceType: Type?): [Type] {
78        return [
79            Type<FungibleTokenMetadataViews.FTView>(),
80            Type<FungibleTokenMetadataViews.FTDisplay>(),
81            Type<FungibleTokenMetadataViews.FTVaultData>(),
82            Type<FungibleTokenMetadataViews.TotalSupply>()
83        ]
84    }
85
86    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
87        switch viewType {
88            case Type<FungibleTokenMetadataViews.FTView>():
89                return FungibleTokenMetadataViews.FTView(
90                    ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTDisplay>()) as! FungibleTokenMetadataViews.FTDisplay?,
91                    ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTVaultData>()) as! FungibleTokenMetadataViews.FTVaultData?
92                )
93            case Type<FungibleTokenMetadataViews.FTDisplay>():
94                let media = MetadataViews.Media(
95                        file: MetadataViews.HTTPFile(
96                        // Change this to your own SVG image
97                        url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
98                    ),
99                    mediaType: "image/svg+xml"
100                )
101                let medias = MetadataViews.Medias([media])
102                return FungibleTokenMetadataViews.FTDisplay(
103                    // Change these to represent your own token
104                    name: "Example Foo Token",
105                    symbol: "EFT",
106                    description: "This fungible token is used as an example to help you develop your next FT #onFlow.",
107                    externalURL: MetadataViews.ExternalURL("https://developers.flow.com/build/guides/fungible-token"),
108                    logos: medias,
109                    socials: {
110                        "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
111                    }
112                )
113            case Type<FungibleTokenMetadataViews.FTVaultData>():
114                return FungibleTokenMetadataViews.FTVaultData(
115                    storagePath: self.VaultStoragePath,
116                    receiverPath: self.VaultPublicPath,
117                    metadataPath: self.VaultPublicPath,
118                    receiverLinkedType: Type<&FooToken.Vault>(),
119                    metadataLinkedType: Type<&FooToken.Vault>(),
120                    createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} {
121                        return <-FooToken.createEmptyVault(vaultType: Type<@FooToken.Vault>())
122                    })
123                )
124            case Type<FungibleTokenMetadataViews.TotalSupply>():
125                return FungibleTokenMetadataViews.TotalSupply(
126                    totalSupply: FooToken.totalSupply
127                )
128        }
129        return nil
130    }
131
132    /// Minter
133    ///
134    /// Resource object that token admin accounts can hold to mint new tokens.
135    ///
136    access(all) resource Minter {
137        /// mintTokens
138        ///
139        /// Function that mints new tokens, adds them to the total supply,
140        /// and returns them to the calling context.
141        ///
142        access(all) fun mintTokens(amount: UFix64): @FooToken.Vault {
143            FooToken.totalSupply = FooToken.totalSupply + amount
144            let vault <-create Vault(balance: amount)
145            emit TokensMinted(amount: amount, type: vault.getType().identifier)
146            return <-vault
147        }
148    }
149
150    init() {
151        self.totalSupply = 1000.0
152
153        self.VaultStoragePath = /storage/fooTokenVault
154        self.VaultPublicPath = /public/fooTokenVault
155        self.MinterStoragePath = /storage/fooTokenMinter
156
157        // Create the Vault with the total supply of tokens and save it in storage
158        //
159        let vault <- create Vault(balance: self.totalSupply)
160        emit TokensMinted(amount: vault.balance, type: vault.getType().identifier)
161        self.account.storage.save(<-vault, to: self.VaultStoragePath)
162
163        // Create a public capability to the stored Vault that exposes
164        // the `deposit` method and getAcceptedTypes method through the `Receiver` interface
165        // and the `balance` method through the `Balance` interface
166        //
167        let fooTokenCap = self.account.capabilities.storage.issue<&FooToken.Vault>(self.VaultStoragePath)
168        self.account.capabilities.publish(fooTokenCap, at: self.VaultPublicPath)
169
170        let minter <- create Minter()
171        self.account.storage.save(<-minter, to: self.MinterStoragePath)
172    }
173}