package cdp import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/kava-labs/kava/x/cdp/keeper" "github.com/kava-labs/kava/x/cdp/types" ) // InitGenesis sets initial genesis state for cdp module func InitGenesis(ctx sdk.Context, k keeper.Keeper, pk types.PricefeedKeeper, ak types.AccountKeeper, gs types.GenesisState) { if err := gs.Validate(); err != nil { panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) } // check if the module accounts exists cdpModuleAcc := ak.GetModuleAccount(ctx, types.ModuleName) if cdpModuleAcc == nil { panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) } liqModuleAcc := ak.GetModuleAccount(ctx, types.LiquidatorMacc) if liqModuleAcc == nil { panic(fmt.Sprintf("%s module account has not been set", types.LiquidatorMacc)) } // validate denoms - check that any collaterals in the params are in the pricefeed, // pricefeed MUST call InitGenesis before cdp collateralMap := make(map[string]int) ap := pk.GetParams(ctx) for _, a := range ap.Markets { collateralMap[a.MarketID] = 1 } for _, col := range gs.Params.CollateralParams { _, found := collateralMap[col.SpotMarketID] if !found { panic(fmt.Sprintf("%s collateral market %v not found in pricefeed", col.Denom, col.SpotMarketID)) } // sets the status of the pricefeed in the store // if pricefeed not active, debt operations are paused _ = k.UpdatePricefeedStatus(ctx, col.SpotMarketID) _, found = collateralMap[col.LiquidationMarketID] if !found { panic(fmt.Sprintf("%s collateral market %v not found in pricefeed", col.Denom, col.LiquidationMarketID)) } // sets the status of the pricefeed in the store // if pricefeed not active, debt operations are paused _ = k.UpdatePricefeedStatus(ctx, col.LiquidationMarketID) } k.SetParams(ctx, gs.Params) for _, gat := range gs.PreviousAccumulationTimes { k.SetInterestFactor(ctx, gat.CollateralType, gat.InterestFactor) if gat.PreviousAccumulationTime.Unix() > 0 { k.SetPreviousAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) } } for _, gtp := range gs.TotalPrincipals { k.SetTotalPrincipal(ctx, gtp.CollateralType, types.DefaultStableDenom, gtp.TotalPrincipal) } // add cdps for _, cdp := range gs.CDPs { if cdp.ID == gs.StartingCdpID { panic(fmt.Sprintf("starting cdp id is assigned to an existing cdp: %v", cdp)) } err := k.SetCDP(ctx, cdp) if err != nil { panic(fmt.Sprintf("error setting cdp: %v", err)) } k.IndexCdpByOwner(ctx, cdp) ratio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal()) k.IndexCdpByCollateralRatio(ctx, cdp.Type, cdp.ID, ratio) } k.SetNextCdpID(ctx, gs.StartingCdpID) k.SetDebtDenom(ctx, gs.DebtDenom) k.SetGovDenom(ctx, gs.GovDenom) for _, d := range gs.Deposits { k.SetDeposit(ctx, d) } } // ExportGenesis export genesis state for cdp module func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { params := k.GetParams(ctx) cdps := types.CDPs{} deposits := types.Deposits{} k.IterateAllCdps(ctx, func(cdp types.CDP) (stop bool) { syncedCdp := k.SynchronizeInterest(ctx, cdp) cdps = append(cdps, syncedCdp) k.IterateDeposits(ctx, cdp.ID, func(deposit types.Deposit) (stop bool) { deposits = append(deposits, deposit) return false }) return false }) cdpID := k.GetNextCdpID(ctx) debtDenom := k.GetDebtDenom(ctx) govDenom := k.GetGovDenom(ctx) var previousAccumTimes types.GenesisAccumulationTimes var totalPrincipals types.GenesisTotalPrincipals for _, cp := range params.CollateralParams { interestFactor, found := k.GetInterestFactor(ctx, cp.Type) if !found { interestFactor = sdk.OneDec() } // Governance param changes happen in the end blocker. If a new collateral type is added and then the chain // is exported before the BeginBlocker can run, previous accrual time won't be found. We can't set it to // current block time because it is not available in the export ctx. We should panic instead of exporting // bad state. previousAccumTime, f := k.GetPreviousAccrualTime(ctx, cp.Type) if !f { panic(fmt.Sprintf("expected previous accrual time to be set in state for %s", cp.Type)) } previousAccumTimes = append(previousAccumTimes, types.NewGenesisAccumulationTime(cp.Type, previousAccumTime, interestFactor)) tp := k.GetTotalPrincipal(ctx, cp.Type, types.DefaultStableDenom) genTotalPrincipal := types.NewGenesisTotalPrincipal(cp.Type, tp) totalPrincipals = append(totalPrincipals, genTotalPrincipal) } return types.NewGenesisState(params, cdps, deposits, cdpID, debtDenom, govDenom, previousAccumTimes, totalPrincipals) }