ACP-103: Dynamic Fees
Details for Avalanche Community Proposal 103: Dynamic Fees
ACP | 103 |
---|---|
Title | Add Dynamic Fees to the P-Chain |
Author(s) | Dhruba Basu (@dhrubabasu), Alberto Benegiamo (@abi87), Stephen Buttolph (@StephenButtolph) |
Status | Activated (Discussion) |
Track | Standards |
Abstract
Introduce a dynamic fee mechanism to the P-Chain. Preview a future transition to a multidimensional fee mechanism.
Motivation
Blockchains are resource-constrained environments. Users are charged for the execution and inclusion of their transactions based on the blockchain's transaction fee mechanism. The mechanism should fluctuate based on the supply of and demand for said resources to serve as a deterrent against spam and denial-of-service attacks.
With a fixed fee mechanism, users are provided with simplicity and predictability but network congestion and resource constraints are not taken into account. There is no incentive for users to withhold transactions since the cost is fixed regardless of the demand. The fee does not adjust the execution and inclusion fee of transactions to the market clearing price.
The C-Chain, in Apricot Phase 3, employs a dynamic fee mechanism to raise the price during periods of high demand and lowering the price during periods of low demand. As the price gets too expensive, network utilization will decrease, which drops the price. This ensures the execution and inclusion fee of transactions closely matches the market clearing price.
The P-Chain currently operates under a fixed fee mechanism. To more robustly handle spikes in load expected from introducing the improvements in ACP-77, it should be migrated to a dynamic fee mechanism.
The X-Chain also currently operates under a fixed fee mechanism. However, due to the current lower usage and lack of new feature introduction, the migration of the X-Chain to a dynamic fee mechanism is deferred to a later ACP to reduce unnecessary additional technical complexity.
Specification
Dimensions
There are four dimensions that will be used to approximate the computational cost of, or "gas" consumed in, a transaction:
- Bandwidth is the amount of network bandwidth used for transaction broadcast. This is set to the size of the transaction in bytes.
- Reads is the number of state/database reads used in transaction execution.
- Writes is the number of state/database writes used in transaction execution.
- Compute is the total amount of compute used to verify and execute a transaction, measured in microseconds.
The gas consumed in a transaction is:
A future ACP could remove the merging of these dimensions to granularly meter usage of each resource in a multidimensional scheme.
Mechanism
This mechanism aims to maintain a target gas consumption per second and adjusts the fee based on the excess gas consumption , defined as the difference between the current gas consumption and .
Prior to the activation of this mechanism, is initialized:
At the start of building/executing block , is updated:
Where is the number of seconds between 's block timestamp and 's parent's block timestamp.
The gas price for block is:
Where:
-
is the minimum gas price
-
is an approximation of following the EIP-4844 specification
-
is a constant to control the rate of change of the gas price
After processing block , is updated with the total gas consumed in the block :
Whenever increases by , the gas price increases by a factor of ~2.7
. If the gas price gets too expensive, average gas consumption drops, and starts decreasing, dropping the price. The gas price constantly adjusts to make sure that, on average, the blockchain consumes gas per second.
A token bucket is employed to meter the maximum rate of gas consumption. Define as the capacity of the bucket, as the amount of gas to add to the bucket per second, and as the amount of gas currently in the bucket.
Prior to the activation of this mechanism, is initialized:
At the beginning of processing block , is set:
Where is the number of seconds between 's block timestamp and 's parent's block timestamp. The maximum gas consumed in a given is . The upper bound across all is .
After processing block , the total gas consumed in , or , will be known. If , is considered an invalid block. If is a valid block, is updated:
A block gas limit does not need to be set as it is implicitly derived from .
The parameters at activation are:
Parameter | P-Chain Configuration |
---|---|
- target gas consumed per second | 50,000 |
- minimum gas price | 1 nAVAX |
- gas price update constant | 2_164_043 |
- maximum gas capacity | 1,000,000 |
- gas capacity added per second | 100,000 |
was chosen such that at sustained maximum capacity ( gas/second), the fee rate will double every ~30 seconds.
As the network gains capacity to handle additional load, this algorithm can be tuned to increase the gas consumption rate.
A note on
There is a subtle reason why an exponential adjustment function was chosen: The adjustment function should be equally reactive irrespective of the actual fee.
Define as the current block's gas fee, as the next block's gas fee, and as the excess gas consumption.
Let's use a linear adjustment function:
Assume and the current block is 1 unit above target utilization, or . Then, , an increase of 10%
. If instead , , an increase of 0.1%
. The fee is less reactive as the fee increases. This is because the rate of change does not scale with .
Now, let's use an exponential adjustment function:
Assume and the current block is 1 unit above target utilization, or . Then, , an increase of 171%
. If instead , , an increase of 171%
again. The fee is equally reactive as the fee increases. This is because the rate of change scales with .
Block Building Procedure
When a transaction is constructed on the P-Chain, the amount of AVAX outputs) - sum(AVAX burned by the amount of gas consumed yields the maximum gas price that the transaction can pay.
Instead of using a FIFO queue for the mempool (like the P-Chain does now), the mempool should use a priority queue ordered by the maximum gas price of each transaction. This ensures that higher paying transactions are included first.
Backwards Compatibility
Modification of a fee mechanism is an execution change and requires a mandatory upgrade for activation. Implementers must take care to not alter the execution behavior prior to activation.
After this ACP is activated, any transaction issued on the P-Chain must account for the fee mechanism defined above. Users are responsible for reconstructing their transactions to include a larger fee for quicker inclusion when the fee increases.
Reference Implementation
ACP-103 was implemented into AvalancheGo behind the Etna
upgrade flag. The full body of work can be found tagged with the acp103
label here.
Security Considerations
The current fixed fee mechanism on the X-Chain and P-Chain does not robustly handle spikes in load. Migrating the P-Chain to a dynamic fee mechanism will ensure that any additional load caused by demand for new P-Chain features (such as those introduced in ACP-77) is properly priced given allotted processing capacity. The X-Chain, in comparison, currently has significantly lower usage, making it less likely for the demand for blockspace on it to exceed the current static fee rates. If necessary or desired, a future ACP can reuse the mechanism introduced here to add dynamic fee rates to the X-Chain.
Acknowledgements
Thank you to @aaronbuchwald and @patrick-ogrady for providing feedback prior to publication.
Thank you to the authors of EIP-4844 for creating the fee design that inspired the above mechanism.
Copyright
Copyright and related rights waived via CC0.
Is this guide helpful?