Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions contracts/FlowExecutionParameters.cdc
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
/// FlowExecutionParameters stores the parameters for metering
/// transaction fees for Flow transactions

access(all) contract FlowExecutionParameters {

// Gets Execution Effort Weights from the parameters account's storage
// Gets Execution Effort Weights from the service account's storage
access(all) view fun getExecutionEffortWeights(): {UInt64: UInt64} {
return self.account.storage.copy<{UInt64: UInt64}>(from: /storage/executionEffortWeights)
?? panic("execution effort weights not set yet")
}

// Gets Execution Memory Weights from the parameters account's storage
// Gets Execution Memory Weights from the service account's storage
access(all) view fun getExecutionMemoryWeights(): {UInt64: UInt64} {
return self.account.storage.copy<{UInt64: UInt64}>(from: /storage/executionMemoryWeights)
?? panic("execution memory weights not set yet")
}

// Gets Execution Memory Limit from the parameters account's storage
// Gets Execution Memory Limit from the service account's storage
access(all) view fun getExecutionMemoryLimit(): UInt64 {
return self.account.storage.copy<UInt64>(from: /storage/executionMemoryLimit)
?? panic("execution memory limit not set yet")
Expand Down
117 changes: 12 additions & 105 deletions contracts/FlowFees.cdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "FungibleToken"
import "FlowToken"
import "FlowStorageFees"
import FungibleToken from 0xf233dcee88fe0abe
import FlowToken from 0x1654653399040a61
import FlowStorageFees from 0xe467b9dd11fa00df

access(all) contract FlowFees {

Expand Down Expand Up @@ -28,85 +28,17 @@ access(all) contract FlowFees {

/// Get the balance of the Fees Vault
access(all) fun getFeeBalance(): UFix64 {
let childFeeAccounts = self.account.storage.borrow<&[Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>]>(from: /storage/ChildFeeAccounts)

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
return self.vault.balance
}

var totalFees = 0.0
totalFees = totalFees + self.vault.balance

for feeAccountRef in childFeeAccounts! {
if let feeAccount = feeAccountRef.borrow() {
totalFees = totalFees + feeAccount.availableBalance
}
}

return totalFees
return self.vault.balance
}

access(all) resource Administrator {
// withdraw
//
// Allows the administrator to withdraw tokens from the fee vault
access(all) fun withdrawTokensFromFeeVault(amount: UFix64): @{FungibleToken.Vault} {
var remainingAmount = amount
var withdrawAmount = 0.0
if FlowFees.vault.balance < remainingAmount {
withdrawAmount = FlowFees.vault.balance
} else {
withdrawAmount = remainingAmount
}
remainingAmount = remainingAmount - withdrawAmount
var vault <- FlowFees.vault.withdraw(amount: withdrawAmount)

let childFeeAccounts = FlowFees.account.storage.borrow<&[Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>]>(from: /storage/ChildFeeAccounts)

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
if remainingAmount > 0.0 {
panic("Cannot withdraw the requested amount of fee tokens. The amount of FLOW of \(amount) requested to withdraw is greater than the total fees in the fee vaults.")
}
if vault.balance != amount {
// unreachable
panic("Unexpected return vault balance!")
}

emit TokensWithdrawn(amount: amount)
return <- vault
}

var accountIndex = 0;
while accountIndex < childFeeAccounts!.length && remainingAmount > 0.0 {
if let feeAccount = childFeeAccounts![accountIndex].borrow() {
if let childVaultRef = feeAccount.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(from: /storage/flowTokenVault) {
let availableBalance = feeAccount.availableBalance

var withdrawAmount = 0.0
if availableBalance < remainingAmount {
withdrawAmount = availableBalance
} else {
withdrawAmount = remainingAmount
}
remainingAmount = remainingAmount - withdrawAmount
vault.deposit(from: <- childVaultRef.withdraw(amount: withdrawAmount))
}
}
accountIndex = accountIndex + 1
}

if remainingAmount > 0.0 {
panic("Cannot withdraw the requested amount of fee tokens. The amount of FLOW of \(amount) requested to withdraw is greater than the total fees in the fee vaults.")
}
if vault.balance != amount {
// unreachable
panic("Unexpected return vault balance!")
}

let vault <- FlowFees.vault.withdraw(amount: amount)
emit TokensWithdrawn(amount: amount)
return <- vault
return <-vault
}

/// Allows the administrator to change all the fee parameters at once
Expand Down Expand Up @@ -211,7 +143,7 @@ access(all) contract FlowFees {
}

let tokenVault = acct.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(from: /storage/flowTokenVault)
?? panic("FlowFees.deductTransactionFee: Unable to borrow reference to the default token vault")
?? panic("Unable to borrow reference to the default token vault")


if feeAmount > tokenVault.balance {
Expand All @@ -224,39 +156,14 @@ access(all) contract FlowFees {
}

let feeVault <- tokenVault.withdraw(amount: feeAmount)

self.collectFeesOnChildAccounts(<- feeVault)
self.vault.deposit(from: <-feeVault)

// The fee calculation can be reconstructed using the data from this event and the FeeParameters at the block when the event happened
emit FeesDeducted(amount: feeAmount, inclusionEffort: inclusionEffort, executionEffort: executionEffort)
}

/// The supplied vault will go to one child fee account according to the current number of child fee accounts and the current transaction index.
/// if there are no child accounts, the fees will be collected in the self.vault
access(self) fun collectFeesOnChildAccounts(_ vault: @{FungibleToken.Vault}) {
let childFeeAccounts = self.account.storage.borrow<&[Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>]>(from: /storage/ChildFeeAccounts)

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
self.vault.deposit(from: <-vault)
return
}

let txIndex = getTransactionIndex()
let accountIndex = Int(txIndex % UInt32(childFeeAccounts!.length))

if let feeAccount = childFeeAccounts![accountIndex].borrow() {
if let receiver = feeAccount.capabilities.borrow<&{FungibleToken.Receiver}>(/public/flowTokenReceiver) {
receiver.deposit(from: <-vault)
return
}
}
// fallback in case there is a problem borrowing a child account
self.vault.deposit(from: <-vault)
}

access(all) view fun getFeeParameters(): FeeParameters {
return self.account.storage.copy<FeeParameters>(from: /storage/FlowTxFeeParameters) ?? panic("FlowFees.getFeeParameters: Error getting tx fee parameters. They need to be initialized first!")
return self.account.storage.copy<FeeParameters>(from: /storage/FlowTxFeeParameters) ?? panic("Error getting tx fee parameters. They need to be initialized first!")
}

access(self) fun setFeeParameters(_ feeParameters: FeeParameters) {
Expand All @@ -275,11 +182,11 @@ access(all) contract FlowFees {
return totalFees
}

init() {
init(adminAccount: auth(SaveValue) &Account) {
// Create a new FlowToken Vault and save it in storage
self.vault <- FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()) as! @FlowToken.Vault

let admin <- create Administrator()
self.account.storage.save(<-admin, to: /storage/flowFeesAdmin)
adminAccount.storage.save(<-admin, to: /storage/flowFeesAdmin)
}
}
}
Loading
Loading