[R4R] fix: validate usdx minting collaterals in incentive genesis (#770)

* fix: validate that usdx incentive collateral types are found in cdp params

* update app initialization and tests
This commit is contained in:
Kevin Davis 2021-01-19 22:42:50 -07:00 committed by GitHub
parent c63ecf908a
commit 67b58f555b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 228 additions and 6 deletions

View File

@ -418,7 +418,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptio
pricefeed.NewAppModule(app.pricefeedKeeper, app.accountKeeper), pricefeed.NewAppModule(app.pricefeedKeeper, app.accountKeeper),
bep3.NewAppModule(app.bep3Keeper, app.accountKeeper, app.supplyKeeper), bep3.NewAppModule(app.bep3Keeper, app.accountKeeper, app.supplyKeeper),
kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper), kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper),
incentive.NewAppModule(app.incentiveKeeper, app.accountKeeper, app.supplyKeeper), incentive.NewAppModule(app.incentiveKeeper, app.accountKeeper, app.supplyKeeper, app.cdpKeeper),
committee.NewAppModule(app.committeeKeeper, app.accountKeeper), committee.NewAppModule(app.committeeKeeper, app.accountKeeper),
issuance.NewAppModule(app.issuanceKeeper, app.accountKeeper, app.supplyKeeper), issuance.NewAppModule(app.issuanceKeeper, app.accountKeeper, app.supplyKeeper),
hard.NewAppModule(app.hardKeeper, app.supplyKeeper, app.pricefeedKeeper), hard.NewAppModule(app.hardKeeper, app.supplyKeeper, app.pricefeedKeeper),
@ -471,7 +471,7 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts AppOptio
auction.NewAppModule(app.auctionKeeper, app.accountKeeper, app.supplyKeeper), auction.NewAppModule(app.auctionKeeper, app.accountKeeper, app.supplyKeeper),
bep3.NewAppModule(app.bep3Keeper, app.accountKeeper, app.supplyKeeper), bep3.NewAppModule(app.bep3Keeper, app.accountKeeper, app.supplyKeeper),
kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper), kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper),
incentive.NewAppModule(app.incentiveKeeper, app.accountKeeper, app.supplyKeeper), incentive.NewAppModule(app.incentiveKeeper, app.accountKeeper, app.supplyKeeper, app.cdpKeeper),
committee.NewAppModule(app.committeeKeeper, app.accountKeeper), committee.NewAppModule(app.committeeKeeper, app.accountKeeper),
issuance.NewAppModule(app.issuanceKeeper, app.accountKeeper, app.supplyKeeper), issuance.NewAppModule(app.issuanceKeeper, app.accountKeeper, app.supplyKeeper),
hard.NewAppModule(app.hardKeeper, app.supplyKeeper, app.pricefeedKeeper), hard.NewAppModule(app.hardKeeper, app.supplyKeeper, app.pricefeedKeeper),

View File

@ -10,7 +10,7 @@ import (
) )
// InitGenesis initializes the store state from a genesis state. // InitGenesis initializes the store state from a genesis state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeeper, gs types.GenesisState) { func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeeper, cdpKeeper types.CdpKeeper, gs types.GenesisState) {
// check if the module account exists // check if the module account exists
moduleAcc := supplyKeeper.GetModuleAccount(ctx, types.IncentiveMacc) moduleAcc := supplyKeeper.GetModuleAccount(ctx, types.IncentiveMacc)
@ -22,6 +22,13 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
} }
for _, rp := range gs.Params.RewardPeriods {
_, found := cdpKeeper.GetCollateral(ctx, rp.CollateralType)
if !found {
panic(fmt.Sprintf("usdx minting collateral type %s not found in cdp collateral types", rp.CollateralType))
}
}
k.SetParams(ctx, gs.Params) k.SetParams(ctx, gs.Params)
for _, gat := range gs.PreviousAccumulationTimes { for _, gat := range gs.PreviousAccumulationTimes {

View File

@ -51,7 +51,7 @@ func (suite *HandlerTestSuite) SetupTest() {
incentive.DefaultGenesisAccumulationTimes, incentive.DefaultGenesisAccumulationTimes,
incentive.DefaultClaims, incentive.DefaultClaims,
) )
tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}) tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti())
suite.addrs = addrs suite.addrs = addrs
suite.handler = incentive.NewHandler(keeper) suite.handler = incentive.NewHandler(keeper)

View File

@ -0,0 +1,212 @@
package incentive_test
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/cdp"
"github.com/kava-labs/kava/x/incentive"
"github.com/kava-labs/kava/x/pricefeed"
)
func NewCDPGenStateMulti() app.GenesisState {
cdpGenesis := cdp.GenesisState{
Params: cdp.Params{
GlobalDebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
SurplusAuctionThreshold: cdp.DefaultSurplusThreshold,
SurplusAuctionLot: cdp.DefaultSurplusLot,
DebtAuctionThreshold: cdp.DefaultDebtThreshold,
DebtAuctionLot: cdp.DefaultDebtLot,
CollateralParams: cdp.CollateralParams{
{
Denom: "xrp",
Type: "xrp-a",
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
LiquidationPenalty: d("0.05"),
AuctionSize: i(7000000000),
Prefix: 0x20,
SpotMarketID: "xrp:usd",
LiquidationMarketID: "xrp:usd",
ConversionFactor: i(6),
},
{
Denom: "btc",
Type: "btc-a",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
LiquidationPenalty: d("0.025"),
AuctionSize: i(10000000),
Prefix: 0x21,
SpotMarketID: "btc:usd",
LiquidationMarketID: "btc:usd",
ConversionFactor: i(8),
},
{
Denom: "bnb",
Type: "bnb-a",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
LiquidationPenalty: d("0.05"),
AuctionSize: i(50000000000),
Prefix: 0x22,
SpotMarketID: "bnb:usd",
LiquidationMarketID: "bnb:usd",
ConversionFactor: i(8),
},
{
Denom: "busd",
Type: "busd-a",
LiquidationRatio: d("1.01"),
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
StabilityFee: sdk.OneDec(), // %0 apr
LiquidationPenalty: d("0.05"),
AuctionSize: i(10000000000),
Prefix: 0x23,
SpotMarketID: "busd:usd",
LiquidationMarketID: "busd:usd",
ConversionFactor: i(8),
},
},
DebtParam: cdp.DebtParam{
Denom: "usdx",
ReferenceAsset: "usd",
ConversionFactor: i(6),
DebtFloor: i(10000000),
},
},
StartingCdpID: cdp.DefaultCdpStartingID,
DebtDenom: cdp.DefaultDebtDenom,
GovDenom: cdp.DefaultGovDenom,
CDPs: cdp.CDPs{},
PreviousAccumulationTimes: cdp.GenesisAccumulationTimes{
cdp.NewGenesisAccumulationTime("btc-a", time.Time{}, sdk.OneDec()),
cdp.NewGenesisAccumulationTime("xrp-a", time.Time{}, sdk.OneDec()),
cdp.NewGenesisAccumulationTime("busd-a", time.Time{}, sdk.OneDec()),
cdp.NewGenesisAccumulationTime("bnb-a", time.Time{}, sdk.OneDec()),
},
TotalPrincipals: cdp.GenesisTotalPrincipals{
cdp.NewGenesisTotalPrincipal("btc-a", sdk.ZeroInt()),
cdp.NewGenesisTotalPrincipal("xrp-a", sdk.ZeroInt()),
cdp.NewGenesisTotalPrincipal("busd-a", sdk.ZeroInt()),
cdp.NewGenesisTotalPrincipal("bnb-a", sdk.ZeroInt()),
},
}
return app.GenesisState{cdp.ModuleName: cdp.ModuleCdc.MustMarshalJSON(cdpGenesis)}
}
func NewPricefeedGenStateMulti() app.GenesisState {
pfGenesis := pricefeed.GenesisState{
Params: pricefeed.Params{
Markets: []pricefeed.Market{
{MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
{MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
{MarketID: "bnb:usd", BaseAsset: "bnb", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
{MarketID: "busd:usd", BaseAsset: "busd", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
},
},
PostedPrices: []pricefeed.PostedPrice{
{
MarketID: "btc:usd",
OracleAddress: sdk.AccAddress{},
Price: sdk.MustNewDecFromStr("8000.00"),
Expiry: time.Now().Add(1 * time.Hour),
},
{
MarketID: "xrp:usd",
OracleAddress: sdk.AccAddress{},
Price: sdk.MustNewDecFromStr("0.25"),
Expiry: time.Now().Add(1 * time.Hour),
},
{
MarketID: "bnb:usd",
OracleAddress: sdk.AccAddress{},
Price: sdk.MustNewDecFromStr("17.25"),
Expiry: time.Now().Add(1 * time.Hour),
},
{
MarketID: "busd:usd",
OracleAddress: sdk.AccAddress{},
Price: sdk.OneDec(),
Expiry: time.Now().Add(1 * time.Hour),
},
},
}
return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)}
}
func NewIncentiveGenState(previousAccumTime, endTime time.Time, rewardPeriods ...incentive.RewardPeriod) app.GenesisState {
var accumulationTimes incentive.GenesisAccumulationTimes
for _, rp := range rewardPeriods {
accumulationTimes = append(
accumulationTimes,
incentive.NewGenesisAccumulationTime(
rp.CollateralType,
previousAccumTime,
sdk.ZeroDec(),
),
)
}
genesis := incentive.NewGenesisState(
incentive.NewParams(
rewardPeriods,
incentive.Multipliers{
incentive.NewMultiplier(incentive.Small, 1, d("0.25")),
incentive.NewMultiplier(incentive.Large, 12, d("1.0")),
},
endTime,
),
accumulationTimes,
incentive.USDXMintingClaims{},
)
return app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(genesis)}
}
func NewCDPGenStateHighInterest() app.GenesisState {
cdpGenesis := cdp.GenesisState{
Params: cdp.Params{
GlobalDebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
SurplusAuctionThreshold: cdp.DefaultSurplusThreshold,
SurplusAuctionLot: cdp.DefaultSurplusLot,
DebtAuctionThreshold: cdp.DefaultDebtThreshold,
DebtAuctionLot: cdp.DefaultDebtLot,
CollateralParams: cdp.CollateralParams{
{
Denom: "bnb",
Type: "bnb-a",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
StabilityFee: sdk.MustNewDecFromStr("1.000000051034942716"), // 500% APR
LiquidationPenalty: d("0.05"),
AuctionSize: i(50000000000),
Prefix: 0x22,
SpotMarketID: "bnb:usd",
LiquidationMarketID: "bnb:usd",
ConversionFactor: i(8),
},
},
DebtParam: cdp.DebtParam{
Denom: "usdx",
ReferenceAsset: "usd",
ConversionFactor: i(6),
DebtFloor: i(10000000),
},
},
StartingCdpID: cdp.DefaultCdpStartingID,
DebtDenom: cdp.DefaultDebtDenom,
GovDenom: cdp.DefaultGovDenom,
CDPs: cdp.CDPs{},
PreviousAccumulationTimes: cdp.GenesisAccumulationTimes{
cdp.NewGenesisAccumulationTime("bnb-a", time.Time{}, sdk.OneDec()),
},
TotalPrincipals: cdp.GenesisTotalPrincipals{
cdp.NewGenesisTotalPrincipal("bnb-a", sdk.ZeroInt()),
},
}
return app.GenesisState{cdp.ModuleName: cdp.ModuleCdc.MustMarshalJSON(cdpGenesis)}
}

View File

@ -105,15 +105,17 @@ type AppModule struct {
keeper Keeper keeper Keeper
accountKeeper auth.AccountKeeper accountKeeper auth.AccountKeeper
supplyKeeper SupplyKeeper supplyKeeper SupplyKeeper
cdpKeeper CdpKeeper
} }
// NewAppModule creates a new AppModule object // NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, accountKeeper auth.AccountKeeper, supplyKeeper SupplyKeeper) AppModule { func NewAppModule(keeper Keeper, accountKeeper auth.AccountKeeper, supplyKeeper SupplyKeeper, cdpKeeper CdpKeeper) AppModule {
return AppModule{ return AppModule{
AppModuleBasic: AppModuleBasic{}, AppModuleBasic: AppModuleBasic{},
keeper: keeper, keeper: keeper,
accountKeeper: accountKeeper, accountKeeper: accountKeeper,
supplyKeeper: supplyKeeper, supplyKeeper: supplyKeeper,
cdpKeeper: cdpKeeper,
} }
} }
@ -149,7 +151,7 @@ func (am AppModule) NewQuerierHandler() sdk.Querier {
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var gs types.GenesisState var gs types.GenesisState
types.ModuleCdc.MustUnmarshalJSON(data, &gs) types.ModuleCdc.MustUnmarshalJSON(data, &gs)
InitGenesis(ctx, am.keeper, am.supplyKeeper, gs) InitGenesis(ctx, am.keeper, am.supplyKeeper, am.cdpKeeper, gs)
return []abci.ValidatorUpdate{} return []abci.ValidatorUpdate{}
} }

View File

@ -20,6 +20,7 @@ type CdpKeeper interface {
GetTotalPrincipal(ctx sdk.Context, collateralType string, principalDenom string) (total sdk.Int) GetTotalPrincipal(ctx sdk.Context, collateralType string, principalDenom string) (total sdk.Int)
GetCdpByOwnerAndCollateralType(ctx sdk.Context, owner sdk.AccAddress, collateralType string) (cdptypes.CDP, bool) GetCdpByOwnerAndCollateralType(ctx sdk.Context, owner sdk.AccAddress, collateralType string) (cdptypes.CDP, bool)
GetInterestFactor(ctx sdk.Context, collateralType string) (sdk.Dec, bool) GetInterestFactor(ctx sdk.Context, collateralType string) (sdk.Dec, bool)
GetCollateral(ctx sdk.Context, collateralType string) (cdptypes.CollateralParam, bool)
} }
// AccountKeeper defines the expected keeper interface for interacting with account // AccountKeeper defines the expected keeper interface for interacting with account