LIP: 0048 Title: Introduce Fee module Author: Maxime Gagnebin <email@example.com> Mitsuaki Uchimoto <firstname.lastname@example.org> Discussions-To: https://research.lisk.com/t/introduce-fee-module/318 Status: Draft Type: Standards Track Created: 2021-08-09 Updated: 2021-09-24 Requires: Define state and state transitions of Token module
The Fee module is responsible for handling the fee of transactions. It allows chains to choose the token used to pay the fee and to define a minimum fee for transactions to be valid.
This LIP is licensed under the Creative Commons Zero 1.0 Universal.
This LIP defines the fee system in a modular way, as currently used in the Lisk ecosystem. The fee handling is implemented in a separate module to allow sidechains to freely update or replace the fee handling module, possibly to implement a more complex fee structure, without needing to modify or update the Token module.
Each chain can configure the token used to pay fees. On the Lisk mainchain, the token used for transaction fees is the LSK token.
As introduced in LIP 0013, all transactions must have a fee greater or equal to a minimum fee (which can be zero). The minimum fee is computed from a part based on the transaction size and a part specific to the command (called extra command fee). Chains can configure their minimum fee per byte and the eventual extra fees.
For example, on the Lisk mainchain, the following extra fees are defined:
extraCommandFee(MODULE_ID_DPOS, COMMAND_ID_DELEGATE_REGISTRATION) = 1000000000,
extraCommandFee(MODULE_ID_INTEROPERABILITY, COMMAND_ID_SIDECHAIN_REG) = 1000000000.
COMMAND_ID_DELEGATE_REGISTRATION are defined in LIP “Define state and state transitions of DPoS module”. The constants
COMMAND_ID_SIDECHAIN_REG are defined in LIP 0045.
The minimum part of the fee should be burned, this is to avoid that validators can send transactions in the blocks they generate without cost. This is only possible if the chosen fee token is a native token (with chain ID equal 0). If the chosen fee token is not a native token (for example the LSK token on sidechains), the minimum fee per byte and the extra fees should be set to zero. This is the only choice that makes sense, as burning non-native tokens is not supported by the Token module.
We define the following constants:
||uint32||1||Module ID of the Fee module.|
||uint64||1000||Minimum amount of fee per byte required for transaction validity.|
|Token ID of the token used to pay the transaction fees.|
The Fee module allows to specify extra fees for each command. This is specified in the module configuration and is written as
extraCommandFee(moduleID, commandID) in this LIP. All
(moduleID, commandID) pairs that do not have a specified extra fee are assumed to have
extraCommandFee(moduleID, commandID) = 0.
The Fee module does not store information in the state.
The Fee module does not contain any commands.
The Fee module does not expose any functions.
trs verification, the following logic is applied:
minFee = MIN_FEE_PER_BYTE * size(trs) + extraCommandFee(trs.moduleID, trs.commandID) if trs.fee < minFee: trs is invalid
Before a transaction
trs is executed, the following logic is applied:
minFee = MIN_FEE_PER_BYTE * size(trs) + extraCommandFee(trs.moduleID, trs.commandID) senderAddress is derived from trs.senderPublicKey generatorAddress is the address of the generator of the block including trs if TOKEN_ID_FEE.chainID == 0: # Fee token is a native token token.burn(senderAddress, TOKEN_ID_FEE, minFee) token.transfer(senderAddress, generatorAddress, TOKEN_ID_FEE, trs.fee - minFee) else: token.transfer(senderAddress, generatorAddress, TOKEN_ID_FEE, trs.fee) if any of those function fails, the transaction is invalid
To be completed by the dev team.
This LIP defines a new Fee module, which follows the same protocol as currently implemented. Changing the implementation to include the Fee module will be backwards compatible.