Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(EIP-1559): Initializing proto, adding readme, and basic construction #11

Merged
merged 37 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
36af853
add interface
aljo242 Nov 9, 2023
f0fa6b1
mock
aljo242 Nov 9, 2023
7523e45
Merge branch 'main' into aljo242/feemarket-interface
aljo242 Nov 9, 2023
dbc62d6
md
aljo242 Nov 9, 2023
2bb20f7
md
aljo242 Nov 9, 2023
f0a006c
md
aljo242 Nov 9, 2023
c84c9a7
lint fix
aljo242 Nov 9, 2023
0ba663d
module
aljo242 Nov 9, 2023
ff86779
add proto
aljo242 Nov 9, 2023
7c5d658
fmt
aljo242 Nov 9, 2023
7ce863c
move files
aljo242 Nov 9, 2023
bc076d3
Merge branch 'aljo242/feemarket-interface' into aljo242/feemarket-proto
aljo242 Nov 9, 2023
096c238
proto-cute
aljo242 Nov 9, 2023
ee0b83f
nit fix
aljo242 Nov 9, 2023
d8d4c4a
Merge branch 'aljo242/feemarket-interface' into aljo242/feemarket-proto
aljo242 Nov 9, 2023
589c493
params
aljo242 Nov 9, 2023
b86573f
Merge branch 'main' into aljo242/feemarket-proto
aljo242 Nov 9, 2023
b876bd5
init
aljo242 Nov 9, 2023
58f2e4b
format
aljo242 Nov 9, 2023
4356a5b
fix
aljo242 Nov 9, 2023
1742a8a
Merge branch 'aljo242/feemarket-proto' into aljo242/feemarket-types
aljo242 Nov 9, 2023
5283e38
clean
aljo242 Nov 9, 2023
fb5a1af
Update proto/feemarket/feemarket/v1/mock.proto
aljo242 Nov 9, 2023
8e007e1
Update x/feemarket/types/genesis.go
aljo242 Nov 9, 2023
73148c2
regen
aljo242 Nov 9, 2023
4d3575a
Merge branch 'main' into aljo242/feemarket-types
aljo242 Nov 9, 2023
fb601fc
fix
aljo242 Nov 9, 2023
685f72b
fix
aljo242 Nov 9, 2023
ea6e913
simplify
aljo242 Nov 9, 2023
a98397c
simplify
aljo242 Nov 9, 2023
08b16f4
simplify
aljo242 Nov 9, 2023
34d86c4
init
davidterpay Nov 10, 2023
d0f9dc3
Merge branch 'main' into terpay/eip1559-proto
davidterpay Nov 10, 2023
fd019dd
md
davidterpay Nov 10, 2023
7bb604a
Merge branch 'main' into terpay/eip1559-proto
davidterpay Nov 10, 2023
35cab07
simpler stuff
davidterpay Nov 10, 2023
2aaaaac
default eip1559 readme addition
davidterpay Nov 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"default": true,
"MD004": { "style": "asterisk" },
"MD007": { "indent": 4 },
"MD024": { "siblings_only": true },
"MD013": false,
"MD025": false,
"MD033": false,
"MD034": false,
"MD014": false,
"no-hard-tabs": false,
"whitespace": false
}

18 changes: 18 additions & 0 deletions .markdownlintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"default": true,
"MD004": {
"style": "asterisk"
},
"MD007": {
"indent": 4
},
"MD013": false,
"MD024": {
"siblings_only": true
},
"MD025": false,
"MD033": false,
"MD034": false,
"no-hard-tabs": false,
"whitespace": false
}
36 changes: 36 additions & 0 deletions proto/feemarket/eip1559/v1/aimd_eip_1559.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
syntax = "proto3";
package feemarket.eip1559.v1;

option go_package = "github.com/skip-mev/feemarket/x/feemarket/plugins/eip1559/types";

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "feemarket/eip1559/v1/params.proto";

// AIMDEIP1559 is the contains the Additive Increase Multiplicative Decrease
// (AIMD) EIP-1559 fee market parameters and state.
message AIMDEIP1559 {
option (cosmos_proto.implements_interface) =
"feemarket.feemarket.v1.FeeMarketImplementation";

// Params are the parameters of the AIMD fee market.
Params params = 1 [(gogoproto.nullable) = false];

// State is the current state of the AIMD fee market.
State state = 2 [(gogoproto.nullable) = false];
}

// State contains the current state of the AIMD fee market.
message State {
// CurrentBaseFee is the current base fee. This is denominated in the fee
// per gas unit.
string current_base_fee = 1 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];

// BlockUtilizationWindow contains a list of the last blocks' utilization
// values. This is used to calculate the next base fee.
repeated uint64 block_utilization_window = 2;
}
80 changes: 80 additions & 0 deletions proto/feemarket/eip1559/v1/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
syntax = "proto3";
package feemarket.eip1559.v1;

option go_package = "github.com/skip-mev/feemarket/x/feemarket/plugins/eip1559/types";

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";

// Params contains the required set of parameters for the EIP1559 fee market
// plugin implementation.
message Params {
// Window determines the number of previous blocks to consider when
// calculating block utilization.
uint64 window = 1;

// Alpha is the amount we additively increase the learninig rate
// when it is above or below the target +/- threshold.
string alpha = 2 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

// Beta is the amount we multiplicatively decrease the learning rate
// when it is within the target +/- threshold.
string beta = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

// Theta is the threshold for the learning rate. If the learning rate is
// above or below the target +/- threshold, we additively increase the
// learning rate by Alpha. Otherwise, we multiplicatively decrease the
// learning rate by Beta.
string theta = 4 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

// Delta is the amount we additively increase/decrease the base fee when the
// net block utilization difference in the window is above/below the target utilization.
string delta = 5 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

// TargetBlockSize is the target block utilization rate. This is denominated in
// gas units consumed.
uint64 target_block_size = 6;

// MaxBlockSize is the upper bound for the block size. This is denominated in
// gas units consumed.
uint64 max_block_size = 7;

// MinBaseFee determines the initial base fee of the module and the global minimum
// for the network. This is denominated in fee per gas unit.
string min_base_fee = 8 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];


// MinLearningRate is the lower bound for the learning rate.
string min_learning_rate = 9 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

// MaxLearningRate is the upper bound for the learning rate.
string max_learning_rate = 10 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
}
3 changes: 0 additions & 3 deletions x/feemarket/interfaces/feemarket.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ type FeeMarketImplementation interface {
// where the fees are being distributed, etc.).
GetFeeMarketInfo(ctx sdk.Context) map[string]string

// GetID returns the identifier of the fee market
GetID() string

aljo242 marked this conversation as resolved.
Show resolved Hide resolved
// ------------------- Fee Market Extraction ------------------- //

// FeeAnteHandler will be called in the module AnteHandler,
Expand Down
2 changes: 1 addition & 1 deletion x/feemarket/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ plugged into the `x/feemarket` module.

Current implementations include:

- [Mock:](mock/feemarket.go) fee market that can be used for basic testing.
* [Mock:](mock/feemarket.go) fee market that can be used for basic testing.
DO NOT use in production.
5 changes: 0 additions & 5 deletions x/feemarket/plugins/defaultmarket/feemarket.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ func (fm *DefaultMarket) GetFeeMarketInfo(_ sdk.Context) map[string]string {
return nil
}

// GetID returns the identifier of the fee market.
func (fm *DefaultMarket) GetID() string {
return "default"
}

// FeeAnteHandler will be called in the module AnteHandler.
// Performs no actions.
func (fm *DefaultMarket) FeeAnteHandler(
Expand Down
123 changes: 123 additions & 0 deletions x/feemarket/plugins/eip1559/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Additive Increase Multiplicative Decrease (AIMD) EIP-1559

## Overview

> **Definitions:**
>
> * **`Target Block Size`**: This is the target block gas consumption.
> * **`Max Block Size`**: This is the maximum block gas consumption.

This plugin implements the AIMD (Additive Increase Multiplicative Decrease) EIP-1559 fee market as described in this [AIMD EIP-1559](https://ieeexplore.ieee.org/document/9680496) research publication.

The AIMD EIP-1559 fee market is a slight modification to Ethereum's EIP-1559 fee market. Specifically it introduces the notion of a adaptive learning rate which scales the base fee (reserve price to be included in a block) more aggressively when the network is congested and less aggressively when the network is not congested. This is primarily done to address the often cited criticism of EIP-1559 that it's base fee often lags behind the current demand for block space. The learning rate on Ethereum is effectively hard-coded to be 12.5%, which means that between any two blocks the base fee can maximally increase by 12.5% or decrease by 12.5%. Additionally, AIMD EIP-1559 differs from Ethereum's EIP-1559 by considering a configured time window (number of blocks) to consider when calculating and comparing target block utilization and current block utilization.

## Parameters

### Ethereum EIP-1559

Base EIP-1559 currently utilizes the following parameters to compute the base fee:

* **`PreviousBaseFee`**: This is the base fee from the previous block. This must be a value that is greater than `0`.
* **`TargetBlockSize`**: This is the target block size in bytes. This must be a value that is greater than `0`.
* **`PreviousBlockSize`**: This is the block size from the previous block.

The calculation for the updated base fee for the next block is as follows:

```golang
currentBaseFee := previousBaseFee * (1 + 0.125 * (currentBlockSize - targetBlockSize) / targetBlockSize)
```

### AIMD EIP-1559

AIMD EIP-1559 introduces a few new parameters to the EIP-1559 fee market:

* **`Alpha`**: This is the amount we additively increase the learning rate when the target utilization is less than the current utilization i.e. the block was more full than the target size. This must be a value that is greater than `0.0`.
* **`Beta`**: This is the amount we multiplicatively decrease the learning rate when the target utilization is greater than the current utilization i.e. the block was less full than the target size. This must be a value that is greater than `0.0`.
* **`Window`**: This is the number of blocks we look back to compute the current utilization. This must be a value that is greater than `0`. Instead of only utilizing the previous block's utilization, we now consider the utilization of the previous `Window` blocks.
* **`Gamma`**: This determines whether you are additively increase or multiplicatively decreasing the learning rate based on the target and current block utilization. This must be a value that is between `[0, 1]`. For example, if `Gamma = 0.25`, then we multiplicatively decrease the learning rate if the average ratio of current block size to max block size over some window of blocks is within `(0.25, 0.75)` and additively increase it if outside that range.
* **`MaxLearningRate`**: This is the maximum learning rate that can be applied to the base fee. This must be a value that is between `[0, 1]`.
* **`MinLearningRate`**: This is the minimum learning rate that can be applied to the base fee. This must be a value that is between `[0, 1]`.
* **`Delta`**: This is a trailing constant that is used to smooth the learning rate. In order to further converge the long term net gas usage and net gas goal, we introduce another integral term which tracks how much gas off from 0 gas we’re at. We add a constant c which basically forces the fee to slowly trend in some direction until this has gone to 0.

The calculation for the updated base fee for the next block is as follows:

```golang

// sumBlockSizesInWindow returns the sum of the block sizes in the window.
blockConsumption := sumBlockSizesInWindow(window) / (window * targetBlockSize)

if blockConsumption < gamma || blockConsumption > 1 - gamma {
// MAX_LEARNING_RATE is a constant that configured by the chain developer
newLearningRate := min(MaxLearningRate, alpha + currencyLearningRate)
} else {
// MIN_LEARNING_RATE is a constant that configured by the chain developer
newLearningRate := max(MinLearningRate, beta * currencyLearningRate)
}

// netGasDelta returns the net gas difference between every block in the window and the target block size.
newBaseFee := currentBaseFee * (1 + newLearningRate * (currentBlockSize - targetBlockSize) / targetBlockSize) + delta * netGasDelta(window)
```

## Examples

> **Assume the following parameters:**
>
> * `TargetBlockSize = 50`
> * `MaxBlockSize = 100`
> * `Window = 1`
> * `Alpha = 0.025`
> * `Beta = 0.95`
> * `Gamma = 0.25`
> * `MAX_LEARNING_RATE = 1.0`
> * `MIN_LEARNING_RATE = 0.0125`
> * `Current Learning Rate = 0.125`
> * `Previous Base Fee = 10`
> * `Delta = 0`

### Block is Completely Empty

In this example, we expect the learning rate to additively increase and the base fee to decrease.

```golang
blockConsumption := sumBlockSizesInWindow(1) / (1 * 100) == 0
maxLearningRate := min(1.0, 0.025 + 0.125) == 0.15
newBaseFee := 10 * (1 + 0.15 * (0 - 50) / 50) == 8.5
```

As we can see, the base fee decreased by 1.5 and the learning rate increases.

### Block is Completely Full

In this example, we expect the learning rate to multiplicatively increase and the base fee to increase.

```golang
blockConsumption := sumBlockSizesInWindow(1) / (1 * 100) == 1
maxLearningRate := min(1.0, 0.025 + 0.125) == 0.15
newBaseFee := 10 * (1 + 0.95 * 0.125) == 11.875
```

As we can see, the base fee increased by 1.875 and the learning rate increases.

### Block is at Target Utilization

In this example, we expect the learning rate to decrease and the base fee to remain the same.

```golang
blockConsumption := sumBlockSizesInWindow(1) / (1 * 100) == 0.5
maxLearningRate := max(0.0125, 0.95 * 0.125) == 0.11875
newBaseFee := 10 * (1 + 0.11875 * (0 - 50) / 50) == 10
```

As we can see, the base fee remained the same and the learning rate decreased.

## Default EIP-1559 With AIMD EIP-1559

It is entirely possible to implement the default EIP-1559 fee market with the AIMD EIP-1559 fee market. This can be done by setting the following parameters:

* `Alpha = 0.0`
* `Beta = 1.0`
* `Gamma = 1.0`
* `MAX_LEARNING_RATE = 0.125`
* `MIN_LEARNING_RATE = 0.125`
* `Delta = 0`
* `Window = 1`
12 changes: 12 additions & 0 deletions x/feemarket/plugins/eip1559/types/aimd_eip_1559.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package types

// NewAIMDEIP1559 instantiates a new AIMD EIP-1559 object.
func NewAIMDEIP1559(
state State,
params Params,
) AIMDEIP1559 {
return AIMDEIP1559{
State: state,
Params: params,
}
}
Loading
Loading