Skip to content

Commit

Permalink
Merge branch 'main' into fix/paper
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Johnson authored Jun 3, 2024
2 parents 56444b5 + 6eee90a commit e60dd4e
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 41 deletions.
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)
119 changes: 86 additions & 33 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 @@ -55,10 +57,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 @@ -79,9 +81,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 @@ -122,8 +124,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 @@ -149,7 +154,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 @@ -231,10 +235,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 @@ -301,7 +305,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 @@ -310,9 +314,10 @@ message Params {
(gogoproto.nullable) = false
];

// MinBaseGasPrice determines the initial gas price of the module and the
// global minimum for the network.
string min_base_gas_price = 5 [
// 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 MinBaseGasPrice = 5 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
Expand Down Expand Up @@ -389,7 +394,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 @@ -423,24 +428,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 @@ -478,7 +503,7 @@ Example Output:
"targetBlockUtilization": "15000000",
"maxBlockUtilization": "30000000",
"window": "1",
"feeDenom": "stake",
"feeDenom": "skip",
"enabled": true
}
}
Expand All @@ -505,7 +530,7 @@ Example Output:
```json
{
"state": {
"baseFee": "1000000",
"baseGasPrice": "1000000",
"learningRate": "125000000000000000",
"window": [
"0"
Expand All @@ -514,29 +539,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 @@ -41,7 +41,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 @@ -31,10 +31,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

0 comments on commit e60dd4e

Please sign in to comment.