@flowtyio/flow-contracts 0.0.18 → 0.1.0-beta.2
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.
- package/contracts/FlowStorageFees.cdc +49 -51
- package/contracts/FlowToken.cdc +90 -53
- package/contracts/FungibleToken.cdc +91 -127
- package/contracts/FungibleTokenMetadataViews.cdc +52 -43
- package/contracts/MetadataViews.cdc +345 -363
- package/contracts/NonFungibleToken.cdc +93 -104
- package/contracts/ViewResolver.cdc +34 -5
- package/contracts/lost-and-found/FeeEstimator.cdc +14 -22
- package/contracts/lost-and-found/LostAndFound.cdc +185 -177
- package/contracts/lost-and-found/LostAndFoundHelper.cdc +12 -12
- package/package.json +1 -1
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The FlowStorageFees smart contract
|
|
3
3
|
*
|
|
4
|
-
* An account's storage capacity determines up to how much storage on chain it can use.
|
|
4
|
+
* An account's storage capacity determines up to how much storage on chain it can use.
|
|
5
5
|
* A storage capacity is calculated by multiplying the amount of reserved flow with `StorageFee.storageMegaBytesPerReservedFLOW`
|
|
6
6
|
* The minimum amount of flow tokens reserved for storage capacity is `FlowStorageFees.minimumStorageReservation` this is paid during account creation, by the creator.
|
|
7
|
-
*
|
|
8
|
-
* At the end of all transactions, any account that had any value changed in their storage
|
|
7
|
+
*
|
|
8
|
+
* At the end of all transactions, any account that had any value changed in their storage
|
|
9
9
|
* has their storage capacity checked against their storage used and their main flow token vault against the minimum reservation.
|
|
10
10
|
* If any account fails this check the transaction wil fail.
|
|
11
|
-
*
|
|
12
|
-
* An account moving/deleting its `FlowToken.Vault` resource will result
|
|
11
|
+
*
|
|
12
|
+
* An account moving/deleting its `FlowToken.Vault` resource will result
|
|
13
13
|
* in the transaction failing because the account will have no storage capacity.
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import "FungibleToken"
|
|
18
18
|
import "FlowToken"
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
access(all) contract FlowStorageFees {
|
|
21
21
|
|
|
22
22
|
// Emitted when the amount of storage capacity an account has per reserved Flow token changes
|
|
23
|
-
|
|
23
|
+
access(all) event StorageMegaBytesPerReservedFLOWChanged(_ storageMegaBytesPerReservedFLOW: UFix64)
|
|
24
24
|
|
|
25
25
|
// Emitted when the minimum amount of Flow tokens that an account needs to have reserved for storage capacity changes.
|
|
26
|
-
|
|
26
|
+
access(all) event MinimumStorageReservationChanged(_ minimumStorageReservation: UFix64)
|
|
27
27
|
|
|
28
28
|
// Defines how much storage capacity every account has per reserved Flow token.
|
|
29
|
-
// definition is written per unit of flow instead of the inverse,
|
|
30
|
-
// so there is no loss of precision calculating storage from flow,
|
|
29
|
+
// definition is written per unit of flow instead of the inverse,
|
|
30
|
+
// so there is no loss of precision calculating storage from flow,
|
|
31
31
|
// but there is loss of precision when calculating flow per storage.
|
|
32
|
-
|
|
32
|
+
access(all) var storageMegaBytesPerReservedFLOW: UFix64
|
|
33
33
|
|
|
34
34
|
// Defines the minimum amount of Flow tokens that every account needs to have reserved for storage capacity.
|
|
35
35
|
// If an account has less then this amount reserved by the end of any transaction it participated in, the transaction will fail.
|
|
36
|
-
|
|
36
|
+
access(all) var minimumStorageReservation: UFix64
|
|
37
37
|
|
|
38
38
|
// An administrator resource that can change the parameters of the FlowStorageFees smart contract.
|
|
39
|
-
|
|
39
|
+
access(all) resource Administrator {
|
|
40
40
|
|
|
41
41
|
// Changes the amount of storage capacity an account has per accounts' reserved storage FLOW.
|
|
42
|
-
|
|
42
|
+
access(all) fun setStorageMegaBytesPerReservedFLOW(_ storageMegaBytesPerReservedFLOW: UFix64) {
|
|
43
43
|
if FlowStorageFees.storageMegaBytesPerReservedFLOW == storageMegaBytesPerReservedFLOW {
|
|
44
44
|
return
|
|
45
45
|
}
|
|
@@ -48,7 +48,7 @@ pub contract FlowStorageFees {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Changes the minimum amount of FLOW an account has to have reserved.
|
|
51
|
-
|
|
51
|
+
access(all) fun setMinimumStorageReservation(_ minimumStorageReservation: UFix64) {
|
|
52
52
|
if FlowStorageFees.minimumStorageReservation == minimumStorageReservation {
|
|
53
53
|
return
|
|
54
54
|
}
|
|
@@ -63,19 +63,19 @@ pub contract FlowStorageFees {
|
|
|
63
63
|
///
|
|
64
64
|
/// Returns megabytes
|
|
65
65
|
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
|
|
66
|
-
|
|
66
|
+
access(all) fun calculateAccountCapacity(_ accountAddress: Address): UFix64 {
|
|
67
67
|
var balance = 0.0
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
let acct = getAccount(accountAddress)
|
|
69
|
+
|
|
70
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
71
|
+
balance = balanceRef.getBalance()
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return self.accountBalanceToAccountStorageCapacity(balance)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/// calculateAccountsCapacity returns the storage capacity of a batch of accounts
|
|
78
|
-
|
|
78
|
+
access(all) fun calculateAccountsCapacity(_ accountAddresses: [Address]): [UFix64] {
|
|
79
79
|
let capacities: [UFix64] = []
|
|
80
80
|
for accountAddress in accountAddresses {
|
|
81
81
|
let capacity = self.calculateAccountCapacity(accountAddress)
|
|
@@ -86,52 +86,52 @@ pub contract FlowStorageFees {
|
|
|
86
86
|
|
|
87
87
|
// getAccountsCapacityForTransactionStorageCheck returns the storage capacity of a batch of accounts
|
|
88
88
|
// This is used to check if a transaction will fail because of any account being over the storage capacity
|
|
89
|
-
// The payer is an exception as its storage capacity is derived from its balance minus the maximum possible transaction fees
|
|
89
|
+
// The payer is an exception as its storage capacity is derived from its balance minus the maximum possible transaction fees
|
|
90
90
|
// (transaction fees if the execution effort is at the execution efort limit, a.k.a.: computation limit, a.k.a.: gas limit)
|
|
91
|
-
|
|
91
|
+
access(all) fun getAccountsCapacityForTransactionStorageCheck(accountAddresses: [Address], payer: Address, maxTxFees: UFix64): [UFix64] {
|
|
92
92
|
let capacities: [UFix64] = []
|
|
93
93
|
for accountAddress in accountAddresses {
|
|
94
94
|
var balance = 0.0
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
let acct = getAccount(accountAddress)
|
|
96
|
+
|
|
97
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
98
|
+
if accountAddress == payer {
|
|
99
|
+
// if the account is the payer, deduct the maximum possible transaction fees from the balance
|
|
100
|
+
balance = balanceRef.getBalance().saturatingSubtract(maxTxFees)
|
|
101
|
+
} else {
|
|
102
|
+
balance = balanceRef.getBalance()
|
|
103
|
+
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
capacities.append(self.accountBalanceToAccountStorageCapacity(balance))
|
|
106
|
+
capacities.append(self.accountBalanceToAccountStorageCapacity(balance))
|
|
107
107
|
}
|
|
108
108
|
return capacities
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// accountBalanceToAccountStorageCapacity returns the storage capacity
|
|
112
112
|
// an account would have with given the flow balance of the account.
|
|
113
|
-
|
|
113
|
+
access(all) view fun accountBalanceToAccountStorageCapacity(_ balance: UFix64): UFix64 {
|
|
114
114
|
// get address token balance
|
|
115
115
|
if balance < self.minimumStorageReservation {
|
|
116
116
|
// if < then minimum return 0
|
|
117
117
|
return 0.0
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// return balance multiplied with megabytes per flow
|
|
120
|
+
// return balance multiplied with megabytes per flow
|
|
121
121
|
return self.flowToStorageCapacity(balance)
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// Amount in Flow tokens
|
|
125
125
|
// Returns megabytes
|
|
126
|
-
|
|
126
|
+
access(all) view fun flowToStorageCapacity(_ amount: UFix64): UFix64 {
|
|
127
127
|
return amount.saturatingMultiply(FlowStorageFees.storageMegaBytesPerReservedFLOW)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
// Amount in megabytes
|
|
131
131
|
// Returns Flow tokens
|
|
132
|
-
|
|
133
|
-
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0
|
|
134
|
-
return 0.0
|
|
132
|
+
access(all) view fun storageCapacityToFlow(_ amount: UFix64): UFix64 {
|
|
133
|
+
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0 {
|
|
134
|
+
return 0.0
|
|
135
135
|
}
|
|
136
136
|
// possible loss of precision
|
|
137
137
|
// putting the result back into `flowToStorageCapacity` might not yield the same result
|
|
@@ -139,9 +139,9 @@ pub contract FlowStorageFees {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// converts storage used from UInt64 Bytes to UFix64 Megabytes.
|
|
142
|
-
|
|
142
|
+
access(all) view fun convertUInt64StorageBytesToUFix64Megabytes(_ storage: UInt64): UFix64 {
|
|
143
143
|
// safe convert UInt64 to UFix64 (without overflow)
|
|
144
|
-
let f = UFix64(storage % 100000000
|
|
144
|
+
let f = UFix64(storage % 100000000) * 0.00000001 + UFix64(storage / 100000000)
|
|
145
145
|
// decimal point correction. Megabytes to bytes have a conversion of 10^-6 while UFix64 minimum value is 10^-8
|
|
146
146
|
let storageMb = f.saturatingMultiply(100.0)
|
|
147
147
|
return storageMb
|
|
@@ -151,14 +151,13 @@ pub contract FlowStorageFees {
|
|
|
151
151
|
///
|
|
152
152
|
/// The available balance of an account is its default token balance minus what is reserved for storage.
|
|
153
153
|
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
|
|
154
|
-
|
|
154
|
+
access(all) fun defaultTokenAvailableBalance(_ accountAddress: Address): UFix64 {
|
|
155
155
|
//get balance of account
|
|
156
156
|
let acct = getAccount(accountAddress)
|
|
157
157
|
var balance = 0.0
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.
|
|
161
|
-
balance = balanceRef.balance
|
|
158
|
+
|
|
159
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
160
|
+
balance = balanceRef.getBalance()
|
|
162
161
|
}
|
|
163
162
|
|
|
164
163
|
// get how much should be reserved for storage
|
|
@@ -171,9 +170,9 @@ pub contract FlowStorageFees {
|
|
|
171
170
|
///
|
|
172
171
|
/// The reserved balance of an account is its storage used multiplied by the storage cost per flow token.
|
|
173
172
|
/// The reserved balance is at least the minimum storage reservation.
|
|
174
|
-
|
|
173
|
+
access(all) view fun defaultTokenReservedBalance(_ accountAddress: Address): UFix64 {
|
|
175
174
|
let acct = getAccount(accountAddress)
|
|
176
|
-
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.
|
|
175
|
+
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.storage.used))
|
|
177
176
|
// at least self.minimumStorageReservation should be reserved
|
|
178
177
|
if reserved < self.minimumStorageReservation {
|
|
179
178
|
reserved = self.minimumStorageReservation
|
|
@@ -187,7 +186,6 @@ pub contract FlowStorageFees {
|
|
|
187
186
|
self.minimumStorageReservation = 0.0 // or 0 kb of minimum storage reservation
|
|
188
187
|
|
|
189
188
|
let admin <- create Administrator()
|
|
190
|
-
self.account.save(<-admin, to: /storage/storageFeesAdmin)
|
|
189
|
+
self.account.storage.save(<-admin, to: /storage/storageFeesAdmin)
|
|
191
190
|
}
|
|
192
191
|
}
|
|
193
|
-
|
package/contracts/FlowToken.cdc
CHANGED
|
@@ -3,31 +3,31 @@ import "MetadataViews"
|
|
|
3
3
|
import "FungibleTokenMetadataViews"
|
|
4
4
|
import "ViewResolver"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
access(all) contract FlowToken: ViewResolver {
|
|
7
7
|
|
|
8
8
|
// Total supply of Flow tokens in existence
|
|
9
|
-
|
|
9
|
+
access(all) var totalSupply: UFix64
|
|
10
10
|
|
|
11
11
|
// Event that is emitted when the contract is created
|
|
12
|
-
|
|
12
|
+
access(all) event TokensInitialized(initialSupply: UFix64)
|
|
13
13
|
|
|
14
14
|
// Event that is emitted when tokens are withdrawn from a Vault
|
|
15
|
-
|
|
15
|
+
access(all) event TokensWithdrawn(amount: UFix64, from: Address?)
|
|
16
16
|
|
|
17
17
|
// Event that is emitted when tokens are deposited to a Vault
|
|
18
|
-
|
|
18
|
+
access(all) event TokensDeposited(amount: UFix64, to: Address?)
|
|
19
19
|
|
|
20
20
|
// Event that is emitted when new tokens are minted
|
|
21
|
-
|
|
21
|
+
access(all) event TokensMinted(amount: UFix64)
|
|
22
22
|
|
|
23
23
|
// Event that is emitted when tokens are destroyed
|
|
24
|
-
|
|
24
|
+
access(all) event TokensBurned(amount: UFix64)
|
|
25
25
|
|
|
26
26
|
// Event that is emitted when a new minter resource is created
|
|
27
|
-
|
|
27
|
+
access(all) event MinterCreated(allowedAmount: UFix64)
|
|
28
28
|
|
|
29
29
|
// Event that is emitted when a new burner resource is created
|
|
30
|
-
|
|
30
|
+
access(all) event BurnerCreated()
|
|
31
31
|
|
|
32
32
|
// Vault
|
|
33
33
|
//
|
|
@@ -41,16 +41,39 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
41
41
|
// out of thin air. A special Minter resource needs to be defined to mint
|
|
42
42
|
// new tokens.
|
|
43
43
|
//
|
|
44
|
-
|
|
44
|
+
access(all) resource Vault: FungibleToken.Vault, FungibleToken.Provider, FungibleToken.Receiver, ViewResolver.Resolver {
|
|
45
45
|
|
|
46
46
|
// holds the balance of a users tokens
|
|
47
|
-
|
|
47
|
+
access(all) var balance: UFix64
|
|
48
|
+
|
|
49
|
+
access(all) view fun getBalance(): UFix64 {
|
|
50
|
+
return self.balance
|
|
51
|
+
}
|
|
48
52
|
|
|
49
53
|
// initialize the balance at resource creation time
|
|
50
54
|
init(balance: UFix64) {
|
|
51
55
|
self.balance = balance
|
|
52
56
|
}
|
|
53
57
|
|
|
58
|
+
/// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
|
|
59
|
+
access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
|
|
60
|
+
return {self.getType(): true}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
access(all) view fun isSupportedVaultType(type: Type): Bool {
|
|
64
|
+
if (type == self.getType()) { return true } else { return false }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Returns the storage path where the vault should typically be stored
|
|
68
|
+
access(all) view fun getDefaultStoragePath(): StoragePath? {
|
|
69
|
+
return /storage/flowTokenVault
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Returns the public path where this vault should have a public capability
|
|
73
|
+
access(all) view fun getDefaultPublicPath(): PublicPath? {
|
|
74
|
+
return /public/flowTokenReceiver
|
|
75
|
+
}
|
|
76
|
+
|
|
54
77
|
// withdraw
|
|
55
78
|
//
|
|
56
79
|
// Function that takes an integer amount as an argument
|
|
@@ -60,7 +83,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
60
83
|
// created Vault to the context that called so it can be deposited
|
|
61
84
|
// elsewhere.
|
|
62
85
|
//
|
|
63
|
-
|
|
86
|
+
access(FungibleToken.Withdrawable) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
|
|
64
87
|
self.balance = self.balance - amount
|
|
65
88
|
emit TokensWithdrawn(amount: amount, from: self.owner?.address)
|
|
66
89
|
return <-create Vault(balance: amount)
|
|
@@ -73,7 +96,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
73
96
|
// It is allowed to destroy the sent Vault because the Vault
|
|
74
97
|
// was a temporary holder of the tokens. The Vault's balance has
|
|
75
98
|
// been consumed and therefore can be destroyed.
|
|
76
|
-
|
|
99
|
+
access(all) fun deposit(from: @{FungibleToken.Vault}) {
|
|
77
100
|
let vault <- from as! @FlowToken.Vault
|
|
78
101
|
self.balance = self.balance + vault.balance
|
|
79
102
|
emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
|
|
@@ -81,18 +104,12 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
81
104
|
destroy vault
|
|
82
105
|
}
|
|
83
106
|
|
|
84
|
-
destroy() {
|
|
85
|
-
if self.balance > 0.0 {
|
|
86
|
-
FlowToken.totalSupply = FlowToken.totalSupply - self.balance
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
107
|
/// Get all the Metadata Views implemented by FlowToken
|
|
91
108
|
///
|
|
92
109
|
/// @return An array of Types defining the implemented views. This value will be used by
|
|
93
110
|
/// developers to know which parameter to pass to the resolveView() method.
|
|
94
111
|
///
|
|
95
|
-
|
|
112
|
+
access(all) view fun getViews(): [Type]{
|
|
96
113
|
return FlowToken.getViews()
|
|
97
114
|
}
|
|
98
115
|
|
|
@@ -101,9 +118,13 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
101
118
|
/// @param view: The Type of the desired view.
|
|
102
119
|
/// @return A structure representing the requested view.
|
|
103
120
|
///
|
|
104
|
-
|
|
121
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
105
122
|
return FlowToken.resolveView(view)
|
|
106
123
|
}
|
|
124
|
+
|
|
125
|
+
access(all) fun createEmptyVault(): @{FungibleToken.Vault} {
|
|
126
|
+
return <-create Vault(balance: 0.0)
|
|
127
|
+
}
|
|
107
128
|
}
|
|
108
129
|
|
|
109
130
|
// createEmptyVault
|
|
@@ -113,14 +134,15 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
113
134
|
// and store the returned Vault in their storage in order to allow their
|
|
114
135
|
// account to be able to receive deposits of this token type.
|
|
115
136
|
//
|
|
116
|
-
|
|
137
|
+
access(all) fun createEmptyVault(): @FlowToken.Vault {
|
|
117
138
|
return <-create Vault(balance: 0.0)
|
|
118
139
|
}
|
|
119
140
|
|
|
120
|
-
|
|
141
|
+
access(all) view fun getViews(): [Type] {
|
|
121
142
|
return [Type<FungibleTokenMetadataViews.FTView>(),
|
|
122
143
|
Type<FungibleTokenMetadataViews.FTDisplay>(),
|
|
123
|
-
Type<FungibleTokenMetadataViews.FTVaultData>()
|
|
144
|
+
Type<FungibleTokenMetadataViews.FTVaultData>(),
|
|
145
|
+
Type<FungibleTokenMetadataViews.TotalSupply>()]
|
|
124
146
|
}
|
|
125
147
|
|
|
126
148
|
/// Get a Metadata View from FlowToken
|
|
@@ -128,7 +150,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
128
150
|
/// @param view: The Type of the desired view.
|
|
129
151
|
/// @return A structure representing the requested view.
|
|
130
152
|
///
|
|
131
|
-
|
|
153
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
132
154
|
switch view {
|
|
133
155
|
case Type<FungibleTokenMetadataViews.FTView>():
|
|
134
156
|
return FungibleTokenMetadataViews.FTView(
|
|
@@ -138,7 +160,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
138
160
|
case Type<FungibleTokenMetadataViews.FTDisplay>():
|
|
139
161
|
let media = MetadataViews.Media(
|
|
140
162
|
file: MetadataViews.HTTPFile(
|
|
141
|
-
url:
|
|
163
|
+
url: FlowToken.getLogoURI()
|
|
142
164
|
),
|
|
143
165
|
mediaType: "image/svg+xml"
|
|
144
166
|
)
|
|
@@ -146,7 +168,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
146
168
|
return FungibleTokenMetadataViews.FTDisplay(
|
|
147
169
|
name: "FLOW Network Token",
|
|
148
170
|
symbol: "FLOW",
|
|
149
|
-
description: "FLOW is the
|
|
171
|
+
description: "FLOW is the native token for the Flow blockchain. It is required for securing the network, transaction fees, storage fees, staking, FLIP voting and may be used by applications built on the Flow Blockchain",
|
|
150
172
|
externalURL: MetadataViews.ExternalURL("https://flow.com"),
|
|
151
173
|
logos: medias,
|
|
152
174
|
socials: {
|
|
@@ -159,23 +181,25 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
159
181
|
receiverPath: /public/flowTokenReceiver,
|
|
160
182
|
metadataPath: /public/flowTokenBalance,
|
|
161
183
|
providerPath: /private/flowTokenVault,
|
|
162
|
-
receiverLinkedType: Type<&FlowToken.Vault
|
|
163
|
-
metadataLinkedType: Type<&FlowToken.Vault
|
|
164
|
-
providerLinkedType: Type<&FlowToken.Vault
|
|
165
|
-
createEmptyVaultFunction: (fun (): @FungibleToken.Vault {
|
|
184
|
+
receiverLinkedType: Type<&FlowToken.Vault>(),
|
|
185
|
+
metadataLinkedType: Type<&FlowToken.Vault>(),
|
|
186
|
+
providerLinkedType: Type<&FlowToken.Vault>(),
|
|
187
|
+
createEmptyVaultFunction: (fun (): @{FungibleToken.Vault} {
|
|
166
188
|
return <-FlowToken.createEmptyVault()
|
|
167
189
|
})
|
|
168
190
|
)
|
|
191
|
+
case Type<FungibleTokenMetadataViews.TotalSupply>():
|
|
192
|
+
return FungibleTokenMetadataViews.TotalSupply(totalSupply: FlowToken.totalSupply)
|
|
169
193
|
}
|
|
170
194
|
return nil
|
|
171
195
|
}
|
|
172
196
|
|
|
173
|
-
|
|
197
|
+
access(all) resource Administrator {
|
|
174
198
|
// createNewMinter
|
|
175
199
|
//
|
|
176
200
|
// Function that creates and returns a new minter resource
|
|
177
201
|
//
|
|
178
|
-
|
|
202
|
+
access(all) fun createNewMinter(allowedAmount: UFix64): @Minter {
|
|
179
203
|
emit MinterCreated(allowedAmount: allowedAmount)
|
|
180
204
|
return <-create Minter(allowedAmount: allowedAmount)
|
|
181
205
|
}
|
|
@@ -184,7 +208,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
184
208
|
//
|
|
185
209
|
// Function that creates and returns a new burner resource
|
|
186
210
|
//
|
|
187
|
-
|
|
211
|
+
access(all) fun createNewBurner(): @Burner {
|
|
188
212
|
emit BurnerCreated()
|
|
189
213
|
return <-create Burner()
|
|
190
214
|
}
|
|
@@ -194,17 +218,17 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
194
218
|
//
|
|
195
219
|
// Resource object that token admin accounts can hold to mint new tokens.
|
|
196
220
|
//
|
|
197
|
-
|
|
221
|
+
access(all) resource Minter {
|
|
198
222
|
|
|
199
223
|
// the amount of tokens that the minter is allowed to mint
|
|
200
|
-
|
|
224
|
+
access(all) var allowedAmount: UFix64
|
|
201
225
|
|
|
202
226
|
// mintTokens
|
|
203
227
|
//
|
|
204
228
|
// Function that mints new tokens, adds them to the total supply,
|
|
205
229
|
// and returns them to the calling context.
|
|
206
230
|
//
|
|
207
|
-
|
|
231
|
+
access(all) fun mintTokens(amount: UFix64): @FlowToken.Vault {
|
|
208
232
|
pre {
|
|
209
233
|
amount > UFix64(0): "Amount minted must be greater than zero"
|
|
210
234
|
amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
|
|
@@ -224,7 +248,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
224
248
|
//
|
|
225
249
|
// Resource object that token admin accounts can hold to burn tokens.
|
|
226
250
|
//
|
|
227
|
-
|
|
251
|
+
access(all) resource Burner {
|
|
228
252
|
|
|
229
253
|
// burnTokens
|
|
230
254
|
//
|
|
@@ -233,42 +257,55 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
233
257
|
// Note: the burned tokens are automatically subtracted from the
|
|
234
258
|
// total supply in the Vault destructor.
|
|
235
259
|
//
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
260
|
+
access(all) fun burnTokens(from: @FlowToken.Vault) {
|
|
261
|
+
FlowToken.burnTokens(from: <-from)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
access(all) fun burnTokens(from: @FlowToken.Vault) {
|
|
266
|
+
let vault <- from as! @FlowToken.Vault
|
|
267
|
+
let amount = vault.balance
|
|
268
|
+
destroy vault
|
|
269
|
+
if amount > 0.0 {
|
|
270
|
+
FlowToken.totalSupply = FlowToken.totalSupply - amount
|
|
240
271
|
emit TokensBurned(amount: amount)
|
|
241
272
|
}
|
|
242
273
|
}
|
|
243
274
|
|
|
244
|
-
|
|
275
|
+
/// Gets the Flow Logo XML URI from storage
|
|
276
|
+
access(all) fun getLogoURI(): String {
|
|
277
|
+
return FlowToken.account.storage.copy<String>(from: /storage/flowTokenLogoURI) ?? ""
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
init(adminAccount: auth(Storage, Capabilities) &Account) {
|
|
245
281
|
self.totalSupply = 0.0
|
|
246
282
|
|
|
247
283
|
// Create the Vault with the total supply of tokens and save it in storage
|
|
248
284
|
//
|
|
249
285
|
let vault <- create Vault(balance: self.totalSupply)
|
|
250
|
-
|
|
286
|
+
|
|
287
|
+
// Example of how to resolve a metadata view for a Vault
|
|
288
|
+
let ftView = vault.resolveView(Type<FungibleTokenMetadataViews.FTView>())
|
|
289
|
+
|
|
290
|
+
adminAccount.storage.save(<-vault, to: /storage/flowTokenVault)
|
|
251
291
|
|
|
252
292
|
// Create a public capability to the stored Vault that only exposes
|
|
253
293
|
// the `deposit` method through the `Receiver` interface
|
|
254
294
|
//
|
|
255
|
-
adminAccount.
|
|
256
|
-
|
|
257
|
-
target: /storage/flowTokenVault
|
|
258
|
-
)
|
|
295
|
+
let receiverCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault)
|
|
296
|
+
adminAccount.capabilities.publish(receiverCapability, at: /public/flowTokenReceiver)
|
|
259
297
|
|
|
260
298
|
// Create a public capability to the stored Vault that only exposes
|
|
261
299
|
// the `balance` field through the `Balance` interface
|
|
262
300
|
//
|
|
263
|
-
adminAccount.
|
|
264
|
-
|
|
265
|
-
target: /storage/flowTokenVault
|
|
266
|
-
)
|
|
301
|
+
let balanceCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault)
|
|
302
|
+
adminAccount.capabilities.publish(balanceCapability, at: /public/flowTokenBalance)
|
|
267
303
|
|
|
268
304
|
let admin <- create Administrator()
|
|
269
|
-
adminAccount.save(<-admin, to: /storage/flowTokenAdmin)
|
|
305
|
+
adminAccount.storage.save(<-admin, to: /storage/flowTokenAdmin)
|
|
270
306
|
|
|
271
307
|
// Emit an event that shows that the contract was initialized
|
|
272
308
|
emit TokensInitialized(initialSupply: self.totalSupply)
|
|
309
|
+
|
|
273
310
|
}
|
|
274
311
|
}
|