Smart Contract
FooToken
A.f7913d7a57ba6555.FooToken
1//testnet
2import FungibleToken from 0xf233dcee88fe0abe //Mainnet address: 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448 //Mainnet address: 0x1d7e57aa55817448
4import FungibleTokenMetadataViews from 0xf233dcee88fe0abe //Mainnet address: 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}