Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: test
test: generate
$(MAKE) test -C lib/go
flow test --cover --covercode="contracts" tests/*.cdc
flow test --cover --covercode="contracts" --jobs 1 tests/*.cdc

.PHONY: generate
generate:
Expand Down
69 changes: 66 additions & 3 deletions contracts/FlowFees.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ access(all) contract FlowFees {
// Event that is emitted when fee parameters change
access(all) event FeeParametersChanged(surgeFactor: UFix64, inclusionEffortCost: UFix64, executionEffortCost: UFix64)

// Event that is emitted when the list of child fee accounts changes.
// Contains the full new list of child fee account addresses
// (the FlowFees account itself is not included)
access(all) event ChildFeeAccountsChanged(addresses: [Address])

// Private vault with public deposit function
access(self) var vault: @FlowToken.Vault

Expand All @@ -28,7 +33,7 @@ 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)
let childFeeAccounts = self.borrowChildFeeAccounts()

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
Expand All @@ -47,6 +52,30 @@ access(all) contract FlowFees {
return totalFees
}

/// Borrows the list of child fee account capabilities from storage.
/// Returns nil if no child fee accounts were added yet.
access(self) view fun borrowChildFeeAccounts(): &[Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>]? {
return self.account.storage.borrow<&[Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>]>(from: /storage/ChildFeeAccounts)
}

/// Returns the addresses of all accounts that may receive transaction
/// fee deposits, i.e. the possible `to` addresses of the deposit events
/// emitted when fees are collected: the FlowFees account plus any
/// child fee accounts.
/// Note that fees received by the FlowFees account itself are held in
/// the contract's internal vault, not in the account's default FLOW
/// vault, so they are not reflected in that account's balance.
/// Use getFeeBalance() to get the total balance of all collected fees.
access(all) fun getFeeReceiverAddresses(): [Address] {
let addresses: [Address] = [self.account.address]
if let childFeeAccounts = self.borrowChildFeeAccounts() {
for childFeeAccount in childFeeAccounts {
addresses.append(childFeeAccount.address)
}
}
return addresses
}

access(all) resource Administrator {
// withdraw
//
Expand All @@ -62,7 +91,7 @@ access(all) contract FlowFees {
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)
let childFeeAccounts = FlowFees.borrowChildFeeAccounts()

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
Expand Down Expand Up @@ -121,6 +150,40 @@ access(all) contract FlowFees {
let newParameters = FeeParameters(surgeFactor: surgeFactor, inclusionEffortCost: oldParameters.inclusionEffortCost, executionEffortCost: oldParameters.executionEffortCost)
FlowFees.setFeeParameters(newParameters)
}

/// Creates the given number of new child fee accounts, paid for
/// by `payer`, and adds them to the list of accounts that may
/// receive transaction fee deposits.
/// The new accounts have no keys and are only accessible through
/// the account capabilities stored in the FlowFees account,
/// so they are fully controlled by the FlowFees contract.
access(all) fun createChildFeeAccounts(count: Int, payer: auth(BorrowValue | Storage) &Account) {
pre {
count > 0:
"FlowFees.createChildFeeAccounts: The number of child fee accounts to create must be positive"
}

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

let childAddresses: [Address] = []
for existingChildFeeAccount in childFeeAccounts {
childAddresses.append(existingChildFeeAccount.address)
}

var i = 0
while i < count {
i = i + 1
let newAccount = Account(payer: payer)
let cap = newAccount.capabilities.account.issue<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>()

childFeeAccounts.append(cap)
childAddresses.append(cap.address)
}

FlowFees.account.storage.save(childFeeAccounts, to: /storage/ChildFeeAccounts)

emit ChildFeeAccountsChanged(addresses: childAddresses)
}
}

/// A struct holding the fee parameters needed to calculate the fees
Expand Down Expand Up @@ -234,7 +297,7 @@ access(all) contract FlowFees {
/// 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)
let childFeeAccounts = self.borrowChildFeeAccounts()

// fallback in case no child accounts were created yet
if childFeeAccounts == nil || childFeeAccounts!.length == 0 {
Expand Down
6 changes: 3 additions & 3 deletions lib/go/contracts/internal/assets/assets.go

Large diffs are not rendered by default.

29 changes: 26 additions & 3 deletions lib/go/templates/internal/assets/assets.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 18 additions & 11 deletions lib/go/templates/service_templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ const (
addAccountCreator = "FlowServiceAccount/add_account_creator.cdc"
removeAccountCreator = "FlowServiceAccount/remove_account_creator.cdc"

depositFeesFilename = "FlowServiceAccount/deposit_fees.cdc"
getFeesBalanceFilename = "FlowServiceAccount/scripts/get_fees_balance.cdc"
getFeeParametersFilename = "FlowServiceAccount/scripts/get_tx_fee_parameters.cdc"
setFeeParametersFilename = "FlowServiceAccount/set_tx_fee_parameters.cdc"
setFeeSurgeFactorFilename = "FlowServiceAccount/set_tx_fee_surge_factor.cdc"
getExecutionEffortWeighs = "FlowServiceAccount/scripts/get_execution_effort_weights.cdc"
setExecutionEffortWeighs = "FlowServiceAccount/set_execution_effort_weights.cdc"
getExecutionMemoryWeighs = "FlowServiceAccount/scripts/get_execution_memory_weights.cdc"
setExecutionMemoryWeighs = "FlowServiceAccount/set_execution_memory_weights.cdc"
getExecutionMemoryLimit = "FlowServiceAccount/scripts/get_execution_memory_limit.cdc"
setExecutionMemoryLimit = "FlowServiceAccount/set_execution_memory_limit.cdc"
depositFeesFilename = "FlowServiceAccount/deposit_fees.cdc"
getFeesBalanceFilename = "FlowServiceAccount/scripts/get_fees_balance.cdc"
getFeeReceiverAddressesFilename = "FlowServiceAccount/scripts/get_fee_receiver_addresses.cdc"
getFeeParametersFilename = "FlowServiceAccount/scripts/get_tx_fee_parameters.cdc"
setFeeParametersFilename = "FlowServiceAccount/set_tx_fee_parameters.cdc"
setFeeSurgeFactorFilename = "FlowServiceAccount/set_tx_fee_surge_factor.cdc"
getExecutionEffortWeighs = "FlowServiceAccount/scripts/get_execution_effort_weights.cdc"
setExecutionEffortWeighs = "FlowServiceAccount/set_execution_effort_weights.cdc"
getExecutionMemoryWeighs = "FlowServiceAccount/scripts/get_execution_memory_weights.cdc"
setExecutionMemoryWeighs = "FlowServiceAccount/set_execution_memory_weights.cdc"
getExecutionMemoryLimit = "FlowServiceAccount/scripts/get_execution_memory_limit.cdc"
setExecutionMemoryLimit = "FlowServiceAccount/set_execution_memory_limit.cdc"

verifyPayerBalanceForTxExecution = "FlowServiceAccount/scripts/verify_payer_balance_for_tx_execution.cdc"

Expand Down Expand Up @@ -186,6 +187,12 @@ func GenerateGetFeesBalanceScript(env Environment) []byte {
return []byte(ReplaceAddresses(code, env))
}

func GenerateGetFeeReceiverAddressesScript(env Environment) []byte {
code := assets.MustAssetString(getFeeReceiverAddressesFilename)

return []byte(ReplaceAddresses(code, env))
}

func GenerateDepositFeesScript(env Environment) []byte {
code := assets.MustAssetString(depositFeesFilename)

Expand Down
Loading
Loading