Smart Contract

FooToken

A.3eebe1cb4a1126b2.FooToken

Valid From

122,354,379

Deployed

5d ago
Feb 22, 2026, 09:32:01 AM UTC

Dependents

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