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

fix(gamm): SpotPrice keeper function #3715

Merged
merged 13 commits into from
Dec 16, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Bug fixes

* [#3608](https://github.com/osmosis-labs/osmosis/pull/3608) Make it possible to state export from any directory.
* [#3715](https://github.com/osmosis-labs/osmosis/pull/3715) Fix x/gamm CalculateSpotPrice, balancer.SpotPrice and Stableswap.SpotPrice base and quote asset.

### Misc Improvements

Expand Down
2 changes: 1 addition & 1 deletion app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ func (s *KeeperTestHelper) SwapAndSetSpotPrice(poolId uint64, fromAsset sdk.Coin
)
s.Require().NoError(err)

spotPrice, err := s.App.GAMMKeeper.CalculateSpotPrice(s.Ctx, poolId, toAsset.Denom, fromAsset.Denom)
spotPrice, err := s.App.GAMMKeeper.CalculateSpotPrice(s.Ctx, poolId, fromAsset.Denom, toAsset.Denom)
s.Require().NoError(err)

return spotPrice
Expand Down
6 changes: 3 additions & 3 deletions wasmbinding/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ func (qp QueryPlugin) GetSpotPrice(ctx sdk.Context, spotPrice *bindings.SpotPric
}

poolId := spotPrice.Swap.PoolId
denomIn := spotPrice.Swap.DenomIn
denomOut := spotPrice.Swap.DenomOut
baseAsset := spotPrice.Swap.DenomOut
quoteAsset := spotPrice.Swap.DenomIn
withSwapFee := spotPrice.WithSwapFee

price, err := qp.gammKeeper.CalculateSpotPrice(ctx, poolId, denomIn, denomOut)
price, err := qp.gammKeeper.CalculateSpotPrice(ctx, poolId, quoteAsset, baseAsset)
if err != nil {
return nil, sdkerrors.Wrap(err, "gamm get spot price")
}
Expand Down
2 changes: 2 additions & 0 deletions x/gamm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ func (q Querier) SpotPrice(ctx context.Context, req *types.QuerySpotPriceRequest

sdkCtx := sdk.UnwrapSDKContext(ctx)

// Note: the base and quote asset are provided as argument incorrectly intentionally.
// due to the historic bug in the original implementation.
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
sp, err := q.Keeper.CalculateSpotPrice(sdkCtx, req.PoolId, req.BaseAssetDenom, req.QuoteAssetDenom)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
Expand Down
4 changes: 2 additions & 2 deletions x/gamm/keeper/pool_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
func (k Keeper) CalculateSpotPrice(
ctx sdk.Context,
poolID uint64,
baseAssetDenom string,
quoteAssetDenom string,
baseAssetDenom string,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the order is changed to avoid twap migrations

) (spotPrice sdk.Dec, err error) {
pool, err := k.GetPoolAndPoke(ctx, poolID)
if err != nil {
Expand All @@ -40,7 +40,7 @@ func (k Keeper) CalculateSpotPrice(
}
}()

spotPrice, err = pool.SpotPrice(ctx, baseAssetDenom, quoteAssetDenom)
spotPrice, err = pool.SpotPrice(ctx, quoteAssetDenom, baseAssetDenom)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: technically, pools could keep the existing parameter order and just get fixed on the implementation level. However, I think it is useful to keep the order consistent with the keeper. As a result, I changed the denom order for pools as well

if err != nil {
return sdk.Dec{}, err
}
Expand Down
6 changes: 3 additions & 3 deletions x/gamm/keeper/pool_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ func (suite *KeeperTestSuite) TestSpotPriceOverflow() {
poolLiquidity: sdk.NewCoins(sdk.NewCoin(denomA, types.MaxSpotPrice.TruncateInt().Add(sdk.OneInt())),
sdk.NewCoin(denomB, sdk.OneInt())),
poolWeights: []int64{1, 1},
quoteAssetDenom: denomB,
baseAssetDenom: denomA,
quoteAssetDenom: denomA,
baseAssetDenom: denomB,
overflows: true,
},
"uniV2 internal error": {
Expand All @@ -363,7 +363,7 @@ func (suite *KeeperTestSuite) TestSpotPriceOverflow() {
osmoassert.ConditionalPanic(suite.T(), tc.panics, func() {
poolSpotPrice, poolErr = pool.SpotPrice(suite.Ctx, tc.baseAssetDenom, tc.quoteAssetDenom)
})
keeperSpotPrice, keeperErr := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, poolId, tc.baseAssetDenom, tc.quoteAssetDenom)
keeperSpotPrice, keeperErr := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, poolId, tc.quoteAssetDenom, tc.baseAssetDenom)
if tc.overflows {
suite.Require().NoError(poolErr)
suite.Require().ErrorIs(keeperErr, types.ErrSpotPriceOverflow)
Expand Down
20 changes: 12 additions & 8 deletions x/gamm/pool-models/balancer/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,24 +611,28 @@ func (p *Pool) applySwap(ctx sdk.Context, tokensIn sdk.Coins, tokensOut sdk.Coin

// SpotPrice returns the spot price of the pool
// This is the weight-adjusted balance of the tokens in the pool.
// In order reduce the propagated effect of incorrect trailing digits,
// To reduce the propagated effect of incorrect trailing digits,
// we take the ratio of weights and divide this by ratio of supplies
// this is equivalent to spot_price = (Base_supply / Weight_base) / (Quote_supply / Weight_quote)
// but cancels out the common term in weight.
// this is equivalent to spot_price = (Quote Supply / Quote Weight) / (Base Supply / Base Weight)
//
// As an example, assume equal weights. uosmo supply of 2 and uatom supply of 4.
//
// Case 1: base = uosmo, quote = uatom -> for one uosmo, get 2 uatom = 4 / 2 = 2
//
// Case 2: base = uatom, quote = uosmo -> for one uatom, get 0.5 uosmo = 2 / 4 = 0.5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same thing, but I find it easier to read "it costs 0.5 uosmo to get one uatom" and "it costs "2 uatom to get 1 osmo".

I think this is because the word "quote" implies to me that it is the price/cost of the base asset denominated in quote asset. So, what you're "getting" is the base asset.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, I added your interpretation in comments as well

//
// panics if the pool in state is incorrect, and has any weight that is 0.
// TODO: Come back and improve docs for this.
func (p Pool) SpotPrice(ctx sdk.Context, baseAsset, quoteAsset string) (spotPrice sdk.Dec, err error) {
quote, base, err := p.parsePoolAssetsByDenoms(quoteAsset, baseAsset)
func (p Pool) SpotPrice(ctx sdk.Context, quoteAsset, baseAsset string) (spotPrice sdk.Dec, err error) {
quote, base, err := p.parsePoolAssetsByDenoms(baseAsset, quoteAsset)
if err != nil {
return sdk.Dec{}, err
}
if base.Weight.IsZero() || quote.Weight.IsZero() {
return sdk.Dec{}, errors.New("pool is misconfigured, got 0 weight")
}

// spot_price = (Base_supply / Weight_base) / (Quote_supply / Weight_quote)
// spot_price = (weight_quote / weight_base) * (base_supply / quote_supply)
// spot_price = (Quote Supply / Quote Weight) / (Base Supply / Base Weight)
// spot_price = (Quote Weight / Base Weight) * (Quote Supply / Base Supply)
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
invWeightRatio := quote.Weight.ToDec().Quo(base.Weight.ToDec())
supplyRatio := base.Token.Amount.ToDec().Quo(quote.Token.Amount.ToDec())
spotPrice = supplyRatio.Mul(invWeightRatio)
Expand Down
46 changes: 23 additions & 23 deletions x/gamm/pool-models/balancer/pool_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,57 +713,57 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() {

tests := []struct {
name string
baseDenomPoolInput sdk.Coin
baseDenomWeight sdk.Int
quoteDenomPoolInput sdk.Coin
quoteDenomWeight sdk.Int
baseDenomPoolInput sdk.Coin
baseDenomWeight sdk.Int
expectError bool
expectedOutput sdk.Dec
}{
{
name: "spot price check at max bitlen supply",
// 2^196, as >= 2^197 trips max bitlen of 256
baseDenomPoolInput: sdk.NewCoin(baseDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206336").TruncateInt()),
baseDenomWeight: sdk.NewInt(100),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206337").TruncateInt()),
quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206336").TruncateInt()),
quoteDenomWeight: sdk.NewInt(100),
baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206337").TruncateInt()),
baseDenomWeight: sdk.NewInt(100),
expectError: false,
expectedOutput: sdk.MustNewDecFromStr("1.000000000000000000"),
},
{
name: "spot price check at min supply",
baseDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()),
baseDenomWeight: sdk.NewInt(100),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()),
quoteDenomWeight: sdk.NewInt(100),
baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
baseDenomWeight: sdk.NewInt(100),
expectError: false,
expectedOutput: sdk.MustNewDecFromStr("1.000000000000000000"),
},
{
name: "max spot price with equal weights",
baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()),
baseDenomWeight: sdk.NewInt(100),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()),
quoteDenomWeight: sdk.NewInt(100),
baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
baseDenomWeight: sdk.NewInt(100),
expectError: false,
expectedOutput: types.MaxSpotPrice,
},
{
// test int overflows
name: "max spot price with extreme weights",
baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()),
baseDenomWeight: sdk.OneInt(),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
quoteDenomWeight: sdk.NewInt(1 << 19),
quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()),
quoteDenomWeight: sdk.OneInt(),
baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
baseDenomWeight: sdk.NewInt(1 << 19),
expectError: true,
},
{
name: "greater than max spot price with equal weights",
// Max spot price capped at 2^160
baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt().Add(sdk.OneInt())),
baseDenomWeight: sdk.NewInt(100),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt().Add(sdk.OneInt())),
quoteDenomWeight: sdk.NewInt(100),
baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()),
baseDenomWeight: sdk.NewInt(100),
expectError: true,
},
}
Expand All @@ -773,13 +773,13 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() {
suite.Run(tc.name, func() {
// pool assets
defaultBaseAsset := balancer.PoolAsset{
Weight: tc.baseDenomWeight,
Token: tc.baseDenomPoolInput,
}
defaultQuoteAsset := balancer.PoolAsset{
Weight: tc.quoteDenomWeight,
Token: tc.quoteDenomPoolInput,
}
defaultQuoteAsset := balancer.PoolAsset{
Weight: tc.baseDenomWeight,
Token: tc.baseDenomPoolInput,
}

poolAssets := []balancer.PoolAsset{defaultBaseAsset, defaultQuoteAsset}
poolId := suite.PrepareBalancerPoolWithPoolAsset(poolAssets)
Expand All @@ -790,7 +790,7 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() {

sut := func() {
spotPrice, err := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx,
poolId, tc.baseDenomPoolInput.Denom, tc.quoteDenomPoolInput.Denom)
poolId, tc.quoteDenomPoolInput.Denom, tc.baseDenomPoolInput.Denom)
if tc.expectError {
suite.Require().Error(err, "test: %s", tc.name)
} else {
Expand Down
5 changes: 2 additions & 3 deletions x/gamm/pool-models/stableswap/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func solveCFMMBinarySearchMulti(xReserve, yReserve, wSumSquares, yIn osmomath.Bi
return xOut
}

func (p Pool) spotPrice(baseDenom, quoteDenom string) (spotPrice sdk.Dec, err error) {
func (p Pool) spotPrice(quoteDenom, baseDenom string) (spotPrice sdk.Dec, err error) {
// Define f_{y -> x}(a) as the function that outputs the amount of tokens X you'd get by
// trading "a" units of Y against the pool, assuming 0 swap fee, at the current liquidity.
// The spot price of the pool is then lim a -> 0, f_{y -> x}(a) / a
Expand All @@ -373,8 +373,7 @@ func (p Pool) spotPrice(baseDenom, quoteDenom string) (spotPrice sdk.Dec, err er
// xReserve & yReserve.
a := sdk.OneInt()

// We swap quoteDenom and baseDenom intentionally, due to the odd issue needed for balancer v1 query compat
res, err := p.calcOutAmtGivenIn(sdk.NewCoin(quoteDenom, a), baseDenom, sdk.ZeroDec())
res, err := p.calcOutAmtGivenIn(sdk.NewCoin(baseDenom, a), quoteDenom, sdk.ZeroDec())
// fmt.Println("spot price res", res)
return res, err
}
Expand Down
4 changes: 2 additions & 2 deletions x/gamm/pool-models/stableswap/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ func (p *Pool) SwapInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coins, tokenInDen

// SpotPrice calculates the approximate amount of `baseDenom` one would receive for
// an input dx of `quoteDenom` (to simplify calculations, we approximate dx = 1)
func (p Pool) SpotPrice(ctx sdk.Context, baseAssetDenom string, quoteAssetDenom string) (sdk.Dec, error) {
return p.spotPrice(baseAssetDenom, quoteAssetDenom)
func (p Pool) SpotPrice(ctx sdk.Context, quoteAssetDenom string, baseAssetDenom string) (sdk.Dec, error) {
return p.spotPrice(quoteAssetDenom, baseAssetDenom)
}

func (p Pool) Copy() Pool {
Expand Down
11 changes: 6 additions & 5 deletions x/gamm/pool-models/stableswap/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/tendermint/tendermint/crypto/ed25519"

"github.com/osmosis-labs/osmosis/v13/app/apptesting/osmoassert"
"github.com/osmosis-labs/osmosis/v13/osmomath"
"github.com/osmosis-labs/osmosis/v13/x/gamm/pool-models/internal/cfmm_common"
"github.com/osmosis-labs/osmosis/v13/x/gamm/types"
"github.com/tendermint/tendermint/crypto/ed25519"
)

var (
Expand Down Expand Up @@ -1217,15 +1218,15 @@ func TestStableswapSpotPrice(t *testing.T) {
quoteDenom: "bar",
poolAssets: twoUnevenStablePoolAssets,
scalingFactors: []uint64{10000, 20000},
expectedPrice: sdk.NewDec(2),
expectedPrice: sdk.NewDecWithPrec(5, 1),
expectPass: true,
},
"even two-asset pool with different scaling factors (bar -> foo)": {
baseDenom: "bar",
quoteDenom: "foo",
poolAssets: twoUnevenStablePoolAssets,
scalingFactors: []uint64{10000, 20000},
expectedPrice: sdk.NewDecWithPrec(5, 1),
expectedPrice: sdk.NewDec(2),
expectPass: true,
},
"uneven two-asset pool": {
Expand Down Expand Up @@ -1328,7 +1329,7 @@ func TestStableswapSpotPrice(t *testing.T) {
t.Run(name, func(t *testing.T) {
ctx := sdk.Context{}
p := poolStructFromAssets(tc.poolAssets, tc.scalingFactors)
spotPrice, err := p.SpotPrice(ctx, tc.baseDenom, tc.quoteDenom)
spotPrice, err := p.SpotPrice(ctx, tc.quoteDenom, tc.baseDenom)

if tc.expectPass {
require.NoError(t, err)
Expand All @@ -1337,7 +1338,7 @@ func TestStableswapSpotPrice(t *testing.T) {
if (tc.expectedPrice != sdk.Dec{}) {
expectedSpotPrice = tc.expectedPrice
} else {
expectedSpotPrice, err = p.calcOutAmtGivenIn(sdk.NewInt64Coin(tc.quoteDenom, 1), tc.baseDenom, sdk.ZeroDec())
expectedSpotPrice, err = p.calcOutAmtGivenIn(sdk.NewInt64Coin(tc.baseDenom, 1), tc.quoteDenom, sdk.ZeroDec())
require.NoError(t, err)
}

Expand Down
2 changes: 1 addition & 1 deletion x/swaprouter/types/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ type PoolI interface {
// errors if either baseAssetDenom, or quoteAssetDenom does not exist.
// For example, if this was a UniV2 50-50 pool, with 2 ETH, and 8000 UST
// pool.SpotPrice(ctx, "eth", "ust") = 4000.00
SpotPrice(ctx sdk.Context, baseAssetDenom string, quoteAssetDenom string) (sdk.Dec, error)
SpotPrice(ctx sdk.Context, quoteAssetDenom string, baseAssetDenom string) (sdk.Dec, error)
}
2 changes: 2 additions & 0 deletions x/twap/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ func getSpotPrices(
previousErrorTime time.Time,
) (sp0 sdk.Dec, sp1 sdk.Dec, latestErrTime time.Time) {
latestErrTime = previousErrorTime
// sp0 = denom0 base, denom1 quote.
sp0, err0 := k.CalculateSpotPrice(ctx, poolId, denom0, denom1)
// sp1 = denom0 quote, denom1 base.
sp1, err1 := k.CalculateSpotPrice(ctx, poolId, denom1, denom0)
if err0 != nil || err1 != nil {
latestErrTime = ctx.BlockTime()
Expand Down
2 changes: 1 addition & 1 deletion x/twap/types/expected_interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type AmmInterface interface {
CalculateSpotPrice(
ctx sdk.Context,
poolID uint64,
baseAssetDenom string,
quoteAssetDenom string,
baseAssetDenom string,
) (price sdk.Dec, err error)
}
8 changes: 4 additions & 4 deletions x/twap/types/twapmock/amminterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (p *ProgrammedAmmInterface) ProgramPoolDenomsOverride(poolId uint64, overri
}

func (p *ProgrammedAmmInterface) ProgramPoolSpotPriceOverride(poolId uint64,
baseDenom, quoteDenom string, overrideSp sdk.Dec, overrideErr error,
quoteDenom, baseDenom string, overrideSp sdk.Dec, overrideErr error,
) {
input := SpotPriceInput{poolId, baseDenom, quoteDenom}
p.programmedSpotPrice[input] = SpotPriceResult{overrideSp, overrideErr}
Expand All @@ -71,12 +71,12 @@ func (p *ProgrammedAmmInterface) GetPoolDenoms(ctx sdk.Context, poolId uint64) (

func (p *ProgrammedAmmInterface) CalculateSpotPrice(ctx sdk.Context,
poolId uint64,
baseDenom,
quoteDenom string,
quoteDenom,
baseDenom string,
) (price sdk.Dec, err error) {
input := SpotPriceInput{poolId, baseDenom, quoteDenom}
if res, ok := p.programmedSpotPrice[input]; ok {
return res.Sp, res.Err
}
return p.underlyingKeeper.CalculateSpotPrice(ctx, poolId, baseDenom, quoteDenom)
return p.underlyingKeeper.CalculateSpotPrice(ctx, poolId, quoteDenom, baseDenom)
}
1 change: 1 addition & 0 deletions x/txfees/keeper/feetokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"github.com/gogo/protobuf/proto"

"github.com/osmosis-labs/osmosis/v13/x/txfees/types"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down
6 changes: 4 additions & 2 deletions x/txfees/keeper/feetokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ func (suite *KeeperTestSuite) TestFeeTokenConversions() {
baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100),
feeTokenPoolInput: sdk.NewInt64Coin("foo", 200),
inputFee: sdk.NewInt64Coin("foo", 10),
// expected to get 5.000000000005368710 baseDenom without rounding
// expected to get approximately 5 base denom
// foo supply / stake supply = 200 / 100 = 2 foo for 1 stake
// 10 foo in / 2 foo for 1 stake = 5 base denom
expectedOutput: sdk.NewInt64Coin(baseDenom, 5),
expectedConvertable: true,
},
Expand Down Expand Up @@ -215,7 +217,7 @@ func (suite *KeeperTestSuite) TestFeeTokenConversions() {
converted, err := suite.App.TxFeesKeeper.ConvertToBaseToken(suite.Ctx, tc.inputFee)
if tc.expectedConvertable {
suite.Require().NoError(err, "test: %s", tc.name)
suite.Require().True(converted.IsEqual(tc.expectedOutput), "test: %s", tc.name)
suite.Require().Equal(tc.expectedOutput, converted)
} else {
suite.Require().Error(err, "test: %s", tc.name)
}
Expand Down
2 changes: 1 addition & 1 deletion x/txfees/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
// SpotPriceCalculator defines the contract that must be fulfilled by a spot price calculator
// The x/gamm keeper is expected to satisfy this interface.
type SpotPriceCalculator interface {
CalculateSpotPrice(ctx sdk.Context, poolId uint64, tokenInDenom, tokenOutDenom string) (sdk.Dec, error)
CalculateSpotPrice(ctx sdk.Context, poolId uint64, quoteDenom, baseDenom string) (sdk.Dec, error)
}

// GammKeeper defines the contract needed for AccountKeeper related APIs.
Expand Down