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

docs: create UPGRADING guide (backport #92) #95

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
81 changes: 81 additions & 0 deletions INTEGRATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Gas Price Queries for Integrations

Because `x/feemarket` uses a dynamic fee, end-users will need to query the module for the current `gasPrice` to use when building a transaction.

A summary for the flow to query this information is as follows:

* Create an RPC connection with the chain
* Create a `feemarket` client
* Submit the `GasPrice` query
* Use the `gasPrice` to populate the Tx fee field.

Extensive querying information can be seen in the module [spec](./README.md#query).

The specific query for `GasPrices` can be found [here](./README.md#gas-prices).

## Code Snippet

Wallet, relayers, and other users will want to add programmatic ways to query this before building their transactions. Below is an example of how a user could implement this lightweight query in Go:

### Create A gRPC Connection

First, a base connection to the chain you are querying must be created.

A chain gRPC (below) or CometBFT ABCI RPC connection can be created:

```go
// Set up gRPC connection to chain
cc, err := grpc.NewClient(endpoint, insecure.NewCredentials())
if err != nil {
panic(err)
}
defer cc.Close()
```

### Create a FeeMarket Query Client

An `x/feemarket` query client can then be created using the created gRPC connection.

This client exposes all [queries](./README.md#query) that the `x/feemarket` module exposes.

```go
// Create FeeMarketClient with underlying gRPC connection
feeMarketClient := feemarkettypes.NewQueryClient(cc)
```

### Query Gas Prices

The `gas price` (as an `sdk.DecCoin`) can be queried using the `GasPrice` query. This query requires the desired coin denomination for the fee to be paid with.

The query will return an error if the given denomination is not supported.

```go
gasPrice, err := feeMarketClient.GasPrice(ctx, &feemarkettypes.GasPriceRequest{
Denom: denom,
})
if err != nil {
panic(err)
}
```

### Using `gasPrice` to construct a transaction

There are two ways to construct a transaction with `gasPrice`:

1. Provide the minimum fee: `feeAmount = gasPrice * gasLimit` (`gasLimit` gives the maximum amount of gas a transaction can consume. You can obtain appropriate `gasLimit` by simulating a transaction to see how much gas it consumes under normal conditions).
2. Provide a "tip" in addition to the minimum fee: `feeAmount=gasPrice * gasLimit + tip` This will be paid to the block proposer and result in your transaction being placed ahead of others with lower tips (or being included in the block instead of others when the block is full)

### Understanding Fee Deducted

The actual amount of fee deducted from the fee payer is based on gas consumed, not `gasLimit`.

The amount consumed is equal to the `inferredTip + gasPrice * gasConsumed`, where `inferredTip = feeAmount - gasLimit * gasPrice` (This may be different than the tip you specified when building the transaction because the `gasPrice` on chain may have changed since when you queried it.)

## Examples of Other EIP-1559 Integrations

The [Osmosis](https://github.com/osmosis-labs/osmosis) Blockchain has a similar EIP-1559 feemarket that has been integrated by wallets and relayers. Below are some examples as to how different projects query the dynamic fee for transactions:

* [Keplr Wallet EIP-1559 BaseFee Query](https://github.com/chainapsis/keplr-wallet/blob/b0a96c2c713d8163ce840fcd5abbac4eb612607c/packages/stores/src/query/osmosis/base-fee/index.ts#L18)
* [Cosmos-Relayer EIP-1559 BaseFee Query](https://github.com/cosmos/relayer/blob/9b140b664fe6b10161af1093ccd26627b942742e/relayer/chains/cosmos/fee_market.go#L13)
* [Hermes Relayer EIP-1559 Fee Query](https://github.com/informalsystems/hermes/blob/fc8376ba98e4b595e446b366b736a0c046d6026a/crates/relayer/src/chain/cosmos/eip_base_fee.rs#L15)
* Note: Hermes also already implements a query `x/feemarket` seen [here](https://github.com/informalsystems/hermes/blob/fc8376ba98e4b595e446b366b736a0c046d6026a/crates/relayer/src/chain/cosmos/eip_base_fee.rs#L33)
116 changes: 84 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ This document specifies the feemarket module.
The feemarket module is an implementation of the Additive Increase Multiplicative Decrease (AIMD) EIP-1559
feemarket. More information about the implementation can be found [here](./x/feemarket/README.md).

This module is planned to be used in the Cosmos Hub.
## Upgrading to FeeMarket

## Status
More information about upgrading your chain to `x/feemarket` can be found in our dedicated [guide](./UPGRADING.md).

The team has not yet completed acceptance testing of the feemarket. We do not recommend integrating it until final testing has been completed (expected May 2024), and we have removed this warning from the readme.
## Important Considerations for End-Users

Wallets, relayers and other end-users should refer to our [guide](./INTEGRATIONS.md) for using dynamic fees for transaction submission.

## Contents

* [State](#state)
* [BaseFee](#basefee)
* [GasPrice](#gas-price)
* [LearningRate](#learningrate)
* [Window](#window)
* [Index](#index)
Expand Down Expand Up @@ -56,10 +58,10 @@ aforementioned state:

* State: `0x02 |ProtocolBuffer(State)`

### BaseFee
### GasPrice

BaseFee is the current base fee. This is denominated in the fee per gas
unit.
GasPrice is the current gas price. This is denominated in the fee per gas
unit in the base fee denom.

### LearningRate

Expand All @@ -80,9 +82,9 @@ Index is the index of the current block in the block utilization window.
// the current base fee, learning rate, and block utilization within the
// specified AIMD window.
message State {
// BaseFee is the current base fee. This is denominated in the fee per gas
// BaseGasPrice is the current base fee. This is denominated in the fee per gas
// unit.
string base_fee = 1 [
string base_gas_price = 1 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
Expand Down Expand Up @@ -123,8 +125,11 @@ type FeeMarketKeeper interface {
// Set the params in the store.
SetParams(ctx sdk.Context, params types.Params) error

// Get the current minimum gas prices (base fee) from the store.
GetMinGasPrices(ctx sdk.Context) (sdk.Coins, error)
// Get the minimum gas price for a given denom from the store.
GetMinGasPrice(ctx sdk.Context, denom string) (sdk.DecCoin, error) {

// Get the current minimum gas prices from the store.
GetMinGasPrices(ctx sdk.Context) (sdk.DecCoins, error)
}
```

Expand All @@ -150,7 +155,6 @@ The message handling can fail if:

* signer is not the gov module account address.


## Events

The feemarket module emits the following events:
Expand Down Expand Up @@ -232,10 +236,10 @@ 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.

### MinBaseFee
### MinBaseGasPrice

MinBaseFee determines the initial base fee of the module and the global
minimum for the network. This is denominated in fee per gas unit.
MinBaseGasPrice determines the initial gas price of the module and the global
minimum for the network. This is denominated in fee per gas unit in the `FeeDenom`.

### MinLearningRate

Expand Down Expand Up @@ -300,7 +304,7 @@ message Params {
(gogoproto.nullable) = false
];

// Delta is the amount we additively increase/decrease the base fee when the
// Delta is the amount we additively increase/decrease the gas price when the
// net block utilization difference in the window is above/below the target
// utilization.
string delta = 4 [
Expand All @@ -309,10 +313,10 @@ message Params {
(gogoproto.nullable) = false
];

// MinBaseFee determines the initial base fee of the module and the global
// MinBaseGasPrice determines the initial gas price of the module and the global
// minimum
// for the network. This is denominated in fee per gas unit.
string min_base_fee = 5 [
string MinBaseGasPrice = 5 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
Expand Down Expand Up @@ -386,7 +390,7 @@ alpha: "0.000000000000000000"
beta: "1.000000000000000000"
delta: "0.000000000000000000"
enabled: true
fee_denom: stake
fee_denom: skip
max_block_utilization: "30000000"
max_learning_rate: "0.125000000000000000"
min_base_fee: "1.000000000000000000"
Expand Down Expand Up @@ -420,24 +424,44 @@ window:
- "0"
```

##### base-fee
##### gas-price

The `gas-price` command allows users to query the current gas-price for a given denom.

```shell
feemarketd query feemarket gas-price [denom ][flags]
```

Example:

```shell
feemarketd query feemarket gas-price skip
```

Example Output:

```yml
1000000skip
```

##### gas-prices

The `base-fee` command allows users to query the current base-fee.
The `gas-prices` command allows users to query the current gas-price for all supported denoms.

```shell
feemarketd query feemarket base-fee [flags]
feemarketd query feemarket gas-prices [flags]
```

Example:

```shell
feemarketd query feemarket base-fee
feemarketd query feemarket gas-prices
```

Example Output:

```yml
1000000stake
1000000stake,100000skip
```

## gRPC
Expand Down Expand Up @@ -475,7 +499,7 @@ Example Output:
"targetBlockUtilization": "15000000",
"maxBlockUtilization": "30000000",
"window": "1",
"feeDenom": "stake",
"feeDenom": "skip",
"enabled": true
}
}
Expand All @@ -502,7 +526,7 @@ Example Output:
```json
{
"state": {
"baseFee": "1000000",
"baseGasPrice": "1000000",
"learningRate": "125000000000000000",
"window": [
"0"
Expand All @@ -511,29 +535,57 @@ Example Output:
}
```

### BaseFee
### GasPrice

The `GasPrice` endpoint allows users to query the current on-chain gas price for a given denom.

```shell
feemarket.feemarket.v1.Query/GasPrice
```

Example:

```shell
grpcurl -plaintext \
-d '{"denom": "skip"}' \
localhost:9090 \
feemarket.feemarket.v1.Query/GasPrice/
```

Example Output:

```json
{
"price": {
"denom": "skip",
"amount": "1000000"
}
}
```

### GasPrices

The `BaseFee` endpoint allows users to query the current on-chain base-fee.
The `GasPrices` endpoint allows users to query the current on-chain gas prices for all denoms.

```shell
feemarket.feemarket.v1.Query/BaseFee
feemarket.feemarket.v1.Query/GasPrices
```

Example:

```shell
grpcurl -plaintext \
localhost:9090 \
feemarket.feemarket.v1.Query/BaseFee
feemarket.feemarket.v1.Query/GasPrices
```

Example Output:

```json
{
"fees": [
"prices": [
{
"denom": "stake",
"denom": "skip",
"amount": "1000000"
}
]
Expand Down
38 changes: 38 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Upgrading Your Chain to Use FeeMarket

## Code Changes

To integrate your chain with `x/feemarket`, the following steps should be performed:

### Add the Module to Your App

* The `FeeMarketKeeper` must be added to your application as seen [here](https://github.com/skip-mev/feemarket/blob/0f83e172c92a02db45f83bf89065fd9543967729/tests/app/app.go#L163).
* A `DenomResolver` (if desired) must be set in your application as seen [here](https://github.com/skip-mev/feemarket/blob/0f83e172c92a02db45f83bf89065fd9543967729/tests/app/app.go#L509).
* `Ante` and `Post` handlers must be configured and set with the application `FeeMarketKeeper` as seen [here](https://github.com/skip-mev/feemarket/blob/0f83e172c92a02db45f83bf89065fd9543967729/tests/app/app.go#L513).

### Determine Parameters

We provide sensible default parameters for running either the [EIP-1559](https://github.com/skip-mev/feemarket/blob/0f83e172c92a02db45f83bf89065fd9543967729/x/feemarket/types/eip1559.go#L56) or [AIMD EIP-1559](https://github.com/skip-mev/feemarket/blob/0f83e172c92a02db45f83bf89065fd9543967729/x/feemarket/types/eip1559_aimd.go#L65) feemarkets.

> **Note**
>
> The default parameters use the default Cosmos SDK bond denomination. The should be modified to your chain's fee denomination.

## Changes for End-Users

With the addition of `x/feemarket`, there are some important changes that end-users must be aware of.

1. A non-zero fee is _always required_ for all transactions.
1. Pre-`x/feemarket` validators were able to set their `MinGasPrice` field locally, meaning it was possibly for some to have no required fees. This is no longer true as there is always a non-zero global fee for transactions.
2. Fees are no longer static.
1. The `gas price` will change with market activity, so to ensure that transactions will be included, wallets, relayers, etc. will need to query `x/feemarket` for the current fee state. See the [Querying Gas Price](#querying-gas-price-) section below.
3. Fees _must_ always be a single coin denomination.
1. Example `--fees skip` is valid while `--fees 10stake,10skip` is invalid

> **Note**
>
> Fees are still paid using the `fees` [field](https://github.com/cosmos/cosmos-sdk/blob/d1aab15790570bff77aa0b8652288a276205efb0/proto/cosmos/tx/v1beta1/tx.proto#L214) of a Cosmos SDK Transaction as they were before.

### Querying Gas Price

Information on how to query and use dynamic gas prices can be found [here](./INTEGRATIONS.md).
2 changes: 1 addition & 1 deletion proto/feemarket/feemarket/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ message Params {
(gogoproto.nullable) = false
];

// Delta is the amount we additively increase/decrease the base fee when the
// Delta is the amount we additively increase/decrease the gas price when the
// net block utilization difference in the window is above/below the target
// utilization.
string delta = 4 [
Expand Down
6 changes: 2 additions & 4 deletions x/feemarket/types/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ var (
// on Ethereum. This denominated in units of gas consumed in a block.
DefaultMaxBlockUtilization uint64 = 30_000_000

// DefaultMinBaseGasPrice is the default minimum base fee. This is the default
// on Ethereum. Note that Ethereum is denominated in 1e18 wei. Cosmos chains will
// likely want to change this to 1e6.
DefaultMinBaseGasPrice = math.LegacyMustNewDecFromStr("1")
// DefaultMinBaseGasPrice is the default minimum base fee.
DefaultMinBaseGasPrice = math.LegacyOneDec()

// DefaultMinLearningRate is not used in the base EIP-1559 implementation.
DefaultMinLearningRate = math.LegacyMustNewDecFromStr("0.125")
Expand Down
Loading
Loading