LIP: 0013
Title: Replace static fee system by dynamic fee system
Author: Iker Alustiza, [email protected]
Discussions-To: https://research.lisk.com/t/replace-static-fee-system-by-dynamic-fee-system/
Status: Replaced
Type: Standards Track
Created: 2019-02-13
Updated: 2024-01-04
Requires: 0009
Superseded-By: 0048
This LIP proposes a dynamic fee system as a free fee market where the fixed fee for all transaction types will be removed and a minimum fee will be defined for every transaction. Any transactions received with a fee below that minimum fee will be rejected. For each transaction, it will be up to the issuer to choose an appropriate transaction fee depending on the network load, which has to be at least the minimum transaction fee.
This LIP is licensed under the Creative Commons Zero 1.0 Universal.
Currently, the fee system in the Lisk protocol consists of a fixed fee for each transaction type:
fees: {
send: 10000000,
vote: 100000000,
secondsignature: 500000000,
delegate: 2500000000,
multisignature: 500000000,
dapp: 2500000000
},
With the huge increase in price of the Lisk token (LSK) in 2017, these fixed fees have become too expensive to allow a healthy usage of the network (as of August 2018, a vote transaction has been averaging at around 8$, 2nd passphrase transactions around 40$ each and registering an account as a delegate at around 200$).
With this in mind, one of the main priorities of the Lisk community has been to make fees cheaper. Indeed, we believe that in order to have a scalable and usable network, this issue needs to be addressed and a fee system has to be implemented able to adapt to the market and network circumstances.
This new fee system must stimulate the Lisk network usage (voting, balance transfers, new delegates registrations, etc...) with reasonable prices per transaction, encouraging people to participate in the network, without putting at stake the security and performance of it (spam attacks).
With the objective of solving the issue of an expensive to use and stagnant network, we propose a dynamic fee system as a free fee market. The protocol will define a minimum fee for every transaction. It will be up to each user to set the fee for each transaction, but any transaction received with a fee below that minimum fee will be considered invalid by the protocol.
Each time a transaction is broadcast into the network and eventually included into a block, resources are consumed. In the case of the Lisk network, there are two types of resources being used depending on the type of transaction:
-
Bandwidth in the network, dynamic memory and disk storage in the nodes : all transaction types.
-
Namespace: delegate registration and dapp registration transactions.
The new fee system takes into account the usage of these resources to give a minimum required fee for a certain transaction to be valid. We define this minimum fee per transaction as:
trs.minFee = trs.nameFee + minFeePerByte * sizeof(trs)
trs.minFee
is given in LSK, minFeePerByte
stands for the minimum fee per byte, given in LSK/byte, sizeof(trs)
is the size of the transaction object in bytes and trs.nameFee
is a parameter, given in LSK, that takes different values depending on the transaction type:
-
For transaction types 0, 1, 3 and 4 (balance transfer, second passphrase registration, voting and multisignature registration transactions),
trs.nameFee
= 0. -
For transaction types 2 and 5 (delegate registration and dapp registration transactions),
trs.nameFee
> 0.
The right choice of the minimum fee per byte, minFeePerByte
, will have a great impact in the network. If the minimum required fee were too high, users would be discouraged from using the network. If the value were too low, attackers would be able to broadcast many valid transactions at a very low cost and congest the network. Regarding the last issue, in this proposal, it is assumed that adequate measures are in place to prevent this from occurring. These measures are mostly implemented in the peer-to-peer (P2P) layer and in the transaction pool. Later in this section, the impact on these modules will be commented more in detail.
With the assumption of having these βanti-spamβ measures in the previously mentioned modules, it would be interesting to consider how these resources mentioned above are used by all the transaction types and the cost implied. Unfortunately, the calculation of the exact cost of these resources is very complex and depends on several unrelated points as, hardware specifications, connection bandwidth, software platform, cost of electricity, Lisk token price volatility, etc. An accurate research about this would be extremely complex and it is out of the scope of this proposal. However, it is still important to study the price of the different transactions and the price of broadcasting several of them depending on the value of minFeePerByte
:
-
Appendix A has an overview of minimum transaction fees depending on different values of
minFeePerByte
and the estimated direct implications for the network. -
This spreadsheet studies the cost of broadcasting a number of balance transactions depending on
minFeePerByte
and the price of LSK in USD.
In view of the computations referenced before, and with the mentioned considerations, a minimum fee in the range of 5 * 10-6 to 5 * 10-5 LSK/byte is reasonable. Therefore, we propose to set minFeePerByte
= 1*10-5 LSK/byte. With this minimum fee per byte, keeping the nodes busy for a brief period of time and having full blocks for 2 minutes (around 1500 basic balance transactions with 15 KB blocks every 10 seconds) will cost at least 1.8 LSK.
Regarding the namespace fee, trs.nameFee
, for transaction types 2 and 5, there are different issues to consider: If the minimum fee for these transaction types were not sufficiently high, theoretically, someone could perform a namespace attack and try to exhaust the namespace by registering a huge number of names. Also, these transaction types give special attributes to the issuing account. Thus, the value of the trs.nameFee
has to be chosen with these criteria in mind. In Appendix B, one can find an overview of the minimum transaction fee for different values of this constant.
In this regard, it is worth noting the important differences between transaction types 2 and 5 for the choice of the trs.nameFee
value. First, type 2 and type 5 transactions have different namespace constraints (the longest possible name for a delegate is 20 characters while the longest name for a dapp is 32 characters), being both of them large enough to make the mentioned exhausting attack infeasible. Therefore, we consider other factors to play a more important role in the decision: For type 2 transactions, registering a delegate implies a commit to become an active delegate and to secure the network. Also, there are only 101 possible active delegates, which makes name squatting attacks (registering a significant amount of popular names) not attractive for amounts much greater than 101. For type 5 transactions, users can register as many dapps as they wish from their accounts. In this case, every dapp registered in the Lisk platform implies a potential development and release of a future sidechain with the consequent consumption of resources. In other words, a type 5 transaction has a potential future impact in the Lisk blockchain that should be reflected in the price of the registration transaction. Thus, it is reasonable to have different constants for the two considered transaction types: trs.nameFee = delegateFee
for transaction type 2, and trs.nameFee = dappFee
for transaction type 5. In particular, and considering the aforementioned differences, we propose:
delegateFee
= 10 LSKdappFee
= 25 LSK
- Remove name uniqueness: If the name uniqueness for delegate and dapp registrations is removed, then the
trs.nameFee
constant can be removed. Users will be able to register exactly the same string as delegates or for their dapp from different Lisk addresses.
- Advantage: Code simplicity and easier parametrization.
- Drawback: Delegates and dapps get dispersed and difficult to tell apart in a sea of spamming copies. Name registrations become a simple flag to signify a property of the account.
- Fixed fee for delegate/dapp transaction: Delegate and dapp registration transactions will have a unique fixed fee in the same way they have it now (adjusted to the cheaper fees situation).
- Advantage: Simplicity in the parametrization. This will follow a rationale of setting a fixed fee for transactions which can only be issued once per account.
- Drawback: This breaks the main point of a dynamic fee system based on a free market. Fixed fees can become inadequate in certain market/network situations.
- Unique global minimum fee (
trs.nameFee
= 0): Even though this will equate all transactions regardless the resources they use, it can be suitable for certainminFeePerByte
values. For example, if the chosenminFeePerByte
is already high (e.g. imposed by network limitations), we may not need an extra parametertrs.nameFee
to account for the namespace usage.
- Advantage: Code simplicity and easier parametrization.
- Drawback: This depends on specific values of
minFeePerByte
. It will not follow the rule of minimum fee depending on the resources.
- No minimum fee given by the protocol: The protocol will not set any rules for a minimum fee for transactions. In principle, a transaction can be included in the blockchain with
trs.fee
= 0 as long as there is space in the next block.
- Advantage: Code simplicity and easier parametrization. Attractive feature from the user point of view.
- Drawback: This allows the pollution of the blockchain with meaningless transactions. There would not be any cost in filling blocks continuously resulting in a bigger blockchain with transactions that provide little utility.
In order to implement a useful and fair fee system based on free market of fees, the main protocol changes should be accompanied with other important changes and improvements:
The transaction pool logic needs to be adapted to the new fee system: It needs to take into account the different fees of the incoming transactions. First, transactions with a fee lower than the minimum fee have to be automatically rejected as soon as they reach the pool. Secondly, a sorting algorithm is beneficial to prioritize transactions depending on the fees. Thirdly, a set of constraints regarding received transactions should be implemented in order to prevent (or mitigate) spam attacks in the network. In the next section, there is a general specification of the proposed changes in the transaction pool. However, it is worth noting that the transaction pool is not a part of the Lisk protocol and node maintainers are free to implement it as they prefer.
The P2P layer plays a critical role in the security and stability of the Lisk network, as in any decentralized network. With the new fee system, sending valid transactions will be, on average, much cheaper than now. Hence, a malicious user may have an incentive of creating and broadcasting thousands of low fee but valid transactions to the network for a long period of time, such that it would be overloaded and other users would experience artificially inflated fees and/or unwanted delays. In this proposal, we assume that the P2P layer enforces a limit on the number of transactions that a node accepts and broadcasts in a given time window. Nodes not following these limits are banned and therefore other nodes cannot be overloaded with too many transactions. However, covering the details of this mechanism is out of the scope of this proposal.
In the current protocol, the fees collected from all transactions confirmed in a round are added up together and then split equally among all the forging delegates (delegates that forged at least one block in the considered round) at the end of this round. We propose to change this mechanism as per the following rationales:
- Assign transaction fees to block forger:
The mentioned mechanism of sharing fees among all forging delegates after every round needs to be changed to avoid the incentive of side channel (or off-chain) payments to delegates. The authors of [1] prove for the auction model defined in the paper that the first-price auction is the unique mechanism which is incentive-compatible for the auctioneer to follow the rules. In a free fee market, one can make the assumption for Lisk that the fees collected in a block are given by the transactions chosen by the auctioneer (the delegates) following a certain auction scheme. In order to have a behaviour close to the first-price auction scheme as defined in the reference, these collected fees will be assigned to the delegate who forged that block, in the same way block rewards are assigned currently. Otherwise, the most profitable strategy for delegates will not be to include transactions with the highest fees per byte, which is against the foundations of a dynamic fee system as a free fee market.
- Burn the minimum fee per transaction:
With the change in the fees sharing mechanism commented above comes an issue which is not to be ignored: If delegates get the fees of the corresponding blocks they generate, they can include their transactions for free. This is not a new problem, since it is present in other networks with free fee markets as Bitcoin or Ethereum (refer to Other considerations subsection below). In fact, sometimes in Bitcoin, it is used as a feature for a service [2]. However, this issue is exacerbated for the Lisk protocol due to specific transaction types like dapp registration transaction. In Lisk, an active delegate could register as many dapps as they wanted for free by including the corresponding transactions in their forged block. This would not only go against the minimum fee rationale exposed before but would incentive behaviours as buying voting power in exchange of discounted dapp registrations.
To solve this situation, we propose to burn the minimum fee of each transaction, trs.minFee
, included in the blockchain. This implies that these collected fees per block mentioned above will not be the sum of all the fees of the transactions included. It will actually be the difference between this sum and the sum of the minimum fees of all the transactions included. Hence, the incentives for delegates to include transactions with higher fees per byte and for users to spend a higher fee for priority are maintained. Moreover, every transaction included in the blockchain will reduce the total supply of the token. This implies that a higher network usage will benefit every stakeholder including the delegates. Appendix C presents a brief study about the impact, in terms of inflation decrease, in the token supply of burning the minimum fee.
With the implementation of the free fee market, users may experience the undesired situation of having stuck transactions waiting in the transaction pool to be included in the blockchain: For example, if a transaction is sent with a fee too low to get into a block when the network is busy (full blocks), it will be stuck in the transaction pool until this situation changes. This would be especially problematic if the transaction had high priority for the sender. With this in mind, it is reasonable to have a method to invalidate or replace pending transactions. There are several ways to approach this issue. Examples of this are the use of an ordered nonce for the transaction (used in Ethereum and Stellar), a non-ordered nonce for the transaction or a time-out parameter in the transaction (used in NXT and NEM). In this proposal, we are not going to cover the specification of such a feature and it will be assumed that a proper transaction invalidating feature is available in the protocol.
The user needs to be aware of the current suitable fee for transactions, which is related to the immediate past situation of the network. Hence, it is reasonable to develop a fee estimation algorithm to recommend the fee that the users should include in their transaction for it to be included in a block after a certain period of time.
Wallets, including Lisk Hub and Lisk Mobile, need to include the functionality for the user to choose the transaction fee. The wallet should not allow a fee below the minimum fee when creating a transaction, and it should suggest the different estimations for the fee depending on the priority of the transaction to the user (using the output of the mentioned fee estimation algorithm). It has to be clear to the users that the estimated fee is just a suggestion or a guidance and they can spend any fee they want (as long as it is equal or above the minimum fee).
Moreover, in order to avoid costly mistakes for the user when setting the fee, the wallets should return a warning if the fee chosen for a certain transaction is extremely high. For example, a balance transaction spending a fee over 4 LSK is most likely a mistake by the issuer.
One of the most discussed issues for blockchains with a free fee market, as Bitcoin or Ethereum, is the ability of block generators to inflate the price of transaction fees artificially for their own benefit. The issue consists of generating low fee transactions to fill blocks such that other users are forced to spend a higher fee to get their transactions accepted. Since the block generators usually get the fees of their generated blocks, theoretically, they can perform this "attack" for free. Although one can argue that this issue occurred several times in the past in the mentioned blockchains, it seems that it had the origin in third parties with other interests and not in block generators themselves [3, 4]. For Lisk and the proposed fee system, we argue that there are mainly two reasons which make this behaviour not practical:
- Lisk uses a Delegated Proof of Stake (DPoS) consensus algorithm. This means that being a block generator does not depend on the investment in the mining hardware or the investment in the token stake (only). In DPoS, being a block generator (delegate) depends on the amount of available stake supporting this account (i.e. amount of vote power for the delegate). Therefore, if a group of delegates attempts to inflate fees, they risk to be detected and consequently down-voted out of the 101 active delegates.
- The proposed mechanism of burning the minimum fee of each transaction will impose a mandatory cost for delegates to inflate the fees, discouraging this kind of behaviour. As it is discussed in [5], this mechanism keeps the desired incentives for block generators without introducing the negative incentives of a traditional fee model (where the whole transaction fee is assigned to the block generator) exposed before. Refer to [5] for a more detailed study of this issue and the broader topic of transaction fees.
Regarding the protocol, the changes involved for the dynamic fee system are the following:
-
Three constants will define the minimum required fee as explained in the previous section[1]:
fees: { minFeePerByte: 1000, delegateFee: 1000000000, dappFee: 2500000000, },
-
Transactions verification: The fixed fee logic has to be replaced in the transaction verification process to accept a dynamic fee structure:
-
A transaction,
trs
, is valid if it spends a fee equal or higher thantrs.minFee
. Depending on the transaction type,trs.minFee
is calculated as:- For transaction types 0, 1, 3 and 4:
trs.minFee = fees.minFeePerByte * sizeof(trs)
- For transaction type 2:
trs.minFee = fees.delegateFee + fees.minFeePerByte * sizeof(trs)
- For transaction type 5:
trs.minFee = fees.dappFee + fees.minFeePerByte * sizeof(trs)
-
The previous point implies to have a method to calculate the size of the specific transaction in bytes:
sizeof()
. In this proposal, we define the size of a transaction,trs
, as the size in bytes of the byte array used to generate the transaction ID (as for example it is done here in the current implementation).
-
-
Include fee property in transaction JSON object: With the implementation of LIP-0012, the
trs.fee
property can be removed from the transaction JSON object since it is not needed for the current static fee system. However, thistrs.fee
has to be included in the transaction object, otherwise the nodes would not be able to get and verify the transaction fee. It must be a string matching theamount
format. -
Include fee property in transaction signature and transaction ID: To prevent transaction fee forging and manipulation by malicious nodes/delegates, the transaction fee has to be part of the byte array used as input for the transaction signature generation and transaction ID generation (e.g. implemented by
getBytes
in Lisk core). Thetrs.fee
property, with a size of 8 bytes and encoded in big-endian, has to follow thetrs.senderPublicKey
property during serialisation. Additionally, thegetTransactionBytes
function must be implemented in the same way in Lisk Elements.[2] -
Assignment of transaction fees: Every transaction included in a block
B
spends a fee equal totrs.fee
which is subtracted from the sender account balance. Fromtrs.fee
,trs.minFee
is burnt whereastrs.fee - trs.minFee
is assigned to the delegate forgingB
. In terms ofB
, this means that the sum of the minimum fees of all the transactions included in it, i.e.,B.burntFee
, is not assigned to any account balance. The remaining fees, i.e.,B.totalFee - B.burntFee
, are added to the account balance of the delegate forgingB
.
[1]It is important to point out that the values given in this document for the three constants fees.minFeePerByte
, fees.delegateFee
and fees.dappFee
may vary in the future. It is possible that the rationale given in this proposal is not accurate at some point (e.g. due to a change of the block size) and a new LIP will propose to adjust these constants consequently.
[2]Note that, this proposal assumes that LIP-0009 is already implemented to avoid any kind of transaction replay attack from a previous protocol version.
A function needs to be implemented to calculate the minimum fee required for a given transaction. The output of this function can be used by user interfaces and wallets as a default value and as guidance for the user so they do not issue invalid transactions with a fee below the minimum fee.
The transaction pool is not per se part of the Lisk protocol, however, it is essential for the correct functioning of the dynamic fee system as explained in the previous section. That is why we include here a general implementation proposal covering the most important changes and rules to be added:
-
An initial check for the minimum fee of the transactions arriving at the node should be implemented, i.e.:
if (trs.fee < trs.minFee) discard trs
-
The transactions in the transaction pool should be sorted from highest to lowest fee in terms of LSK per byte considering the non-burnt part of the fee,
trs.fee - trs.minFee
. These transactions must go through several format checks and validations before they are ready to be included in the next block. For this task, the transaction pool implements successive queues with different checks and purposes. It is not the object of this proposal to explain this process and it should be noted that the transactions received at the pool can be sorted or prioritized using any adequate selection or sorting algorithm. However, considering this process in the transaction pool, we propose to implement a priority queue where each arriving transaction is assigned a priority depending on its non-burnt fee per byte. This transaction priority is maintained along the successive validations (successive queues) until the transaction is ready to be included in the blockchain:feePriority = (trs.fee - trs.minFee) / sizeof(trs)
-
Once the transactions are ready to be included in the next block (i.e., transactions in
ready
queue as per the current implementation), those with higher priority (i.e. with the highestfeePriority
) are included until the block's available space is not enough for another transaction. To do this, we propose a greedy strategy: The transactions are fetched together to be added to the block starting with the transactions offering the highest fee per byte. Any transaction that does not fit into the current block due to its size is skipped. We continue considering transactions with smaller fees, as these may have smaller size and still fit into the block. More specifically, this can be described as follows:for each trs in queue: if (maxBlockByteSize - newBlock.payloadLength >= sizeof(trs)) add trs to newBlock.payload if (newBlock.payloadLength + sizeofType0 >= maxBlockByteSize) break
Where
newBlock.payloadLength
is the size of the unconfirmed (not yet part of the blockchain) payload of the new block andsizeofType0
is a constant representing the size of a basic type 0 transaction, both in bytes. Then,maxBlockByteSize
is the maximum allowed size of the block in bytes (a constant given by the protocol) andnextTrs
is the top transaction in the priority queue to be included in the block. Once the next block has been either created or received at the node, the included transactions are removed from the transaction pool. -
For the sake of simplicity, in this proposal, we assume that the previous process is performed only by the next forging delegate and considering enough transactions in the
ready
queue (when available) to efficiently fill the next block. -
If the pool has reached its maximum size, a transaction arriving at the node will be compared against the lowest
feePriority
. It will be discarded if it has a fee below that lowest value. It will be applied to the queue otherwise, and hence, the transaction with the lowest priority in the queue will be discarded. -
The maximum size of the transaction pool must be large enough to avoid discarding incoming transactions as much as possible (see previous point). Each node operator should choose this parameter (for example, in a JSON config file) depending on their memory limitations and network situation. By default, we propose to set the maximum number of entries in the transaction pool to 4000 transactions. This will imply an approximate average size of 900 KB when the pool is full (assuming 95% of simple balance transactions) and a maximum size of 9.2 MB (assuming only full vote transactions). Note that this default value is a recommendation and it should be adapted during implementation.
-
We propose to implement a fee threshold, in terms of
feePriority
, for incoming transactions. Transactions with afeePriority
lower than this threshold are immediately removed from the pool and only new transactions with afeePriority
high enough are accepted. The value of this threshold will be a parameter set by the node operator in a JSON config file. By default, this fee threshold is set to 0. This way delegates and node operators can set their required transaction fee if preferred and alleviate the workload in their transaction pool. -
Transactions from multisignature accounts: The size considered for the LSK/byte calculation needs to consider the final multisignature transaction object with all the included signatures (i.e. once the transaction is ready to be included in the blockchain). Hence, the issuer of the transaction should take this into account in order to choose the appropriate fee.
Given the mathematical complexity and nature of this topic, the specification of the fee estimation algorithm proposal is included in another LIP directly dependent on this one.
This change will cause a hard fork:
- All transactions with the new fee system would be invalid in the current protocol:
- The transaction signature will differ with respect to the previous version since the field for the fee is included now.
- The fee of each transaction is not a constant parameter given by transaction type anymore, but a parameter chosen by the user. Therefore, all the transaction verification logic in this regard is different.
- Fees are not shared equally among delegates every round anymore. The minimum fee for each transaction will be burnt, whereas the remaining fee will be assigned to the delegate that forged the block.
Network Economics - Implement dynamic fee system
- [1] M. Akbarpour and S. Li, "Credible Mechanisms", SSRN Electronic Journal: Economics Elsevier (SSRN), 2018.
- [2] Bitcoin transaction accelerator
- [3] J. Young, "Suspicious Bitcoin Mempool Activity, Transaction Fees Spike to $16", Cointelegraph, 2017.
- [4] T. Prentiss, "Ethereum Network Congested, Spam Attack Suspected", EthNews, 2018.
- [5] V. Buterin, "On Inflation, Transaction Fees and Cryptocurrency Monetary Policy", Ethereum blog, 2016.
- [6] Johoe's Bitcoin Mempool Statistics
Different values for the minimum fee per byte, minFeePerByte
, and the direct implications for the current protocol reference implementation:
- Minimum possible fee per byte (given by the protocol specification): 1 Beddow per byte (10-8 LSK/byte):
- Balance transaction: 125 bytes* 10-8 LSK/byte = 1.25 *10-6 LSK (1.82 *10-6 LSK with 2nd passphrase)
- Voting transaction (with 2nd passphrase): 2334 bytes* 10-8 LSK/byte = 2.33 *10-5 LSK
- Minimum fee of a full block[1]: 15 KB* 10-8 LSK/byte = 1.5 * 10-4 LSK
With this minimum fee, and with a quiet network, a malicious user can issue 1 million transactions spending just a bit more than 1 LSK. These transactions will cause around of 150 MB of spam in the network. Assuming 1 LSK < 40$, the minimum fee for a full vote transaction will be below 0.001$ cost, encouraging this way a dynamic and vivid voting system.
- One order of magnitude greater (10-7 LSK/byte):
- Balance transaction: 125 bytes* 10-7 LSK/byte = 1.25 *10-5 LSK (1.82 *10-5 LSK with 2nd passphrase)
- Voting transaction (with 2nd passphrase): 2334 bytes* 10-7 LSK/byte = 0.0002334 LSK
- Minimum fee of a full block[1]: 15 KB* 10-7 LSK/byte = 0.0015 LSK
With this minimum fee, and with a quiet network, a malicious user can issue 100000 transactions spending just a bit more than 1 LSK. These transactions will cause around of 15 MB of spam in the network. Assuming 1 LSK < 40$, the minimum fee for a full vote transaction will be below 0.01$ cost, which is cheap enough to encourage a dynamic and vivid voting system.
- Two orders of magnitude greater (10-6 LSK/byte):
- Balance transaction: 125 bytes* 10-6 LSK/byte = 1.25 *10-4 LSK (1.82 * 10-4 LSK with 2nd passphrase)
- Voting transaction (with 2nd passphrase): 2334 bytes* 10-6 LSK/byte = 0.002334 LSK
- Minimum fee of a full block[1]: 15 KB* 10-6 LSK/byte = 0.015 LSK
With this minimum fee, and with a quiet network, a malicious user can issue 10000 transactions spending just a bit more than 1 LSK. These transactions will cause around of 1.5 MB of spam in the network. Assuming 1 LSK < 40$, the minimum fee for a full vote transaction will be below 0.1$ cost, which is cheap enough to encourage a dynamic and vivid voting system.
- Three Orders of magnitude greater (10-5 LSK/byte):
- Balance transaction: 125 bytes* 10-5 LSK/byte = 0.00125 LSK (0.00182 LSK with 2nd passphrase)
- Voting transaction (with 2nd passphrase): 2334 bytes* 10-5 LSK/byte = 0.02334 LSK
- Minimum fee of a full block[1]: 15 KB* 10-5 LSK/byte= 0.15 LSK
With this minimum fee, and with a quiet network, a malicious user can issue 1000 transactions spending just a bit more than 1 LSK. These transactions will cause around of 150 KB of spam in the network. Assuming 1 LSK < 40$, the minimum fee for a full vote transaction will be below 1$, which will encourage a dynamic voting situation in most of the cases.
[1]We are assuming that a full block has a size of 15 KB (15000 bytes). Also, we are assuming that they do not include any transaction of types 2 or 5. In those cases, the fee per block will be higher due to the trs.nameFee
constant included in the fee of these transactions.
Minimum fee, trs.minFee
, for transaction types 2 and 5 for different values of trs.nameFee
for the current protocol reference implementation:
trs.nameFee
= 0:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 1.45*10-5 LSK | 7.25*10-5 LSK | 1.45*10-4 LSK | 7.25*10-4 LSK | 0.0015 LSK |
Dapp reg avg size (200 bytes) | 2*10-5 LSK | 1*10-4 LSK | 2*10-4 LSK | 0.001 LSK | 0.002 LSK |
Dapp reg max size (4.3 KB) | 4.3*10-4 LSK | 0.0022 LSK | 0.0043 LSK | 0.0215 LSK | 0.043 LSK |
trs.nameFee
= 0.5:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 0.5 LSK | 0.5 LSK | 0.5001 LSK | 0.5007 LSK | 0.5015 LSK |
Dapp reg avg size (200 bytes) | 0.5 LSK | 0.5001 LSK | 0.5002 LSK | 0.501 LSK | 0.502 LSK |
Dapp reg max size (4.3 KB) | 0.5004 LSK | 0.5022 LSK | 0.5043 LSK | 0.5215 LSK | 0.543 LSK |
trs.nameFee
= 1:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 1 LSK | 1 LSK | 1.0001 LSK | 1.0007 LSK | 1.0015 LSK |
Dapp reg avg size (200 bytes) | 1 LSK | 1.0001 LSK | 1.0002 LSK | 1.001 LSK | 1.002 LSK |
Dapp reg max size (4.3 KB) | 1.0004 LSK | 1.0022 LSK | 1.0043 LSK | 1.0215 LSK | 1.043 LSK |
trs.nameFee
= 5:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 5 LSK | 5 LSK | 5.0001 LSK | 5.0007 LSK | 5.0015 LSK |
Dapp reg avg size (200 bytes) | 5 LSK | 5.0001 LSK | 5.0002 LSK | 5.001 LSK | 5.002 LSK |
Dapp reg max size (4.3 KB) | 5.0004 LSK | 5.0022 LSK | 5.0043 LSK | 5.0215 LSK | 5.043 LSK |
trs.nameFee
= 10:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 10 LSK | 10 LSK | 10.0001 LSK | 10.0007 LSK | 10.0015 LSK |
Dapp reg avg size (200 bytes) | 10 LSK | 10.0001 LSK | 10.0002 LSK | 10.001 LSK | 10.002 LSK |
Dapp reg max size (4.3 KB) | 10.0004 LSK | 10.0022 LSK | 10.0043 LSK | 10.0215 LSK | 10.043 LSK |
trs.nameFee
= 20:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 20 LSK | 20 LSK | 20.0001 LSK | 20.0007 LSK | 20.0015 LSK |
Dapp reg avg size (200 bytes) | 20 LSK | 20.0001 LSK | 20.0002 LSK | 20.001 LSK | 20.002 LSK |
Dapp reg max size (4.3 KB) | 20.0004 LSK | 20.0022 LSK | 20.0043 LSK | 20.0215 LSK | 20.043 LSK |
trs.nameFee
= 25:
Tx type/ Min fee | 1*10-7 LSK/byte | 5*10-7 LSK/byte | 1*10-6 LSK/byte | 5*10-6 LSK/byte | 1*10-5 LSK/byte |
---|---|---|---|---|---|
Delegate reg (145 bytes) | 25 LSK | 25 LSK | 25.0001 LSK | 25.0007 LSK | 25.0015 LSK |
Dapp reg avg size (200 bytes) | 25 LSK | 25.0001 LSK | 25.0002 LSK | 25.001 LSK | 20.002 LSK |
Dapp reg max size (4.3 KB) | 25.0004 LSK | 25.0022 LSK | 25.0043 LSK | 25.0215 LSK | 25.043 LSK |
This appendix covers the impact of burning the minimum fee on the token supply depending on the minFeePerByte
value. The study assumes the extreme case of having full blocks for a whole reward milestone (approx one year), so that the impact is maximized. It is assumed that only type 0 and type 3 transactions are getting included, since they make the overwhelming majority of the transaction activity, and that the maximum block size is 15 KB. The results are displayed for the current reward (3 LSK) and future rewards (2 LSK and 1 LSK). Note that, for the final reward milestone of 1 LSK, there is a reasonable value for minFeePerByte
for which the token supply could decrease and be deflationary if the network activity is high enough (minFeePerByte
= 6.66*10-5 LSK/byte). For the other two reward milestones, a value for minFeeBerByte
such that the supply is deflationary would need to be higher than any value for minFeeBerByte
considered in this proposal.