[R4R] Add cdp simulations (#422)

feat: cdp sims
Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com>
Co-authored-by: John Maheswaran <john@kava.io>
This commit is contained in:
Kevin Davis 2020-04-13 21:29:46 -04:00 committed by GitHub
parent 004837d7fc
commit 1fab788fd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 436 additions and 11 deletions

View File

@ -330,8 +330,8 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
distr.NewAppModule(app.distrKeeper, app.supplyKeeper), distr.NewAppModule(app.distrKeeper, app.supplyKeeper),
staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper), staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper),
slashing.NewAppModule(app.slashingKeeper, app.stakingKeeper), slashing.NewAppModule(app.slashingKeeper, app.stakingKeeper),
cdp.NewAppModule(app.cdpKeeper, app.pricefeedKeeper, app.supplyKeeper), // TODO how is the order be decided here? Is this order correct?
pricefeed.NewAppModule(app.pricefeedKeeper), pricefeed.NewAppModule(app.pricefeedKeeper),
cdp.NewAppModule(app.cdpKeeper, app.pricefeedKeeper, app.supplyKeeper),
auction.NewAppModule(app.auctionKeeper, app.supplyKeeper), auction.NewAppModule(app.auctionKeeper, app.supplyKeeper),
bep3.NewAppModule(app.bep3Keeper, app.supplyKeeper), bep3.NewAppModule(app.bep3Keeper, app.supplyKeeper),
kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper), kavadist.NewAppModule(app.kavadistKeeper, app.supplyKeeper),

View File

@ -37,6 +37,7 @@ import (
auctionsimops "github.com/kava-labs/kava/x/auction/simulation/operations" auctionsimops "github.com/kava-labs/kava/x/auction/simulation/operations"
bep3simops "github.com/kava-labs/kava/x/bep3/simulation/operations" bep3simops "github.com/kava-labs/kava/x/bep3/simulation/operations"
cdpsimops "github.com/kava-labs/kava/x/cdp/simulation/operations"
pricefeedsimops "github.com/kava-labs/kava/x/pricefeed/simulation/operations" pricefeedsimops "github.com/kava-labs/kava/x/pricefeed/simulation/operations"
) )
@ -63,6 +64,7 @@ const (
OpWeightMsgPlaceBid = "op_weight_msg_place_bid" OpWeightMsgPlaceBid = "op_weight_msg_place_bid"
OpWeightMsgPricefeed = "op_weight_msg_pricefeed" OpWeightMsgPricefeed = "op_weight_msg_pricefeed"
OpWeightMsgCreateAtomicSwap = "op_weight_msg_create_atomic_Swap" OpWeightMsgCreateAtomicSwap = "op_weight_msg_create_atomic_Swap"
OpWeightMsgCdp = "op_weight_msg_cdp"
) )
// TestMain runs setup and teardown code before all tests. // TestMain runs setup and teardown code before all tests.
@ -304,6 +306,17 @@ func testAndRunTxs(app *App, config simulation.Config) []simulation.WeightedOper
}(nil), }(nil),
pricefeedsimops.SimulateMsgUpdatePrices(app.pricefeedKeeper), pricefeedsimops.SimulateMsgUpdatePrices(app.pricefeedKeeper),
}, },
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(app.cdc, OpWeightMsgCdp, &v, nil,
func(_ *rand.Rand) {
v = 100 // TODO
})
return v
}(nil),
cdpsimops.SimulateMsgCdp(app.accountKeeper, app.cdpKeeper, app.pricefeedKeeper),
},
} }
} }

View File

@ -41,3 +41,5 @@ AWS Batch allows for "array jobs" which are a way of specifying many duplicates
- click on the compute environment name, to get details, then click the link ECS Cluster Name to get details on the actual machines running - click on the compute environment name, to get details, then click the link ECS Cluster Name to get details on the actual machines running
- for array jobs, click the job name to get details of the individual jobs - for array jobs, click the job name to get details of the individual jobs
## Sims - TODO

View File

@ -4,19 +4,164 @@ import (
"fmt" "fmt"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/supply"
supplyExported "github.com/cosmos/cosmos-sdk/x/supply/exported"
"github.com/kava-labs/kava/x/cdp/types" "github.com/kava-labs/kava/x/cdp/types"
) )
// RandomizedGenState generates a random GenesisState for cdp // RandomizedGenState generates a random GenesisState for cdp
func RandomizedGenState(simState *module.SimulationState) { func RandomizedGenState(simState *module.SimulationState) {
// TODO implement this fully cdpGenesis := randomCdpGenState(simState.Rand.Intn(2))
// - randomly generating the genesis params
// - overwriting with genesis provided to simulation // hacky way to give accounts coins so they can create cdps (coins includes usdx so it's possible to have sufficient balance to close a cdp)
cdpGenesis := types.DefaultGenesisState() var authGenesis auth.GenesisState
simState.Cdc.MustUnmarshalJSON(simState.GenState[auth.ModuleName], &authGenesis)
totalCdpCoins := sdk.NewCoins()
for _, acc := range authGenesis.Accounts {
_, ok := acc.(supplyExported.ModuleAccountI)
if ok {
continue
}
coinsToAdd := sdk.NewCoins(
sdk.NewCoin("bnb", sdk.NewInt(int64(simState.Rand.Intn(100000000000)))),
sdk.NewCoin("xrp", sdk.NewInt(int64(simState.Rand.Intn(100000000000)))),
sdk.NewCoin("btc", sdk.NewInt(int64(simState.Rand.Intn(500000000)))),
sdk.NewCoin("usdx", sdk.NewInt(int64(simState.Rand.Intn(1000000000)))),
)
err := acc.SetCoins(acc.GetCoins().Add(coinsToAdd))
if err != nil {
panic(err)
}
totalCdpCoins = totalCdpCoins.Add(coinsToAdd)
authGenesis.Accounts = replaceOrAppendAccount(authGenesis.Accounts, acc)
}
simState.GenState[auth.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis)
var supplyGenesis supply.GenesisState
simState.Cdc.MustUnmarshalJSON(simState.GenState[supply.ModuleName], &supplyGenesis)
supplyGenesis.Supply = supplyGenesis.Supply.Add(totalCdpCoins)
simState.GenState[supply.ModuleName] = simState.Cdc.MustMarshalJSON(supplyGenesis)
fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, cdpGenesis)) fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, cdpGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(cdpGenesis) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(cdpGenesis)
} }
// In a list of accounts, replace the first account found with the same address. If not found, append the account.
func replaceOrAppendAccount(accounts []authexported.GenesisAccount, acc authexported.GenesisAccount) []authexported.GenesisAccount {
newAccounts := accounts
for i, a := range accounts {
if a.GetAddress().Equals(acc.GetAddress()) {
newAccounts[i] = acc
return newAccounts
}
}
return append(newAccounts, acc)
}
func randomCdpGenState(selection int) types.GenesisState {
switch selection {
case 0:
return types.GenesisState{
Params: types.Params{
GlobalDebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 100000000000000)),
SurplusAuctionThreshold: types.DefaultSurplusThreshold,
DebtAuctionThreshold: types.DefaultDebtThreshold,
SavingsDistributionFrequency: types.DefaultSavingsDistributionFrequency,
CollateralParams: types.CollateralParams{
{
Denom: "xrp",
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
DebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 20000000000000)),
StabilityFee: sdk.MustNewDecFromStr("1.000000004431822130"),
LiquidationPenalty: sdk.MustNewDecFromStr("0.075"),
AuctionSize: sdk.NewInt(10000000000),
Prefix: 0x20,
MarketID: "xrp:usd",
ConversionFactor: sdk.NewInt(6),
},
{
Denom: "btc",
LiquidationRatio: sdk.MustNewDecFromStr("1.25"),
DebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 50000000000000)),
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"),
LiquidationPenalty: sdk.MustNewDecFromStr("0.05"),
AuctionSize: sdk.NewInt(50000000),
Prefix: 0x21,
MarketID: "btc:usd",
ConversionFactor: sdk.NewInt(8),
},
{
Denom: "bnb",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 30000000000000)),
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
LiquidationPenalty: sdk.MustNewDecFromStr("0.15"),
AuctionSize: sdk.NewInt(10000000000),
Prefix: 0x22,
MarketID: "bnb:usd",
ConversionFactor: sdk.NewInt(8),
},
},
DebtParams: types.DebtParams{
{
Denom: "usdx",
ReferenceAsset: "usd",
ConversionFactor: sdk.NewInt(6),
DebtFloor: sdk.NewInt(10000000),
SavingsRate: sdk.MustNewDecFromStr("0.95"),
},
},
},
StartingCdpID: types.DefaultCdpStartingID,
DebtDenom: types.DefaultDebtDenom,
GovDenom: types.DefaultGovDenom,
CDPs: types.CDPs{},
PreviousBlockTime: types.DefaultPreviousBlockTime,
PreviousDistributionTime: types.DefaultPreviousDistributionTime,
}
case 1:
return types.GenesisState{
Params: types.Params{
GlobalDebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 100000000000000)),
SurplusAuctionThreshold: types.DefaultSurplusThreshold,
DebtAuctionThreshold: types.DefaultDebtThreshold,
SavingsDistributionFrequency: types.DefaultSavingsDistributionFrequency,
CollateralParams: types.CollateralParams{
{
Denom: "bnb",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewCoins(sdk.NewInt64Coin("usdx", 100000000000000)),
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
LiquidationPenalty: sdk.MustNewDecFromStr("0.075"),
AuctionSize: sdk.NewInt(10000000000),
Prefix: 0x20,
MarketID: "bnb:usd",
ConversionFactor: sdk.NewInt(8),
},
},
DebtParams: types.DebtParams{
{
Denom: "usdx",
ReferenceAsset: "usd",
ConversionFactor: sdk.NewInt(6),
DebtFloor: sdk.NewInt(10000000),
SavingsRate: sdk.MustNewDecFromStr("0.95"),
},
},
},
StartingCdpID: types.DefaultCdpStartingID,
DebtDenom: types.DefaultDebtDenom,
GovDenom: types.DefaultGovDenom,
CDPs: types.CDPs{},
PreviousBlockTime: types.DefaultPreviousBlockTime,
PreviousDistributionTime: types.DefaultPreviousDistributionTime,
}
default:
panic("invalid genesis state selector")
}
}

View File

@ -0,0 +1,215 @@
package operations
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/kava-labs/kava/x/cdp"
"github.com/kava-labs/kava/x/pricefeed"
)
// SimulateMsgCdp generates a MsgCreateCdp or MsgDepositCdp with random values.
func SimulateMsgCdp(ak auth.AccountKeeper, k cdp.Keeper, pfk pricefeed.Keeper) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
handler := cdp.NewHandler(k)
simacc := simulation.RandomAcc(r, accs)
acc := ak.GetAccount(ctx, simacc.Address)
if acc == nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, nil
}
coins := acc.GetCoins()
collateralParams := k.GetParams(ctx).CollateralParams
if len(collateralParams) == 0 {
return simulation.NoOpMsg(cdp.ModuleName), nil, nil
}
randCollateralParam := collateralParams[r.Intn(len(collateralParams))]
randDebtAsset := randCollateralParam.DebtLimit[r.Intn(len(randCollateralParam.DebtLimit))]
randDebtParam, _ := k.GetDebtParam(ctx, randDebtAsset.Denom)
if coins.AmountOf(randCollateralParam.Denom).IsZero() {
return simulation.NoOpMsg(cdp.ModuleName), nil, nil
}
price, err := pfk.GetCurrentPrice(ctx, randCollateralParam.MarketID)
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, err
}
// convert the price to the same units as the debt param
priceShifted := ShiftDec(price.Price, randDebtParam.ConversionFactor)
existingCDP, found := k.GetCdpByOwnerAndDenom(ctx, acc.GetAddress(), randCollateralParam.Denom)
if !found {
// calculate the minimum amount of collateral that is needed to create a cdp with the debt floor amount of debt and the minimum liquidation ratio
// (debtFloor * liquidationRatio)/priceShifted
minCollateralDeposit := (sdk.NewDecFromInt(randDebtParam.DebtFloor).Mul(randCollateralParam.LiquidationRatio)).Quo(priceShifted)
// convert to proper collateral units
minCollateralDeposit = ShiftDec(minCollateralDeposit, randCollateralParam.ConversionFactor)
// convert to integer and always round up
minCollateralDepositRounded := minCollateralDeposit.TruncateInt().Add(sdk.OneInt())
// if the account has less than the min deposit, return
if coins.AmountOf(randCollateralParam.Denom).LT(minCollateralDepositRounded) {
return simulation.NoOpMsg(cdp.ModuleName), nil, nil
}
// set the max collateral deposit to the amount of coins in the account
maxCollateralDeposit := coins.AmountOf(randCollateralParam.Denom)
// randomly select a collateral deposit amount
collateralDeposit := sdk.NewInt(int64(simulation.RandIntBetween(r, int(minCollateralDepositRounded.Int64()), int(maxCollateralDeposit.Int64()))))
// calculate how much the randomly selected deposit is worth
collateralDepositValue := ShiftDec(sdk.NewDecFromInt(collateralDeposit), randCollateralParam.ConversionFactor.Neg()).Mul(priceShifted)
// calculate the max amount of debt that could be drawn for the chosen deposit
maxDebtDraw := collateralDepositValue.Quo(randCollateralParam.LiquidationRatio).TruncateInt()
// randomly select a debt draw amount
debtDraw := sdk.NewInt(int64(simulation.RandIntBetween(r, int(randDebtParam.DebtFloor.Int64()), int(maxDebtDraw.Int64()))))
msg := cdp.NewMsgCreateCDP(acc.GetAddress(), sdk.NewCoins(sdk.NewCoin(randCollateralParam.Denom, collateralDeposit)), sdk.NewCoins(sdk.NewCoin(randDebtParam.Denom, debtDraw)))
err := msg.ValidateBasic()
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("expected msg to pass ValidateBasic: %v", err)
}
ok := submitMsg(msg, handler, ctx)
if !ok {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("could not submit create cdp msg")
}
return simulation.NewOperationMsg(msg, ok, "create cdp"), nil, nil
}
// a cdp already exists, deposit to it, draw debt from it, or repay debt to it
// close 25% of the time
if canClose(acc, existingCDP, randDebtParam.Denom) && shouldClose(r) {
repaymentAmount := coins.AmountOf(randDebtParam.Denom)
msg := cdp.NewMsgRepayDebt(acc.GetAddress(), randCollateralParam.Denom, sdk.NewCoins(sdk.NewCoin(randDebtParam.Denom, repaymentAmount)))
err := msg.ValidateBasic()
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("expected repay (close) msg to pass ValidateBasic: %v", err)
}
ok := submitMsg(msg, handler, ctx)
if !ok {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("could not submit repay (close) msg")
}
return simulation.NewOperationMsg(msg, ok, "repay debt (close) cdp"), nil, nil
}
// deposit 25% of the time
if hasCoins(acc, randCollateralParam.Denom) && shouldDeposit(r) {
randDepositAmount := sdk.NewInt(int64(simulation.RandIntBetween(r, 1, int(acc.GetCoins().AmountOf(randCollateralParam.Denom).Int64()))))
msg := cdp.NewMsgDeposit(acc.GetAddress(), acc.GetAddress(), sdk.NewCoins(sdk.NewCoin(randCollateralParam.Denom, randDepositAmount)))
err := msg.ValidateBasic()
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("expected deposit msg to pass ValidateBasic: %v", err)
}
ok := submitMsg(msg, handler, ctx)
if !ok {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("could not submit deposit msg")
}
return simulation.NewOperationMsg(msg, ok, "deposit to cdp"), nil, nil
}
// draw debt 25% of the time
if shouldDraw(r) {
collateralShifted := ShiftDec(sdk.NewDecFromInt(existingCDP.Collateral.AmountOf(randCollateralParam.Denom)), randCollateralParam.ConversionFactor.Neg())
collateralValue := collateralShifted.Mul(priceShifted)
debt := (existingCDP.Principal.Add(existingCDP.AccumulatedFees)).AmountOf(randDebtParam.Denom)
maxTotalDebt := collateralValue.Quo(randCollateralParam.LiquidationRatio)
maxDebt := maxTotalDebt.Sub(sdk.NewDecFromInt(debt)).TruncateInt().Sub(sdk.OneInt())
randDrawAmount := sdk.NewInt(int64(simulation.RandIntBetween(r, 1, int(maxDebt.Int64()))))
msg := cdp.NewMsgDrawDebt(acc.GetAddress(), randCollateralParam.Denom, sdk.NewCoins(sdk.NewCoin(randDebtParam.Denom, randDrawAmount)))
err := msg.ValidateBasic()
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("expected draw msg to pass ValidateBasic: %v", err)
}
ok := submitMsg(msg, handler, ctx)
if !ok {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("could not submit draw msg")
}
return simulation.NewOperationMsg(msg, ok, "draw debt from cdp"), nil, nil
}
// repay debt 25% of the time
if hasCoins(acc, randDebtParam.Denom) {
debt := (existingCDP.Principal.Add(existingCDP.AccumulatedFees)).AmountOf(randDebtParam.Denom)
maxRepay := acc.GetCoins().AmountOf(randDebtParam.Denom)
payableDebt := debt.Sub(randDebtParam.DebtFloor)
if maxRepay.GT(payableDebt) {
maxRepay = payableDebt
}
randRepayAmount := sdk.NewInt(int64(simulation.RandIntBetween(r, 1, int(maxRepay.Int64()))))
if debt.Equal(randDebtParam.DebtFloor) {
if acc.GetCoins().AmountOf(randDebtParam.Denom).GTE(debt) {
randRepayAmount = debt
}
}
msg := cdp.NewMsgRepayDebt(acc.GetAddress(), randCollateralParam.Denom, sdk.NewCoins(sdk.NewCoin(randDebtParam.Denom, randRepayAmount)))
err := msg.ValidateBasic()
if err != nil {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("expected repay msg to pass ValidateBasic: %v", err)
}
ok := submitMsg(msg, handler, ctx)
if !ok {
return simulation.NoOpMsg(cdp.ModuleName), nil, fmt.Errorf("could not submit repay msg")
}
return simulation.NewOperationMsg(msg, ok, "repay debt cdp"), nil, nil
}
return simulation.NewOperationMsgBasic(cdp.ModuleName, "no-operation (no valid actions)", "", false, nil), nil, nil
}
}
func submitMsg(msg sdk.Msg, handler sdk.Handler, ctx sdk.Context) (ok bool) {
ctx, write := ctx.CacheContext()
res := handler(ctx, msg)
if res.IsOK() {
write()
} else {
fmt.Println(res.Log)
}
return res.IsOK()
}
func shouldDraw(r *rand.Rand) bool {
threshold := 50
value := simulation.RandIntBetween(r, 1, 100)
if value > threshold {
return true
}
return false
}
func shouldDeposit(r *rand.Rand) bool {
threshold := 66
value := simulation.RandIntBetween(r, 1, 100)
if value > threshold {
return true
}
return false
}
func hasCoins(acc authexported.Account, denom string) bool {
if acc.GetCoins().AmountOf(denom).IsZero() {
return false
}
return true
}
func shouldClose(r *rand.Rand) bool {
threshold := 75
value := simulation.RandIntBetween(r, 1, 100)
if value > threshold {
return true
}
return false
}
func canClose(acc authexported.Account, c cdp.CDP, denom string) bool {
repaymentAmount := c.Principal.Add(c.AccumulatedFees).AmountOf(denom)
if acc.GetCoins().AmountOf(denom).GTE(repaymentAmount) {
return true
}
return false
}

View File

@ -0,0 +1,26 @@
package operations
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
func ShiftDec(x sdk.Dec, places sdk.Int) sdk.Dec {
neg := places.IsNegative()
for i := 0; i < int(abs(places.Int64())); i++ {
if neg {
x = x.Mul(sdk.MustNewDecFromStr("0.1"))
} else {
x = x.Mul(sdk.NewDecFromInt(sdk.NewInt(10)))
}
}
return x
}
// abs returns the absolute value of x.
func abs(x int64) int64 {
if x < 0 {
return -x
}
return x
}

View File

@ -0,0 +1,28 @@
package operations_test
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/cdp/simulation/operations"
"github.com/stretchr/testify/require"
)
func TestShiftDec(t *testing.T) {
tests := []struct {
value sdk.Dec
shift sdk.Int
expected sdk.Dec
}{
{sdk.MustNewDecFromStr("5.5"), sdk.NewInt(1), sdk.MustNewDecFromStr("55")},
{sdk.MustNewDecFromStr("5.5"), sdk.NewInt(-1), sdk.MustNewDecFromStr("0.55")},
{sdk.MustNewDecFromStr("5.5"), sdk.NewInt(2), sdk.MustNewDecFromStr("550")},
{sdk.MustNewDecFromStr("5.5"), sdk.NewInt(-2), sdk.MustNewDecFromStr("0.055")},
}
for _, tt := range tests {
t.Run(tt.value.String(), func(t *testing.T) {
require.Equal(t, tt.expected, operations.ShiftDec(tt.value, tt.shift))
})
}
}

View File

@ -9,6 +9,5 @@ import (
// ParamChanges defines the parameters that can be modified by param change proposals // ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation // on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange { func ParamChanges(r *rand.Rand) []simulation.ParamChange {
// TODO implement this
return []simulation.ParamChange{} return []simulation.ParamChange{}
} }

View File

@ -5,13 +5,11 @@ import (
"time" "time"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/simulation" "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/kava-labs/kava/x/pricefeed/types" "github.com/kava-labs/kava/x/pricefeed/types"
pricefeed "github.com/kava-labs/kava/x/pricefeed/types" pricefeed "github.com/kava-labs/kava/x/pricefeed/types"
sdk "github.com/cosmos/cosmos-sdk/types"
) )
// RandomizedGenState generates a random GenesisState for pricefeed // RandomizedGenState generates a random GenesisState for pricefeed
@ -31,7 +29,6 @@ func RandomizedGenState(simState *module.SimulationState) {
} }
params = types.NewParams(markets) params = types.NewParams(markets)
pricefeedGenesis := types.NewGenesisState(params, genPrices) pricefeedGenesis := types.NewGenesisState(params, genPrices)
fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, pricefeedGenesis)) fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, pricefeedGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(pricefeedGenesis) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(pricefeedGenesis)
} }