Current Fee Implementation
In the current implementation, which can be referred to as “semi-feeless”, transaction fees are dynamically adjusted based on network congestion. Under normal conditions, transactions are feeless, but when the network becomes congested, the fee system is triggered and will increase as long as the blockchain stays saturated. This system is implemented directly at the step where the transaction weights are converted into fees. Additionally, allowing data to be stored on-chain (such as with remarks) could lead to a vulnerability by increasing the chain size with abuse of microtransactions, which could become problematic in the long term, even if fees are applied.
Totally feeless
In Substrate, each transaction should be associated with a weight (then translated into a fee) proportional to the computation performed by the chain to prevent abuse. However, some operations do not incur fees and do not impact the chain. For example, calling an extrinsic with a non-existent account (e.g., zero balance, wrong key, etc.) will result in an error that could not incur a fee as the account has no balance. In these cases, the checks are performed by an extrinsic extension polkadot-sdk/substrate/frame/system/src/extensions/check_nonce.rs at master · paritytech/polkadot-sdk · GitHub. If the operations performed are small (meaning only one database read and minimal calculation), this approach ensures security.
I created a minimal proof of concept for a feeless chain: GitHub - bgallois/substrate-feeless-solochain-template. Each account is assigned a transaction rate that is checked and updated using an extrinsic extension. The chain remains secure from spamming by limiting each account to the specified rate of transactions (e.g., x transactions over y blocks). Since all information is stored in the AccountData, additional data can be stored at minimal cost; this will allow for features such as adding a quota for bytes stored per account, as well as modulating the rate and quota depending on whether the account is a member or not, among other possibilities.
The transaction extension system is currently undergoing refactoring (see Follow up work on `TransactionExtension` - fix weights and clean up `UncheckedExtrinsic` by georgepisaltu · Pull Request #6418 · paritytech/polkadot-sdk · GitHub), so we should only implement it once the new implementation is part of a release. However, it’s a good idea to start thinking about this approach, as it could be a valuable solution for our chain.
This is by no means a fully thought-through solution, and it can also be applied in conjunction with the current system, or vice versa, by monitoring the transaction rate/data stored in chain and limiting only users who are abusing the system.
This breaks the paradigm a little bit, so to summarize:
Current Semi-Feeless | Feeless | |
---|---|---|
Fee Forecast | Depending on the network (0 or variable amount depending on the number of blocks where the network was saturated) | Always 0 |
Transactions Rate | Illimited | Limited |
Blockchain Size Increase | Controlled by max allowed by block | Controlled by block size and by account |
Paradigm | Rich accounts can prioritize transactions | Everyone is equal |
Incentive | Fees go to treasury and can be spent for… | No fee = no treasury |