Transaction Costing
  • 29 May 2024
  • 5 Minutes to read
  • Dark
    Light
  • PDF

Transaction Costing

  • Dark
    Light
  • PDF

Article summary

What are transaction costs?

At the very high-level, transaction costs can be broken down into the following categories:


Item
Unit of MeasurementDescription
ExecutionExecution Cost UnitThis is to account for the CPU usage during the execution of a transaction.


In this context, execution refers to the process of determining the state changes and other side effects by interpreting the instructions one-by-one upon some existing world state.

FinalisationFinalisation Cost UnitThis is to account for the CPU usage during the finalisation of a transaction.

In this context, finalisation refers to the process of committing state changes derived from a transaction and other auxiliary indices.
StorageBytesThis is to account for the additional data being added to a Node database.

There are currently two type of storage costs:
  1. State Storage - The substates
  2. Archive Storage - Transaction payload, events and logs
RoyaltiesXRD and USDThe amount of XRD paid to blueprint developers and component owners for the use of the code or component instances.
TipPercentageThe extra amount of XRD paid to validators for the processing of a transaction.

This is designed to help prioritise transaction when there is a traffic jam.

How does costing work?

Transaction costing is done through the costing module within the System.

This module is responsible for tracking the fee balance, counting execution and finalisation cost units and applying the costs listed above, with the help of a fee reserve.

At the beginning of a transaction, the fee reserve is provided with a loan of XRD to bootstrap transaction execution. 

  • The amount is defined as:
execution_cost_unit_price  * ( 1 + tip_percentage / 100) * execution_cost_unit_loan
  • This loan must be repaid before execution_cost_unit_loan number of execution cost units are consumed ("repay condition"), otherwise the transaction is rejected.

After that, transaction execution starts, during which two processes happen

  • Kernel and system sends execution cost events (such as CPU usage, royalties) to the costing module:
    • To deduct the fee balance
    • To increase the cost unit counter
    • To repay system loan and apply deferred costs, if repay condition is met
  • System sends vault lock fee events to the costing module:
    • To credit fee balance

Once execution is done, costing module is instructed to apply finalisation cost and storage cost.

Costing Parameters

The following parameters are used by the costing module.

Protocol defined parameters

NameValueDescription
execution_cost_unit_price0.00000005The price of execution cost unit in XRD.
execution_cost_unit_limit100,000,000The maximum number of execution cost units that a transaction can consume.
execution_cost_unit_loan4,000,000The number of execution cost units loaned from the system, to bootstrap transaction execution.
finalization_cost_unit_price0.00000005The price of finalisation cost unit in XRD.
finalization_cost_unit_limit50,000,000The maximum number of finalisation cost units that a transaction can consume.
usd_price16.666666666666666666The price of USD in XRD.  1 XRD = 0.06 USD
state_storage_price0.00009536743The price of state storage. 1 MiB = 6 USD
archive_storage_price0.00009536743The price of archive storage.  1MiB = 6 USD

Transaction defined parameters

NameDescription
tip_percentageThe tip percentage specified by the transaction.
free_credit_in_xrdThe free credit amount specified by a preview request.

Fee Table

The table below further defines the cost of each costing entry.

CategoryEntryDescriptionCost
Execution
(execution cost unit)
VerifyTxSignatures
Verify transaction signature.Variable: num_of_signature * 7000
ValidateTxPayload
Verify transaction payload.Variable: size(payload) * 40
RunNativeCode
Run native code.Native code execution is billed in native execution unit per function based on table here.
34 native execution units = 1 execution cost unit
RunWasmCode
Run WASM code.WASM code execution is billed in WASM execution units per instruction based on weights here.
3000 WASM execution units = 1 execution cost unit
PrepareWasmCode
Prepare WASM code.Variable: size(wasm) * 2
BeforeInvoke
Before function invocation.Variable: size(input) * 2
AfterInvoke
After function invocation.Variable: size(output) * 2
AllocateNodeId
Allocate a new node id. Node is the lower level representation of an object or key value store.Fixed: 97
CreateNode
Create a new node.

Variable: size(substate) + 456
 

DropNode
Drop a node.Variable: size(substate) +1143
PinNode
Pin a node to a device (heap or track).Variable: 12 + IO access
MoveModule
Move module from one node to another.Variable: 140 + IO access
OpenSubstate
Open a substate of a node.Variable: 303 + IO access
ReadSubstate
Read the value of a substate.

Variable:

  • If from heap: 65 + size(substate) * 2 + IO access
  • If from track: 113 + size(substate) * 2 + IO access
WriteSubstate
Update the value of a substate.Variable: 218 + size(substate) * 2 + IO access
CloseSubstate
Cloes a substate.Fixed: 129
MarkSubstateAsTransient
Marks a substate a transient. Transient substates are not committed after transaction.Fixed: 55
SetSubstate
Set the value of a substateVariable: 133 + size(substate) * 2 + IO access
RemoveSubstate
Remove a substateVariable: 717 + IO access
ScanKeys
Scan substate keys in a collectionVariable: 498 + IO access
ScanSortedSubstates
Scan substates in a collectionVariable: 187 + IO access
DrainSubstates
Drain substates in a collectionVariable: 273 * num_of_substates + 272 + IO access
LockFee
Lock feeFixed: 500
QueryFeeReserve
Query state of fee reserveFixed: 500
QueryActor
Query actor of this call frameFixed: 500
QueryTransactionHash
Query the transaction hashFixed: 500
GenerateRuid
Generate a RUIDFixed: 500
EmitEvent
Emit an eventVariable: 500 + size(event) * 2
EmitLog
Emit a logVariable: 500 + size(log) * 2
Panic
Panic and abort executionVariable: 500 + size(message) * 2 
Finalisation
(finalisation cost unit)
CommitStateUpdates
Commit state updatesVariable, per substate:
  • Insert or update: 100,000 + size(substate) / 4
  • Delete: 100,000
CommitEvents
Commit eventsVariable, per event: 5,000 + size(event) / 4
CommitLogs
Commit logsVariable, per log: 1,000 + size (log) / 4
Storage
(XRD)
IncreaseStateStorageSize
Increase the size of the state storageVariable, per byte: 0.00009536743
IncreaseArchiveStorageSize
Increase the size of the archive storageVariable, per byte: 0.00009536743

IO access cost:

  • Read from database and found: 40,000 + size / 10
  • Read from database and not found: 160,000

Costing Runtime APIs

The system exposes a list of API to query the current state of the fee reserve.

See WASM API and Scrypto rustdoc.

Fee Distribution

CostTo ProposerTo Validator SetTo BurnTo Royalty Owners
Execution25%25%50%0
Finalisation25%25%50%0
Storage25%25%50%0
Royalty000100%
Tip100%000



Was this article helpful?