diff --git a/x/incentive/keeper/querier.go b/x/incentive/keeper/querier.go index 197ddd49..f94352ee 100644 --- a/x/incentive/keeper/querier.go +++ b/x/incentive/keeper/querier.go @@ -493,7 +493,10 @@ func GetAPYFromMultiRewardPeriod( // Get USD value of collateral type collateralUSDValue, err := k.pricefeedKeeper.GetCurrentPrice(ctx, getMarketID(collateralType)) if err != nil { - return sdk.ZeroDec(), err + return sdk.ZeroDec(), fmt.Errorf( + "failed to get price for incentive collateralType %s with market ID %s: %w", + collateralType, getMarketID(collateralType), err, + ) } // Total USD value of the collateral type total supply @@ -524,9 +527,22 @@ func GetAPYFromMultiRewardPeriod( } func getMarketID(denom string) string { - if denom == types.BondDenom { - // Rewrite "ukava" to "kava" as pricefeed only has "kava" and not "ukava" - return getMarketID("kava") + // Rewrite denoms as pricefeed has different names for some assets, + // e.g. "ukava" -> "kava", "erc20/multichain/usdc" -> "usdc" + // bkava is not included as it is handled separately + + // TODO: Replace hardcoded conversion with possible params set somewhere + // to be more flexible. E.g. a map of denoms to pricefeed market denoms in + // pricefeed params. + switch denom { + case types.BondDenom: + denom = "kava" + case "erc20/multichain/usdc": + denom = "usdc" + case "erc20/multichain/usdt": + denom = "usdt" + case "erc20/multichain/dai": + denom = "dai" } return fmt.Sprintf("%s:usd:30", denom) diff --git a/x/incentive/keeper/querier_test.go b/x/incentive/keeper/querier_test.go index a37725aa..2076fbff 100644 --- a/x/incentive/keeper/querier_test.go +++ b/x/incentive/keeper/querier_test.go @@ -30,6 +30,13 @@ func (suite *QuerierTestSuite) TestGetStakingAPR() { liquidStakedTokens := int64(60_000_000_000000) totalSupply := int64(289_138_414_286684) + usdcDenom := "erc20/multichain/usdc" + usdcSupply := int64(2_500_000_000000) + + earnKeeper := newFakeEarnKeeper(). + addVault("bkava-asdf", earntypes.NewVaultShare("bkava-asdf", sdk.NewDec(liquidStakedTokens))). + addVault(usdcDenom, earntypes.NewVaultShare(usdcDenom, sdk.NewDec(usdcSupply))) + suite.keeper = suite.NewTestKeeper(&fakeParamSubspace{}). WithDistrKeeper( newFakeDistrKeeper().setCommunityTax(communityTax), @@ -44,20 +51,14 @@ func (suite *QuerierTestSuite) TestGetStakingAPR() { WithBankKeeper( newFakeBankKeeper().setSupply(sdk.NewCoin(types.BondDenom, sdk.NewInt(totalSupply))), ). - WithEarnKeeper( - newFakeEarnKeeper(). - addVault("bkava-asdf", earntypes.NewVaultShare("bkava-asdf", sdk.NewDec(liquidStakedTokens))), - ). + WithEarnKeeper(earnKeeper). WithLiquidKeeper( newFakeLiquidKeeper().addDerivative(suite.ctx, "bkava-asdf", sdk.NewInt(liquidStakedTokens)), ). WithPricefeedKeeper( newFakePricefeedKeeper(). - setPrice( - pricefeedtypes.NewCurrentPrice( - "kava:usd:30", - sdk.MustNewDecFromStr("1.5"), - )), + setPrice(pricefeedtypes.NewCurrentPrice("kava:usd:30", sdk.MustNewDecFromStr("1.5"))). + setPrice(pricefeedtypes.NewCurrentPrice("usdc:usd:30", sdk.OneDec())), ). Build() @@ -87,16 +88,47 @@ func (suite *QuerierTestSuite) TestGetStakingAPR() { sdk.NewCoin("ukava", sdk.NewInt(190258)), ), }, + { + Active: true, + CollateralType: "erc20/multichain/usdc", + Start: suite.ctx.BlockTime().Add(-time.Hour), + End: suite.ctx.BlockTime().Add(time.Hour), + RewardsPerSecond: sdk.NewCoins( + sdk.NewCoin("ukava", sdk.NewInt(5284)), + ), + }, }, } - aprWithIncentives, err := keeper.GetStakingAPR(suite.ctx, suite.keeper, params) - suite.Require().NoError(err) - // Approx 10% increase in APR from incentives - suite.Require().Equal(sdk.MustNewDecFromStr("0.280711113729177500"), aprWithIncentives) + suite.Run("GetStakingAPR", func() { + aprWithIncentives, err := keeper.GetStakingAPR(suite.ctx, suite.keeper, params) + suite.Require().NoError(err) + // Approx 10% increase in APR from incentives + suite.Require().Equal(sdk.MustNewDecFromStr("0.280711113729177500"), aprWithIncentives) - suite.Require().Truef( - aprWithIncentives.GT(aprWithoutIncentives), - "APR with incentives (%s) should be greater than APR without incentives (%s)", - ) + suite.Require().Truef( + aprWithIncentives.GT(aprWithoutIncentives), + "APR with incentives (%s) should be greater than APR without incentives (%s)", + ) + }) + + suite.Run("GetAPYFromMultiRewardPeriod", func() { + vaultTotalValue, err := earnKeeper.GetVaultTotalValue(suite.ctx, usdcDenom) + suite.Require().NoError(err) + suite.Require().True(vaultTotalValue.Amount.IsPositive()) + + apy, err := keeper.GetAPYFromMultiRewardPeriod( + suite.ctx, + suite.keeper, + usdcDenom, + params.EarnRewardPeriods[1], + vaultTotalValue.Amount, + ) + suite.Require().NoError(err) + suite.Require().Equal( + sdk.MustNewDecFromStr("0.099981734400000000"), + apy, + "usdc apy should be approx 10%", + ) + }) }