update liquidator tests

This commit is contained in:
rhuairahrighairigh 2019-12-06 23:49:47 +00:00
parent 688b7830c0
commit 1295dfbffc
5 changed files with 130 additions and 248 deletions

View File

@ -72,7 +72,7 @@ func (tApp TestApp) GetLiquidatorKeeper() liquidator.Keeper { return tApp.liquid
func (tApp TestApp) GetPriceFeedKeeper() pricefeed.Keeper { return tApp.pricefeedKeeper }
// Create a new auth genesis state from some addresses and coins. The state is returned marshalled into a map.
// TODO this is only a TestApp method because it needs access to the codec, could be another way to structure it
// TODO make this not a TestApp method.
func (tApp TestApp) NewAuthGenStateFromAccounts(addresses []sdk.AccAddress, coins []sdk.Coins) GenesisState {
// Create GenAccounts
accounts := authexported.GenesisAccounts{}
@ -81,7 +81,7 @@ func (tApp TestApp) NewAuthGenStateFromAccounts(addresses []sdk.AccAddress, coin
}
// Create the auth genesis state
authGenesis := auth.NewGenesisState(auth.DefaultParams(), accounts)
return GenesisState{auth.ModuleName: tApp.cdc.MustMarshalJSON(authGenesis)}
return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
}
// This calls InitChain on the app using the default genesis state, overwitten with any passed in genesis states

View File

@ -0,0 +1,73 @@
package keeper_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/liquidator"
"github.com/kava-labs/kava/x/liquidator/types"
"github.com/kava-labs/kava/x/pricefeed"
)
// Avoid cluttering test cases with long function name
func i(in int64) sdk.Int { return sdk.NewInt(in) }
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
// Default genesis states to initialize test apps
func NewPFGenState(asset string, price sdk.Dec) app.GenesisState {
quote := "usd"
ap := pricefeed.Params{
Markets: []pricefeed.Market{
pricefeed.Market{MarketID: asset, BaseAsset: asset, QuoteAsset: quote, Oracles: pricefeed.Oracles{}, Active: true}},
}
pfGenesis := pricefeed.GenesisState{
Params: ap,
PostedPrices: []pricefeed.PostedPrice{
pricefeed.PostedPrice{
MarketID: asset,
OracleAddress: sdk.AccAddress{},
Price: price,
Expiry: time.Unix(9999999999, 0), // some deterministic future date,
},
},
}
return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)}
}
func NewCDPGenState() app.GenesisState {
cdpGenesis := cdp.GenesisState{
Params: cdp.CdpParams{
GlobalDebtLimit: sdk.NewInt(1000000),
CollateralParams: []cdp.CollateralParams{
{
Denom: "btc",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewInt(500000),
},
},
},
GlobalDebt: sdk.ZeroInt(),
CDPs: cdp.CDPs{},
}
return app.GenesisState{cdp.ModuleName: cdp.ModuleCdc.MustMarshalJSON(cdpGenesis)}
}
func NewLiquidatorGenState() app.GenesisState {
liquidatorGenesis := types.GenesisState{
Params: types.LiquidatorParams{
DebtAuctionSize: sdk.NewInt(1000),
CollateralParams: []types.CollateralParams{
{
Denom: "btc",
AuctionSize: sdk.NewInt(1),
},
},
},
}
return app.GenesisState{liquidator.ModuleName: liquidator.ModuleCdc.MustMarshalJSON(liquidatorGenesis)}
}

View File

@ -55,7 +55,7 @@ func (k Keeper) SeizeAndStartCollateralAuction(ctx sdk.Context, owner sdk.AccAdd
stableToRaise := sdk.NewDecFromInt(collateralToSell).Quo(sdk.NewDecFromInt(cdp.CollateralAmount)).Mul(sdk.NewDecFromInt(cdp.Debt)).RoundInt()
// Seize the collateral and debt from the CDP
err := k.partialSeizeCDP(ctx, owner, collateralDenom, collateralToSell, stableToRaise)
err := k.PartialSeizeCDP(ctx, owner, collateralDenom, collateralToSell, stableToRaise)
if err != nil {
return 0, err
}
@ -99,7 +99,7 @@ func (k Keeper) StartDebtAuction(ctx sdk.Context) (auction.ID, sdk.Error) {
}
// Record amount of debt sent for auction. Debt can only be reduced in lock step with reducing stable coin
seizedDebt.SentToAuction = seizedDebt.SentToAuction.Add(params.DebtAuctionSize)
k.setSeizedDebt(ctx, seizedDebt)
k.SetSeizedDebt(ctx, seizedDebt)
return auctionID, nil
}
@ -131,7 +131,7 @@ func (k Keeper) StartDebtAuction(ctx sdk.Context) (auction.ID, sdk.Error) {
// }
// PartialSeizeCDP seizes some collateral and debt from an under-collateralized CDP.
func (k Keeper) partialSeizeCDP(ctx sdk.Context, owner sdk.AccAddress, collateralDenom string, collateralToSeize sdk.Int, debtToSeize sdk.Int) sdk.Error { // aka Cat.bite
func (k Keeper) PartialSeizeCDP(ctx sdk.Context, owner sdk.AccAddress, collateralDenom string, collateralToSeize sdk.Int, debtToSeize sdk.Int) sdk.Error { // aka Cat.bite
// Seize debt and collateral in the cdp module. This also validates the inputs.
err := k.cdpKeeper.PartialSeizeCDP(ctx, owner, collateralDenom, collateralToSeize, debtToSeize)
if err != nil {
@ -141,7 +141,7 @@ func (k Keeper) partialSeizeCDP(ctx sdk.Context, owner sdk.AccAddress, collatera
// increment the total seized debt (Awe) by cdp.debt
seizedDebt := k.GetSeizedDebt(ctx)
seizedDebt.Total = seizedDebt.Total.Add(debtToSeize)
k.setSeizedDebt(ctx, seizedDebt)
k.SetSeizedDebt(ctx, seizedDebt)
// add cdp.collateral amount of coins to the moduleAccount (so they can be transferred to the auction later)
coins := sdk.NewCoins(sdk.NewCoin(collateralDenom, collateralToSeize))
@ -172,7 +172,7 @@ func (k Keeper) SettleDebt(ctx sdk.Context) sdk.Error {
if err != nil {
return err // this should not error in this context
}
k.setSeizedDebt(ctx, updatedDebt)
k.SetSeizedDebt(ctx, updatedDebt)
// Subtract stable coin from moduleAccout
k.bankKeeper.SubtractCoins(ctx, k.cdpKeeper.GetLiquidatorAccountAddress(), sdk.Coins{sdk.NewCoin(k.cdpKeeper.GetStableDenom(), settleAmount)})
@ -197,7 +197,7 @@ func (k Keeper) GetSeizedDebt(ctx sdk.Context) types.SeizedDebt {
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &seizedDebt)
return seizedDebt
}
func (k Keeper) setSeizedDebt(ctx sdk.Context, debt types.SeizedDebt) {
func (k Keeper) SetSeizedDebt(ctx sdk.Context, debt types.SeizedDebt) {
store := ctx.KVStore(k.key)
bz := k.cdc.MustMarshalBinaryLengthPrefixed(debt)
store.Set(k.getSeizedDebtKey(), bz)

View File

@ -1,124 +1,103 @@
package keeper
package keeper_test
import (
"testing"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/kava-labs/kava/x/cdp"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/liquidator/types"
"github.com/kava-labs/kava/x/pricefeed"
)
func TestKeeper_SeizeAndStartCollateralAuction(t *testing.T) {
// Setup
ctx, k := setupTestKeepers()
_, addrs := app.GeneratePrivKeyAddressPairs(1)
_, addrs := mock.GeneratePrivKeyAddressPairs(1)
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates(
tApp.NewAuthGenStateFromAccounts(addrs, []sdk.Coins{cs(c("btc", 100))}),
NewPFGenState("btc", sdk.MustNewDecFromStr("8000.00")),
NewCDPGenState(),
NewLiquidatorGenState(),
)
ctx := tApp.NewContext(false, abci.Header{})
pricefeed.InitGenesis(ctx, k.pricefeedKeeper, pricefeedGenesis())
k.pricefeedKeeper.SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("8000.00"), tmtime.Now().Add(time.Hour*1))
k.pricefeedKeeper.SetCurrentPrices(ctx, "btc")
cdp.InitGenesis(ctx, k.cdpKeeper, k.pricefeedKeeper, cdpDefaultGenesis())
dp := defaultParams()
k.liquidatorKeeper.SetParams(ctx, dp)
k.bankKeeper.AddCoins(ctx, addrs[0], cs(c("btc", 100)))
require.NoError(t, tApp.GetCDPKeeper().ModifyCDP(ctx, addrs[0], "btc", i(3), i(16000)))
k.cdpKeeper.ModifyCDP(ctx, addrs[0], "btc", i(3), i(16000))
k.pricefeedKeeper.SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("7999.99"), tmtime.Now().Add(time.Hour*1))
k.pricefeedKeeper.SetCurrentPrices(ctx, "btc")
_, err := tApp.GetPriceFeedKeeper().SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("7999.99"), time.Unix(9999999999, 0))
require.NoError(t, err)
require.NoError(t, tApp.GetPriceFeedKeeper().SetCurrentPrices(ctx, "btc"))
// Run test function
auctionID, err := k.liquidatorKeeper.SeizeAndStartCollateralAuction(ctx, addrs[0], "btc")
auctionID, err := tApp.GetLiquidatorKeeper().SeizeAndStartCollateralAuction(ctx, addrs[0], "btc")
// Check CDP
require.NoError(t, err)
cdp, found := k.cdpKeeper.GetCDP(ctx, addrs[0], "btc")
cdp, found := tApp.GetCDPKeeper().GetCDP(ctx, addrs[0], "btc")
require.True(t, found)
require.Equal(t, cdp.CollateralAmount, i(2)) // original amount - params.CollateralAuctionSize
require.Equal(t, cdp.Debt, i(10667)) // original debt scaled by amount of collateral removed
// Check auction exists
_, found = k.auctionKeeper.GetAuction(ctx, auctionID)
_, found = tApp.GetAuctionKeeper().GetAuction(ctx, auctionID)
require.True(t, found)
// TODO check auction values are correct?
}
func TestKeeper_StartDebtAuction(t *testing.T) {
// Setup
ctx, k := setupTestKeepers()
k.liquidatorKeeper.SetParams(ctx, defaultParams())
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates(
NewLiquidatorGenState(),
)
keeper := tApp.GetLiquidatorKeeper()
ctx := tApp.NewContext(false, abci.Header{})
initSDebt := types.SeizedDebt{i(2000), i(0)}
k.liquidatorKeeper.setSeizedDebt(ctx, initSDebt)
keeper.SetSeizedDebt(ctx, initSDebt)
// Execute
auctionID, err := k.liquidatorKeeper.StartDebtAuction(ctx)
auctionID, err := keeper.StartDebtAuction(ctx)
// Check
require.NoError(t, err)
require.Equal(t,
types.SeizedDebt{
initSDebt.Total,
initSDebt.SentToAuction.Add(k.liquidatorKeeper.GetParams(ctx).DebtAuctionSize),
initSDebt.SentToAuction.Add(keeper.GetParams(ctx).DebtAuctionSize),
},
k.liquidatorKeeper.GetSeizedDebt(ctx),
keeper.GetSeizedDebt(ctx),
)
_, found := k.auctionKeeper.GetAuction(ctx, auctionID)
_, found := tApp.GetAuctionKeeper().GetAuction(ctx, auctionID)
require.True(t, found)
// TODO check auction values are correct?
}
// func TestKeeper_StartSurplusAuction(t *testing.T) {
// // Setup
// ctx, k := setupTestKeepers()
// initSurplus := i(2000)
// k.liquidatorKeeper.bankKeeper.AddCoins(ctx, k.cdpKeeper.GetLiquidatorAccountAddress(), cs(sdk.NewCoin(k.cdpKeeper.GetStableDenom(), initSurplus)))
// k.liquidatorKeeper.setSeizedDebt(ctx, i(0))
// // Execute
// auctionID, err := k.liquidatorKeeper.StartSurplusAuction(ctx)
// // Check
// require.NoError(t, err)
// require.Equal(t,
// initSurplus.Sub(SurplusAuctionSize),
// k.liquidatorKeeper.bankKeeper.GetCoins(ctx,
// k.cdpKeeper.GetLiquidatorAccountAddress(),
// ).AmountOf(k.cdpKeeper.GetStableDenom()),
// )
// _, found := k.auctionKeeper.GetAuction(ctx, auctionID)
// require.True(t, found)
// }
func TestKeeper_partialSeizeCDP(t *testing.T) {
// Setup
ctx, k := setupTestKeepers()
_, addrs := app.GeneratePrivKeyAddressPairs(1)
_, addrs := mock.GeneratePrivKeyAddressPairs(1)
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates(
tApp.NewAuthGenStateFromAccounts(addrs, []sdk.Coins{cs(c("btc", 100))}),
NewPFGenState("btc", sdk.MustNewDecFromStr("8000.00")),
NewCDPGenState(),
NewLiquidatorGenState(),
)
ctx := tApp.NewContext(false, abci.Header{})
pricefeed.InitGenesis(ctx, k.pricefeedKeeper, pricefeedGenesis())
tApp.GetCDPKeeper().ModifyCDP(ctx, addrs[0], "btc", i(3), i(16000))
k.pricefeedKeeper.SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("8000.00"), tmtime.Now().Add(time.Hour*1))
k.pricefeedKeeper.SetCurrentPrices(ctx, "btc")
k.bankKeeper.AddCoins(ctx, addrs[0], cs(c("btc", 100)))
cdp.InitGenesis(ctx, k.cdpKeeper, k.pricefeedKeeper, cdpDefaultGenesis())
k.liquidatorKeeper.SetParams(ctx, defaultParams())
k.cdpKeeper.ModifyCDP(ctx, addrs[0], "btc", i(3), i(16000))
k.pricefeedKeeper.SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("7999.99"), tmtime.Now().Add(time.Hour*1))
k.pricefeedKeeper.SetCurrentPrices(ctx, "btc")
tApp.GetPriceFeedKeeper().SetPrice(ctx, addrs[0], "btc", sdk.MustNewDecFromStr("7999.99"), tmtime.Now().Add(time.Hour*1))
tApp.GetPriceFeedKeeper().SetCurrentPrices(ctx, "btc")
// Run test function
err := k.liquidatorKeeper.partialSeizeCDP(ctx, addrs[0], "btc", i(2), i(10000))
err := tApp.GetLiquidatorKeeper().PartialSeizeCDP(ctx, addrs[0], "btc", i(2), i(10000))
// Check
require.NoError(t, err)
cdp, found := k.cdpKeeper.GetCDP(ctx, addrs[0], "btc")
cdp, found := tApp.GetCDPKeeper().GetCDP(ctx, addrs[0], "btc")
require.True(t, found)
require.Equal(t, i(1), cdp.CollateralAmount)
require.Equal(t, i(6000), cdp.Debt)
@ -126,12 +105,13 @@ func TestKeeper_partialSeizeCDP(t *testing.T) {
func TestKeeper_GetSetSeizedDebt(t *testing.T) {
// Setup
ctx, k := setupTestKeepers()
tApp := app.NewTestApp()
ctx := tApp.NewContext(true, abci.Header{})
debt := types.SeizedDebt{i(234247645), i(2343)}
// Run test function
k.liquidatorKeeper.setSeizedDebt(ctx, debt)
readDebt := k.liquidatorKeeper.GetSeizedDebt(ctx)
tApp.GetLiquidatorKeeper().SetSeizedDebt(ctx, debt)
readDebt := tApp.GetLiquidatorKeeper().GetSeizedDebt(ctx)
// Check
require.Equal(t, debt, readDebt)

View File

@ -1,171 +0,0 @@
package keeper
import (
"time"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmtime "github.com/tendermint/tendermint/types/time"
dbm "github.com/tendermint/tm-db"
"github.com/kava-labs/kava/x/auction"
"github.com/kava-labs/kava/x/cdp"
"github.com/kava-labs/kava/x/liquidator/types"
"github.com/kava-labs/kava/x/pricefeed"
)
// Avoid cluttering test cases with long function name
func i(in int64) sdk.Int { return sdk.NewInt(in) }
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
type keepers struct {
paramsKeeper params.Keeper
accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper
pricefeedKeeper pricefeed.Keeper
auctionKeeper auction.Keeper
cdpKeeper cdp.Keeper
liquidatorKeeper Keeper
}
func setupTestKeepers() (sdk.Context, keepers) {
// Setup in memory database
keyParams := sdk.NewKVStoreKey(params.StoreKey)
tkeyParams := sdk.NewTransientStoreKey(params.TStoreKey)
keyAcc := sdk.NewKVStoreKey(auth.StoreKey)
keyPriceFeed := sdk.NewKVStoreKey(pricefeed.StoreKey)
keyCDP := sdk.NewKVStoreKey("cdp")
keyAuction := sdk.NewKVStoreKey("auction")
keyLiquidator := sdk.NewKVStoreKey("liquidator")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyPriceFeed, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyCDP, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyAuction, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyLiquidator, sdk.StoreTypeIAVL, db)
err := ms.LoadLatestVersion()
if err != nil {
panic(err)
}
// Create Codec
cdc := makeTestCodec()
// Create Keepers
paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace)
accountKeeper := auth.NewAccountKeeper(
cdc,
keyAcc,
paramsKeeper.Subspace(auth.DefaultParamspace),
auth.ProtoBaseAccount,
)
blacklistedAddrs := make(map[string]bool)
bankKeeper := bank.NewBaseKeeper(
accountKeeper,
paramsKeeper.Subspace(bank.DefaultParamspace),
bank.DefaultCodespace,
blacklistedAddrs,
)
pricefeedKeeper := pricefeed.NewKeeper(cdc, keyPriceFeed, paramsKeeper.Subspace(pricefeed.DefaultParamspace), pricefeed.DefaultCodespace)
cdpKeeper := cdp.NewKeeper(
cdc,
keyCDP,
paramsKeeper.Subspace(cdp.DefaultParamspace),
pricefeedKeeper,
bankKeeper,
)
auctionKeeper := auction.NewKeeper(cdc, cdpKeeper, keyAuction, paramsKeeper.Subspace(auction.DefaultParamspace)) // Note: cdp keeper stands in for bank keeper
liquidatorKeeper := NewKeeper(
cdc,
keyLiquidator,
paramsKeeper.Subspace(types.DefaultParamspace),
cdpKeeper,
auctionKeeper,
cdpKeeper,
) // Note: cdp keeper stands in for bank keeper
// Create context
ctx := sdk.NewContext(ms, abci.Header{ChainID: "testchain"}, false, log.NewNopLogger())
return ctx, keepers{
paramsKeeper,
accountKeeper,
bankKeeper,
pricefeedKeeper,
auctionKeeper,
cdpKeeper,
liquidatorKeeper,
}
}
func makeTestCodec() *codec.Codec {
var cdc = codec.New()
auth.RegisterCodec(cdc)
bank.RegisterCodec(cdc)
pricefeed.RegisterCodec(cdc)
auction.RegisterCodec(cdc)
cdp.RegisterCodec(cdc)
types.RegisterCodec(cdc)
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
return cdc
}
func defaultParams() types.LiquidatorParams {
return types.LiquidatorParams{
DebtAuctionSize: sdk.NewInt(1000),
CollateralParams: []types.CollateralParams{
{
Denom: "btc",
AuctionSize: sdk.NewInt(1),
},
},
}
}
func cdpDefaultGenesis() cdp.GenesisState {
return cdp.GenesisState{
cdp.CdpParams{
GlobalDebtLimit: sdk.NewInt(1000000),
CollateralParams: []cdp.CollateralParams{
{
Denom: "btc",
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
DebtLimit: sdk.NewInt(500000),
},
},
},
sdk.ZeroInt(),
cdp.CDPs{},
}
}
func pricefeedGenesis() pricefeed.GenesisState {
ap := pricefeed.Params{
Markets: []pricefeed.Market{
pricefeed.Market{MarketID: "btc", BaseAsset: "btc", QuoteAsset: "usd", Oracles: pricefeed.Oracles{}, Active: true}},
}
return pricefeed.GenesisState{
Params: ap,
PostedPrices: []pricefeed.PostedPrice{
pricefeed.PostedPrice{
MarketID: "btc",
OracleAddress: sdk.AccAddress{},
Price: sdk.MustNewDecFromStr("8000.00"),
Expiry: tmtime.Now().Add(1 * time.Hour),
},
},
}
}