@@ -9,6 +9,12 @@ pub contract FlowFees {
9
9
// Event that is emitted when tokens are withdrawn from the fee vault
10
10
pub event TokensWithdrawn (amount : UFix64 )
11
11
12
+ // Event that is emitted when fees are deducted
13
+ pub event FeesDeducted (amount : UFix64 , inclusionEffort : UFix64 , executionEffort : UFix64 )
14
+
15
+ // Event that is emitted when fee parameters change
16
+ pub event FeeParametersChanged (surgeFactor : UFix64 , inclusionEffortCost : UFix64 , executionEffortCost : UFix64 )
17
+
12
18
// Private vault with public deposit function
13
19
access (self ) var vault : @FlowToken .Vault
14
20
@@ -33,6 +39,86 @@ pub contract FlowFees {
33
39
emit TokensWithdrawn (amount : amount)
34
40
return <- vault
35
41
}
42
+
43
+ /// Allows the administrator to change all the fee parameters at once
44
+ pub fun setFeeParameters (surgeFactor : UFix64 , inclusionEffortCost : UFix64 , executionEffortCost : UFix64 ) {
45
+ let newParameters = FeeParameters (surgeFactor : surgeFactor, inclusionEffortCost : inclusionEffortCost, executionEffortCost : executionEffortCost)
46
+ FlowFees.setFeeParameters (newParameters)
47
+ }
48
+
49
+ /// Allows the administrator to change the fee surge factor
50
+ pub fun setFeeSurgeFactor (_ surgeFactor : UFix64 ) {
51
+ let oldParameters = FlowFees.getFeeParameters ()
52
+ let newParameters = FeeParameters (surgeFactor : surgeFactor, inclusionEffortCost : oldParameters.inclusionEffortCost, executionEffortCost : oldParameters.executionEffortCost)
53
+ FlowFees.setFeeParameters (newParameters)
54
+ }
55
+ }
56
+
57
+ /// A struct holding the fee parameters needed to calculate the fees
58
+ pub struct FeeParameters {
59
+ /// The surge factor is used to make transaction fees respond to high loads on the network
60
+ pub var surgeFactor : UFix64
61
+ /// The FLOW cost of one unit of inclusion effort. The FVM is responsible for metering inclusion effort.
62
+ pub var inclusionEffortCost : UFix64
63
+ /// The FLOW cost of one unit of execution effort. The FVM is responsible for metering execution effort.
64
+ pub var executionEffortCost : UFix64
65
+
66
+ init (surgeFactor : UFix64 , inclusionEffortCost : UFix64 , executionEffortCost : UFix64 ){
67
+ self .surgeFactor = surgeFactor
68
+ self .inclusionEffortCost = inclusionEffortCost
69
+ self .executionEffortCost = executionEffortCost
70
+ }
71
+ }
72
+
73
+ /// Called when a transaction is submitted to deduct the fee
74
+ /// from the AuthAccount that submitted it
75
+ pub fun deductTransactionFee (_ acct : AuthAccount , inclusionEffort : UFix64 , executionEffort : UFix64 ) {
76
+ var feeAmount = self .computeFees (inclusionEffort : inclusionEffort, executionEffort : executionEffort)
77
+
78
+ if feeAmount == UFix64 (0 ) {
79
+ // If there are no fees to deduct, do not continue,
80
+ // so that there are no unnecessarily emitted events
81
+ return
82
+ }
83
+
84
+ let tokenVault = acct.borrow< &FlowToken.Vault> (from : / storage/ flowTokenVault)
85
+ ?? panic (" Unable to borrow reference to the default token vault" )
86
+
87
+
88
+ if feeAmount > tokenVault.balance {
89
+ // In the future this code path will never be reached,
90
+ // as payers that are under account minimum balance will not have their transactions included in a collection
91
+ //
92
+ // Currently this is not used to fail the transaction (as that is the responsibility of the minimum account balance logic),
93
+ // But is used to reduce the balance of the vault to 0.0, if the vault has less available balance than the transaction fees.
94
+ feeAmount = tokenVault.balance
95
+ }
96
+
97
+ let feeVault <- tokenVault.withdraw (amount : feeAmount)
98
+ self .vault.deposit (from : <- feeVault)
99
+
100
+ // The fee calculation can be reconstructed using the data from this event and the FeeParameters at the block when the event happened
101
+ emit FeesDeducted (amount : feeAmount, inclusionEffort : inclusionEffort, executionEffort : executionEffort)
102
+ }
103
+
104
+ pub fun getFeeParameters (): FeeParameters {
105
+ return self .account.copy< FeeParameters> (from : / storage/ FlowTxFeeParameters) ?? panic (" Error getting tx fee parameters. They need to be initialized first!" )
106
+ }
107
+
108
+ access (self ) fun setFeeParameters (_ feeParameters : FeeParameters ) {
109
+ // empty storage before writing new FeeParameters to it
110
+ self .account.load< FeeParameters> (from : / storage/ FlowTxFeeParameters)
111
+ self .account.save (feeParameters,to : / storage/ FlowTxFeeParameters)
112
+ emit FeeParametersChanged (surgeFactor : feeParameters.surgeFactor, inclusionEffortCost : feeParameters.inclusionEffortCost, executionEffortCost : feeParameters.executionEffortCost)
113
+ }
114
+
115
+
116
+ // compute the transaction fees with the current fee parameters and the given inclusionEffort and executionEffort
117
+ pub fun computeFees (inclusionEffort : UFix64 , executionEffort : UFix64 ): UFix64 {
118
+ let params = self .getFeeParameters ()
119
+
120
+ let totalFees = params.surgeFactor * ( inclusionEffort * params.inclusionEffortCost + executionEffort * params.executionEffortCost )
121
+ return totalFees
36
122
}
37
123
38
124
init (adminAccount : AuthAccount ) {
0 commit comments