From ae1ba4e3097d363d81f1bd96cf835bd802f0cbf0 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Mon, 24 Feb 2025 15:22:36 -0300 Subject: [PATCH 01/13] docs: adds transaction fee minting rfc --- text/0045-rfc-token-without-deposit.md | 78 ++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 text/0045-rfc-token-without-deposit.md diff --git a/text/0045-rfc-token-without-deposit.md b/text/0045-rfc-token-without-deposit.md new file mode 100644 index 0000000..48c18e9 --- /dev/null +++ b/text/0045-rfc-token-without-deposit.md @@ -0,0 +1,78 @@ +- Feature Name: transaction_fee_minting +- Start Date: 2025-02-24 +- RFC PR: (to be created) +- Hathor Issue: (leave this empty) +- Author: Raul Soares de Oliveira + +# Summary +[summary]: #summary +Currently, when minting X tokens, a [deposit of P% (1%) of X in HTR is required](./0011-token-deposit.md). This deposit can later be withdrawn when the tokens are melted. + +This proposal suggests an alternative mechanism where, instead of requiring an upfront deposit of HTR when minting new tokens, a transaction fee is charged on each transfer of the newly minted tokens. + +# Motivation +[motivation]: #motivation +A user from the Hathor network suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to remove the 1% deposit requirement and, instead, implement a transaction fee for every transfer of the minted tokens. + +This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +## As is + + When a user mints X tokens, they must deposit P% (1%) of X in HTR. If X = 100, then 1 HTR must be deposited. This deposit is returned if the tokens are later melted. + +## To be + + Instead of requiring a deposit, minted tokens will be subject to a transaction fee. Every time a transfer occurs with these tokens, a percentage-based fee (to be defined) will be charged. + +## Example: + +1. A user mints 1000 tokens without depositing HTR. +2. When transferring 500 tokens, a fee (e.g., 0.5% or 1%) is deducted and sent to miners or the network treasury. +3. This fee structure continues for all transactions involving the newly minted tokens. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation +TODO + +# Drawbacks +[drawbacks]: #drawbacks + +Introducing a transaction fee may discourage frequent transfers of these tokens. + +Miners’ incentives might change as fees will be spread over multiple transactions rather than collected upfront. + +Tokens minted under different mechanisms will have different behaviors, which could add complexity to user experience and wallet support. + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +The main alternative is to keep the current deposit model. However, this locks up liquidity for token creators, making token issuance less attractive. + +Another alternative is a hybrid model, where users can choose between: + 1. Paying the upfront HTR deposit (current model). + 2. Opting for the per-transaction fee model (new proposal). + +This hybrid approach could offer flexibility while maintaining incentives for both users and miners. + +# Prior art +[prior-art]: #prior-art + +Ethereum, the most used platform for token issuance, charges a fee to run any operation. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +- What should the transaction fee percentage be? +- How will fee distribution work? +- How will wallets distinguish between tokens under different models? +- Does make sense having a portion of the fee in a treasury to fund the ecosystem development? +- How will the melt behave? + +# Future possibilities +[future-possibilities]: #future-possibilities + +TODO + From 3d9201188e7a52d29d2dcaf83f0896c70637d846 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Wed, 5 Mar 2025 15:06:56 -0300 Subject: [PATCH 02/13] feat: v2 --- text/0045-rfc-token-without-deposit.md | 78 --------- text/0045-transaction_fee_minting.md | 232 +++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 78 deletions(-) delete mode 100644 text/0045-rfc-token-without-deposit.md create mode 100644 text/0045-transaction_fee_minting.md diff --git a/text/0045-rfc-token-without-deposit.md b/text/0045-rfc-token-without-deposit.md deleted file mode 100644 index 48c18e9..0000000 --- a/text/0045-rfc-token-without-deposit.md +++ /dev/null @@ -1,78 +0,0 @@ -- Feature Name: transaction_fee_minting -- Start Date: 2025-02-24 -- RFC PR: (to be created) -- Hathor Issue: (leave this empty) -- Author: Raul Soares de Oliveira - -# Summary -[summary]: #summary -Currently, when minting X tokens, a [deposit of P% (1%) of X in HTR is required](./0011-token-deposit.md). This deposit can later be withdrawn when the tokens are melted. - -This proposal suggests an alternative mechanism where, instead of requiring an upfront deposit of HTR when minting new tokens, a transaction fee is charged on each transfer of the newly minted tokens. - -# Motivation -[motivation]: #motivation -A user from the Hathor network suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to remove the 1% deposit requirement and, instead, implement a transaction fee for every transfer of the minted tokens. - -This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. - -# Guide-level explanation -[guide-level-explanation]: #guide-level-explanation - -## As is - - When a user mints X tokens, they must deposit P% (1%) of X in HTR. If X = 100, then 1 HTR must be deposited. This deposit is returned if the tokens are later melted. - -## To be - - Instead of requiring a deposit, minted tokens will be subject to a transaction fee. Every time a transfer occurs with these tokens, a percentage-based fee (to be defined) will be charged. - -## Example: - -1. A user mints 1000 tokens without depositing HTR. -2. When transferring 500 tokens, a fee (e.g., 0.5% or 1%) is deducted and sent to miners or the network treasury. -3. This fee structure continues for all transactions involving the newly minted tokens. - -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation -TODO - -# Drawbacks -[drawbacks]: #drawbacks - -Introducing a transaction fee may discourage frequent transfers of these tokens. - -Miners’ incentives might change as fees will be spread over multiple transactions rather than collected upfront. - -Tokens minted under different mechanisms will have different behaviors, which could add complexity to user experience and wallet support. - -# Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives - -The main alternative is to keep the current deposit model. However, this locks up liquidity for token creators, making token issuance less attractive. - -Another alternative is a hybrid model, where users can choose between: - 1. Paying the upfront HTR deposit (current model). - 2. Opting for the per-transaction fee model (new proposal). - -This hybrid approach could offer flexibility while maintaining incentives for both users and miners. - -# Prior art -[prior-art]: #prior-art - -Ethereum, the most used platform for token issuance, charges a fee to run any operation. - -# Unresolved questions -[unresolved-questions]: #unresolved-questions - -- What should the transaction fee percentage be? -- How will fee distribution work? -- How will wallets distinguish between tokens under different models? -- Does make sense having a portion of the fee in a treasury to fund the ecosystem development? -- How will the melt behave? - -# Future possibilities -[future-possibilities]: #future-possibilities - -TODO - diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md new file mode 100644 index 0000000..1227bd9 --- /dev/null +++ b/text/0045-transaction_fee_minting.md @@ -0,0 +1,232 @@ +- Feature Name: transaction_fee_minting +- Start Date: 2025-02-24 +- RFC PR: (to be created) +- Hathor Issue: (leave this empty) +- Author: Raul Soares de Oliveira + +# Summary +[summary]: #summary +Currently, when minting X tokens, a [deposit of P% (1%) of X in HTR is required](./0011-token-deposit.md). This deposit can later be withdrawn when the tokens are melted. + +This proposal suggests an alternative mechanism where, instead of requiring an upfront deposit of HTR when minting new tokens, a transaction fee is charged on each transfer of the newly minted tokens. + +# Motivation +[motivation]: #motivation + +Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to remove the 1% deposit requirement and, instead, implement a transaction fee for every transfer of the minted tokens. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) + +This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. + +An explicit use case is meme coins creation. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. + +## Deposit-Based Model + +In this [model](https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md), creators must deposit a percentage (P%) of the minted tokens’ value in HTR. For example, if P% is set at 1% and a user mints 100 tokens, they must deposit 1 HTR. This deposit acts as a reserve and is fully refundable if the tokens are later melted. + +## Fee-Based Model + +The fee-based model does not require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee, which is deducted automatically. The exact fee rate will be defined at a later stage. + +By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A key use case is the creation of memecoins. + +### How Bitcoin deals with fee + +Bitcoin handles transaction fees through a system based on competition for limited block space. Each transaction has a weight measured in vBytes, and users set their fees by offering satoshis per vByte, which influences the confirmation speed. During periods of high demand, fees increase due to competition, while in lower traffic periods, they decrease. + +Wallets and services use fee estimators to suggest optimal fees based on the mempool. The protocol does not enforce a minimum fee, but nodes can set a "relay fee" to prevent spam from very low-value transactions. + +### How Etherium deals with fee + +Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. + +The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. + +### An hybrid approach + +A third option for blockchain fees is a hybrid model that combines minimum fees with payments based on actual resource usage, along with policies to prevent spam on the network. This model aims to balance user simplicity, protection against spam attacks, and long-term sustainability. + +The adaptive minimum fee consists of a fixed base fee that all users pay per transaction, ensuring a minimum cost for network usage and preventing abuse. Additionally, there is a variable component that adjusts the fee based on resource consumption, such as transaction size or script complexity. + +To address the spam problem, some networks have tested models with proof of work (PoW) embedded in transactions. This mechanism requires users to perform a small computational task before sending transactions, making mass spam transactions more difficult. Another approach is the use of dynamically adjusted microfees to maintain network balance. + +This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. + +### General Fee calculation rule + +1. HTR is always used as the fee unit, regardless of the tokens involved in the transaction. +2. If only fee-based tokens are used, a single fee in HTR will be charged, regardless of the number of tokens. +3. If a transaction includes both deposit-based and fee-based tokens, only the fee-based tokens will incur a fee. +4. Interacting with nano contracts may introduce an additional fee depending on the execution complexity. + +### Example Scenarios + +#### Token A x Token A (fee in HTR) + +Description: Transfer of the same token (A) between two parties. + + +Fee Calculation: + +- Since Token A is fee-based, the transaction requires a fee in HTR. +``` +- Base Fee: 0.001 HTR +- Total Fee: 0.001 HTR (regardless of the amount transferred) +``` +---- +#### Token A x Token B x Token C (only 1 fee, in HTR) + +Description: Multi-token transfer involving three fee-based tokens. + +Fee Calculation: +- Only one HTR fee is charged, regardless of the number of tokens. +``` +- Base Fee: 0.001 HTR +- Complexity Fee (extra tokens): 0.0005 HTR per additional token. +- Total Fee: 0.002 HTR (0.001 + 0.0005 + 0.0005) +``` + +#### Token A x HTR (fee in HTR) + +Description: Transfer of a fee-based token and HTR in the same transaction. + +Fee Calculation: +- Since a fee-based token is involved, an HTR fee will be charged. +``` +- Base Fee: 0.001 HTR +- Total Fee: 0.001 HTR +``` + +#### Token D (deposit-based) x Token B (fee-based) +Description: Transfer of a deposit-based token (D) and a fee-based token (B). + +Fee Calculation: +- The deposit-based token (D) does not pay a fee. +- The fee-based token (B) pays the standard fee. + +``` +- Base Fee: 0.001 HTR +- Total Fee: 0.001 HTR (no extra charge for Token D) +``` + +#### Transaction Interacting with a Nano Contract +Description: A transfer involving a nano contract, which may require additional execution on the network. + +Fee Calculation: +- The standard transaction base fee still applies. +- Since nano contract execution involves additional computation, an extra fee may be charged based on complexity. +- Execution Fee (depends on contract complexity): Example, 0.002 HTR. + +``` +- Base Fee: 0.001 HTR +- Total Fee: 0.003 HTR (0.001 base + 0.002 contract execution) +``` + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation +TODO + +# Drawbacks of the Hybrid Fee Model +[drawbacks]: #drawbacks + +While the hybrid fee model balances incentives and network sustainability, it also introduces potential drawbacks that must be considered. Below are key concerns and challenges: + +### 1. Token Inflation and Supply Growth + +**Issue:** Since there is no burning mechanism tied to fee-based token transfers, the total supply of tokens may continuously increase without a natural deflationary counterbalance. + +**Impact:** Over time, token supply inflation can reduce the value of individual tokens, especially if demand does not grow proportionally. + +**Potential Mitigation:** + - Introduce a **burn mechanism** where a percentage of the transaction fee is permanently removed from circulation. + - Implement an **optional melt requirement** where token issuers must periodically remove supply from circulation. + +--- + +### 2. Potential for Low-Cost Network Congestion + +**Issue:** If fees are too low, bad actors could create a high volume of low-value transactions, leading to congestion. + +**Impact:** + - Increased load on network validators and miners. + - Slower transaction processing times during peak usage. + +**Potential Mitigation:** + - Introduce **dynamic fee adjustments** where fees scale based on network congestion. + - Set **minimum transaction fees** to prevent microtransactions from overloading the system. + +--- + +### 3. Complexity in Multi-Token Transactions + +**Issue:** Transactions involving multiple tokens introduce a more complex fee structure, requiring additional computation to determine the appropriate charge. + +**Impact:** + - Increased processing overhead for nodes. + - Potential user confusion when sending transactions with different token types. + +**Potential Mitigation:** + - Improve **wallet UX** to clearly display estimated fees before confirming transactions. + - Optimize **fee calculation logic** to minimize the processing impact. + +--- + +### 4. Miner Incentive Model May Need Adjustments + +**Issue:** Since miners are currently incentivized through TX mining and HTR block rewards, a shift to fee-based transactions could impact their revenue model. + +**Impact:** + - If transaction volume is low, fee revenue might not be sufficient to replace TX mining incentives. + - Long-term miner participation may decline if fees do not adequately compensate for network maintenance. + +**Potential Mitigation:** + - Transition **gradually** from TX mining to a full fee-based model. + - Allow **fee-burning mechanisms** to ensure that fees remain valuable to miners. + +--- + +### 5. Interactions with Smart Contracts and Additional Execution Costs + +**Issue:** Nano contracts and other execution-based transactions introduce **variable computational costs** that are not reflected in a simple per-transaction fee model. + +**Impact:** + - Fees may be **too low to cover execution costs**, leading to **free rider issues**. + - Overuse of nano contracts for cheap computation could **strain network resources**. + +**Potential Mitigation:** + - Charge **additional execution fees** based on contract complexity. + - Implement **gas-like metering** for smart contract interactions. + + + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +- How should melt operations be handled for fee-based custom tokens? +- Should storage fees be one-time or recurring (rent model)? +- Should there be discounts for batch transactions? +- Should fee adjustments be governed by community proposals? +- Should TX mining remain if transaction fees are introduced? + +# Future possibilities +[future-possibilities]: #future-possibilities + +- L2 Solutions (e.g., batch-processing for lower fees). +- Custom Fee Markets (letting users optimize fees). +- Dynamic Fee Adjustment Mechanism, where fees scale based on network congestion. + + +# References + +- https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md +- https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md +- https://github.com/HathorNetwork/rfcs/blob/master/text/0015-anatomy-of-tx.md +- https://bitcoin.org/bitcoin.pdf +- https://eips.ethereum.org/EIPS/eip-1559 +- https://ethereum.org/en/developers/docs/gas/ +- https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change + From 7953366db88089e8d8cab14e9b14e385f96f105e Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Wed, 12 Mar 2025 12:25:30 -0300 Subject: [PATCH 03/13] pr comments --- text/0045-transaction_fee_minting.md | 97 ++++++---------------------- 1 file changed, 20 insertions(+), 77 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 1227bd9..47943f4 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -13,46 +13,28 @@ This proposal suggests an alternative mechanism where, instead of requiring an u # Motivation [motivation]: #motivation -Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to remove the 1% deposit requirement and, instead, implement a transaction fee for every transfer of the minted tokens. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) +Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom tokens where tokens would be minted for free (i.e., no deposits) and fess will be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. -An explicit use case is meme coins creation. - # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. +When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. For handle it we will use the same definitions of the [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md), possibly adding a variation of it using a new version. -## Deposit-Based Model +## Deposit-Based Model (as is) -In this [model](https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md), creators must deposit a percentage (P%) of the minted tokens’ value in HTR. For example, if P% is set at 1% and a user mints 100 tokens, they must deposit 1 HTR. This deposit acts as a reserve and is fully refundable if the tokens are later melted. +Currently, creators must [deposit a percentage](https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md) (P%) of the minted tokens’ value in HTR. For example, if P% is set at 1% and a user mints 100 tokens, they must deposit 1 HTR. This deposit acts as a reserve and is fully refundable if the tokens are later melted. ## Fee-Based Model -The fee-based model does not require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee, which is deducted automatically. The exact fee rate will be defined at a later stage. +Adding the fee-based model the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee, which is deducted automatically. The exact fee rate will be defined at a later stage. By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A key use case is the creation of memecoins. -### How Bitcoin deals with fee - -Bitcoin handles transaction fees through a system based on competition for limited block space. Each transaction has a weight measured in vBytes, and users set their fees by offering satoshis per vByte, which influences the confirmation speed. During periods of high demand, fees increase due to competition, while in lower traffic periods, they decrease. - -Wallets and services use fee estimators to suggest optimal fees based on the mempool. The protocol does not enforce a minimum fee, but nodes can set a "relay fee" to prevent spam from very low-value transactions. - -### How Etherium deals with fee - -Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. - -The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. - ### An hybrid approach -A third option for blockchain fees is a hybrid model that combines minimum fees with payments based on actual resource usage, along with policies to prevent spam on the network. This model aims to balance user simplicity, protection against spam attacks, and long-term sustainability. - -The adaptive minimum fee consists of a fixed base fee that all users pay per transaction, ensuring a minimum cost for network usage and preventing abuse. Additionally, there is a variable component that adjusts the fee based on resource consumption, such as transaction size or script complexity. - -To address the spam problem, some networks have tested models with proof of work (PoW) embedded in transactions. This mechanism requires users to perform a small computational task before sending transactions, making mass spam transactions more difficult. Another approach is the use of dynamically adjusted microfees to maintain network balance. +An alternative to bitcoin and etherium approchaes for blockchain fees is a hybrid model that combines minimum fees with payments based on actual resource usage, along with policies to prevent spam on the network. This model aims to balance user simplicity, protection against spam attacks, and long-term sustainability. This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. @@ -65,11 +47,10 @@ This model offers several advantages. First, it simplifies the user experience b ### Example Scenarios -#### Token A x Token A (fee in HTR) +#### Swapping Token A for Token A with a fee paid in HTR (fee in HTR) Description: Transfer of the same token (A) between two parties. - Fee Calculation: - Since Token A is fee-based, the transaction requires a fee in HTR. @@ -126,6 +107,10 @@ Fee Calculation: - Total Fee: 0.003 HTR (0.001 base + 0.002 contract execution) ``` +## Wallet UI + +We should provide to the users the option to select between the two models (deposit and fee) when minting. + # Reference-level explanation [reference-level-explanation]: #reference-level-explanation TODO @@ -135,72 +120,30 @@ TODO While the hybrid fee model balances incentives and network sustainability, it also introduces potential drawbacks that must be considered. Below are key concerns and challenges: -### 1. Token Inflation and Supply Growth - -**Issue:** Since there is no burning mechanism tied to fee-based token transfers, the total supply of tokens may continuously increase without a natural deflationary counterbalance. - -**Impact:** Over time, token supply inflation can reduce the value of individual tokens, especially if demand does not grow proportionally. - -**Potential Mitigation:** - - Introduce a **burn mechanism** where a percentage of the transaction fee is permanently removed from circulation. - - Implement an **optional melt requirement** where token issuers must periodically remove supply from circulation. - ---- - -### 2. Potential for Low-Cost Network Congestion - -**Issue:** If fees are too low, bad actors could create a high volume of low-value transactions, leading to congestion. - -**Impact:** - - Increased load on network validators and miners. - - Slower transaction processing times during peak usage. - -**Potential Mitigation:** - - Introduce **dynamic fee adjustments** where fees scale based on network congestion. - - Set **minimum transaction fees** to prevent microtransactions from overloading the system. - ---- - -### 3. Complexity in Multi-Token Transactions +### Complexity in Multi-Token Transactions **Issue:** Transactions involving multiple tokens introduce a more complex fee structure, requiring additional computation to determine the appropriate charge. **Impact:** - - Increased processing overhead for nodes. + - Increased processing overhead for wallets. - Potential user confusion when sending transactions with different token types. **Potential Mitigation:** - Improve **wallet UX** to clearly display estimated fees before confirming transactions. - - Optimize **fee calculation logic** to minimize the processing impact. - ---- - -### 4. Miner Incentive Model May Need Adjustments - -**Issue:** Since miners are currently incentivized through TX mining and HTR block rewards, a shift to fee-based transactions could impact their revenue model. -**Impact:** - - If transaction volume is low, fee revenue might not be sufficient to replace TX mining incentives. - - Long-term miner participation may decline if fees do not adequately compensate for network maintenance. - -**Potential Mitigation:** - - Transition **gradually** from TX mining to a full fee-based model. - - Allow **fee-burning mechanisms** to ensure that fees remain valuable to miners. +# Prior art ---- +### How Bitcoin deals with fee -### 5. Interactions with Smart Contracts and Additional Execution Costs +Bitcoin handles transaction fees through a system based on competition for limited block space. Each transaction has a weight measured in vBytes, and users set their fees by offering satoshis per vByte, which influences the confirmation speed. During periods of high demand, fees increase due to competition, while in lower traffic periods, they decrease. -**Issue:** Nano contracts and other execution-based transactions introduce **variable computational costs** that are not reflected in a simple per-transaction fee model. +Wallets and services use fee estimators to suggest optimal fees based on the mempool. The protocol does not enforce a minimum fee, but nodes can set a "relay fee" to prevent spam from very low-value transactions. -**Impact:** - - Fees may be **too low to cover execution costs**, leading to **free rider issues**. - - Overuse of nano contracts for cheap computation could **strain network resources**. +### How Etherium deals with fee -**Potential Mitigation:** - - Charge **additional execution fees** based on contract complexity. - - Implement **gas-like metering** for smart contract interactions. +Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. +The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. # Unresolved questions From e41d948a2c2f96dba97a3069b179648340194c39 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Thu, 13 Mar 2025 15:23:40 -0300 Subject: [PATCH 04/13] adding fee calculation and pow --- text/0045-transaction_fee_minting.md | 106 +++++++++++++-------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 47943f4..8c3a60d 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -32,80 +32,74 @@ Adding the fee-based model the platform won't require an upfront deposit. Instea By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A key use case is the creation of memecoins. -### An hybrid approach +### How to pproach -An alternative to bitcoin and etherium approchaes for blockchain fees is a hybrid model that combines minimum fees with payments based on actual resource usage, along with policies to prevent spam on the network. This model aims to balance user simplicity, protection against spam attacks, and long-term sustainability. +An alternative to bitcoin and etherium approchaes for blockchain fees is a hybrid model that combines fees based in the transaction size, with priority tip payments. This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. -### General Fee calculation rule +### Fee calculation +Hathor’s fees will be calculated similarly to Bitcoin, depending only on transaction size (in bytes) and a network-defined fee rate (in HTR per byte). + +Proof-of-Work difficulty (transaction weight) will not influence the fee calculation. + +Let's assume: 1. HTR is always used as the fee unit, regardless of the tokens involved in the transaction. -2. If only fee-based tokens are used, a single fee in HTR will be charged, regardless of the number of tokens. -3. If a transaction includes both deposit-based and fee-based tokens, only the fee-based tokens will incur a fee. -4. Interacting with nano contracts may introduce an additional fee depending on the execution complexity. +2. Even if fee-based tokens are used alone, or with a deposit-based token, a single fee in HTR will be charged, regarding the transaction size. +3. Interacting with nano contracts may introduce an additional fee depending on the execution complexity. -### Example Scenarios +Below is a pseudo code that explain how fee should be calculated, using a fee rate per byte: -#### Swapping Token A for Token A with a fee paid in HTR (fee in HTR) +*(Note: Excluded "hash" size from calculation, hence 114 reduced to 84 bytes.)* -Description: Transfer of the same token (A) between two parties. +```python +def calculate_tx_fee(tx, fee_rate_per_byte): + # Fixed size fields (always present) + fixed_size = 84 # version (2) + timestamp (4) + nonce (4) + weight (8) + parents (64) -Fee Calculation: + # Tokens array size + tokens_size = 32 * len(tx.tokens) -- Since Token A is fee-based, the transaction requires a fee in HTR. -``` -- Base Fee: 0.001 HTR -- Total Fee: 0.001 HTR (regardless of the amount transferred) -``` ----- -#### Token A x Token B x Token C (only 1 fee, in HTR) + # Inputs size calculation + inputs_size = 0 + for input in tx.inputs: + inputs_size += 35 + len(input.data) + # 32 bytes (tx_id) + 1 byte (index) + 2 bytes (data length prefix) + len(data) -Description: Multi-token transfer involving three fee-based tokens. + # Outputs size calculation + outputs_size = 0 + for output in tx.outputs: + outputs_size += 7 + len(output.script) + # 4 bytes (value) + 1 byte (token_data) + 2 bytes (script length prefix) + len(script) -Fee Calculation: -- Only one HTR fee is charged, regardless of the number of tokens. -``` -- Base Fee: 0.001 HTR -- Complexity Fee (extra tokens): 0.0005 HTR per additional token. -- Total Fee: 0.002 HTR (0.001 + 0.0005 + 0.0005) -``` + # Total transaction size + tx_size = fixed_size + tokens_size + inputs_size + outputs_size -#### Token A x HTR (fee in HTR) + # Fee calculation + fee = tx_size * fee_rate_per_byte -Description: Transfer of a fee-based token and HTR in the same transaction. + return fee + tx.priority_tip # plus any nano fee that should match -Fee Calculation: -- Since a fee-based token is involved, an HTR fee will be charged. ``` -- Base Fee: 0.001 HTR -- Total Fee: 0.001 HTR -``` - -#### Token D (deposit-based) x Token B (fee-based) -Description: Transfer of a deposit-based token (D) and a fee-based token (B). -Fee Calculation: -- The deposit-based token (D) does not pay a fee. -- The fee-based token (B) pays the standard fee. -``` -- Base Fee: 0.001 HTR -- Total Fee: 0.001 HTR (no extra charge for Token D) -``` +### **Example Calculation:** -#### Transaction Interacting with a Nano Contract -Description: A transfer involving a nano contract, which may require additional execution on the network. +**Hypothetical Transaction:** +- 1 token UID +- 2 inputs (with 108 bytes of data each, common signature size) +- 2 outputs (with 25 bytes of script each, common P2PKH script) -Fee Calculation: -- The standard transaction base fee still applies. -- Since nano contract execution involves additional computation, an extra fee may be charged based on complexity. -- Execution Fee (depends on contract complexity): Example, 0.002 HTR. +Calculate size: -``` -- Base Fee: 0.001 HTR -- Total Fee: 0.003 HTR (0.001 base + 0.002 contract execution) -``` +| Field | Calculation | Size | +|----------------------|-----------------------------|----------| +| Fixed-size fields | | **84** bytes | +| Tokens | 1 token × 32 bytes | **32** bytes | +| Inputs | 2 × (35 + 108) | **286** bytes | +| Outputs | 2 × (7 + 25) | **64** bytes | +| **Total Tx Size** | 84 + 32 + 286 + 64 | **466** bytes | ## Wallet UI @@ -149,20 +143,18 @@ The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes t # Unresolved questions [unresolved-questions]: #unresolved-questions +- What will happen to the fees? Will they be collected by the miners? - How should melt operations be handled for fee-based custom tokens? - Should storage fees be one-time or recurring (rent model)? -- Should there be discounts for batch transactions? -- Should fee adjustments be governed by community proposals? -- Should TX mining remain if transaction fees are introduced? +- How fee adjustments will be governed? +- Should TX mining remain if transaction fees are introduced? How will it affect the tx-mining-service? # Future possibilities [future-possibilities]: #future-possibilities -- L2 Solutions (e.g., batch-processing for lower fees). - Custom Fee Markets (letting users optimize fees). - Dynamic Fee Adjustment Mechanism, where fees scale based on network congestion. - # References - https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md From b24592616deeb55441d28c7b4b7ab069bbdf3859 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Tue, 18 Mar 2025 11:09:09 -0300 Subject: [PATCH 05/13] fix: typos --- text/0045-transaction_fee_minting.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 8c3a60d..7568f7a 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -13,7 +13,7 @@ This proposal suggests an alternative mechanism where, instead of requiring an u # Motivation [motivation]: #motivation -Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom tokens where tokens would be minted for free (i.e., no deposits) and fess will be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) +Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom tokens where tokens would be minted for free (i.e., no deposits) and fees will be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. @@ -32,9 +32,9 @@ Adding the fee-based model the platform won't require an upfront deposit. Instea By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A key use case is the creation of memecoins. -### How to pproach +### How to approach -An alternative to bitcoin and etherium approchaes for blockchain fees is a hybrid model that combines fees based in the transaction size, with priority tip payments. +An alternative to Bitcoin and Ethereum approchaes for blockchain fees is a hybrid model that combines fees based in the transaction size, with priority tip payments. This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. @@ -133,7 +133,7 @@ Bitcoin handles transaction fees through a system based on competition for limit Wallets and services use fee estimators to suggest optimal fees based on the mempool. The protocol does not enforce a minimum fee, but nodes can set a "relay fee" to prevent spam from very low-value transactions. -### How Etherium deals with fee +### How Ethereum deals with fee Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. From a953eb275a8d6fdf4a2d857892963be8df9441a4 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Tue, 18 Mar 2025 11:36:21 -0300 Subject: [PATCH 06/13] mining topic --- text/0045-transaction_fee_minting.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 7568f7a..cc9bbc8 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -38,6 +38,9 @@ An alternative to Bitcoin and Ethereum approchaes for blockchain fees is a hybri This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. +### Minning +By adding fees to the transactions, we don't need to mine them anymore. So the proof of work (PoW) won't affect the fee calculation. + ### Fee calculation Hathor’s fees will be calculated similarly to Bitcoin, depending only on transaction size (in bytes) and a network-defined fee rate (in HTR per byte). @@ -147,7 +150,7 @@ The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes t - How should melt operations be handled for fee-based custom tokens? - Should storage fees be one-time or recurring (rent model)? - How fee adjustments will be governed? -- Should TX mining remain if transaction fees are introduced? How will it affect the tx-mining-service? +- Removing the transaction fee from minning, how will it affect the tx-mining-service? # Future possibilities [future-possibilities]: #future-possibilities From 84c27c2da6bf9fcc639b84a5c2a0f1e1d8b7bb0a Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Mon, 24 Mar 2025 14:54:07 -0300 Subject: [PATCH 07/13] addressing pr comments --- text/0045-transaction_fee_minting.md | 88 ++++++++++++++++++---------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index cc9bbc8..9e80b00 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -30,17 +30,23 @@ Currently, creators must [deposit a percentage](https://github.com/HathorNetwork Adding the fee-based model the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee, which is deducted automatically. The exact fee rate will be defined at a later stage. -By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A key use case is the creation of memecoins. +By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A popular use case is the creation of memecoins. However, the user can use for any other scenario that might appear. + ### How to approach -An alternative to Bitcoin and Ethereum approchaes for blockchain fees is a hybrid model that combines fees based in the transaction size, with priority tip payments. +An alternative to Bitcoin and Ethereum approchaes for blockchain fees is a model that charge fees based in the transaction size. -This model offers several advantages. First, it simplifies the user experience by providing a predictable fee without major fluctuations. Additionally, it enables a filtering mechanism to prevent excessively large or complex transactions, protecting the network from spam. Finally, its structure promotes sustainability, ensuring controlled blockchain growth. +This model offers two advantages: + - It simplifies the user experience by providing a predictable fee without major fluctuations. + - It creates a fair mechanism that makes simple transactions cheaper and charges more for complex ones. -### Minning +### Transaction Mining By adding fees to the transactions, we don't need to mine them anymore. So the proof of work (PoW) won't affect the fee calculation. +### Fee destination +The fees will be burned, if we need to do something with it, possibly in another issue we can change the behavior. For now let's keep it simple. + ### Fee calculation Hathor’s fees will be calculated similarly to Bitcoin, depending only on transaction size (in bytes) and a network-defined fee rate (in HTR per byte). @@ -51,38 +57,54 @@ Let's assume: 1. HTR is always used as the fee unit, regardless of the tokens involved in the transaction. 2. Even if fee-based tokens are used alone, or with a deposit-based token, a single fee in HTR will be charged, regarding the transaction size. 3. Interacting with nano contracts may introduce an additional fee depending on the execution complexity. +4. Fee rate, static and dynamic, are arbitary values to be defined by the business. + +We'll adopt a fee_rate_per_static_byte, and fee_rate_per_dynamic_byte that assumes the fixed size of the tx to act as our flat fee and the dynamic part of the tx to ensure we'll charge less for simple transaction and more for larger. + +In this proposal we are excluding simple transactions, 1 input, 1 token, and up to 2 outputs from the dynamic calculation. Below is a pseudo code that explain how fee should be calculated, using a fee rate per byte: *(Note: Excluded "hash" size from calculation, hence 114 reduced to 84 bytes.)* +*(Note: We already have a way to calculate the tx size, here the idea is to shown what is the flat part and what is considered the dynamic part. Where we can mainupulate the rates to create flat fee and dynamic fees that are predictable to the user)* + ```python -def calculate_tx_fee(tx, fee_rate_per_byte): +def calculate_tx_fee(tx, fee_rate_per_static_byte, fee_rate_per_dynamic_byte): # Fixed size fields (always present) fixed_size = 84 # version (2) + timestamp (4) + nonce (4) + weight (8) + parents (64) - + # Tokens array size - tokens_size = 32 * len(tx.tokens) - + tokens_size = 0 + if len(tx.tokens) > 1: + tokens_size = 32 * len(tx.tokens) - 1 + # Inputs size calculation inputs_size = 0 - for input in tx.inputs: - inputs_size += 35 + len(input.data) - # 32 bytes (tx_id) + 1 byte (index) + 2 bytes (data length prefix) + len(data) - + if len(tx.inputs) > 1: + for i in range(len(tx.inputs) - 1): + input = tx.outputs[i] + inputs_size += 35 + len(input.data) + # 32 bytes (tx_id) + 1 byte (index) + 2 bytes (data length prefix) + len(data) + # Outputs size calculation outputs_size = 0 - for output in tx.outputs: - outputs_size += 7 + len(output.script) - # 4 bytes (value) + 1 byte (token_data) + 2 bytes (script length prefix) + len(script) + if len(tx.outputs) > 2: + for i in range(len(tx.outputs) - 2): + output = tx.outputs[i] + outputs_size += 7 + len(output.script) + # 4 bytes (value) + 1 byte (token_data) + 2 bytes (script length prefix) + len(script) # Total transaction size - tx_size = fixed_size + tokens_size + inputs_size + outputs_size + flat_fee = fixed_size * fee_rate_per_static_byte + + ## Here we can also define how we want to calculate the dynamic fee. For example, imagine that we only want to charge fee for transactions that have more than two outputs, or ignore how the inputs size on the formula in order to make it predictable according to business needs. + dynamic_fee = (tokens_size + inputs_size + outputs_size) * fee_rate_per_dynamic_byte # Fee calculation - fee = tx_size * fee_rate_per_byte + fee = flat_fee + dynamic_fee + tx.priority_tip - return fee + tx.priority_tip # plus any nano fee that should match + return fee # plus any nano fee that should match ``` @@ -90,19 +112,21 @@ def calculate_tx_fee(tx, fee_rate_per_byte): ### **Example Calculation:** **Hypothetical Transaction:** +- Fee rate per static byte to result in 0.01 HTR (flat): 0,000119047619048 +- Fee rate per dynamic byte to increase the fee based on the complexity of the tx: 0,000119047619048 - 1 token UID -- 2 inputs (with 108 bytes of data each, common signature size) -- 2 outputs (with 25 bytes of script each, common P2PKH script) +- 2 inputs +- 2 outputs -Calculate size: +Calculate fee: -| Field | Calculation | Size | -|----------------------|-----------------------------|----------| -| Fixed-size fields | | **84** bytes | -| Tokens | 1 token × 32 bytes | **32** bytes | -| Inputs | 2 × (35 + 108) | **286** bytes | -| Outputs | 2 × (7 + 25) | **64** bytes | -| **Total Tx Size** | 84 + 32 + 286 + 64 | **466** bytes | +| Field | Calculation | Size | Byte type | Total +|----------------------|-----------------------------|---------------|-----------|-----| +| Fixed-size fields | | **84** bytes | static | 0.01 HTR +| Tokens | 1 token × 32 bytes | **32** bytes | dynamic | 0 HTR +| Inputs | 2 × 35 | **286** bytes | dynamic | 0.0038 HTR +| Outputs | 2 × (7 + 25) | **64** bytes | dynamic | 0 HTR +| **Total Fee** | | | | 0.0138 HTR ## Wallet UI @@ -142,13 +166,17 @@ Ethereum handles transaction fees through the concept of Gas, where each operati The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. +# Business unresolved questions +- Should we allow deposit based tokens to collect fees? +- Should we burn or move it to a burn address? +- How the fee will be calculated? +- Should we only consider the outputs in the fee calculation? + # Unresolved questions [unresolved-questions]: #unresolved-questions -- What will happen to the fees? Will they be collected by the miners? - How should melt operations be handled for fee-based custom tokens? -- Should storage fees be one-time or recurring (rent model)? - How fee adjustments will be governed? - Removing the transaction fee from minning, how will it affect the tx-mining-service? From 5357efba16f680546bd5905d072c07b0ea92cb4c Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Fri, 4 Apr 2025 18:20:15 -0300 Subject: [PATCH 08/13] Pr comments --- text/0045-transaction_fee_minting.md | 141 ++++++++------------------- 1 file changed, 43 insertions(+), 98 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 9e80b00..1ff7318 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -28,129 +28,75 @@ Currently, creators must [deposit a percentage](https://github.com/HathorNetwork ## Fee-Based Model -Adding the fee-based model the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee, which is deducted automatically. The exact fee rate will be defined at a later stage. +Adding the fee-based model the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee. -By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A popular use case is the creation of memecoins. However, the user can use for any other scenario that might appear. +By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A popular use case is the creation of memecoins by minting tokens that aren’t bound to HTR value. Besides that, the user can use it for any other scenario that may arise. +### Fee cost -### How to approach +Fees will be proportional to the amount of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens and another 5 with fee-based tokens, only the latter 5 will count towards the fee. -An alternative to Bitcoin and Ethereum approchaes for blockchain fees is a model that charge fees based in the transaction size. - -This model offers two advantages: - - It simplifies the user experience by providing a predictable fee without major fluctuations. - - It creates a fair mechanism that makes simple transactions cheaper and charges more for complex ones. +This proposal suggests **0.01 HTR per output**. +Appart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. It means **0.01 HTR or 1.00 deposit-based-token** + ### Transaction Mining + By adding fees to the transactions, we don't need to mine them anymore. So the proof of work (PoW) won't affect the fee calculation. ### Fee destination -The fees will be burned, if we need to do something with it, possibly in another issue we can change the behavior. For now let's keep it simple. - -### Fee calculation - -Hathor’s fees will be calculated similarly to Bitcoin, depending only on transaction size (in bytes) and a network-defined fee rate (in HTR per byte). - -Proof-of-Work difficulty (transaction weight) will not influence the fee calculation. - -Let's assume: -1. HTR is always used as the fee unit, regardless of the tokens involved in the transaction. -2. Even if fee-based tokens are used alone, or with a deposit-based token, a single fee in HTR will be charged, regarding the transaction size. -3. Interacting with nano contracts may introduce an additional fee depending on the execution complexity. -4. Fee rate, static and dynamic, are arbitary values to be defined by the business. - -We'll adopt a fee_rate_per_static_byte, and fee_rate_per_dynamic_byte that assumes the fixed size of the tx to act as our flat fee and the dynamic part of the tx to ensure we'll charge less for simple transaction and more for larger. - -In this proposal we are excluding simple transactions, 1 input, 1 token, and up to 2 outputs from the dynamic calculation. -Below is a pseudo code that explain how fee should be calculated, using a fee rate per byte: - -*(Note: Excluded "hash" size from calculation, hence 114 reduced to 84 bytes.)* +The fees will be burned, if we need to do something with it, possibly in another issue we can change the behavior. For now let's keep it simple. -*(Note: We already have a way to calculate the tx size, here the idea is to shown what is the flat part and what is considered the dynamic part. Where we can mainupulate the rates to create flat fee and dynamic fees that are predictable to the user)* -```python -def calculate_tx_fee(tx, fee_rate_per_static_byte, fee_rate_per_dynamic_byte): - # Fixed size fields (always present) - fixed_size = 84 # version (2) + timestamp (4) + nonce (4) + weight (8) + parents (64) - - # Tokens array size - tokens_size = 0 - if len(tx.tokens) > 1: - tokens_size = 32 * len(tx.tokens) - 1 - - # Inputs size calculation - inputs_size = 0 - if len(tx.inputs) > 1: - for i in range(len(tx.inputs) - 1): - input = tx.outputs[i] - inputs_size += 35 + len(input.data) - # 32 bytes (tx_id) + 1 byte (index) + 2 bytes (data length prefix) + len(data) - - # Outputs size calculation - outputs_size = 0 - if len(tx.outputs) > 2: - for i in range(len(tx.outputs) - 2): - output = tx.outputs[i] - outputs_size += 7 + len(output.script) - # 4 bytes (value) + 1 byte (token_data) + 2 bytes (script length prefix) + len(script) +## Wallet UI - # Total transaction size - flat_fee = fixed_size * fee_rate_per_static_byte +Since Hathor has an easy to use approach, we should provide to the users the option to select between the two models (deposit and fee) when minting. Also, in the wallet we should always require fee payment in HTR to incentivize HTR demand. - ## Here we can also define how we want to calculate the dynamic fee. For example, imagine that we only want to charge fee for transactions that have more than two outputs, or ignore how the inputs size on the formula in order to make it predictable according to business needs. - dynamic_fee = (tokens_size + inputs_size + outputs_size) * fee_rate_per_dynamic_byte +That's the initial recommendation. After testing and feedback, we may choose to allow paying with other tokens as well. Note that this is just for the Hathor wallet. **At the protocol level, other tokens are accepted**. - # Fee calculation - fee = flat_fee + dynamic_fee + tx.priority_tip +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation - return fee # plus any nano fee that should match +In this section, technical details are expanded for what was described above. -``` +## Token info version +Given Hathor's [Anatomy of a Transaction RFC](https://github.com/HathorNetwork/rfcs/blob/master/text/0015-anatomy-of-tx.md#token-creation), it is reasonable to suggest that the byte used by the token creation transaction `token_info_version` will be used to determine fee-created tokens. +Since each custom token `id` is the hash of the token creation transaction that created it, we can assume the enum values below that can be assigned to the `token_info_version` byte in the token creation tx and then we can retrieve it. -### **Example Calculation:** +So, by adding an TokenInfoVersion enum we have: +- DEPOSIT = 1 (as is) +- FEE = 2 -**Hypothetical Transaction:** -- Fee rate per static byte to result in 0.01 HTR (flat): 0,000119047619048 -- Fee rate per dynamic byte to increase the fee based on the complexity of the tx: 0,000119047619048 -- 1 token UID -- 2 inputs -- 2 outputs +Then, we must allow the versions above in the `deserialize_token_info` method, by checking the enum values. -Calculate fee: +## Transaction +From the section below we know how to diferenciate between deposit and fee tokens, based on that we need to add a couple of method to the transaction in order to calculate the fee. -| Field | Calculation | Size | Byte type | Total -|----------------------|-----------------------------|---------------|-----------|-----| -| Fixed-size fields | | **84** bytes | static | 0.01 HTR -| Tokens | 1 token × 32 bytes | **32** bytes | dynamic | 0 HTR -| Inputs | 2 × 35 | **286** bytes | dynamic | 0.0038 HTR -| Outputs | 2 × (7 + 25) | **64** bytes | dynamic | 0 HTR -| **Total Fee** | | | | 0.0138 HTR +`should_charge_fee` method will check if the transaction has any fee based output and if the `FEE_FEATURE_FLAG` is enabled. -## Wallet UI +`calculate_fee` method will count the fee based outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee. This one should also be in the `base_transaction.py` returning a 0 value, so it won't affect any calculation from not being implemented. -We should provide to the users the option to select between the two models (deposit and fee) when minting. +## Transaction verifier -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation -TODO +Inside the transaction verifier we have the `verify_sum` method which is responsible for check if the sum of outputs are equal of the sum of inputs. If the sum of inputs and outputs is not 0, we'll add the new case. -# Drawbacks of the Hybrid Fee Model -[drawbacks]: #drawbacks +- Melting: Amount > 0 +- Minting: Amount < 0 +- Fee: Amount < 0 -While the hybrid fee model balances incentives and network sustainability, it also introduces potential drawbacks that must be considered. Below are key concerns and challenges: +Here the `tx.should_charge_fee()` comes into action and help us to bypass any deposit that should be made for the current token and move on charging the (`tx.calculate_fee()`) fee without conflict. -### Complexity in Multi-Token Transactions +## Feature flag in settings +For development purpose this feature will be feature flagged to run only in local net by changing the FEE_FEATURE_FLAG in settings to true -**Issue:** Transactions involving multiple tokens introduce a more complex fee structure, requiring additional computation to determine the appropriate charge. +## Feature activation +For production, we'll rely on the feature activation to release this feature. -**Impact:** - - Increased processing overhead for wallets. - - Potential user confusion when sending transactions with different token types. +# Drawbacks -**Potential Mitigation:** - - Improve **wallet UX** to clearly display estimated fees before confirming transactions. +A drawback would be an increase in CPU consumption, because the verification algorithm will be more complicated, but it seems to be a minor drawback. # Prior art @@ -167,24 +113,23 @@ Ethereum handles transaction fees through the concept of Gas, where each operati The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. # Business unresolved questions -- Should we allow deposit based tokens to collect fees? -- Should we burn or move it to a burn address? -- How the fee will be calculated? -- Should we only consider the outputs in the fee calculation? +- ~~Should we allow deposit based tokens to collect fees?~~ +- ~~Should we burn or move it to a burn address?~~ +- ~~How the fee will be calculated?~~ +- ~~Should we only consider the outputs in the fee calculation?~~ # Unresolved questions [unresolved-questions]: #unresolved-questions - How should melt operations be handled for fee-based custom tokens? -- How fee adjustments will be governed? +- ~~How fee adjustments will be governed?~~ - Removing the transaction fee from minning, how will it affect the tx-mining-service? # Future possibilities [future-possibilities]: #future-possibilities - Custom Fee Markets (letting users optimize fees). -- Dynamic Fee Adjustment Mechanism, where fees scale based on network congestion. # References From 3345c58142d796862402dbc2842bf1bc0e2e2e12 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Fri, 4 Apr 2025 18:32:25 -0300 Subject: [PATCH 09/13] English fixes --- text/0045-transaction_fee_minting.md | 55 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 1ff7318..9a07511 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -13,14 +13,14 @@ This proposal suggests an alternative mechanism where, instead of requiring an u # Motivation [motivation]: #motivation -Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom tokens where tokens would be minted for free (i.e., no deposits) and fees will be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) +Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom token where tokens would be minted for free (i.e., no deposits) and fees would be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. For handle it we will use the same definitions of the [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md), possibly adding a variation of it using a new version. +When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. To handle this, we will use the same definitions from the [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md), possibly adding a variation of it using a new version. ## Deposit-Based Model (as is) @@ -28,32 +28,31 @@ Currently, creators must [deposit a percentage](https://github.com/HathorNetwork ## Fee-Based Model -Adding the fee-based model the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee. +With the fee-based model, the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee. By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A popular use case is the creation of memecoins by minting tokens that aren’t bound to HTR value. Besides that, the user can use it for any other scenario that may arise. ### Fee cost -Fees will be proportional to the amount of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens and another 5 with fee-based tokens, only the latter 5 will count towards the fee. +Fees will be proportional to the number of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens, and another 5 with fee-based tokens, only the latter 5 will count towards the fee. This proposal suggests **0.01 HTR per output**. -Appart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. It means **0.01 HTR or 1.00 deposit-based-token** - +Apart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. That means **0.01 HTR or 1.00 deposit-based-token**. + ### Transaction Mining By adding fees to the transactions, we don't need to mine them anymore. So the proof of work (PoW) won't affect the fee calculation. ### Fee destination -The fees will be burned, if we need to do something with it, possibly in another issue we can change the behavior. For now let's keep it simple. - +The fees will be burned. ## Wallet UI -Since Hathor has an easy to use approach, we should provide to the users the option to select between the two models (deposit and fee) when minting. Also, in the wallet we should always require fee payment in HTR to incentivize HTR demand. +Since Hathor has an easy-to-use approach, we should provide users the option to select between the two models (deposit and fee) when minting. Also, in the wallet, we should always require fee payment in HTR to incentivize HTR demand. -That's the initial recommendation. After testing and feedback, we may choose to allow paying with other tokens as well. Note that this is just for the Hathor wallet. **At the protocol level, other tokens are accepted**. +**At the protocol level, other tokens are accepted**. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation @@ -63,40 +62,42 @@ In this section, technical details are expanded for what was described above. ## Token info version Given Hathor's [Anatomy of a Transaction RFC](https://github.com/HathorNetwork/rfcs/blob/master/text/0015-anatomy-of-tx.md#token-creation), it is reasonable to suggest that the byte used by the token creation transaction `token_info_version` will be used to determine fee-created tokens. -Since each custom token `id` is the hash of the token creation transaction that created it, we can assume the enum values below that can be assigned to the `token_info_version` byte in the token creation tx and then we can retrieve it. +Since each custom token `id` is the hash of the token creation transaction that created it, we can assume the enum values below can be assigned to the `token_info_version` byte in the token creation tx and then we can retrieve it. -So, by adding an TokenInfoVersion enum we have: +So, by adding a TokenInfoVersion enum we have: - DEPOSIT = 1 (as is) - FEE = 2 -Then, we must allow the versions above in the `deserialize_token_info` method, by checking the enum values. +Then, we must allow the versions above in the `deserialize_token_info` method by checking the enum values. ## Transaction -From the section below we know how to diferenciate between deposit and fee tokens, based on that we need to add a couple of method to the transaction in order to calculate the fee. +From the section below, we know how to differentiate between deposit-based and fee-based tokens. Based on that, we need to add a couple of methods to the transaction in order to calculate the fee. -`should_charge_fee` method will check if the transaction has any fee based output and if the `FEE_FEATURE_FLAG` is enabled. +The `should_charge_fee` method will check if the transaction has any fee-based output and if the `FEE_FEATURE_FLAG` is enabled. -`calculate_fee` method will count the fee based outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee. This one should also be in the `base_transaction.py` returning a 0 value, so it won't affect any calculation from not being implemented. +The `calculate_fee` method will count the fee-based outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee. This method should also be in `base_transaction.py`, returning a value of 0 so it won't affect any calculation from not being implemented. ## Transaction verifier -Inside the transaction verifier we have the `verify_sum` method which is responsible for check if the sum of outputs are equal of the sum of inputs. If the sum of inputs and outputs is not 0, we'll add the new case. +Inside the transaction verifier, we have the `verify_sum` method, which is responsible for checking if the sum of outputs equals the sum of inputs. If the sum of inputs and outputs is not 0, we'll add the new case. - Melting: Amount > 0 - Minting: Amount < 0 - Fee: Amount < 0 -Here the `tx.should_charge_fee()` comes into action and help us to bypass any deposit that should be made for the current token and move on charging the (`tx.calculate_fee()`) fee without conflict. +Here, the `tx.should_charge_fee()` comes into action and helps us bypass any deposit that should be made for the current token and proceed with charging the fee via `tx.calculate_fee()` without conflict. + +Once we have the transaction fee value in hand, we should iterate over each input and output to collect the required amount. It can come from HTR, deposit-based tokens, or a combination of both. ## Feature flag in settings -For development purpose this feature will be feature flagged to run only in local net by changing the FEE_FEATURE_FLAG in settings to true +For development purposes, this feature will be feature-flagged to run only on the local network by setting the `FEE_FEATURE_FLAG` in settings to true. ## Feature activation -For production, we'll rely on the feature activation to release this feature. +For production, we'll rely on feature activation to release this feature. # Drawbacks -A drawback would be an increase in CPU consumption, because the verification algorithm will be more complicated, but it seems to be a minor drawback. +A drawback would be an increase in CPU consumption because the verification algorithm will be more complicated, but it seems to be a minor drawback. # Prior art @@ -113,18 +114,17 @@ Ethereum handles transaction fees through the concept of Gas, where each operati The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. # Business unresolved questions -- ~~Should we allow deposit based tokens to collect fees?~~ +- ~~Should we allow deposit-based tokens to collect fees?~~ - ~~Should we burn or move it to a burn address?~~ -- ~~How the fee will be calculated?~~ +- ~~How will the fee be calculated?~~ - ~~Should we only consider the outputs in the fee calculation?~~ - # Unresolved questions [unresolved-questions]: #unresolved-questions - How should melt operations be handled for fee-based custom tokens? -- ~~How fee adjustments will be governed?~~ -- Removing the transaction fee from minning, how will it affect the tx-mining-service? +- ~~How will fee adjustments be governed?~~ +- By removing the transaction fee from mining, how will it affect the tx-mining-service? # Future possibilities [future-possibilities]: #future-possibilities @@ -139,5 +139,4 @@ The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes t - https://bitcoin.org/bitcoin.pdf - https://eips.ethereum.org/EIPS/eip-1559 - https://ethereum.org/en/developers/docs/gas/ -- https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change - +- https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change \ No newline at end of file From f2446a4c6c82e61d26e04ff8de9b135e3b1c2b74 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Mon, 7 Apr 2025 12:33:27 -0300 Subject: [PATCH 10/13] typo fixes --- text/0045-transaction_fee_minting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 9a07511..70b102a 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -20,7 +20,7 @@ This change would reduce the upfront cost of minting tokens, making it more acce # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. To handle this, we will use the same definitions from the [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md), possibly adding a variation of it using a new version. +When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. To handle this, we will use the same definitions from both [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md) and this proposal. ## Deposit-Based Model (as is) @@ -71,7 +71,7 @@ So, by adding a TokenInfoVersion enum we have: Then, we must allow the versions above in the `deserialize_token_info` method by checking the enum values. ## Transaction -From the section below, we know how to differentiate between deposit-based and fee-based tokens. Based on that, we need to add a couple of methods to the transaction in order to calculate the fee. +From the section above, we know how to differentiate between deposit-based and fee-based tokens. Based on that, we need to add a couple of methods to the transaction in order to calculate the fee. The `should_charge_fee` method will check if the transaction has any fee-based output and if the `FEE_FEATURE_FLAG` is enabled. From 9d18ae1ec4f07bf65ab36db4fd49c36ddbf9fda4 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Fri, 11 Apr 2025 12:30:11 -0300 Subject: [PATCH 11/13] updates based on comments --- text/0045-transaction_fee_minting.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 70b102a..5b0b00a 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -15,7 +15,7 @@ This proposal suggests an alternative mechanism where, instead of requiring an u Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom token where tokens would be minted for free (i.e., no deposits) and fees would be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) -This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. The network would still benefit from a fee mechanism that contributes to miners’ incentives and overall network security. +This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -28,14 +28,14 @@ Currently, creators must [deposit a percentage](https://github.com/HathorNetwork ## Fee-Based Model -With the fee-based model, the platform won't require an upfront deposit. Instead, each transfer of the minted tokens incurs a transaction fee. - -By selecting the appropriate model, token creators can optimize their minting strategy based on their specific needs and usage scenarios. A popular use case is the creation of memecoins by minting tokens that aren’t bound to HTR value. Besides that, the user can use it for any other scenario that may arise. +In the fee-based model, no upfront deposit is required — each transfer simply incurs a transaction fee. This gives token creators flexibility to tailor their strategy to specific use cases, such as minting large quantities of memecoins without tying them to HTR value. The model also supports other scenarios that benefit from predictable, low-cost transactions. For example, it enables the creation of scalable in-game currencies or loyalty tokens, where frequent, small transactions don’t incur high fees, and projects can monetize their services more effectively by using custom tokens for fees. ### Fee cost Fees will be proportional to the number of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens, and another 5 with fee-based tokens, only the latter 5 will count towards the fee. +For melting operations which doesn't contain any output we'll count as 1 output in the fee calculation. + This proposal suggests **0.01 HTR per output**. Apart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. That means **0.01 HTR or 1.00 deposit-based-token**. @@ -48,7 +48,11 @@ By adding fees to the transactions, we don't need to mine them anymore. So the p The fees will be burned. -## Wallet UI +## Explorer + +Add the fee field in the transaction view, and the token_info_version in the token creation transaction. + +## Wallet (desktop, mobile, wallet-lib) Since Hathor has an easy-to-use approach, we should provide users the option to select between the two models (deposit and fee) when minting. Also, in the wallet, we should always require fee payment in HTR to incentivize HTR demand. @@ -95,6 +99,9 @@ For development purposes, this feature will be feature-flagged to run only on th ## Feature activation For production, we'll rely on feature activation to release this feature. +## Transaction fee rosource +Add an endpoint to calculate fees based in the inputs and outputs, in order to expose the logic used in the transaction verifiers to the wallets. + # Drawbacks A drawback would be an increase in CPU consumption because the verification algorithm will be more complicated, but it seems to be a minor drawback. From 14e066602c3493f852f499b191ac11a5d4becb54 Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Mon, 14 Apr 2025 14:49:31 -0300 Subject: [PATCH 12/13] fix typos --- text/0045-transaction_fee_minting.md | 67 +++++++++++++++++++++------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index 5b0b00a..e5cc442 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -34,15 +34,29 @@ In the fee-based model, no upfront deposit is required — each transfer simply Fees will be proportional to the number of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens, and another 5 with fee-based tokens, only the latter 5 will count towards the fee. -For melting operations which doesn't contain any output we'll count as 1 output in the fee calculation. +For melting operations that don't contain any outputs, we'll count them as 1 output in the fee calculation. This proposal suggests **0.01 HTR per output**. Apart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. That means **0.01 HTR or 1.00 deposit-based-token**. -### Transaction Mining +### Fee and melting operations +The fee will be charged before any melting operation and doesn't require any authority for it. -By adding fees to the transactions, we don't need to mine them anymore. So the proof of work (PoW) won't affect the fee calculation. +For instance, if there is a transaction with: +Fee-based Token (FBT), Deposit-based Token (DBT) + + Inputs: [1000 FBT, FBT Melt Authority, 500 DBT] + Outputs: [500 FBT, 400 DBT] + +In this scenario, 100 DBT is used to pay the fee without requiring any authority. + +For a combination of paying the fee and also melting the token, we'll have the following: + + Inputs: [1000 FBT, FBT Melt Authority, 500 DBT, DBT Melt Authority] + Outputs: [500 FBT, FBT Melt Authority, 300 DBT, DBT Melt Authority] + +Here, 100 DBT is used to pay the fee, and there is a melt of 500 FBT and 100 DBT. For melting tokens, the behavior remains the same, requiring authority. ### Fee destination @@ -74,24 +88,45 @@ So, by adding a TokenInfoVersion enum we have: Then, we must allow the versions above in the `deserialize_token_info` method by checking the enum values. -## Transaction -From the section above, we know how to differentiate between deposit-based and fee-based tokens. Based on that, we need to add a couple of methods to the transaction in order to calculate the fee. +## Transaction token_dict +From the section above, we know how to differentiate between deposit and fee tokens. Based on that, we need to add the input and output data to the current `token_dict` in order to calculate the outputs and check for melting operations without outputs. -The `should_charge_fee` method will check if the transaction has any fee-based output and if the `FEE_FEATURE_FLAG` is enabled. +## Fee (fee.py) +This new file is responsible for keeping the fee logic, but not for orchestrating it; this will be done in the transaction verifier. -The `calculate_fee` method will count the fee-based outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee. This method should also be in `base_transaction.py`, returning a value of 0 so it won't affect any calculation from not being implemented. +The `should_charge_fee` method will check if the transaction has any fee-based input or output and if the `FEE_FEATURE_FLAG` is enabled. + +The `calculate_fee` method will receive a `token_dict` as input, then count the fee-based non-authority outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee in HTR. + +It will consider 1 output for melting operations that don't have any output. +It won't consider mint and melt authorities. + +The `collect_fee` method will receive the `token_dict` and the fee. It will use the differences between the input and output amounts and return the paid fee in HTR. For each token that has a difference, it will collect the fee by incrementing the amount value in the corresponding `token_dict` entry. ## Transaction verifier -Inside the transaction verifier, we have the `verify_sum` method, which is responsible for checking if the sum of outputs equals the sum of inputs. If the sum of inputs and outputs is not 0, we'll add the new case. +### verify_fee() +Inside the transaction verifier, the `verify_fee` method will be added. It's responsible for orchestrating the fee flow by checking if the fee should be charged, calculating it, and checking the payment availability: + +Example: +```python +if not should_charge_fee(token_dict): + return + +fee = calculate_fee(token_dict) +paid_fee = collect_fee(token_dict) -- Melting: Amount > 0 -- Minting: Amount < 0 -- Fee: Amount < 0 +if fee - paid_fee > 0: + raise InputOutputMismatch( + 'HTR or deposit tokens are not enough to pay the fee. (amount={}, expected={})'.format( + paid_fee, + fee, + )) +``` -Here, the `tx.should_charge_fee()` comes into action and helps us bypass any deposit that should be made for the current token and proceed with charging the fee via `tx.calculate_fee()` without conflict. +### verify_sum() -Once we have the transaction fee value in hand, we should iterate over each input and output to collect the required amount. It can come from HTR, deposit-based tokens, or a combination of both. +Since we already normalized the `token_dict` values in the `verify_fee` method before calling this one, we just need to adjust the withdraw and deposit amounts here, collecting only for deposit tokens. ## Feature flag in settings For development purposes, this feature will be feature-flagged to run only on the local network by setting the `FEE_FEATURE_FLAG` in settings to true. @@ -99,8 +134,8 @@ For development purposes, this feature will be feature-flagged to run only on th ## Feature activation For production, we'll rely on feature activation to release this feature. -## Transaction fee rosource -Add an endpoint to calculate fees based in the inputs and outputs, in order to expose the logic used in the transaction verifiers to the wallets. +## Transaction fee resource +Add an endpoint to calculate fees based on the inputs and outputs, in order to expose the logic used in the transaction verifiers to the wallets. # Drawbacks @@ -146,4 +181,4 @@ The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes t - https://bitcoin.org/bitcoin.pdf - https://eips.ethereum.org/EIPS/eip-1559 - https://ethereum.org/en/developers/docs/gas/ -- https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change \ No newline at end of file +- https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change From 36922f193c21c01fe16ee001808f9fce784e800f Mon Sep 17 00:00:00 2001 From: raul-oliveira Date: Mon, 28 Apr 2025 23:57:46 -0300 Subject: [PATCH 13/13] reference level update --- text/0045-transaction_fee_minting.md | 502 ++++++++++++++++++++++----- 1 file changed, 424 insertions(+), 78 deletions(-) diff --git a/text/0045-transaction_fee_minting.md b/text/0045-transaction_fee_minting.md index e5cc442..0a351dd 100644 --- a/text/0045-transaction_fee_minting.md +++ b/text/0045-transaction_fee_minting.md @@ -1,36 +1,57 @@ -- Feature Name: transaction_fee_minting +# Fee Custom Tokens RFC + +- Feature Name: Fee custom tokens - Start Date: 2025-02-24 -- RFC PR: (to be created) -- Hathor Issue: (leave this empty) +- RFC PR: https://github.com/HathorNetwork/rfcs/pull/94 +- Hathor Issue: - Author: Raul Soares de Oliveira -# Summary +## Summary + [summary]: #summary -Currently, when minting X tokens, a [deposit of P% (1%) of X in HTR is required](./0011-token-deposit.md). This deposit can later be withdrawn when the tokens are melted. + +Currently, when minting X tokens, a [deposit of P% (1%) of X in HTR is required](./0011-token-deposit.md). This deposit can later be withdrawn when the tokens are melted. This proposal suggests an alternative mechanism where, instead of requiring an upfront deposit of HTR when minting new tokens, a transaction fee is charged on each transfer of the newly minted tokens. -# Motivation +For nano contracts, the fee is charged from the caller, whether it's a transaction or another nano contract. The charging mechanism follows the same pattern as deposit-based tokens: deposits are considered as outputs and withdrawals as inputs. For actions called from within a nano contract, fees are charged per action from the caller's balance. Fees are calculated per action and transfer, not as computational gas costs like in Ethereum. + +## Motivation [motivation]: #motivation Dozer suggested an alternative to the HTR deposit requirement when minting tokens. The idea is to create a new type of custom token where tokens would be minted for free (i.e., no deposits) and fees would be charged for transactions. [RFC](https://github.com/Dozer-Protocol/hathor-rfcs/blob/new-token-economics/projects/new-token-economics/token-economics.md) -This change would reduce the upfront cost of minting tokens, making it more accessible to users who may not have sufficient HTR at the time of minting. +This change would reduce the upfront cost of minting tokens, making them more accessible to users who may not have sufficient HTR at the time of minting. -# Guide-level explanation -[guide-level-explanation]: #guide-level-explanation +## Guide-level Explanation When minting tokens, creators can choose between two transaction models: Deposit-Based and Fee-Based. Each model offers different benefits, depending on how the tokens will be used. To handle this, we will use the same definitions from both [Token Creation Transaction](https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md) and this proposal. -## Deposit-Based Model (as is) +### Deposit-Based Model (Current Implementation) + +Currently, creators must [deposit a percentage](https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md) (P%) of the minted tokens' value in HTR. For example, if P% is set at 1% and a user mints 100 tokens, they must deposit 1 HTR. This deposit acts as a reserve and is fully refundable if the tokens are later melted. -Currently, creators must [deposit a percentage](https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md) (P%) of the minted tokens’ value in HTR. For example, if P% is set at 1% and a user mints 100 tokens, they must deposit 1 HTR. This deposit acts as a reserve and is fully refundable if the tokens are later melted. +In nano contracts, the caller (whether a UTXO transaction or another nano contract) pays the deposit. For UTXO transactions, the deposit is charged from the imbalance between inputs and outputs when a token creation transaction occurs. In nano contracts, the deposit is charged from the contract's balance when it calls the syscall to create deposit-based tokens. -## Fee-Based Model +### Fee-Based Model -In the fee-based model, no upfront deposit is required — each transfer simply incurs a transaction fee. This gives token creators flexibility to tailor their strategy to specific use cases, such as minting large quantities of memecoins without tying them to HTR value. The model also supports other scenarios that benefit from predictable, low-cost transactions. For example, it enables the creation of scalable in-game currencies or loyalty tokens, where frequent, small transactions don’t incur high fees, and projects can monetize their services more effectively by using custom tokens for fees. +In the fee-based model, no upfront deposit is required — each transfer simply incurs a transaction fee. This gives token creators flexibility to tailor their strategy to specific use cases, such as minting large quantities of memecoins without tying them to HTR value. The model also supports other scenarios that benefit from predictable, low-cost transactions. For example, it enables the creation of scalable in-game currencies or loyalty tokens, where frequent, small transactions don't incur high fees, and projects can monetize their services more effectively by using custom tokens for fees. -### Fee cost +#### Fee Header + +A fee header will be added to transactions to signal which tokens will be used for fee payment. + +In the example below we'll use Fee-based Token (FBT), and Deposit-based Token (DBT) as our tokens. + +``` +inputs: [100 DBT, 1000 FBT] +outputs: [1000 FBT] +tokens: [DBT, FBT] +fee_header: + fees: [(100, 1)] ← index of DBT in the tokens array +``` + +#### Fee Cost Fees will be proportional to the number of outputs with fee-based tokens. For instance, if there are 3 HTR outputs, 2 outputs with deposit-based tokens, and another 5 with fee-based tokens, only the latter 5 will count towards the fee. @@ -38,142 +59,465 @@ For melting operations that don't contain any outputs, we'll count them as 1 out This proposal suggests **0.01 HTR per output**. -Apart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-as-is)), the fee needs to be 100x the HTR rate. That means **0.01 HTR or 1.00 deposit-based-token**. +Apart from accepting HTR for fee payment, any deposit-based token will be accepted. In this case, since the token was created with a 100:1 ratio of HTR ([deposit model](#deposit-based-model-current-implementation)), the fee needs to be 100x the HTR rate. That means **0.01 HTR or 1.00 deposit-based-token**. + +##### Melting Operations + +Melting tokens without authority is forbidden. Fee payments will be accepted as long as their total is exactly equal to the required fee. Any other case will be rejected. -### Fee and melting operations -The fee will be charged before any melting operation and doesn't require any authority for it. +In the examples below we'll use Fee-based Token (FBT), and Deposit-based Token (DBT) as our tokens. + +In this case the fee is 1 HTR or 100 DBT, but the user is providing 150 DBT as payment, which will cause this transaction to be rejected. + +``` +inputs: [FBT MELT AUTHORITY, 100 FBT, 200 DBT] +outputs: [100 FBT, 50 DBT] +tokens: [DBT, FBT] +fee_header: + fees: [(150, 1)] ← index of DBT in the tokens array +``` +**Example 2: Valid fee payment** For instance, if there is a transaction with: -Fee-based Token (FBT), Deposit-based Token (DBT) - Inputs: [1000 FBT, FBT Melt Authority, 500 DBT] - Outputs: [500 FBT, 400 DBT] +``` +inputs: [1000 FBT, FBT Melt Authority, 500 DBT] +outputs: [500 FBT, 400 DBT] +tokens: [DBT, FBT] +fee_header: + fees: [(100, 1)] ← index of DBT in the tokens array +``` In this scenario, 100 DBT is used to pay the fee without requiring any authority. +**Example 3: Combined fee payment and token melting** For a combination of paying the fee and also melting the token, we'll have the following: - Inputs: [1000 FBT, FBT Melt Authority, 500 DBT, DBT Melt Authority] - Outputs: [500 FBT, FBT Melt Authority, 300 DBT, DBT Melt Authority] +``` +inputs: [1000 FBT, FBT Melt Authority, 500 DBT, DBT Melt Authority] +outputs: [500 FBT, FBT Melt Authority, 300 DBT, DBT Melt Authority] +tokens: [DBT, FBT] +fee_header: + fees: [(100, 1)] ← index of DBT in the tokens array +``` Here, 100 DBT is used to pay the fee, and there is a melt of 500 FBT and 100 DBT. For melting tokens, the behavior remains the same, requiring authority. -### Fee destination +##### Nano Contracts + +It's important to mention that this fee should behave similarly to **deposit-based tokens and not like gas fees in Ethereum**. The fee is charged per action and syscall, following the same pattern already established for nano contracts with deposit-based tokens, rather than being a computational resource cost like gas. + +We'll support fee payments with deposit tokens that will be created in the same nano contract execution. + +Based on this [issue](https://github.com/HathorNetwork/rfcs/issues/97), the items below will be charged **0.01 HTR** when dealing with Fee-based tokens: + +**Syscalls:** +- `create_fee_token` +- `mint_tokens` +- `melt_tokens` + +**Actions:** +- Deposit +- Withdraw + +For transactions that are calling a Deposit/Withdraw action, they will be charged both from the outputs count and by the action cost. Nano contracts transferring funds between each other will pay fees based on the actions they might call. + +**Fee calculation formulas:** + +Transaction depositing funds in a nano contract: +``` +0.01 * len(outputs) + len(deposits) +``` + +If the same fee-based token is in the inputs but not in the outputs, we'll consider the same fee used for melting operations: 0.01 HTR (check [Fee cost](#fee-cost)). + +Transaction withdrawing funds from a nano contract: +``` +0.01 * len(outputs) + len(withdraws) +``` + +Nano contracts transferring funds within a nano contract: +``` +0.01 * (len(deposits) + len(withdraws)) +``` + +**Practical Example:** + +To demonstrate the above with an example we will consider: +- A nano contract (nc1) that is already initialized +- The initial balance of the nc1 is 0.00 HTR +- The nc1 doesn't call any other contract + +```python +class MyBlueprint(Blueprint): + @public(allow_deposit=True, allow_withdrawal=True) + def create_tokens(self, ctx: Context): + fbt = self.syscall.create_fee_token(5000, 'FBT') + + @public + def no_op(self): + pass +``` + +###### Creating a Fee-based token (FBT) - UTXO → Nano contract + +``` +inputs: [200.01 HTR] +outputs: [5000.00 FBT, 100.00 HTR] +nano_header: + nc_id: nc1, + action: deposit (100.00 HTR), withdraw (5000.00 FBT), + method: create_tokens +fee_header: + fees: [(0.01, 0)] ← HTR index in the tokens array +``` + +In this case, the caller is the transaction, so the fee will be charged from it in the form of an output. + +**Fee breakdown:** +- 0.01 HTR from the outputs count, provided by the withdraw action +- 0.01 HTR from the `create_fee_token` syscall ← charged from the contract's balance + +**Contract State:** +- balance: + - HTR: 99.99 + - FBT: 0.00 + +Although HTR was used in the example, deposit-based tokens are also accepted. + +###### Deposit a Fee-based token (FBT) - UTXO → Nano contract + +In this example, we'll deposit part of the fee-based tokens created into a contract. + +``` +inputs: [5000.00 FBT, 100.00 HTR] +outputs: [4000.00 FBT, 99.98 HTR] +nano_header: + nc_id: nc1, + action: deposit (1000.00 FBT), + method: no_op +fee_header: + fees: [(0.02, 0)] ← HTR index in the tokens array +``` + +**Fee breakdown:** +- 0.01 HTR from the outputs count +- 0.01 HTR from the `deposit` action + +**Contract State:** +- balance: + - HTR: 99.99 + - FBT: 1000.00 + +###### Creating a Fee-based token (FBT) - Nano contract → Nano contract + +This is a pseudo code example: + +```python +class BlueprintA(Blueprint): + def initialize(self, ctx: Context, token_creator_nc_id: ContractId) -> None: + self.token_creator_nc_id = token_creator_nc_id + + @public(allow_deposit=True, allow_withdrawal=True) + def create_tokens(self, ctx: Context): + ctx = { + 'actions': [Withdraw(5000, FBT), Deposit(0.01, HTR)], + 'fees': [(0.01, HTR)] + } + fbt = self.syscall.call_public_method(self.token_creator_nc_id, 'create_fee_tokens') + + @public + def no_op(self): + pass +``` + +```python +class TokenCreator(Blueprint): + @public(allow_deposit=True, allow_withdrawal=True) + def create_fee_tokens(self, ctx: Context): + fbt = self.syscall.create_fee_token(5000, 'FBT') + + @public + def no_op(self): + pass +``` + +In this example, we'll call contract "nc_1" which will call "token_creator_nc_1" that is responsible for creating the tokens. + +``` +inputs: [0.02 HTR] +outputs: [] +nano_header: + nc_id: nc1, # using BlueprintA + action: deposit (0.02 HTR), + method: create_tokens +``` + +After executing the `create_tokens` method from `nc_1` (using BlueprintA), we'll have the following balances: + +**nc_1:** +- HTR: 0.00 +- FBT: 5000.00 +- fees: 0.01 HTR from the withdraw action + +**token_creator_nc1:** +- HTR: 0.00 +- FBT: 0.00 +- fees: 0.01 HTR from the create fee tokens syscall + +With this example we can see that each action (DEPOSIT or WITHDRAW) using fee tokens charges 0.01 HTR. + +#### Fee Destination The fees will be burned. -## Explorer +### Affected Projects + +The implementation in the following projects does not support fee payments with custom deposit-based tokens initially, although it will be available at the protocol level. + +#### Wallet-lib + +This project handles methods that are responsible for preparing a transaction and choosing UTXOs that will serve as inputs. With the Fee-based token version, those methods need to be refactored to handle it and prepare the UTXOs according to the requirements described in this document. + +#### Wallet-service + +The wallet service has its own database with the token details data stored. It will be necessary to add the token `version` field introduced by this document, since before it wasn't used and was hardcoded. + +#### Explorer + +The Explorer service ingestors are prepared to bring all columns from the wallet-service database into Elasticsearch, where they will be used by the Explorer service to provide data for the token detail API. We will update the token list view, token detail view, and transaction detail view by adding fee data and token version descriptions. + +#### Wallet-headless + +This is the official headless wallet of Hathor. We'll need to update the create tokens methods (both UTXO and nano) arguments to support the new token version. -Add the fee field in the transaction view, and the token_info_version in the token creation transaction. +#### RPC-lib -## Wallet (desktop, mobile, wallet-lib) +The RPC lib acts as a bridge between the wallet-lib and the desktop and mobile clients. It's required to update the create tokens handlers (UTXO and nano) to accept the token version argument. -Since Hathor has an easy-to-use approach, we should provide users the option to select between the two models (deposit and fee) when minting. Also, in the wallet, we should always require fee payment in HTR to incentivize HTR demand. +#### Wallet (Desktop, Mobile) -**At the protocol level, other tokens are accepted**. +The wallets will have a new create token experience. It will allow the user to choose between the token versions (deposit or fee based), see the fees and check the token detail data. -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation +Also, we'll provide information about the transaction fee while approving a transaction and before sending it. The user will be able to check the paid fee in the transaction detail screen, similar to explorer. + +## Reference-level Explanation In this section, technical details are expanded for what was described above. -## Token info version -Given Hathor's [Anatomy of a Transaction RFC](https://github.com/HathorNetwork/rfcs/blob/master/text/0015-anatomy-of-tx.md#token-creation), it is reasonable to suggest that the byte used by the token creation transaction `token_info_version` will be used to determine fee-created tokens. +### Changes in the Transaction Anatomy + +#### Token Info Version (aka Token Version) + +Given Hathor's [Anatomy of a Transaction RFC](https://github.com/HathorNetwork/rfcs/blob/master/text/0015-anatomy-of-tx.md#token-creation), it is reasonable to suggest that the byte used by the token creation transaction `token_info_version` will be used to determine fee-based tokens. -Since each custom token `id` is the hash of the token creation transaction that created it, we can assume the enum values below can be assigned to the `token_info_version` byte in the token creation tx and then we can retrieve it. +Since each custom token `id` is the hash of the token creation transaction that created it, we can assume the enum values below can be assigned to the `token_info_version` byte in the token creation tx and then we can retrieve it. We'll discuss token creation in nano contracts in a later section. -So, by adding a TokenInfoVersion enum we have: -- DEPOSIT = 1 (as is) -- FEE = 2 +So, by adding a TokenVersion enum we have: + +- `NATIVE = 0` (internal) +- `DEPOSIT = 1` (current implementation) +- `FEE = 2` (new) Then, we must allow the versions above in the `deserialize_token_info` method by checking the enum values. -## Transaction token_dict -From the section above, we know how to differentiate between deposit and fee tokens. Based on that, we need to add the input and output data to the current `token_dict` in order to calculate the outputs and check for melting operations without outputs. +#### Fee Header + +To correctly validate a transaction, we need to know the version of the tokens we're transacting with (which wasn't necessary before) and which token and what amount of that token the user wants to pay the fee with. -## Fee (fee.py) -This new file is responsible for keeping the fee logic, but not for orchestrating it; this will be done in the transaction verifier. +The fee header comes to resolve the explicit intention of how the transaction wants to pay the fee. + +For example: + +``` +Transaction with fee-based tokens: +input: [1.00 dbt, 100.00 fbt] +tokens: [dbt, fbt] +fee_header: + fees: [(0.01, 1)] ← index of the deposit token +``` -The `should_charge_fee` method will check if the transaction has any fee-based input or output and if the `FEE_FEATURE_FLAG` is enabled. +### Transaction Class -The `calculate_fee` method will receive a `token_dict` as input, then count the fee-based non-authority outputs and apply a constant value `FEE_OUTPUT_VALUE` to each, returning the total fee in HTR. +Inside the transaction class we can obtain a dictionary `token_dict: dict[TokenUid, TokenInfo]` which is generated by the `get_complete_token_info()` method. This method iterates over the inputs and the outputs consolidating the amount, and checking the authorities of each token. + +To obtain the expected result, we'll consider fees as outputs. + +``` +inputs: [1_000 FBT, 1_00 DBT] +outputs: [1_000 FBT] +tokens: [DBT, FBT] +fee_header: + fees: [(1_00 DBT)] +``` + +In this case we'll have the following equation: + +``` +sum(inputs) = sum(outputs) +(1000 - 1000)FBT = (100 - 100)DBT +0 = 0 ← Valid +``` -It will consider 1 output for melting operations that don't have any output. -It won't consider mint and melt authorities. +#### Calculate Fee Method -The `collect_fee` method will receive the `token_dict` and the fee. It will use the differences between the input and output amounts and return the paid fee in HTR. For each token that has a difference, it will collect the fee by incrementing the amount value in the corresponding `token_dict` entry. +This method will be called during block confirmation after nano execution, as a guarantee that we'll have access to all tokens and their respective versions, both in tx_storage and in nc_block_storage. It will be used to confirm if the fee that the transaction specified is correct; otherwise, the transaction will be rejected. -## Transaction verifier +By creating `TokenInfoDict` class, that extends `dict[TokenUid, TokenInfo]`, we add two counters: `chargeable_outputs` and `chargeable_spent_outputs`. Since the previous token_dict iterates over the outputs as said before, incrementing the counters here saves resources by avoiding the need to retrieve the information elsewhere. -### verify_fee() -Inside the transaction verifier, the `verify_fee` method will be added. It's responsible for orchestrating the fee flow by checking if the fee should be charged, calculating it, and checking the payment availability: +With the counters in hand we just need to add a method to calculate the fee. Below is the method implementation proposal: -Example: ```python -if not should_charge_fee(token_dict): - return +def calculate_fee(self, settings: 'HathorSettings') -> int: + fee = 0 + + if self.chargeable_spent_outputs > 0 and self.chargeable_outputs == 0: + fee += settings.FEE_PER_OUTPUT + + fee += self.chargeable_outputs * settings.FEE_PER_OUTPUT + + return fee +``` + +As mentioned in the [fee cost](#fee-cost) section: + +> "For melting operations that don't contain any outputs, we'll count them as 1 output in the fee calculation." + +### Transaction Verifier + +#### verify_sum Method + +Previously, only token creation transactions could create tokens and these had only one version, so it wasn't necessary to search for the token creation transaction that created that token to validate its version. + +The problem arises when we need to query the token version to validate fee payment. With the advent of nano contracts, we don't depend only on the UTXO universe and token creation transactions, but also on the nano universe. + +Tokens in nano contracts have deterministic IDs and can be passed to contracts and transactions normally; however, we don't know their true versions until the end of their execution in the block. + +The `verify_sum` is executed during the verification phase. In the verification phase, we cannot guarantee which block is correct for querying the nc_block_storage. -fee = calculate_fee(token_dict) -paid_fee = collect_fee(token_dict) +To resolve these issues, we'll call `verify_sum` in two different phases: one during the verification phase and another after nano execution when the block confirms the transactions. + +##### verify_sum_without_storage Method + +This method will be executed during the verification phase and will rely on the `token_dict` already aggregated with the `fee_header`. In this step, we'll maintain behavior similar to the current `verify_sum`, analyzing what's possible between unauthorized mint/melt attempts and invalid quantities. + +##### verify_sum Method + +This method will be executed after nano execution in a block. To fully validate the transaction, we need both `tx_storage` and `nc_block_storage`. We'll receive the block ID to access the `nc_block_storage`. + +With both storages in hand, we can generate a complete `token_dict` with the versions of each token, and consequently calculate the fee using `calculate_fee`. + +In this validation, we'll check if the fee value calculated using the token versions matches those provided by the transaction. If equal, the validation passes; otherwise, we reject the transaction. -if fee - paid_fee > 0: - raise InputOutputMismatch( - 'HTR or deposit tokens are not enough to pay the fee. (amount={}, expected={})'.format( - paid_fee, - fee, - )) ``` +sum(fee_header) = calculated_fee +``` + +As mentioned in the guide-level explanation: -### verify_sum() +> Fee payments will be accepted as long as their total is exactly equal to the required fee. Any other case will be rejected. -Since we already normalized the `token_dict` values in the `verify_fee` method before calling this one, we just need to adjust the withdraw and deposit amounts here, collecting only for deposit tokens. +##### Examples -## Feature flag in settings -For development purposes, this feature will be feature-flagged to run only on the local network by setting the `FEE_FEATURE_FLAG` in settings to true. +Tokens: Deposit-Based Token (DBT), and Fee-Based Token (FBT). + +**Example 1: Transferring a fee token and paying with HTR** + +``` +inputs: [ + 0.02 HTR, + 1000.00 FBT +] +outputs: [ + 0.01 HTR, + 1000.00 FBT, +] +tokens: [HTR, DBT, FBT] ← HTR(0), DBT(1), FBT(2) +fee_header: + fees: [ + (0.01, 0) ← HTR + ] +``` + +**Verifications:** +- sum(fee_header): 0.01 HTR +- calculated_fee: 0.01 HTR + +**Example 2: Transferring a fee token and paying with deposit token and HTR** + +``` +inputs: [ + 0.01 HTR, + 1.00 DBT, + 1000.00 FBT +] +outputs: [ + 500.00 FBT, + 500.00 FBT, +] +tokens: [HTR, DBT, FBT] ← HTR(0), DBT(1), FBT(2) +fee_header: + fees: [ + (0.01, 0), ← HTR + (1.00, 1), ← DBT + ] +``` + +**Verifications:** +- sum(fee_header): 0.02 HTR +- calculated_fee: 0.02 HTR + +### Feature Flag in Settings + +For development purposes, this feature will be feature-flagged to run only on the local network by setting the `ENABLE_FEE_TOKENS` in settings to true. + +### Feature Activation -## Feature activation For production, we'll rely on feature activation to release this feature. -## Transaction fee resource -Add an endpoint to calculate fees based on the inputs and outputs, in order to expose the logic used in the transaction verifiers to the wallets. +### Transaction Resource + +We should provide a field with the transaction fee and the token version in the detailed response. -# Drawbacks +## Drawbacks A drawback would be an increase in CPU consumption because the verification algorithm will be more complicated, but it seems to be a minor drawback. -# Prior art +## Prior Art -### How Bitcoin deals with fee +### How Bitcoin Deals with Fees -Bitcoin handles transaction fees through a system based on competition for limited block space. Each transaction has a weight measured in vBytes, and users set their fees by offering satoshis per vByte, which influences the confirmation speed. During periods of high demand, fees increase due to competition, while in lower traffic periods, they decrease. +Bitcoin handles transaction fees through a system based on competition for limited block space. Each transaction has a weight measured in vBytes, and users set their fees by offering satoshis per vByte, which influences the confirmation speed. During periods of high demand, fees increase due to competition, while in lower traffic periods, they decrease. Wallets and services use fee estimators to suggest optimal fees based on the mempool. The protocol does not enforce a minimum fee, but nodes can set a "relay fee" to prevent spam from very low-value transactions. -### How Ethereum deals with fee +### How Ethereum Deals with Fees -Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. +Ethereum handles transaction fees through the concept of Gas, where each operation consumes a specific amount of computational resources. Before EIP-1559, users set the Gas Price, and those who paid more had priority. With EIP-1559, a dynamically adjusted Base Fee was introduced based on demand, along with an optional Priority Tip to incentivize validators. The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes to validators. This model improves fee predictability, making costs more stable and transparent for users. # Business unresolved questions + - ~~Should we allow deposit-based tokens to collect fees?~~ - ~~Should we burn or move it to a burn address?~~ - ~~How will the fee be calculated?~~ - ~~Should we only consider the outputs in the fee calculation?~~ # Unresolved questions + [unresolved-questions]: #unresolved-questions -- How should melt operations be handled for fee-based custom tokens? -- ~~How will fee adjustments be governed?~~ -- By removing the transaction fee from mining, how will it affect the tx-mining-service? +- ~~How should melt operations be handled for fee-based custom tokens? +- ~~How will fee adjustments be governed? +- How transactions without a deeper verification will behave in the long term, since we are splitting the verify_sum in two steps? -# Future possibilities +## Future Possibilities [future-possibilities]: #future-possibilities -- Custom Fee Markets (letting users optimize fees). +- Custom Fee Markets (letting users optimize fees) -# References +## References - https://github.com/HathorNetwork/rfcs/blob/master/text/0011-token-deposit.md - https://github.com/HathorNetwork/rfcs/blob/master/text/0004-tokens.md @@ -182,3 +526,5 @@ The Base Fee is burned, reducing the Ether supply, while the Priority Tip goes t - https://eips.ethereum.org/EIPS/eip-1559 - https://ethereum.org/en/developers/docs/gas/ - https://developer.bitcoin.org/devguide/transactions.html#transaction-fees-and-change +- https://beta-test.docs.hathor.network/explanations/features/nano-contracts/ +- https://beta-test.docs.hathor.network/explanations/features/nano-contracts/how-it-works/ \ No newline at end of file