-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement support for Osmosis EIP-1559
Add support for querying the dynamic gas price base fee on Osmosis.
- Loading branch information
Showing
6 changed files
with
213 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package cosmos | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
|
||
sdkmath "cosmossdk.io/math" | ||
"go.uber.org/zap" | ||
) | ||
|
||
const queryPath = "/osmosis.txfees.v1beta1.Query/GetEipBaseFee" | ||
|
||
// DynamicFee queries the dynamic gas price base fee and returns a string with the base fee and token denom concatenated. | ||
// If the chain does not have dynamic fees enabled in the config, nothing happens and an empty string is always returned. | ||
func (cc *CosmosProvider) DynamicFee(ctx context.Context) string { | ||
if !cc.PCfg.DynamicGasPrice { | ||
return "" | ||
} | ||
|
||
dynamicFee, err := cc.QueryBaseFee(ctx) | ||
if err != nil { | ||
// If there was an error querying the dynamic base fee, do nothing and fall back to configured gas price. | ||
cc.log.Warn("Failed to query the dynamic gas price base fee", zap.Error(err)) | ||
return "" | ||
} | ||
|
||
return dynamicFee | ||
} | ||
|
||
// QueryBaseFee attempts to make an ABCI query to retrieve the base fee on chains using the Osmosis EIP-1559 implementation. | ||
// This is currently hardcoded to only work on Osmosis. | ||
func (cc *CosmosProvider) QueryBaseFee(ctx context.Context) (string, error) { | ||
resp, err := cc.RPCClient.ABCIQuery(ctx, queryPath, nil) | ||
if err != nil || resp.Response.Code != 0 { | ||
return "", err | ||
} | ||
|
||
// The response value contains the data link escape control character which must be removed before parsing. | ||
cleanedString := strings.ReplaceAll(strings.TrimSpace(string(resp.Response.Value)), "\u0010", "") | ||
|
||
decFee, err := sdkmath.LegacyNewDecFromStr(cleanedString) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
baseFee, err := decFee.Float64() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// The current EIP-1559 implementation returns an integer and does not return any value that tells us how many | ||
// decimal places we need to account for. | ||
// | ||
// This may be problematic because we are assuming that we always need to move the decimal 18 places. | ||
fee := baseFee / 1e18 | ||
|
||
denom, err := parseTokenDenom(cc.PCfg.GasPrices) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return fmt.Sprintf("%f%s", fee, denom), nil | ||
} | ||
|
||
// parseTokenDenom takes a string in the format numericGasPrice + tokenDenom (e.g. 0.0025uosmo), | ||
// and parses the tokenDenom portion (e.g. uosmo) before returning just the token denom. | ||
func parseTokenDenom(gasPrice string) (string, error) { | ||
regex := regexp.MustCompile(`^0\.\d+([a-zA-Z]+)$`) | ||
|
||
matches := regex.FindStringSubmatch(gasPrice) | ||
|
||
if len(matches) != 2 { | ||
return "", fmt.Errorf("failed to parse token denom from string %s", gasPrice) | ||
} | ||
|
||
return matches[1], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package cosmos | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var ( | ||
coinType = 118 | ||
|
||
testCfg = CosmosProviderConfig{ | ||
KeyDirectory: "", | ||
Key: "default", | ||
ChainName: "osmosis", | ||
ChainID: "osmosis-1", | ||
RPCAddr: "https://rpc.osmosis.strange.love:443", | ||
AccountPrefix: "osmo", | ||
KeyringBackend: "test", | ||
DynamicGasPrice: true, | ||
GasAdjustment: 1.2, | ||
GasPrices: "0.0025uosmo", | ||
MinGasAmount: 1, | ||
MaxGasAmount: 0, | ||
Debug: false, | ||
Timeout: "30s", | ||
BlockTimeout: "30s", | ||
OutputFormat: "json", | ||
SignModeStr: "direct", | ||
ExtraCodecs: nil, | ||
Modules: nil, | ||
Slip44: &coinType, | ||
SigningAlgorithm: "", | ||
Broadcast: "batch", | ||
MinLoopDuration: 0, | ||
ExtensionOptions: nil, | ||
FeeGrants: nil, | ||
} | ||
) | ||
|
||
func TestQueryBaseFee(t *testing.T) { | ||
p, err := testCfg.NewProvider(nil, t.TempDir(), true, testCfg.ChainName) | ||
require.NoError(t, err) | ||
|
||
ctx := context.Background() | ||
err = p.Init(ctx) | ||
require.NoError(t, err) | ||
|
||
cp := p.(*CosmosProvider) | ||
|
||
baseFee, err := cp.QueryBaseFee(ctx) | ||
require.NoError(t, err) | ||
require.NotEqual(t, "", baseFee) | ||
} | ||
|
||
func TestParseDenom(t *testing.T) { | ||
denom, err := parseTokenDenom(testCfg.GasPrices) | ||
require.NoError(t, err) | ||
require.Equal(t, "uosmo", denom) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters