@flowtyio/flow-contracts 0.0.11 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,183 @@
1
+ import "FungibleToken"
2
+ import "MetadataViews"
3
+
4
+ /// This contract implements the metadata standard proposed
5
+ /// in FLIP-1087.
6
+ ///
7
+ /// Ref: https://github.com/onflow/flow/blob/master/flips/20220811-fungible-tokens-metadata.md
8
+ ///
9
+ /// Structs and resources can implement one or more
10
+ /// metadata types, called views. Each view type represents
11
+ /// a different kind of metadata.
12
+ ///
13
+ pub contract FungibleTokenMetadataViews {
14
+ /// FTView wraps FTDisplay and FTVaultData, and is used to give a complete
15
+ /// picture of a Fungible Token. Most Fungible Token contracts should
16
+ /// implement this view.
17
+ ///
18
+ pub struct FTView {
19
+ pub let ftDisplay: FTDisplay?
20
+ pub let ftVaultData: FTVaultData?
21
+ init(
22
+ ftDisplay: FTDisplay?,
23
+ ftVaultData: FTVaultData?
24
+ ) {
25
+ self.ftDisplay = ftDisplay
26
+ self.ftVaultData = ftVaultData
27
+ }
28
+ }
29
+
30
+ /// Helper to get a FT view.
31
+ ///
32
+ /// @param viewResolver: A reference to the resolver resource
33
+ /// @return A FTView struct
34
+ ///
35
+ pub fun getFTView(viewResolver: &{MetadataViews.Resolver}): FTView {
36
+ let maybeFTView = viewResolver.resolveView(Type<FTView>())
37
+ if let ftView = maybeFTView {
38
+ return ftView as! FTView
39
+ }
40
+ return FTView(
41
+ ftDisplay: self.getFTDisplay(viewResolver),
42
+ ftVaultData: self.getFTVaultData(viewResolver)
43
+ )
44
+ }
45
+
46
+ /// View to expose the information needed to showcase this FT.
47
+ /// This can be used by applications to give an overview and
48
+ /// graphics of the FT.
49
+ ///
50
+ pub struct FTDisplay {
51
+ /// The display name for this token.
52
+ ///
53
+ /// Example: "Flow"
54
+ ///
55
+ pub let name: String
56
+
57
+ /// The abbreviated symbol for this token.
58
+ ///
59
+ /// Example: "FLOW"
60
+ pub let symbol: String
61
+
62
+ /// A description the provides an overview of this token.
63
+ ///
64
+ /// Example: "The FLOW token is the native currency of the Flow network."
65
+ pub let description: String
66
+
67
+ /// External link to a URL to view more information about the fungible token.
68
+ pub let externalURL: MetadataViews.ExternalURL
69
+
70
+ /// One or more versions of the fungible token logo.
71
+ pub let logos: MetadataViews.Medias
72
+
73
+ /// Social links to reach the fungible token's social homepages.
74
+ /// Possible keys may be "instagram", "twitter", "discord", etc.
75
+ pub let socials: {String: MetadataViews.ExternalURL}
76
+
77
+ init(
78
+ name: String,
79
+ symbol: String,
80
+ description: String,
81
+ externalURL: MetadataViews.ExternalURL,
82
+ logos: MetadataViews.Medias,
83
+ socials: {String: MetadataViews.ExternalURL}
84
+ ) {
85
+ self.name = name
86
+ self.symbol = symbol
87
+ self.description = description
88
+ self.externalURL = externalURL
89
+ self.logos = logos
90
+ self.socials = socials
91
+ }
92
+ }
93
+
94
+ /// Helper to get FTDisplay in a way that will return a typed optional.
95
+ ///
96
+ /// @param viewResolver: A reference to the resolver resource
97
+ /// @return An optional FTDisplay struct
98
+ ///
99
+ pub fun getFTDisplay(_ viewResolver: &{MetadataViews.Resolver}): FTDisplay? {
100
+ if let maybeDisplayView = viewResolver.resolveView(Type<FTDisplay>()) {
101
+ if let displayView = maybeDisplayView as? FTDisplay {
102
+ return displayView
103
+ }
104
+ }
105
+ return nil
106
+ }
107
+
108
+ /// View to expose the information needed store and interact with a FT vault.
109
+ /// This can be used by applications to setup a FT vault with proper
110
+ /// storage and public capabilities.
111
+ ///
112
+ pub struct FTVaultData {
113
+ /// Path in storage where this FT vault is recommended to be stored.
114
+ pub let storagePath: StoragePath
115
+
116
+ /// Public path which must be linked to expose the public receiver capability.
117
+ pub let receiverPath: PublicPath
118
+
119
+ /// Public path which must be linked to expose the balance and resolver public capabilities.
120
+ pub let metadataPath: PublicPath
121
+
122
+ /// Private path which should be linked to expose the provider capability to withdraw funds
123
+ /// from the vault.
124
+ pub let providerPath: PrivatePath
125
+
126
+ /// Type that should be linked at the `receiverPath`. This is a restricted type requiring
127
+ /// the `FungibleToken.Receiver` interface.
128
+ pub let receiverLinkedType: Type
129
+
130
+ /// Type that should be linked at the `receiverPath`. This is a restricted type requiring
131
+ /// the `FungibleToken.Balance` and `MetadataViews.Resolver` interfaces.
132
+ pub let metadataLinkedType: Type
133
+
134
+ /// Type that should be linked at the aforementioned private path. This
135
+ /// is normally a restricted type with at a minimum the `FungibleToken.Provider` interface.
136
+ pub let providerLinkedType: Type
137
+
138
+ /// Function that allows creation of an empty FT vault that is intended
139
+ /// to store the funds.
140
+ pub let createEmptyVault: ((): @FungibleToken.Vault)
141
+
142
+ init(
143
+ storagePath: StoragePath,
144
+ receiverPath: PublicPath,
145
+ metadataPath: PublicPath,
146
+ providerPath: PrivatePath,
147
+ receiverLinkedType: Type,
148
+ metadataLinkedType: Type,
149
+ providerLinkedType: Type,
150
+ createEmptyVaultFunction: ((): @FungibleToken.Vault)
151
+ ) {
152
+ pre {
153
+ receiverLinkedType.isSubtype(of: Type<&{FungibleToken.Receiver}>()): "Receiver public type must include FungibleToken.Receiver."
154
+ metadataLinkedType.isSubtype(of: Type<&{FungibleToken.Balance, MetadataViews.Resolver}>()): "Metadata public type must include FungibleToken.Balance and MetadataViews.Resolver interfaces."
155
+ providerLinkedType.isSubtype(of: Type<&{FungibleToken.Provider}>()): "Provider type must include FungibleToken.Provider interface."
156
+ }
157
+ self.storagePath = storagePath
158
+ self.receiverPath = receiverPath
159
+ self.metadataPath = metadataPath
160
+ self.providerPath = providerPath
161
+ self.receiverLinkedType = receiverLinkedType
162
+ self.metadataLinkedType = metadataLinkedType
163
+ self.providerLinkedType = providerLinkedType
164
+ self.createEmptyVault = createEmptyVaultFunction
165
+ }
166
+ }
167
+
168
+ /// Helper to get FTVaultData in a way that will return a typed Optional.
169
+ ///
170
+ /// @param viewResolver: A reference to the resolver resource
171
+ /// @return A optional FTVaultData struct
172
+ ///
173
+ pub fun getFTVaultData(_ viewResolver: &{MetadataViews.Resolver}): FTVaultData? {
174
+ if let view = viewResolver.resolveView(Type<FTVaultData>()) {
175
+ if let v = view as? FTVaultData {
176
+ return v
177
+ }
178
+ }
179
+ return nil
180
+ }
181
+
182
+ }
183
+
@@ -0,0 +1,82 @@
1
+ /**
2
+
3
+ # Fungible Token Forwarding Contract
4
+
5
+ This contract shows how an account could set up a custom FungibleToken Receiver
6
+ to allow them to forward tokens to a different account whenever they receive tokens.
7
+
8
+ They can publish this Forwarder resource as a Receiver capability just like a Vault,
9
+ and the sender doesn't even need to know it is different.
10
+
11
+ When an account wants to create a Forwarder, they call the createNewForwarder
12
+ function and provide it with the Receiver reference that they want to forward
13
+ their tokens to.
14
+
15
+ */
16
+
17
+ import "FungibleToken"
18
+
19
+ pub contract TokenForwarding {
20
+
21
+ // Event that is emitted when tokens are deposited to the target receiver
22
+ pub event ForwardedDeposit(amount: UFix64, from: Address?)
23
+
24
+ pub resource interface ForwarderPublic {
25
+ pub fun check(): Bool
26
+ pub fun safeBorrow(): &{FungibleToken.Receiver}?
27
+ }
28
+
29
+ pub resource Forwarder: FungibleToken.Receiver, ForwarderPublic {
30
+
31
+ // This is where the deposited tokens will be sent.
32
+ // The type indicates that it is a reference to a receiver
33
+ //
34
+ access(self) var recipient: Capability
35
+
36
+ // deposit
37
+ //
38
+ // Function that takes a Vault object as an argument and forwards
39
+ // it to the recipient's Vault using the stored reference
40
+ //
41
+ pub fun deposit(from: @FungibleToken.Vault) {
42
+ let receiverRef = self.recipient.borrow<&{FungibleToken.Receiver}>()!
43
+
44
+ let balance = from.balance
45
+
46
+ receiverRef.deposit(from: <-from)
47
+
48
+ emit ForwardedDeposit(amount: balance, from: self.owner?.address)
49
+ }
50
+
51
+ pub fun check(): Bool {
52
+ return self.recipient.check<&{FungibleToken.Receiver}>()
53
+ }
54
+
55
+ pub fun safeBorrow(): &{FungibleToken.Receiver}? {
56
+ return self.recipient.borrow<&{FungibleToken.Receiver}>()
57
+ }
58
+
59
+ // changeRecipient changes the recipient of the forwarder to the provided recipient
60
+ //
61
+ pub fun changeRecipient(_ newRecipient: Capability) {
62
+ pre {
63
+ newRecipient.borrow<&{FungibleToken.Receiver}>() != nil: "Could not borrow Receiver reference from the Capability"
64
+ }
65
+ self.recipient = newRecipient
66
+ }
67
+
68
+ init(recipient: Capability) {
69
+ pre {
70
+ recipient.borrow<&{FungibleToken.Receiver}>() != nil: "Could not borrow Receiver reference from the Capability"
71
+ }
72
+ self.recipient = recipient
73
+ }
74
+ }
75
+
76
+ // createNewForwarder creates a new Forwarder reference with the provided recipient
77
+ //
78
+ pub fun createNewForwarder(recipient: Capability): @Forwarder {
79
+ return <-create Forwarder(recipient: recipient)
80
+ }
81
+ }
82
+
@@ -0,0 +1,199 @@
1
+ import "FungibleToken"
2
+
3
+ pub contract DapperUtilityCoin: FungibleToken {
4
+
5
+ // Total supply of DapperUtilityCoins in existence
6
+ pub var totalSupply: UFix64
7
+
8
+ // Event that is emitted when the contract is created
9
+ pub event TokensInitialized(initialSupply: UFix64)
10
+
11
+ // Event that is emitted when tokens are withdrawn from a Vault
12
+ pub event TokensWithdrawn(amount: UFix64, from: Address?)
13
+
14
+ // Event that is emitted when tokens are deposited to a Vault
15
+ pub event TokensDeposited(amount: UFix64, to: Address?)
16
+
17
+ // Event that is emitted when new tokens are minted
18
+ pub event TokensMinted(amount: UFix64)
19
+
20
+ // Event that is emitted when tokens are destroyed
21
+ pub event TokensBurned(amount: UFix64)
22
+
23
+ // Event that is emitted when a new minter resource is created
24
+ pub event MinterCreated(allowedAmount: UFix64)
25
+
26
+ // Event that is emitted when a new burner resource is created
27
+ pub event BurnerCreated()
28
+
29
+ // Vault
30
+ //
31
+ // Each user stores an instance of only the Vault in their storage
32
+ // The functions in the Vault and governed by the pre and post conditions
33
+ // in FungibleToken when they are called.
34
+ // The checks happen at runtime whenever a function is called.
35
+ //
36
+ // Resources can only be created in the context of the contract that they
37
+ // are defined in, so there is no way for a malicious user to create Vaults
38
+ // out of thin air. A special Minter resource needs to be defined to mint
39
+ // new tokens.
40
+ //
41
+ pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
42
+
43
+ // holds the balance of a users tokens
44
+ pub var balance: UFix64
45
+
46
+ // initialize the balance at resource creation time
47
+ init(balance: UFix64) {
48
+ self.balance = balance
49
+ }
50
+
51
+ // withdraw
52
+ //
53
+ // Function that takes an integer amount as an argument
54
+ // and withdraws that amount from the Vault.
55
+ // It creates a new temporary Vault that is used to hold
56
+ // the money that is being transferred. It returns the newly
57
+ // created Vault to the context that called so it can be deposited
58
+ // elsewhere.
59
+ //
60
+ pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
61
+ self.balance = self.balance - amount
62
+ emit TokensWithdrawn(amount: amount, from: self.owner?.address)
63
+ return <-create Vault(balance: amount)
64
+ }
65
+
66
+ // deposit
67
+ //
68
+ // Function that takes a Vault object as an argument and adds
69
+ // its balance to the balance of the owners Vault.
70
+ // It is allowed to destroy the sent Vault because the Vault
71
+ // was a temporary holder of the tokens. The Vault's balance has
72
+ // been consumed and therefore can be destroyed.
73
+ pub fun deposit(from: @FungibleToken.Vault) {
74
+ let vault <- from as! @DapperUtilityCoin.Vault
75
+ self.balance = self.balance + vault.balance
76
+ emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
77
+ vault.balance = 0.0
78
+ destroy vault
79
+ }
80
+
81
+ destroy() {
82
+ DapperUtilityCoin.totalSupply = DapperUtilityCoin.totalSupply - self.balance
83
+ }
84
+ }
85
+
86
+ // createEmptyVault
87
+ //
88
+ // Function that creates a new Vault with a balance of zero
89
+ // and returns it to the calling context. A user must call this function
90
+ // and store the returned Vault in their storage in order to allow their
91
+ // account to be able to receive deposits of this token type.
92
+ //
93
+ pub fun createEmptyVault(): @FungibleToken.Vault {
94
+ return <-create Vault(balance: 0.0)
95
+ }
96
+
97
+ pub resource Administrator {
98
+ // createNewMinter
99
+ //
100
+ // Function that creates and returns a new minter resource
101
+ //
102
+ pub fun createNewMinter(allowedAmount: UFix64): @Minter {
103
+ emit MinterCreated(allowedAmount: allowedAmount)
104
+ return <-create Minter(allowedAmount: allowedAmount)
105
+ }
106
+
107
+ // createNewBurner
108
+ //
109
+ // Function that creates and returns a new burner resource
110
+ //
111
+ pub fun createNewBurner(): @Burner {
112
+ emit BurnerCreated()
113
+ return <-create Burner()
114
+ }
115
+ }
116
+
117
+ // Minter
118
+ //
119
+ // Resource object that token admin accounts can hold to mint new tokens.
120
+ //
121
+ pub resource Minter {
122
+
123
+ // the amount of tokens that the minter is allowed to mint
124
+ pub var allowedAmount: UFix64
125
+
126
+ // mintTokens
127
+ //
128
+ // Function that mints new tokens, adds them to the total supply,
129
+ // and returns them to the calling context.
130
+ //
131
+ pub fun mintTokens(amount: UFix64): @DapperUtilityCoin.Vault {
132
+ pre {
133
+ amount > UFix64(0): "Amount minted must be greater than zero"
134
+ amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
135
+ }
136
+ DapperUtilityCoin.totalSupply = DapperUtilityCoin.totalSupply + amount
137
+ self.allowedAmount = self.allowedAmount - amount
138
+ emit TokensMinted(amount: amount)
139
+ return <-create Vault(balance: amount)
140
+ }
141
+
142
+ init(allowedAmount: UFix64) {
143
+ self.allowedAmount = allowedAmount
144
+ }
145
+ }
146
+
147
+ // Burner
148
+ //
149
+ // Resource object that token admin accounts can hold to burn tokens.
150
+ //
151
+ pub resource Burner {
152
+
153
+ // burnTokens
154
+ //
155
+ // Function that destroys a Vault instance, effectively burning the tokens.
156
+ //
157
+ // Note: the burned tokens are automatically subtracted from the
158
+ // total supply in the Vault destructor.
159
+ //
160
+ pub fun burnTokens(from: @FungibleToken.Vault) {
161
+ let vault <- from as! @DapperUtilityCoin.Vault
162
+ let amount = vault.balance
163
+ destroy vault
164
+ emit TokensBurned(amount: amount)
165
+ }
166
+ }
167
+
168
+ init() {
169
+ // we're using a high value as the balance here to make it look like we've got a ton of money,
170
+ // just in case some contract manually checks that our balance is sufficient to pay for stuff
171
+ self.totalSupply = 999999999.0
172
+
173
+ let admin <- create Administrator()
174
+ let minter <- admin.createNewMinter(allowedAmount: self.totalSupply)
175
+ self.account.save(<-admin, to: /storage/dapperUtilityCoinAdmin)
176
+
177
+ // mint tokens
178
+ let tokenVault <- minter.mintTokens(amount: self.totalSupply)
179
+ self.account.save(<-tokenVault, to: /storage/dapperUtilityCoinVault)
180
+ destroy minter
181
+
182
+ // Create a public capability to the stored Vault that only exposes
183
+ // the balance field through the Balance interface
184
+ self.account.link<&DapperUtilityCoin.Vault{FungibleToken.Balance}>(
185
+ /public/dapperUtilityCoinBalance,
186
+ target: /storage/dapperUtilityCoinVault
187
+ )
188
+
189
+ // Create a public capability to the stored Vault that only exposes
190
+ // the deposit method through the Receiver interface
191
+ self.account.link<&{FungibleToken.Receiver}>(
192
+ /public/dapperUtilityCoinReceiver,
193
+ target: /storage/dapperUtilityCoinVault
194
+ )
195
+
196
+ // Emit an event that shows that the contract was initialized
197
+ emit TokensInitialized(initialSupply: self.totalSupply)
198
+ }
199
+ }
@@ -0,0 +1,199 @@
1
+ import "FungibleToken"
2
+
3
+ pub contract FlowUtilityToken: FungibleToken {
4
+
5
+ // Total supply of DapperUtilityCoins in existence
6
+ pub var totalSupply: UFix64
7
+
8
+ // Event that is emitted when the contract is created
9
+ pub event TokensInitialized(initialSupply: UFix64)
10
+
11
+ // Event that is emitted when tokens are withdrawn from a Vault
12
+ pub event TokensWithdrawn(amount: UFix64, from: Address?)
13
+
14
+ // Event that is emitted when tokens are deposited to a Vault
15
+ pub event TokensDeposited(amount: UFix64, to: Address?)
16
+
17
+ // Event that is emitted when new tokens are minted
18
+ pub event TokensMinted(amount: UFix64)
19
+
20
+ // Event that is emitted when tokens are destroyed
21
+ pub event TokensBurned(amount: UFix64)
22
+
23
+ // Event that is emitted when a new minter resource is created
24
+ pub event MinterCreated(allowedAmount: UFix64)
25
+
26
+ // Event that is emitted when a new burner resource is created
27
+ pub event BurnerCreated()
28
+
29
+ // Vault
30
+ //
31
+ // Each user stores an instance of only the Vault in their storage
32
+ // The functions in the Vault and governed by the pre and post conditions
33
+ // in FungibleToken when they are called.
34
+ // The checks happen at runtime whenever a function is called.
35
+ //
36
+ // Resources can only be created in the context of the contract that they
37
+ // are defined in, so there is no way for a malicious user to create Vaults
38
+ // out of thin air. A special Minter resource needs to be defined to mint
39
+ // new tokens.
40
+ //
41
+ pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
42
+
43
+ // holds the balance of a users tokens
44
+ pub var balance: UFix64
45
+
46
+ // initialize the balance at resource creation time
47
+ init(balance: UFix64) {
48
+ self.balance = balance
49
+ }
50
+
51
+ // withdraw
52
+ //
53
+ // Function that takes an integer amount as an argument
54
+ // and withdraws that amount from the Vault.
55
+ // It creates a new temporary Vault that is used to hold
56
+ // the money that is being transferred. It returns the newly
57
+ // created Vault to the context that called so it can be deposited
58
+ // elsewhere.
59
+ //
60
+ pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
61
+ self.balance = self.balance - amount
62
+ emit TokensWithdrawn(amount: amount, from: self.owner?.address)
63
+ return <-create Vault(balance: amount)
64
+ }
65
+
66
+ // deposit
67
+ //
68
+ // Function that takes a Vault object as an argument and adds
69
+ // its balance to the balance of the owners Vault.
70
+ // It is allowed to destroy the sent Vault because the Vault
71
+ // was a temporary holder of the tokens. The Vault's balance has
72
+ // been consumed and therefore can be destroyed.
73
+ pub fun deposit(from: @FungibleToken.Vault) {
74
+ let vault <- from as! @FlowUtilityToken.Vault
75
+ self.balance = self.balance + vault.balance
76
+ emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
77
+ vault.balance = 0.0
78
+ destroy vault
79
+ }
80
+
81
+ destroy() {
82
+ FlowUtilityToken.totalSupply = FlowUtilityToken.totalSupply - self.balance
83
+ }
84
+ }
85
+
86
+ // createEmptyVault
87
+ //
88
+ // Function that creates a new Vault with a balance of zero
89
+ // and returns it to the calling context. A user must call this function
90
+ // and store the returned Vault in their storage in order to allow their
91
+ // account to be able to receive deposits of this token type.
92
+ //
93
+ pub fun createEmptyVault(): @FungibleToken.Vault {
94
+ return <-create Vault(balance: 0.0)
95
+ }
96
+
97
+ pub resource Administrator {
98
+ // createNewMinter
99
+ //
100
+ // Function that creates and returns a new minter resource
101
+ //
102
+ pub fun createNewMinter(allowedAmount: UFix64): @Minter {
103
+ emit MinterCreated(allowedAmount: allowedAmount)
104
+ return <-create Minter(allowedAmount: allowedAmount)
105
+ }
106
+
107
+ // createNewBurner
108
+ //
109
+ // Function that creates and returns a new burner resource
110
+ //
111
+ pub fun createNewBurner(): @Burner {
112
+ emit BurnerCreated()
113
+ return <-create Burner()
114
+ }
115
+ }
116
+
117
+ // Minter
118
+ //
119
+ // Resource object that token admin accounts can hold to mint new tokens.
120
+ //
121
+ pub resource Minter {
122
+
123
+ // the amount of tokens that the minter is allowed to mint
124
+ pub var allowedAmount: UFix64
125
+
126
+ // mintTokens
127
+ //
128
+ // Function that mints new tokens, adds them to the total supply,
129
+ // and returns them to the calling context.
130
+ //
131
+ pub fun mintTokens(amount: UFix64): @FlowUtilityToken.Vault {
132
+ pre {
133
+ amount > UFix64(0): "Amount minted must be greater than zero"
134
+ amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
135
+ }
136
+ FlowUtilityToken.totalSupply = FlowUtilityToken.totalSupply + amount
137
+ self.allowedAmount = self.allowedAmount - amount
138
+ emit TokensMinted(amount: amount)
139
+ return <-create Vault(balance: amount)
140
+ }
141
+
142
+ init(allowedAmount: UFix64) {
143
+ self.allowedAmount = allowedAmount
144
+ }
145
+ }
146
+
147
+ // Burner
148
+ //
149
+ // Resource object that token admin accounts can hold to burn tokens.
150
+ //
151
+ pub resource Burner {
152
+
153
+ // burnTokens
154
+ //
155
+ // Function that destroys a Vault instance, effectively burning the tokens.
156
+ //
157
+ // Note: the burned tokens are automatically subtracted from the
158
+ // total supply in the Vault destructor.
159
+ //
160
+ pub fun burnTokens(from: @FungibleToken.Vault) {
161
+ let vault <- from as! @FlowUtilityToken.Vault
162
+ let amount = vault.balance
163
+ destroy vault
164
+ emit TokensBurned(amount: amount)
165
+ }
166
+ }
167
+
168
+ init() {
169
+ // we're using a high value as the balance here to make it look like we've got a ton of money,
170
+ // just in case some contract manually checks that our balance is sufficient to pay for stuff
171
+ self.totalSupply = 999999999.0
172
+
173
+ let admin <- create Administrator()
174
+ let minter <- admin.createNewMinter(allowedAmount: self.totalSupply)
175
+ self.account.save(<-admin, to: /storage/flowUtilityTokenAdmin)
176
+
177
+ // mint tokens
178
+ let tokenVault <- minter.mintTokens(amount: self.totalSupply)
179
+ self.account.save(<-tokenVault, to: /storage/flowUtilityTokenVault)
180
+ destroy minter
181
+
182
+ // Create a public capability to the stored Vault that only exposes
183
+ // the balance field through the Balance interface
184
+ self.account.link<&FlowUtilityToken.Vault{FungibleToken.Balance}>(
185
+ /public/flowUtilityTokenBalance,
186
+ target: /storage/flowUtilityTokenVault
187
+ )
188
+
189
+ // Create a public capability to the stored Vault that only exposes
190
+ // the deposit method through the Receiver interface
191
+ self.account.link<&{FungibleToken.Receiver}>(
192
+ /public/flowUtilityTokenReceiver,
193
+ target: /storage/flowUtilityTokenVault
194
+ )
195
+
196
+ // Emit an event that shows that the contract was initialized
197
+ emit TokensInitialized(initialSupply: self.totalSupply)
198
+ }
199
+ }