- 29 May 2024
- 5 Minutes to read
- DarkLight
- PDF
Transaction Costing
- Updated on 29 May 2024
- 5 Minutes to read
- DarkLight
- PDF
What are transaction costs?
At the very high-level, transaction costs can be broken down into the following categories:
Item | Unit of Measurement | Description |
---|---|---|
Execution | Execution Cost Unit | This 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. |
Finalisation | Finalisation Cost Unit | This 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. |
Storage | Bytes | This is to account for the additional data being added to a Node database. There are currently two type of storage costs:
|
Royalties | XRD and USD | The amount of XRD paid to blueprint developers and component owners for the use of the code or component instances. |
Tip | Percentage | The 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
Name | Value | Description |
---|---|---|
execution_cost_unit_price | 0.00000005 | The price of execution cost unit in XRD. |
execution_cost_unit_limit | 100,000,000 | The maximum number of execution cost units that a transaction can consume. |
execution_cost_unit_loan | 4,000,000 | The number of execution cost units loaned from the system, to bootstrap transaction execution. |
finalization_cost_unit_price | 0.00000005 | The price of finalisation cost unit in XRD. |
finalization_cost_unit_limit | 50,000,000 | The maximum number of finalisation cost units that a transaction can consume. |
usd_price | 16.666666666666666666 | The price of USD in XRD. 1 XRD = 0.06 USD |
state_storage_price | 0.00009536743 | The price of state storage. 1 MiB = 6 USD |
archive_storage_price | 0.00009536743 | The price of archive storage. 1MiB = 6 USD |
Transaction defined parameters
Name | Description |
---|---|
tip_percentage | The tip percentage specified by the transaction. |
free_credit_in_xrd | The free credit amount specified by a preview request. |
Fee Table
The table below further defines the cost of each costing entry.
Category | Entry | Description | Cost |
---|---|---|---|
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: | |
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:
| |
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 substate | Variable: 133 + size(substate) * 2 + IO access | |
RemoveSubstate | Remove a substate | Variable: 717 + IO access | |
ScanKeys | Scan substate keys in a collection | Variable: 498 + IO access | |
ScanSortedSubstates | Scan substates in a collection | Variable: 187 + IO access | |
DrainSubstates | Drain substates in a collection | Variable: 273 * num_of_substates + 272 + IO access | |
LockFee | Lock fee | Fixed: 500 | |
QueryFeeReserve | Query state of fee reserve | Fixed: 500 | |
QueryActor | Query actor of this call frame | Fixed: 500 | |
QueryTransactionHash | Query the transaction hash | Fixed: 500 | |
GenerateRuid | Generate a RUID | Fixed: 500 | |
EmitEvent | Emit an event | Variable: 500 + size(event) * 2 | |
EmitLog | Emit a log | Variable: 500 + size(log) * 2 | |
Panic | Panic and abort execution | Variable: 500 + size(message) * 2 | |
Finalisation (finalisation cost unit) | CommitStateUpdates | Commit state updates | Variable, per substate:
|
CommitEvents | Commit events | Variable, per event: 5,000 + size(event) / 4 | |
CommitLogs | Commit logs | Variable, per log: 1,000 + size (log) / 4 | |
Storage (XRD) | IncreaseStateStorageSize | Increase the size of the state storage | Variable, per byte: 0.00009536743 |
IncreaseArchiveStorageSize | Increase the size of the archive storage | Variable, 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
Cost | To Proposer | To Validator Set | To Burn | To Royalty Owners |
---|---|---|---|---|
Execution | 25% | 25% | 50% | 0 |
Finalisation | 25% | 25% | 50% | 0 |
Storage | 25% | 25% | 50% | 0 |
Royalty | 0 | 0 | 0 | 100% |
Tip | 100% | 0 | 0 | 0 |