mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-11-10 10:05:18 +00:00
Incentive Test Refactors (#908)
* organise testing committee gen state * remove repeated test app initialization * minor fixes from linter in tests * move more setup to SetupApp * split up KeeperTestSuite for each reward type * simplify KeeperTestSuite * simplify PayoutKeeperSuite * simplify DelegatorRewardSuite * simplify SupplyRewardsSuite * simplify BorrowRewardsSuite * simplify USDXRewardsSuite * add auth genesis builder for easier test setup * migrate all incentive tests to auth builder * add incentive genesis builder for easier setup migrate hard incentive tests * migrate all tests to incentive builder * add hard genesis builder * small tidy ups * deduplicate initialTime from borrow tests * deduplicate initialtTime from supply tests * deduplicate initialTime from usdx and keeper tests * deduplicate initialTime in delgator tests * deduplicate genesis time in payout test * deduplicate test app initialization * make authGenesisBuilder available for all modules * remove unused pricefeed setup * export incentive genesis builder * remove commented out test cases * migrate cdp test to new test state builders * migrate vv payout tests to use new builders
This commit is contained in:
parent
9d9b169e6a
commit
d56bb77231
@ -18,6 +18,7 @@ import (
|
||||
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/auth/vesting"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
@ -42,6 +43,11 @@ import (
|
||||
validatorvesting "github.com/kava-labs/kava/x/validator-vesting"
|
||||
)
|
||||
|
||||
var (
|
||||
emptyTime time.Time
|
||||
emptyChainID string
|
||||
)
|
||||
|
||||
// TestApp is a simple wrapper around an App. It exposes internal keepers for use in integration tests.
|
||||
// This file also contains test helpers. Ideally they would be in separate package.
|
||||
// Basic Usage:
|
||||
@ -92,55 +98,12 @@ func (tApp TestApp) GetSwapKeeper() swap.Keeper { return tApp.swapKeep
|
||||
|
||||
// InitializeFromGenesisStates calls InitChain on the app using the default genesis state, overwitten with any passed in genesis states
|
||||
func (tApp TestApp) InitializeFromGenesisStates(genesisStates ...GenesisState) TestApp {
|
||||
// Create a default genesis state and overwrite with provided values
|
||||
genesisState := NewDefaultGenesisState()
|
||||
for _, state := range genesisStates {
|
||||
for k, v := range state {
|
||||
genesisState[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the chain
|
||||
stateBytes, err := codec.MarshalJSONIndent(tApp.cdc, genesisState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tApp.InitChain(
|
||||
abci.RequestInitChain{
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
AppStateBytes: stateBytes,
|
||||
},
|
||||
)
|
||||
tApp.Commit()
|
||||
tApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: tApp.LastBlockHeight() + 1}})
|
||||
return tApp
|
||||
return tApp.InitializeFromGenesisStatesWithTimeAndChainID(emptyTime, emptyChainID, genesisStates...)
|
||||
}
|
||||
|
||||
// InitializeFromGenesisStatesWithTime calls InitChain on the app using the default genesis state, overwitten with any passed in genesis states and genesis Time
|
||||
func (tApp TestApp) InitializeFromGenesisStatesWithTime(genTime time.Time, genesisStates ...GenesisState) TestApp {
|
||||
// Create a default genesis state and overwrite with provided values
|
||||
genesisState := NewDefaultGenesisState()
|
||||
for _, state := range genesisStates {
|
||||
for k, v := range state {
|
||||
genesisState[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the chain
|
||||
stateBytes, err := codec.MarshalJSONIndent(tApp.cdc, genesisState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tApp.InitChain(
|
||||
abci.RequestInitChain{
|
||||
Time: genTime,
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
AppStateBytes: stateBytes,
|
||||
},
|
||||
)
|
||||
tApp.Commit()
|
||||
tApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: tApp.LastBlockHeight() + 1, Time: genTime}})
|
||||
return tApp
|
||||
return tApp.InitializeFromGenesisStatesWithTimeAndChainID(genTime, emptyChainID, genesisStates...)
|
||||
}
|
||||
|
||||
// InitializeFromGenesisStatesWithTimeAndChainID calls InitChain on the app using the default genesis state, overwitten with any passed in genesis states and genesis Time
|
||||
@ -177,18 +140,6 @@ func (tApp TestApp) CheckBalance(t *testing.T, ctx sdk.Context, owner sdk.AccAdd
|
||||
require.Equal(t, expectedCoins, acc.GetCoins())
|
||||
}
|
||||
|
||||
// Create a new auth genesis state from some addresses and coins. The state is returned marshalled into a map.
|
||||
func NewAuthGenState(addresses []sdk.AccAddress, coins []sdk.Coins) GenesisState {
|
||||
// Create GenAccounts
|
||||
accounts := authexported.GenesisAccounts{}
|
||||
for i := range addresses {
|
||||
accounts = append(accounts, auth.NewBaseAccount(addresses[i], coins[i], nil, 0, 0))
|
||||
}
|
||||
// Create the auth genesis state
|
||||
authGenesis := auth.NewGenesisState(auth.DefaultParams(), accounts)
|
||||
return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
|
||||
}
|
||||
|
||||
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n secp256k1 private keys and addresses.
|
||||
func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
|
||||
r := rand.New(rand.NewSource(12345)) // make the generation deterministic
|
||||
@ -205,3 +156,102 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create a new auth genesis state from some addresses and coins. The state is returned marshalled into a map.
|
||||
func NewAuthGenState(addresses []sdk.AccAddress, coins []sdk.Coins) GenesisState {
|
||||
// Create GenAccounts
|
||||
accounts := authexported.GenesisAccounts{}
|
||||
for i := range addresses {
|
||||
accounts = append(accounts, auth.NewBaseAccount(addresses[i], coins[i], nil, 0, 0))
|
||||
}
|
||||
// Create the auth genesis state
|
||||
authGenesis := auth.NewGenesisState(auth.DefaultParams(), accounts)
|
||||
return GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
|
||||
}
|
||||
|
||||
// AuthGenesisBuilder is a tool for creating an auth genesis state.
|
||||
// Helper methods create basic accounts types and add them to a default genesis state.
|
||||
// All methods are immutable and return updated copies of the builder.
|
||||
// The builder inherits from auth.GenesisState, so fields can be accessed directly if a helper method doesn't exist.
|
||||
//
|
||||
// Example:
|
||||
// // create a single account genesis state
|
||||
// builder := NewAuthGenesisBuilder().WithSimpleAccount(testUserAddress, testCoins)
|
||||
// genesisState := builder.Build()
|
||||
//
|
||||
type AuthGenesisBuilder struct {
|
||||
auth.GenesisState
|
||||
}
|
||||
|
||||
// NewAuthGenesisBuilder creates a AuthGenesisBuilder containing a default genesis state.
|
||||
func NewAuthGenesisBuilder() AuthGenesisBuilder {
|
||||
return AuthGenesisBuilder{
|
||||
GenesisState: auth.DefaultGenesisState(),
|
||||
}
|
||||
}
|
||||
|
||||
// Build assembles and returns the final GenesisState
|
||||
func (builder AuthGenesisBuilder) Build() auth.GenesisState {
|
||||
return builder.GenesisState
|
||||
}
|
||||
|
||||
// BuildMarshalled assembles the final GenesisState and json encodes it into a generic genesis type.
|
||||
func (builder AuthGenesisBuilder) BuildMarshalled() GenesisState {
|
||||
return GenesisState{
|
||||
auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(builder.Build()),
|
||||
}
|
||||
}
|
||||
|
||||
// WithAccounts adds accounts of any type to the genesis state.
|
||||
func (builder AuthGenesisBuilder) WithAccounts(account ...authexported.GenesisAccount) AuthGenesisBuilder {
|
||||
builder.Accounts = append(builder.Accounts, account...)
|
||||
return builder
|
||||
}
|
||||
|
||||
// WithSimpleAccount adds a standard account to the genesis state.
|
||||
func (builder AuthGenesisBuilder) WithSimpleAccount(address sdk.AccAddress, balance sdk.Coins) AuthGenesisBuilder {
|
||||
return builder.WithAccounts(auth.NewBaseAccount(address, balance, nil, 0, 0))
|
||||
}
|
||||
|
||||
// WithSimpleModuleAccount adds a module account to the genesis state.
|
||||
func (builder AuthGenesisBuilder) WithSimpleModuleAccount(moduleName string, balance sdk.Coins, permissions ...string) AuthGenesisBuilder {
|
||||
account := supply.NewEmptyModuleAccount(moduleName, permissions...)
|
||||
account.SetCoins(balance)
|
||||
return builder.WithAccounts(account)
|
||||
}
|
||||
|
||||
// WithSimplePeriodicVestingAccount adds a periodic vesting account to the genesis state.
|
||||
func (builder AuthGenesisBuilder) WithSimplePeriodicVestingAccount(address sdk.AccAddress, balance sdk.Coins, periods vesting.Periods, firstPeriodStartTimestamp int64) AuthGenesisBuilder {
|
||||
baseAccount := auth.NewBaseAccount(address, balance, nil, 0, 0)
|
||||
|
||||
originalVesting := sdk.NewCoins()
|
||||
for _, p := range periods {
|
||||
originalVesting = originalVesting.Add(p.Amount...)
|
||||
}
|
||||
|
||||
var totalPeriods int64
|
||||
for _, p := range periods {
|
||||
totalPeriods += p.Length
|
||||
}
|
||||
endTime := firstPeriodStartTimestamp + totalPeriods
|
||||
|
||||
baseVestingAccount, err := vesting.NewBaseVestingAccount(baseAccount, originalVesting, endTime)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
periodicVestingAccount := vesting.NewPeriodicVestingAccountRaw(baseVestingAccount, firstPeriodStartTimestamp, periods)
|
||||
|
||||
return builder.WithAccounts(periodicVestingAccount)
|
||||
}
|
||||
|
||||
// WithEmptyValidatorVestingAccount adds a stub validator vesting account to the genesis state.
|
||||
func (builder AuthGenesisBuilder) WithEmptyValidatorVestingAccount(address sdk.AccAddress) AuthGenesisBuilder {
|
||||
// TODO create a validator vesting account builder and remove this method
|
||||
bacc := auth.NewBaseAccount(address, nil, nil, 0, 0)
|
||||
bva, err := vesting.NewBaseVestingAccount(bacc, nil, 1)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
account := validatorvesting.NewValidatorVestingAccountRaw(bva, 0, nil, sdk.ConsAddress{}, nil, 90)
|
||||
return builder.WithAccounts(account)
|
||||
}
|
||||
|
@ -1,70 +1,69 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestRiskyCDPsAccumulateRewards() {
|
||||
suite.SetupWithGenState()
|
||||
initialTime := suite.ctx.BlockTime()
|
||||
func TestRiskyCDPsAccumulateRewards(t *testing.T) {
|
||||
genesisTime := time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
_, addrs := app.GeneratePrivKeyAddressPairs(5)
|
||||
|
||||
initialCollateral := c("bnb", 1_000_000_000)
|
||||
user := addrs[0]
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(user, cs(initialCollateral))
|
||||
|
||||
// Setup incentive state
|
||||
collateralType := "bnb-a"
|
||||
rewardsPerSecond := c(types.USDXMintingRewardDenom, 1_000_000)
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, collateralType, initialTime, initialTime.Add(4*oneYear), rewardsPerSecond)},
|
||||
nil, // hard rewards not needed
|
||||
nil,
|
||||
nil, // delegator rewards not needed
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
initialTime.Add(5*oneYear),
|
||||
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(genesisTime).
|
||||
WithSimpleUSDXRewardPeriod(collateralType, rewardsPerSecond)
|
||||
|
||||
tApp := app.NewTestApp()
|
||||
tApp.InitializeFromGenesisStates(
|
||||
authBuilder.BuildMarshalled(),
|
||||
NewPricefeedGenStateMultiFromTime(genesisTime),
|
||||
NewCDPGenStateMulti(),
|
||||
incentBuilder.BuildMarshalled(),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, collateralType, initialTime)
|
||||
suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, collateralType, sdk.ZeroDec())
|
||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: genesisTime})
|
||||
|
||||
// Setup cdp state containing one CDP
|
||||
cdpKeeper := suite.app.GetCDPKeeper()
|
||||
initialCollateral := c("bnb", 1_000_000_000)
|
||||
initialPrincipal := c("usdx", 100_000_000)
|
||||
cdpKeeper.SetPreviousAccrualTime(suite.ctx, collateralType, suite.ctx.BlockTime())
|
||||
cdpKeeper.SetInterestFactor(suite.ctx, collateralType, sdk.OneDec())
|
||||
// add coins to user's address // TODO move this to auth genesis setup
|
||||
sk := suite.app.GetSupplyKeeper()
|
||||
sk.MintCoins(suite.ctx, cdptypes.ModuleName, cs(initialCollateral))
|
||||
sk.SendCoinsFromModuleToAccount(suite.ctx, cdptypes.ModuleName, suite.addrs[0], cs(initialCollateral))
|
||||
|
||||
err := cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], initialCollateral, initialPrincipal, collateralType)
|
||||
suite.Require().NoError(err)
|
||||
cdpKeeper := tApp.GetCDPKeeper()
|
||||
err := cdpKeeper.AddCdp(ctx, user, initialCollateral, c("usdx", 100_000_000), collateralType)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Skip ahead two blocks to accumulate both interest and usdx reward for the cdp
|
||||
// Two blocks are required because the cdp begin blocker runs before incentive begin blocker.
|
||||
// In the first begin block the cdp is synced, which triggers its claim to sync. But no global rewards have accumulated yet so the sync does nothing.
|
||||
// Global rewards accumulate immediately after during the incentive begin blocker.
|
||||
// Rewards are added to the cdp's claim in the next block when the cdp is synced.
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(10 * time.Minute))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
_ = tApp.EndBlocker(ctx, abci.RequestEndBlock{})
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(10 * time.Minute))
|
||||
_ = tApp.BeginBlocker(ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(10 * time.Minute))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{})
|
||||
_ = tApp.EndBlocker(ctx, abci.RequestEndBlock{})
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(10 * time.Minute))
|
||||
_ = tApp.BeginBlocker(ctx, abci.RequestBeginBlock{})
|
||||
|
||||
// check cdp rewards
|
||||
cdp, found := cdpKeeper.GetCdpByOwnerAndCollateralType(suite.ctx, suite.addrs[0], collateralType)
|
||||
suite.Require().True(found)
|
||||
cdp, found := cdpKeeper.GetCdpByOwnerAndCollateralType(ctx, user, collateralType)
|
||||
require.True(t, found)
|
||||
// This additional sync adds the rewards accumulated at the end of the last begin block.
|
||||
// They weren't added during the begin blocker as the incentive BB runs after the CDP BB.
|
||||
suite.keeper.SynchronizeUSDXMintingReward(suite.ctx, cdp)
|
||||
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||
suite.Require().True(found)
|
||||
incentiveKeeper := tApp.GetIncentiveKeeper()
|
||||
incentiveKeeper.SynchronizeUSDXMintingReward(ctx, cdp)
|
||||
claim, found := incentiveKeeper.GetUSDXMintingClaim(ctx, user)
|
||||
require.True(t, found)
|
||||
|
||||
// rewards are roughly rewardsPerSecond * secondsElapsed (10mins) * num blocks (2)
|
||||
suite.Require().Equal(c(types.USDXMintingRewardDenom, 1_200_001_671), claim.Reward)
|
||||
require.Equal(t, c(types.USDXMintingRewardDenom, 1_200_000_557), claim.Reward)
|
||||
}
|
||||
|
@ -6,16 +6,25 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/cdp"
|
||||
committeetypes "github.com/kava-labs/kava/x/committee/types"
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
hardtypes "github.com/kava-labs/kava/x/hard/types"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
"github.com/kava-labs/kava/x/pricefeed"
|
||||
)
|
||||
|
||||
const (
|
||||
oneYear time.Duration = time.Hour * 24 * 365
|
||||
)
|
||||
|
||||
// Avoid cluttering test cases with long function names
|
||||
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
||||
func d(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) }
|
||||
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
||||
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
||||
|
||||
func NewCDPGenStateMulti() app.GenesisState {
|
||||
cdpGenesis := cdp.GenesisState{
|
||||
Params: cdp.Params{
|
||||
@ -105,7 +114,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
||||
return app.GenesisState{cdp.ModuleName: cdp.ModuleCdc.MustMarshalJSON(cdpGenesis)}
|
||||
}
|
||||
|
||||
func NewPricefeedGenStateMulti() app.GenesisState {
|
||||
func NewPricefeedGenStateMultiFromTime(t time.Time) app.GenesisState {
|
||||
pfGenesis := pricefeed.GenesisState{
|
||||
Params: pricefeed.Params{
|
||||
Markets: []pricefeed.Market{
|
||||
@ -122,82 +131,57 @@ func NewPricefeedGenStateMulti() app.GenesisState {
|
||||
MarketID: "kava:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.MustNewDecFromStr("2.00"),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
{
|
||||
MarketID: "btc:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.MustNewDecFromStr("8000.00"),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
{
|
||||
MarketID: "xrp:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.MustNewDecFromStr("0.25"),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
{
|
||||
MarketID: "bnb:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.MustNewDecFromStr("17.25"),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
{
|
||||
MarketID: "busd:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.OneDec(),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
{
|
||||
MarketID: "zzz:usd",
|
||||
OracleAddress: sdk.AccAddress{},
|
||||
Price: sdk.MustNewDecFromStr("2.00"),
|
||||
Expiry: time.Now().Add(1 * time.Hour),
|
||||
Expiry: t.Add(1 * time.Hour),
|
||||
},
|
||||
},
|
||||
}
|
||||
return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)}
|
||||
}
|
||||
|
||||
func NewHardGenStateMulti() app.GenesisState {
|
||||
loanToValue, _ := sdk.NewDecFromStr("0.6")
|
||||
borrowLimit := sdk.NewDec(1000000000000000)
|
||||
func NewHardGenStateMulti(genTime time.Time) HardGenesisBuilder {
|
||||
kavaMM := NewStandardMoneyMarket("ukava")
|
||||
kavaMM.SpotMarketID = "kava:usd"
|
||||
btcMM := NewStandardMoneyMarket("btcb")
|
||||
btcMM.SpotMarketID = "btc:usd"
|
||||
|
||||
hardGS := hard.NewGenesisState(hard.NewParams(
|
||||
hard.MoneyMarkets{
|
||||
hard.NewMoneyMarket("usdx", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "usdx:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
hard.NewMoneyMarket("ukava", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "kava:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
hard.NewMoneyMarket("bnb", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "bnb:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
hard.NewMoneyMarket("btcb", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "btc:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
hard.NewMoneyMarket("xrp", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "xrp:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
hard.NewMoneyMarket("zzz", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "zzz:usd", sdk.NewInt(1000000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()),
|
||||
},
|
||||
sdk.NewDec(10),
|
||||
), hard.DefaultAccumulationTimes, hard.DefaultDeposits, hard.DefaultBorrows,
|
||||
hard.DefaultTotalSupplied, hard.DefaultTotalBorrowed, hard.DefaultTotalReserves,
|
||||
)
|
||||
|
||||
return app.GenesisState{hard.ModuleName: hard.ModuleCdc.MustMarshalJSON(hardGS)}
|
||||
}
|
||||
|
||||
func NewAuthGenState(addresses []sdk.AccAddress, coins sdk.Coins) app.GenesisState {
|
||||
coinsList := []sdk.Coins{}
|
||||
for range addresses {
|
||||
coinsList = append(coinsList, coins)
|
||||
}
|
||||
|
||||
// Load up our primary user address
|
||||
if len(addresses) >= 4 {
|
||||
coinsList[3] = sdk.NewCoins(
|
||||
sdk.NewCoin("bnb", sdk.NewInt(1000000000000000)),
|
||||
sdk.NewCoin("ukava", sdk.NewInt(1000000000000000)),
|
||||
sdk.NewCoin("btcb", sdk.NewInt(1000000000000000)),
|
||||
sdk.NewCoin("xrp", sdk.NewInt(1000000000000000)),
|
||||
sdk.NewCoin("zzz", sdk.NewInt(1000000000000000)),
|
||||
)
|
||||
}
|
||||
|
||||
return app.NewAuthGenState(addresses, coinsList)
|
||||
builder := NewHardGenesisBuilder().WithGenesisTime(genTime).
|
||||
WithInitializedMoneyMarket(NewStandardMoneyMarket("usdx")).
|
||||
WithInitializedMoneyMarket(kavaMM).
|
||||
WithInitializedMoneyMarket(NewStandardMoneyMarket("bnb")).
|
||||
WithInitializedMoneyMarket(btcMM).
|
||||
WithInitializedMoneyMarket(NewStandardMoneyMarket("xrp")).
|
||||
WithInitializedMoneyMarket(NewStandardMoneyMarket("zzz"))
|
||||
return builder
|
||||
}
|
||||
|
||||
func NewStakingGenesisState() app.GenesisState {
|
||||
@ -208,37 +192,185 @@ func NewStakingGenesisState() app.GenesisState {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupWithGenState() {
|
||||
tApp := app.NewTestApp()
|
||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||
|
||||
tApp.InitializeFromGenesisStates(
|
||||
NewAuthGenState(suite.getAllAddrs(), cs(c("ukava", 1_000_000_000))),
|
||||
NewStakingGenesisState(),
|
||||
NewPricefeedGenStateMulti(),
|
||||
NewCDPGenStateMulti(),
|
||||
NewHardGenStateMulti(),
|
||||
)
|
||||
|
||||
// Set up a god committee
|
||||
committeeModKeeper := tApp.GetCommitteeKeeper()
|
||||
godCommittee := committeetypes.MemberCommittee{
|
||||
BaseCommittee: committeetypes.BaseCommittee{
|
||||
ID: 1,
|
||||
Description: "This committee is for testing.",
|
||||
Members: suite.addrs[:2],
|
||||
Permissions: []committeetypes.Permission{committeetypes.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
ProposalDuration: time.Hour * 24 * 7,
|
||||
TallyOption: committeetypes.FirstPastThePost,
|
||||
func NewCommitteeGenesisState(members []sdk.AccAddress) app.GenesisState {
|
||||
genState := committeetypes.DefaultGenesisState()
|
||||
genState.Committees = committeetypes.Committees{
|
||||
committeetypes.MemberCommittee{
|
||||
BaseCommittee: committeetypes.BaseCommittee{
|
||||
ID: genState.NextProposalID,
|
||||
Description: "This committee is for testing.",
|
||||
Members: members,
|
||||
Permissions: []committeetypes.Permission{committeetypes.GodPermission{}},
|
||||
VoteThreshold: d("0.667"),
|
||||
ProposalDuration: time.Hour * 24 * 7,
|
||||
TallyOption: committeetypes.FirstPastThePost,
|
||||
},
|
||||
},
|
||||
}
|
||||
committeeModKeeper.SetCommittee(ctx, godCommittee)
|
||||
|
||||
suite.app = tApp
|
||||
suite.ctx = ctx
|
||||
suite.keeper = tApp.GetIncentiveKeeper()
|
||||
suite.hardKeeper = tApp.GetHardKeeper()
|
||||
suite.stakingKeeper = tApp.GetStakingKeeper()
|
||||
suite.committeeKeeper = committeeModKeeper
|
||||
genState.NextProposalID += 1
|
||||
return app.GenesisState{
|
||||
committeetypes.ModuleName: committeetypes.ModuleCdc.MustMarshalJSON(genState),
|
||||
}
|
||||
}
|
||||
|
||||
// IncentiveGenesisBuilder is a tool for creating an incentive genesis state.
|
||||
// Helper methods add values onto a default genesis state.
|
||||
// All methods are immutable and return updated copies of the builder.
|
||||
type IncentiveGenesisBuilder struct {
|
||||
types.GenesisState
|
||||
genesisTime time.Time
|
||||
}
|
||||
|
||||
func NewIncentiveGenesisBuilder() IncentiveGenesisBuilder {
|
||||
return IncentiveGenesisBuilder{
|
||||
GenesisState: types.DefaultGenesisState(),
|
||||
genesisTime: time.Time{},
|
||||
}
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) Build() types.GenesisState {
|
||||
return builder.GenesisState
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) BuildMarshalled() app.GenesisState {
|
||||
return app.GenesisState{
|
||||
types.ModuleName: types.ModuleCdc.MustMarshalJSON(builder.Build()),
|
||||
}
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithGenesisTime(time time.Time) IncentiveGenesisBuilder {
|
||||
builder.genesisTime = time
|
||||
builder.Params.ClaimEnd = time.Add(5 * oneYear)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithInitializedBorrowRewardPeriod(period types.MultiRewardPeriod) IncentiveGenesisBuilder {
|
||||
builder.Params.HardBorrowRewardPeriods = append(builder.Params.HardBorrowRewardPeriods, period)
|
||||
|
||||
accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
|
||||
builder.HardBorrowAccumulationTimes = append(builder.HardBorrowAccumulationTimes, accumulationTimeForPeriod)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithSimpleBorrowRewardPeriod(ctype string, rewardsPerSecond sdk.Coins) IncentiveGenesisBuilder {
|
||||
return builder.WithInitializedBorrowRewardPeriod(types.NewMultiRewardPeriod(
|
||||
true,
|
||||
ctype,
|
||||
builder.genesisTime,
|
||||
builder.genesisTime.Add(4*oneYear),
|
||||
rewardsPerSecond,
|
||||
))
|
||||
}
|
||||
func (builder IncentiveGenesisBuilder) WithInitializedSupplyRewardPeriod(period types.MultiRewardPeriod) IncentiveGenesisBuilder {
|
||||
// TODO this could set the start/end times on the period according to builder.genesisTime
|
||||
// Then they could be created by a different builder
|
||||
|
||||
builder.Params.HardSupplyRewardPeriods = append(builder.Params.HardSupplyRewardPeriods, period)
|
||||
|
||||
accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
|
||||
builder.HardSupplyAccumulationTimes = append(builder.HardSupplyAccumulationTimes, accumulationTimeForPeriod)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithSimpleSupplyRewardPeriod(ctype string, rewardsPerSecond sdk.Coins) IncentiveGenesisBuilder {
|
||||
return builder.WithInitializedSupplyRewardPeriod(types.NewMultiRewardPeriod(
|
||||
true,
|
||||
ctype,
|
||||
builder.genesisTime,
|
||||
builder.genesisTime.Add(4*oneYear),
|
||||
rewardsPerSecond,
|
||||
))
|
||||
}
|
||||
func (builder IncentiveGenesisBuilder) WithInitializedDelegatorRewardPeriod(period types.RewardPeriod) IncentiveGenesisBuilder {
|
||||
builder.Params.HardDelegatorRewardPeriods = append(builder.Params.HardDelegatorRewardPeriods, period)
|
||||
|
||||
accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
|
||||
builder.HardDelegatorAccumulationTimes = append(builder.HardDelegatorAccumulationTimes, accumulationTimeForPeriod)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithSimpleDelegatorRewardPeriod(ctype string, rewardsPerSecond sdk.Coin) IncentiveGenesisBuilder {
|
||||
return builder.WithInitializedDelegatorRewardPeriod(types.NewRewardPeriod(
|
||||
true,
|
||||
ctype,
|
||||
builder.genesisTime,
|
||||
builder.genesisTime.Add(4*oneYear),
|
||||
rewardsPerSecond,
|
||||
))
|
||||
}
|
||||
func (builder IncentiveGenesisBuilder) WithInitializedUSDXRewardPeriod(period types.RewardPeriod) IncentiveGenesisBuilder {
|
||||
builder.Params.USDXMintingRewardPeriods = append(builder.Params.USDXMintingRewardPeriods, period)
|
||||
|
||||
accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
|
||||
builder.USDXAccumulationTimes = append(builder.USDXAccumulationTimes, accumulationTimeForPeriod)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithSimpleUSDXRewardPeriod(ctype string, rewardsPerSecond sdk.Coin) IncentiveGenesisBuilder {
|
||||
return builder.WithInitializedUSDXRewardPeriod(types.NewRewardPeriod(
|
||||
true,
|
||||
ctype,
|
||||
builder.genesisTime,
|
||||
builder.genesisTime.Add(4*oneYear),
|
||||
rewardsPerSecond,
|
||||
))
|
||||
}
|
||||
|
||||
func (builder IncentiveGenesisBuilder) WithMultipliers(multipliers types.Multipliers) IncentiveGenesisBuilder {
|
||||
builder.Params.ClaimMultipliers = multipliers
|
||||
return builder
|
||||
}
|
||||
|
||||
// HardGenesisBuilder is a tool for creating a hard genesis state.
|
||||
// Helper methods add values onto a default genesis state.
|
||||
// All methods are immutable and return updated copies of the builder.
|
||||
type HardGenesisBuilder struct {
|
||||
hardtypes.GenesisState
|
||||
genesisTime time.Time
|
||||
}
|
||||
|
||||
func NewHardGenesisBuilder() HardGenesisBuilder {
|
||||
return HardGenesisBuilder{
|
||||
GenesisState: hardtypes.DefaultGenesisState(),
|
||||
}
|
||||
}
|
||||
func (builder HardGenesisBuilder) Build() hardtypes.GenesisState {
|
||||
return builder.GenesisState
|
||||
}
|
||||
func (builder HardGenesisBuilder) BuildMarshalled() app.GenesisState {
|
||||
return app.GenesisState{
|
||||
hardtypes.ModuleName: hardtypes.ModuleCdc.MustMarshalJSON(builder.Build()),
|
||||
}
|
||||
}
|
||||
func (builder HardGenesisBuilder) WithGenesisTime(genTime time.Time) HardGenesisBuilder {
|
||||
builder.genesisTime = genTime
|
||||
return builder
|
||||
}
|
||||
func (builder HardGenesisBuilder) WithInitializedMoneyMarket(market hard.MoneyMarket) HardGenesisBuilder {
|
||||
builder.Params.MoneyMarkets = append(builder.Params.MoneyMarkets, market)
|
||||
|
||||
builder.PreviousAccumulationTimes = append(
|
||||
builder.PreviousAccumulationTimes,
|
||||
hardtypes.NewGenesisAccumulationTime(market.Denom, builder.genesisTime, sdk.OneDec(), sdk.OneDec()),
|
||||
)
|
||||
return builder
|
||||
}
|
||||
func (builder HardGenesisBuilder) WithMinBorrow(minUSDValue sdk.Dec) HardGenesisBuilder {
|
||||
builder.Params.MinimumBorrowUSDValue = minUSDValue
|
||||
return builder
|
||||
}
|
||||
func NewStandardMoneyMarket(denom string) hardtypes.MoneyMarket {
|
||||
return hardtypes.NewMoneyMarket(
|
||||
denom,
|
||||
hard.NewBorrowLimit(
|
||||
false,
|
||||
sdk.NewDec(1e15),
|
||||
d("0.6"),
|
||||
),
|
||||
denom+":usd",
|
||||
i(1e6),
|
||||
hard.NewInterestRateModel(d("0.05"), d("2"), d("0.8"), d("10")),
|
||||
d("0.05"),
|
||||
sdk.ZeroDec(),
|
||||
)
|
||||
}
|
||||
|
@ -2,22 +2,14 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
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/auth/vesting"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
supplyexported "github.com/cosmos/cosmos-sdk/x/supply/exported"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
|
||||
hardkeeper "github.com/kava-labs/kava/x/hard/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
@ -26,58 +18,35 @@ import (
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
keeper keeper.Keeper
|
||||
hardKeeper hardkeeper.Keeper
|
||||
stakingKeeper stakingkeeper.Keeper
|
||||
committeeKeeper committeekeeper.Keeper
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
addrs []sdk.AccAddress
|
||||
validatorAddrs []sdk.ValAddress
|
||||
keeper keeper.Keeper
|
||||
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
|
||||
genesisTime time.Time
|
||||
addrs []sdk.AccAddress
|
||||
}
|
||||
|
||||
// The default state used by each test
|
||||
// SetupTest is run automatically before each suite test
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
config := sdk.GetConfig()
|
||||
app.SetBech32AddressPrefixes(config)
|
||||
|
||||
_, allAddrs := app.GeneratePrivKeyAddressPairs(10)
|
||||
suite.addrs = allAddrs[:5]
|
||||
for _, a := range allAddrs[5:] {
|
||||
suite.validatorAddrs = append(suite.validatorAddrs, sdk.ValAddress(a))
|
||||
}
|
||||
_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
|
||||
|
||||
tApp := app.NewTestApp()
|
||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||
|
||||
tApp.InitializeFromGenesisStates()
|
||||
|
||||
suite.keeper = tApp.GetIncentiveKeeper()
|
||||
suite.app = tApp
|
||||
suite.ctx = ctx
|
||||
suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
// getAllAddrs returns all user and validator addresses in the suite
|
||||
func (suite *KeeperTestSuite) getAllAddrs() []sdk.AccAddress {
|
||||
accAddrs := []sdk.AccAddress{} // initialize new slice to avoid accidental modifications to underlying
|
||||
accAddrs = append(accAddrs, suite.addrs...)
|
||||
for _, a := range suite.validatorAddrs {
|
||||
accAddrs = append(accAddrs, sdk.AccAddress(a))
|
||||
}
|
||||
return accAddrs
|
||||
}
|
||||
func (suite *KeeperTestSuite) SetupApp() {
|
||||
suite.app = app.NewTestApp()
|
||||
|
||||
func (suite *KeeperTestSuite) getAccount(addr sdk.AccAddress) authexported.Account {
|
||||
ak := suite.app.GetAccountKeeper()
|
||||
return ak.GetAccount(suite.ctx, addr)
|
||||
}
|
||||
suite.keeper = suite.app.GetIncentiveKeeper()
|
||||
|
||||
func (suite *KeeperTestSuite) getModuleAccount(name string) supplyexported.ModuleAccountI {
|
||||
sk := suite.app.GetSupplyKeeper()
|
||||
return sk.GetModuleAccount(suite.ctx, name)
|
||||
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: suite.genesisTime})
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGetSetDeleteUSDXMintingClaim() {
|
||||
suite.SetupApp()
|
||||
c := types.NewUSDXMintingClaim(suite.addrs[0], c("ukava", 1000000), types.RewardIndexes{types.NewRewardIndex("bnb-a", sdk.ZeroDec())})
|
||||
_, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||
suite.Require().False(found)
|
||||
@ -95,6 +64,7 @@ func (suite *KeeperTestSuite) TestGetSetDeleteUSDXMintingClaim() {
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestIterateUSDXMintingClaims() {
|
||||
suite.SetupApp()
|
||||
for i := 0; i < len(suite.addrs); i++ {
|
||||
c := types.NewUSDXMintingClaim(suite.addrs[i], c("ukava", 100000), types.RewardIndexes{types.NewRewardIndex("bnb-a", sdk.ZeroDec())})
|
||||
suite.Require().NotPanics(func() {
|
||||
@ -112,28 +82,6 @@ func (suite *KeeperTestSuite) TestIterateUSDXMintingClaims() {
|
||||
suite.Require().Equal(len(suite.addrs), len(claims))
|
||||
}
|
||||
|
||||
func createPeriodicVestingAccount(origVesting sdk.Coins, periods vesting.Periods, startTime, endTime int64) (*vesting.PeriodicVestingAccount, error) {
|
||||
_, addr := app.GeneratePrivKeyAddressPairs(1)
|
||||
bacc := auth.NewBaseAccountWithAddress(addr[0])
|
||||
bacc.Coins = origVesting
|
||||
bva, err := vesting.NewBaseVestingAccount(&bacc, origVesting, endTime)
|
||||
if err != nil {
|
||||
return &vesting.PeriodicVestingAccount{}, err
|
||||
}
|
||||
pva := vesting.NewPeriodicVestingAccountRaw(bva, startTime, periods)
|
||||
err = pva.Validate()
|
||||
if err != nil {
|
||||
return &vesting.PeriodicVestingAccount{}, err
|
||||
}
|
||||
return pva, nil
|
||||
}
|
||||
|
||||
// Avoid cluttering test cases with long function names
|
||||
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
||||
func d(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) }
|
||||
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
||||
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,23 +1,75 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/stretchr/testify/suite"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/committee"
|
||||
committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
hardtypes "github.com/kava-labs/kava/x/hard/types"
|
||||
hardkeeper "github.com/kava-labs/kava/x/hard/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
// Test suite used for all keeper tests
|
||||
type BorrowRewardsTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
keeper keeper.Keeper
|
||||
hardKeeper hardkeeper.Keeper
|
||||
committeeKeeper committeekeeper.Keeper
|
||||
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
|
||||
genesisTime time.Time
|
||||
addrs []sdk.AccAddress
|
||||
}
|
||||
|
||||
// SetupTest is run automatically before each suite test
|
||||
func (suite *BorrowRewardsTestSuite) SetupTest() {
|
||||
config := sdk.GetConfig()
|
||||
app.SetBech32AddressPrefixes(config)
|
||||
|
||||
_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
|
||||
|
||||
suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func (suite *BorrowRewardsTestSuite) SetupApp() {
|
||||
suite.app = app.NewTestApp()
|
||||
|
||||
suite.keeper = suite.app.GetIncentiveKeeper()
|
||||
suite.hardKeeper = suite.app.GetHardKeeper()
|
||||
suite.committeeKeeper = suite.app.GetCommitteeKeeper()
|
||||
|
||||
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: suite.genesisTime})
|
||||
}
|
||||
|
||||
func (suite *BorrowRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGenesisBuilder, incentBuilder IncentiveGenesisBuilder, hardBuilder HardGenesisBuilder) {
|
||||
suite.SetupApp()
|
||||
|
||||
suite.app.InitializeFromGenesisStatesWithTime(
|
||||
suite.genesisTime,
|
||||
authBuilder.BuildMarshalled(),
|
||||
NewPricefeedGenStateMultiFromTime(suite.genesisTime),
|
||||
hardBuilder.BuildMarshalled(),
|
||||
NewCommitteeGenesisState(suite.addrs[:2]), // TODO add committee members to suite,
|
||||
incentBuilder.BuildMarshalled(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *BorrowRewardsTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
type args struct {
|
||||
borrow sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
timeElapsed int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
}
|
||||
@ -31,7 +83,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.000000856478000001"))},
|
||||
},
|
||||
@ -41,7 +92,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.010571385600010177"))},
|
||||
},
|
||||
@ -51,7 +101,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 0,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.0"))},
|
||||
},
|
||||
@ -61,7 +110,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.000000856478000001")),
|
||||
@ -74,7 +122,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.010571385600010177")),
|
||||
@ -87,7 +134,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 0,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.0")),
|
||||
@ -100,7 +146,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
args{
|
||||
borrow: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 555555)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.010571385600010177")),
|
||||
@ -111,43 +156,22 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, tc.args.borrow.Denom, rewardIndexes)
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleBorrowRewardPeriod(tc.args.borrow.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
suite.Require().NoError(err)
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Set up chain context at future time
|
||||
@ -175,13 +199,12 @@ func (suite *KeeperTestSuite) TestAccumulateHardBorrowRewards() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
func (suite *BorrowRewardsTestSuite) TestInitializeHardBorrowRewards() {
|
||||
|
||||
type args struct {
|
||||
moneyMarketRewardDenoms map[string][]string
|
||||
moneyMarketRewardDenoms map[string]sdk.Coins
|
||||
deposit sdk.Coins
|
||||
borrow sdk.Coins
|
||||
initialTime time.Time
|
||||
expectedClaimBorrowRewardIndexes types.MultiRewardIndexes
|
||||
}
|
||||
type test struct {
|
||||
@ -189,10 +212,9 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
args args
|
||||
}
|
||||
|
||||
standardMoneyMarketRewardDenoms := map[string][]string{
|
||||
"bnb": {"hard"},
|
||||
"btcb": {"hard", "ukava"},
|
||||
"xrp": {},
|
||||
standardMoneyMarketRewardDenoms := map[string]sdk.Coins{
|
||||
"bnb": cs(c("hard", 1)),
|
||||
"btcb": cs(c("hard", 1), c("ukava", 1)),
|
||||
}
|
||||
|
||||
testCases := []test{
|
||||
@ -202,7 +224,6 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000)),
|
||||
borrow: cs(c("bnb", 100000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimBorrowRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -219,7 +240,6 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("btcb", 1000000000000)),
|
||||
borrow: cs(c("btcb", 100000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimBorrowRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"btcb",
|
||||
@ -237,7 +257,6 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("xrp", 1000000000000)),
|
||||
borrow: cs(c("xrp", 100000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimBorrowRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"xrp",
|
||||
@ -252,7 +271,6 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000), c("btcb", 1000000000000)),
|
||||
borrow: cs(c("bnb", 100000000000), c("btcb", 100000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimBorrowRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -276,7 +294,6 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000), c("xrp", 1000000000000)),
|
||||
borrow: cs(c("bnb", 100000000000), c("xrp", 100000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimBorrowRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -294,64 +311,24 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
userAddr := suite.addrs[3]
|
||||
|
||||
// Prepare money market + reward params
|
||||
i := 0
|
||||
var multiRewardPeriods types.MultiRewardPeriods
|
||||
var rewardPeriods types.RewardPeriods
|
||||
for moneyMarketDenom, rewardDenoms := range tc.args.moneyMarketRewardDenoms {
|
||||
// Set up multi reward periods for supply/borrow indexes with dynamic money market denoms/reward denoms
|
||||
var rewardsPerSecond sdk.Coins
|
||||
for _, rewardDenom := range rewardDenoms {
|
||||
rewardsPerSecond = append(rewardsPerSecond, sdk.NewCoin(rewardDenom, sdk.OneInt()))
|
||||
}
|
||||
multiRewardPeriod := types.NewMultiRewardPeriod(true, moneyMarketDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), rewardsPerSecond)
|
||||
multiRewardPeriods = append(multiRewardPeriods, multiRewardPeriod)
|
||||
|
||||
// Set up generic reward periods for usdx minting/delegator indexes
|
||||
if i == 0 && len(rewardDenoms) > 0 {
|
||||
rewardPeriod := types.NewRewardPeriod(true, moneyMarketDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), rewardsPerSecond[i])
|
||||
rewardPeriods = append(rewardPeriods, rewardPeriod)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize and set incentive params
|
||||
params := types.NewParams(
|
||||
rewardPeriods, multiRewardPeriods, multiRewardPeriods, rewardPeriods,
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
|
||||
// Set each money market's previous accrual time and supply reward indexes
|
||||
for moneyMarketDenom, rewardDenoms := range tc.args.moneyMarketRewardDenoms {
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardDenom := range rewardDenoms {
|
||||
rewardIndex := types.NewRewardIndex(rewardDenom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, moneyMarketDenom, tc.args.initialTime)
|
||||
if len(rewardIndexes) > 0 {
|
||||
suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, moneyMarketDenom, rewardIndexes)
|
||||
}
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime)
|
||||
for moneyMarketDenom, rewardsPerSecond := range tc.args.moneyMarketRewardDenoms {
|
||||
incentBuilder = incentBuilder.WithSimpleBorrowRewardPeriod(moneyMarketDenom, rewardsPerSecond)
|
||||
}
|
||||
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, tc.args.deposit)
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, tc.args.deposit)
|
||||
suite.Require().NoError(err)
|
||||
// User borrows
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.borrow)
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, tc.args.borrow)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
claim, foundClaim := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
@ -361,12 +338,11 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
func (suite *BorrowRewardsTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
type args struct {
|
||||
incentiveBorrowRewardDenom string
|
||||
borrow sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
blockTimes []int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
expectedRewards sdk.Coins
|
||||
@ -389,7 +365,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.001223540000173228"))},
|
||||
expectedRewards: cs(c("hard", 12235400)),
|
||||
@ -402,7 +377,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("10.571385603126235340"))},
|
||||
expectedRewards: cs(c("hard", 105713856031)),
|
||||
@ -414,7 +388,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "ukava",
|
||||
borrow: c("ukava", 1), // borrow a tiny amount so that rewards round to zero
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.122354003908172328"))},
|
||||
expectedRewards: cs(),
|
||||
@ -427,7 +400,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.001223540000173228")),
|
||||
@ -442,7 +414,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("10.571385603126235340")),
|
||||
@ -457,7 +428,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 555555)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.001223540000173228")),
|
||||
@ -466,33 +436,12 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
expectedRewards: cs(c("hard", 12235400), c("ukava", 55555500)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in incentive's hard borrow reward params but it has no rewards; add reward",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
updateRewardsViaCommmittee: true,
|
||||
updatedBaseDenom: "bnb",
|
||||
updatedRewardsPerSecond: cs(c("hard", 100000)),
|
||||
updatedExpectedRewards: cs(c("hard", 8640000000)),
|
||||
updatedExpectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.864000000049803065")),
|
||||
},
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in incentive's hard borrow reward params and has rewards; add new reward type",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("1.057138560060101160")),
|
||||
@ -514,8 +463,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("zzz", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: nil,
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
@ -529,35 +477,12 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom incentive's hard borrow reward params but it has no rewards; add multiple reward types",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
updateRewardsViaCommmittee: true,
|
||||
updatedBaseDenom: "bnb",
|
||||
updatedRewardsPerSecond: cs(c("hard", 100000), c("ukava", 100500), c("swap", 500)),
|
||||
updatedExpectedRewards: cs(c("hard", 8640000000), c("ukava", 8683200001), c("swap", 43200000)),
|
||||
updatedExpectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.864000000049803065")),
|
||||
types.NewRewardIndex("ukava", d("0.868320000050052081")),
|
||||
types.NewRewardIndex("swap", d("0.004320000000249015")),
|
||||
},
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in hard's money market params but not in incentive's hard supply reward params; add multiple reward types",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("zzz", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: nil,
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
@ -573,45 +498,23 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
// TODO test synchronize when there is a reward period with 0 rewardsPerSecond
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[2], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(userAddr, cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// Set up incentive state
|
||||
incentiveParams := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.incentiveBorrowRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.incentiveBorrowRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), sdk.Coins{})}, // Don't set any supply rewards for easier accounting
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.incentiveBorrowRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.incentiveBorrowRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, incentiveParams)
|
||||
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, tc.args.incentiveBorrowRewardDenom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime)
|
||||
if tc.args.rewardsPerSecond != nil {
|
||||
incentBuilder = incentBuilder.WithSimpleBorrowRewardPeriod(tc.args.incentiveBorrowRewardDenom, tc.args.rewardsPerSecond)
|
||||
}
|
||||
if len(rewardIndexes) > 0 {
|
||||
suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, tc.args.incentiveBorrowRewardDenom, rewardIndexes)
|
||||
}
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
// Set the minimum borrow to 0 to allow testing small borrows
|
||||
hardParams := suite.hardKeeper.GetParams(suite.ctx)
|
||||
hardParams.MinimumBorrowUSDValue = sdk.ZeroDec()
|
||||
suite.hardKeeper.SetParams(suite.ctx, hardParams)
|
||||
hardBuilder := NewHardGenStateMulti(suite.genesisTime).WithMinBorrow(sdk.ZeroDec())
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, hardBuilder)
|
||||
|
||||
// Borrow a fixed amount from another user to dilute primary user's rewards per second.
|
||||
suite.Require().NoError(
|
||||
@ -622,11 +525,9 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
)
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
suite.Require().NoError(err)
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Check that Hard hooks initialized a HardLiquidityProviderClaim
|
||||
@ -662,7 +563,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// After we've accumulated, run synchronize
|
||||
borrow, found := hardKeeper.GetBorrow(suite.ctx, userAddr)
|
||||
borrow, found := suite.hardKeeper.GetBorrow(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.keeper.SynchronizeHardBorrowReward(suite.ctx, borrow)
|
||||
@ -714,7 +615,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
// Borrow denom's reward period does not exist
|
||||
_, found := currIncentiveHardBorrowRewardPeriods.GetMultiRewardPeriodIndex(tc.args.borrow.Denom)
|
||||
suite.Require().False(found)
|
||||
newMultiRewardPeriod := types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.updatedRewardsPerSecond)
|
||||
newMultiRewardPeriod := types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, suite.genesisTime, suite.genesisTime.Add(time.Hour*24*365*4), tc.args.updatedRewardsPerSecond)
|
||||
currIncentiveHardBorrowRewardPeriods = append(currIncentiveHardBorrowRewardPeriods, newMultiRewardPeriod)
|
||||
}
|
||||
|
||||
@ -742,7 +643,9 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
|
||||
// 5. Committee votes and passes proposal
|
||||
err = suite.committeeKeeper.AddVote(suite.ctx, proposalID, committeeMemberOne, committee.Yes)
|
||||
suite.Require().NoError(err)
|
||||
err = suite.committeeKeeper.AddVote(suite.ctx, proposalID, committeeMemberTwo, committee.Yes)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// 6. Check proposal passed
|
||||
com, found := suite.committeeKeeper.GetCommittee(suite.ctx, 1)
|
||||
@ -774,7 +677,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// After we've accumulated, run synchronize
|
||||
borrow, found = hardKeeper.GetBorrow(suite.ctx, userAddr)
|
||||
borrow, found = suite.hardKeeper.GetBorrow(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.keeper.SynchronizeHardBorrowReward(suite.ctx, borrow)
|
||||
@ -808,7 +711,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
func (suite *BorrowRewardsTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
type withdrawModification struct {
|
||||
coins sdk.Coins
|
||||
repay bool
|
||||
@ -819,7 +722,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow sdk.Coins
|
||||
modification withdrawModification
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
expectedBorrowIndexDenoms []string
|
||||
}
|
||||
type test struct {
|
||||
@ -835,7 +737,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("ukava", 500000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
||||
},
|
||||
},
|
||||
@ -846,7 +747,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("btcb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
||||
},
|
||||
},
|
||||
@ -857,7 +757,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("bnb", 50000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"bnb"},
|
||||
},
|
||||
},
|
||||
@ -868,7 +767,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("ukava", 500000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
||||
},
|
||||
},
|
||||
@ -879,7 +777,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("btcb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
||||
},
|
||||
},
|
||||
@ -890,7 +787,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 50000000)),
|
||||
modification: withdrawModification{coins: cs(c("bnb", 50000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"bnb"},
|
||||
},
|
||||
},
|
||||
@ -901,7 +797,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 100000000)),
|
||||
modification: withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{},
|
||||
},
|
||||
},
|
||||
@ -912,7 +807,6 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 100000000), c("ukava", 10000000)),
|
||||
modification: withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"ukava"},
|
||||
},
|
||||
},
|
||||
@ -923,70 +817,51 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
firstBorrow: cs(c("bnb", 100000000), c("ukava", 10000000)),
|
||||
modification: withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedBorrowIndexDenoms: []string{"ukava"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
).
|
||||
WithSimpleAccount(
|
||||
suite.addrs[0],
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
|
||||
// Mint coins to hard module account so it can service borrow requests
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := tc.args.firstBorrow.Add(tc.args.modification.coins...)
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleBorrowRewardPeriod("bnb", tc.args.rewardsPerSecond).
|
||||
WithSimpleBorrowRewardPeriod("ukava", tc.args.rewardsPerSecond).
|
||||
WithSimpleBorrowRewardPeriod("btcb", tc.args.rewardsPerSecond).
|
||||
WithSimpleBorrowRewardPeriod("xrp", tc.args.rewardsPerSecond)
|
||||
|
||||
// Set up generic reward periods
|
||||
var multiRewardPeriods types.MultiRewardPeriods
|
||||
var rewardPeriods types.RewardPeriods
|
||||
for i, denom := range tc.args.expectedBorrowIndexDenoms {
|
||||
// Create just one reward period for USDX Minting / Hard Delegator reward periods (otherwise params will panic on duplicate)
|
||||
if i == 0 {
|
||||
rewardPeriod := types.NewRewardPeriod(true, denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[i])
|
||||
rewardPeriods = append(rewardPeriods, rewardPeriod)
|
||||
}
|
||||
multiRewardPeriod := types.NewMultiRewardPeriod(true, denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)
|
||||
multiRewardPeriods = append(multiRewardPeriods, multiRewardPeriod)
|
||||
}
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// Setup incentive state
|
||||
params := types.NewParams(
|
||||
rewardPeriods, multiRewardPeriods, multiRewardPeriods, rewardPeriods,
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
|
||||
// Set each expected borrow denom's previous accrual time and borrow reward factor
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
for _, denom := range tc.args.expectedBorrowIndexDenoms {
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, denom, tc.args.initialTime)
|
||||
suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, denom, rewardIndexes)
|
||||
}
|
||||
// Fill the hard supply to allow user to borrow
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, suite.addrs[0], tc.args.firstBorrow.Add(tc.args.modification.coins...))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// User deposits initial funds (so that user can borrow)
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, tc.args.initialDeposit)
|
||||
err = suite.hardKeeper.Deposit(suite.ctx, userAddr, tc.args.initialDeposit)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Confirm that claim exists but no borrow reward indexes have been added
|
||||
claimAfterDeposit, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimAfterDeposit, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(0, len(claimAfterDeposit.BorrowRewardIndexes))
|
||||
|
||||
// User borrows (first time)
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.firstBorrow)
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, tc.args.firstBorrow)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Confirm that claim's borrow reward indexes have been updated
|
||||
claimAfterFirstBorrow, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimAfterFirstBorrow, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
for _, coin := range tc.args.firstBorrow {
|
||||
_, hasIndex := claimAfterFirstBorrow.HasBorrowRewardIndex(coin.Denom)
|
||||
@ -996,14 +871,14 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
|
||||
// User modifies their Borrow by either repaying or borrowing more
|
||||
if tc.args.modification.repay {
|
||||
err = hardKeeper.Repay(suite.ctx, userAddr, userAddr, tc.args.modification.coins)
|
||||
err = suite.hardKeeper.Repay(suite.ctx, userAddr, userAddr, tc.args.modification.coins)
|
||||
} else {
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
}
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Confirm that claim's borrow reward indexes contain expected values
|
||||
claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
for _, coin := range tc.args.modification.coins {
|
||||
_, hasIndex := claimAfterModification.HasBorrowRewardIndex(coin.Denom)
|
||||
@ -1021,11 +896,10 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
func (suite *BorrowRewardsTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
type args struct {
|
||||
borrow sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
blockTimes []int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
expectedRewards sdk.Coins
|
||||
@ -1041,7 +915,6 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
args{
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.001223540000173228"))},
|
||||
expectedRewards: cs(c("hard", 12235400)),
|
||||
@ -1052,7 +925,6 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
args{
|
||||
borrow: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("10.571385603126235340"))},
|
||||
expectedRewards: cs(c("hard", 105713856031)),
|
||||
@ -1061,55 +933,21 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(userAddr, cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleBorrowRewardPeriod(tc.args.borrow.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.borrow.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, tc.args.borrow.Denom, rewardIndexes)
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(sdk.NewCoin(tc.args.borrow.Denom, tc.args.borrow.Amount.Mul(sdk.NewInt(2)))))
|
||||
suite.Require().NoError(err)
|
||||
err = hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
err = suite.hardKeeper.Borrow(suite.ctx, userAddr, sdk.NewCoins(tc.args.borrow))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Check that Hard hooks initialized a HardLiquidityProviderClaim
|
||||
claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
suite.Require().True(found)
|
||||
multiRewardIndex, _ := claim.BorrowRewardIndexes.GetRewardIndex(tc.args.borrow.Denom)
|
||||
for _, expectedRewardIndex := range tc.args.expectedRewardIndexes {
|
||||
currRewardIndex, found := multiRewardIndex.RewardIndexes.GetRewardIndex(expectedRewardIndex.CollateralType)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(sdk.ZeroDec(), currRewardIndex.RewardFactor)
|
||||
}
|
||||
|
||||
// Run accumulator at several intervals
|
||||
var timeElapsed int
|
||||
previousBlockTime := suite.ctx.BlockTime()
|
||||
@ -1132,7 +970,7 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// Confirm that the user's claim hasn't been synced
|
||||
claimPre, foundPre := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimPre, foundPre := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(foundPre)
|
||||
multiRewardIndexPre, _ := claimPre.BorrowRewardIndexes.GetRewardIndex(tc.args.borrow.Denom)
|
||||
for _, expectedRewardIndex := range tc.args.expectedRewardIndexes {
|
||||
@ -1142,7 +980,7 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
}
|
||||
|
||||
// Check that the synced claim held in memory has properly simulated syncing
|
||||
syncedClaim := suite.keeper.SimulateHardSynchronization(suite.ctx, claim)
|
||||
syncedClaim := suite.keeper.SimulateHardSynchronization(suite.ctx, claimPre)
|
||||
for _, expectedRewardIndex := range tc.args.expectedRewardIndexes {
|
||||
// Check that the user's claim's reward index matches the expected reward index
|
||||
multiRewardIndex, found := syncedClaim.BorrowRewardIndexes.GetRewardIndex(tc.args.borrow.Denom)
|
||||
@ -1160,3 +998,7 @@ func (suite *KeeperTestSuite) TestSimulateHardBorrowRewardSynchronization() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBorrowRewardsTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(BorrowRewardsTestSuite))
|
||||
}
|
||||
|
@ -1,23 +1,73 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/stretchr/testify/suite"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
hardtypes "github.com/kava-labs/kava/x/hard/types"
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
// Test suite used for all keeper tests
|
||||
type DelegatorRewardsTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
keeper keeper.Keeper
|
||||
stakingKeeper stakingkeeper.Keeper
|
||||
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
|
||||
genesisTime time.Time
|
||||
addrs []sdk.AccAddress
|
||||
validatorAddrs []sdk.ValAddress
|
||||
}
|
||||
|
||||
// SetupTest is run automatically before each suite test
|
||||
func (suite *DelegatorRewardsTestSuite) SetupTest() {
|
||||
config := sdk.GetConfig()
|
||||
app.SetBech32AddressPrefixes(config)
|
||||
|
||||
_, allAddrs := app.GeneratePrivKeyAddressPairs(10)
|
||||
suite.addrs = allAddrs[:5]
|
||||
for _, a := range allAddrs[5:] {
|
||||
suite.validatorAddrs = append(suite.validatorAddrs, sdk.ValAddress(a))
|
||||
}
|
||||
suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func (suite *DelegatorRewardsTestSuite) SetupApp() {
|
||||
suite.app = app.NewTestApp()
|
||||
|
||||
suite.keeper = suite.app.GetIncentiveKeeper()
|
||||
suite.stakingKeeper = suite.app.GetStakingKeeper()
|
||||
|
||||
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: suite.genesisTime})
|
||||
}
|
||||
|
||||
func (suite *DelegatorRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGenesisBuilder, incentBuilder IncentiveGenesisBuilder) {
|
||||
suite.SetupApp()
|
||||
|
||||
suite.app.InitializeFromGenesisStatesWithTime(
|
||||
suite.genesisTime,
|
||||
authBuilder.BuildMarshalled(),
|
||||
NewStakingGenesisState(),
|
||||
incentBuilder.BuildMarshalled(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
type args struct {
|
||||
delegation sdk.Coin
|
||||
rewardsPerSecond sdk.Coin
|
||||
initialTime time.Time
|
||||
timeElapsed int
|
||||
expectedRewardFactor sdk.Dec
|
||||
}
|
||||
@ -31,7 +81,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardFactor: d("0.428239000000000000"),
|
||||
},
|
||||
@ -41,7 +90,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardFactor: d("5285.692800000000000000"),
|
||||
},
|
||||
@ -51,7 +99,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 0,
|
||||
expectedRewardFactor: d("0.0"),
|
||||
},
|
||||
@ -59,29 +106,15 @@ func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(tc.args.delegation.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
// Set up incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom, sdk.ZeroDec())
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
err := suite.deliverMsgCreateValidator(suite.ctx, suite.validatorAddrs[0], tc.args.delegation)
|
||||
suite.Require().NoError(err)
|
||||
@ -94,25 +127,21 @@ func (suite *KeeperTestSuite) TestAccumulateHardDelegatorRewards() {
|
||||
runAtTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed))
|
||||
runCtx := suite.ctx.WithBlockTime(runAtTime)
|
||||
|
||||
// Run Hard begin blocker in order to update the denom's index factor
|
||||
hard.BeginBlocker(runCtx, suite.hardKeeper)
|
||||
|
||||
rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(runCtx, tc.args.delegation.Denom)
|
||||
suite.Require().True(found)
|
||||
err = suite.keeper.AccumulateHardDelegatorRewards(runCtx, rewardPeriod)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
rewardFactor, found := suite.keeper.GetHardDelegatorRewardFactor(runCtx, tc.args.delegation.Denom)
|
||||
rewardFactor, _ := suite.keeper.GetHardDelegatorRewardFactor(runCtx, tc.args.delegation.Denom)
|
||||
suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
type args struct {
|
||||
delegation sdk.Coin
|
||||
rewardsPerSecond sdk.Coin
|
||||
initialTime time.Time
|
||||
blockTimes []int
|
||||
expectedRewardFactor sdk.Dec
|
||||
expectedRewards sdk.Coins
|
||||
@ -128,7 +157,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardFactor: d("6.117700000000000000"),
|
||||
expectedRewards: cs(c("hard", 6117700)),
|
||||
@ -139,7 +167,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardFactor: d("52856.928000000000000000"),
|
||||
expectedRewards: cs(c("hard", 52856928000)),
|
||||
@ -150,7 +177,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
args{
|
||||
delegation: c("ukava", 1),
|
||||
rewardsPerSecond: c("hard", 1),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardFactor: d("0.000099999900000100"),
|
||||
expectedRewards: nil,
|
||||
@ -159,29 +185,15 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(tc.args.delegation.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom, sdk.ZeroDec())
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
// Create validator account
|
||||
staking.BeginBlocker(suite.ctx, suite.stakingKeeper)
|
||||
@ -214,9 +226,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
previousBlockTime = updatedBlockTime
|
||||
blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// Run Hard begin blocker for each block ctx to update denom's interest factor
|
||||
hard.BeginBlocker(blockCtx, suite.hardKeeper)
|
||||
|
||||
rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(blockCtx, tc.args.delegation.Denom)
|
||||
suite.Require().True(found)
|
||||
|
||||
@ -232,7 +241,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
})
|
||||
|
||||
// Check that reward factor and claim have been updated as expected
|
||||
rewardFactor, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom)
|
||||
rewardFactor, _ := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom)
|
||||
suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
|
||||
|
||||
claim, found = suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
|
||||
@ -243,11 +252,10 @@ func (suite *KeeperTestSuite) TestSynchronizeHardDelegatorReward() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
type args struct {
|
||||
delegation sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
rewardsPerSecond sdk.Coin
|
||||
blockTimes []int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
expectedRewards sdk.Coins
|
||||
@ -262,8 +270,7 @@ func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
"10 blocks",
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("ukava", d("6.117700000000000000"))}, // Here the reward index stores data differently than inside a MultiRewardIndex
|
||||
expectedRewards: cs(c("hard", 6117700)),
|
||||
@ -273,8 +280,7 @@ func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
"10 blocks - long block time",
|
||||
args{
|
||||
delegation: c("ukava", 1_000_000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: c("hard", 122354),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("ukava", d("52856.928000000000000000"))},
|
||||
expectedRewards: cs(c("hard", 52856928000)),
|
||||
@ -284,29 +290,15 @@ func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(tc.args.delegation.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.delegation.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom, sdk.ZeroDec())
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.delegation.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
// Delegator delegates
|
||||
err := suite.deliverMsgCreateValidator(suite.ctx, suite.validatorAddrs[0], tc.args.delegation)
|
||||
@ -330,9 +322,6 @@ func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
previousBlockTime = updatedBlockTime
|
||||
blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// Run Hard begin blocker for each block ctx to update denom's interest factor
|
||||
hard.BeginBlocker(blockCtx, suite.hardKeeper)
|
||||
|
||||
// Accumulate hard delegator rewards
|
||||
rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(blockCtx, tc.args.delegation.Denom)
|
||||
suite.Require().True(found)
|
||||
@ -360,7 +349,7 @@ func (suite *KeeperTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) deliverMsgCreateValidator(ctx sdk.Context, address sdk.ValAddress, selfDelegation sdk.Coin) error {
|
||||
func (suite *DelegatorRewardsTestSuite) deliverMsgCreateValidator(ctx sdk.Context, address sdk.ValAddress, selfDelegation sdk.Coin) error {
|
||||
msg := staking.NewMsgCreateValidator(
|
||||
address,
|
||||
ed25519.GenPrivKey().PubKey(),
|
||||
@ -374,7 +363,7 @@ func (suite *KeeperTestSuite) deliverMsgCreateValidator(ctx sdk.Context, address
|
||||
return err
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) deliverMsgDelegate(ctx sdk.Context, delegator sdk.AccAddress, validator sdk.ValAddress, amount sdk.Coin) error {
|
||||
func (suite *DelegatorRewardsTestSuite) deliverMsgDelegate(ctx sdk.Context, delegator sdk.AccAddress, validator sdk.ValAddress, amount sdk.Coin) error {
|
||||
msg := staking.NewMsgDelegate(
|
||||
delegator,
|
||||
validator,
|
||||
@ -385,7 +374,7 @@ func (suite *KeeperTestSuite) deliverMsgDelegate(ctx sdk.Context, delegator sdk.
|
||||
return err
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) deliverMsgRedelegate(ctx sdk.Context, delegator sdk.AccAddress, sourceValidator, destinationValidator sdk.ValAddress, amount sdk.Coin) error {
|
||||
func (suite *DelegatorRewardsTestSuite) deliverMsgRedelegate(ctx sdk.Context, delegator sdk.AccAddress, sourceValidator, destinationValidator sdk.ValAddress, amount sdk.Coin) error {
|
||||
msg := staking.NewMsgBeginRedelegate(
|
||||
delegator,
|
||||
sourceValidator,
|
||||
@ -398,28 +387,24 @@ func (suite *KeeperTestSuite) deliverMsgRedelegate(ctx sdk.Context, delegator sd
|
||||
}
|
||||
|
||||
// given a user has a delegation to a bonded validator, when the validator starts unbonding, the user does not accumulate rewards
|
||||
func (suite *KeeperTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
suite.SetupWithGenState()
|
||||
initialTime := time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime)
|
||||
blockDuration := 10 * time.Second
|
||||
func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(suite.addrs[2], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[2]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Setup incentive state
|
||||
rewardsPerSecond := c("hard", 122354)
|
||||
bondDenom := "ukava"
|
||||
params := types.NewParams(
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
types.RewardPeriods{
|
||||
types.NewRewardPeriod(true, bondDenom, initialTime.Add(-1*oneYear), initialTime.Add(4*oneYear), rewardsPerSecond),
|
||||
},
|
||||
types.DefaultMultipliers,
|
||||
initialTime.Add(5*oneYear),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, bondDenom, initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, bondDenom, sdk.ZeroDec())
|
||||
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(bondDenom, rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
blockDuration := 10 * time.Second
|
||||
|
||||
// Reduce the size of the validator set
|
||||
stakingParams := suite.app.GetStakingKeeper().GetParams(suite.ctx)
|
||||
@ -437,7 +422,7 @@ func (suite *KeeperTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
// End the block so top validators become bonded
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(1 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(1 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Delegate to a bonded validator from the test user. This will initialize their incentive claim.
|
||||
@ -446,7 +431,7 @@ func (suite *KeeperTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
|
||||
// Start a new block to accumulate some delegation rewards for the user.
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(2 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(2 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Delegate to the unbonded validator to push it into the bonded validator set, pushing out the user's delegated validator
|
||||
@ -473,7 +458,7 @@ func (suite *KeeperTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
)
|
||||
|
||||
// Run another block and check the claim is not accumulating more rewards
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(3 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{})
|
||||
|
||||
suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, suite.addrs[0], nil, false)
|
||||
@ -492,28 +477,24 @@ func (suite *KeeperTestSuite) TestUnbondingValidatorSyncsClaim() {
|
||||
}
|
||||
|
||||
// given a user has a delegation to an unbonded validator, when the validator becomes bonded, the user starts accumulating rewards
|
||||
func (suite *KeeperTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
suite.SetupWithGenState()
|
||||
initialTime := time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime)
|
||||
blockDuration := 10 * time.Second
|
||||
func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(suite.addrs[2], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[2]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Setup incentive state
|
||||
rewardsPerSecond := c("hard", 122354)
|
||||
bondDenom := "ukava"
|
||||
params := types.NewParams(
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
types.RewardPeriods{
|
||||
types.NewRewardPeriod(true, bondDenom, initialTime.Add(-1*oneYear), initialTime.Add(4*oneYear), rewardsPerSecond),
|
||||
},
|
||||
types.DefaultMultipliers,
|
||||
initialTime.Add(5*oneYear),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, bondDenom, initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, bondDenom, sdk.ZeroDec())
|
||||
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(bondDenom, rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
blockDuration := 10 * time.Second
|
||||
|
||||
// Reduce the size of the validator set
|
||||
stakingParams := suite.app.GetStakingKeeper().GetParams(suite.ctx)
|
||||
@ -531,7 +512,7 @@ func (suite *KeeperTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
// End the block so top validators become bonded
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(1 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(1 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Delegate to an unbonded validator from the test user. This will initialize their incentive claim.
|
||||
@ -540,7 +521,7 @@ func (suite *KeeperTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
|
||||
// Start a new block to accumulate some delegation rewards globally.
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(2 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(2 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{})
|
||||
|
||||
// Delegate to the user's unbonded validator to push it into the bonded validator set
|
||||
@ -567,7 +548,7 @@ func (suite *KeeperTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
)
|
||||
|
||||
// Run another block and check the claim is accumulating more rewards
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(3 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{})
|
||||
|
||||
suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, suite.addrs[0], nil, false)
|
||||
@ -586,28 +567,22 @@ func (suite *KeeperTestSuite) TestBondingValidatorSyncsClaim() {
|
||||
}
|
||||
|
||||
// If a validator is slashed delegators should have their claims synced
|
||||
func (suite *KeeperTestSuite) TestSlashingValidatorSyncsClaim() {
|
||||
suite.SetupWithGenState()
|
||||
initialTime := time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime)
|
||||
blockDuration := 10 * time.Second
|
||||
func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() {
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Setup incentive state
|
||||
rewardsPerSecond := c("hard", 122354)
|
||||
bondDenom := "ukava"
|
||||
params := types.NewParams(
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
types.RewardPeriods{
|
||||
types.NewRewardPeriod(true, bondDenom, initialTime.Add(-1*oneYear), initialTime.Add(4*oneYear), rewardsPerSecond),
|
||||
},
|
||||
types.DefaultMultipliers,
|
||||
initialTime.Add(5*oneYear),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, bondDenom, initialTime.Add(-1*blockDuration))
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, bondDenom, sdk.ZeroDec())
|
||||
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(bondDenom, rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
blockDuration := 10 * time.Second
|
||||
|
||||
// Reduce the size of the validator set
|
||||
stakingParams := suite.app.GetStakingKeeper().GetParams(suite.ctx)
|
||||
@ -623,7 +598,7 @@ func (suite *KeeperTestSuite) TestSlashingValidatorSyncsClaim() {
|
||||
// End the block so validators become bonded
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(1 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(1 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Delegate to a bonded validator from the test user. This will initialize their incentive claim.
|
||||
@ -642,7 +617,7 @@ func (suite *KeeperTestSuite) TestSlashingValidatorSyncsClaim() {
|
||||
|
||||
// Start a new block to accumulate some delegation rewards for the user.
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(2 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(2 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Fetch validator and slash them
|
||||
@ -673,28 +648,23 @@ func (suite *KeeperTestSuite) TestSlashingValidatorSyncsClaim() {
|
||||
}
|
||||
|
||||
// Given a delegation to a bonded validator, when a user redelegates everything to another (bonded) validator, the user's claim is synced
|
||||
func (suite *KeeperTestSuite) TestRedelegationSyncsClaim() {
|
||||
suite.SetupWithGenState()
|
||||
initialTime := time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime)
|
||||
blockDuration := 10 * time.Second
|
||||
func (suite *DelegatorRewardsTestSuite) TestRedelegationSyncsClaim() {
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[0], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9)))
|
||||
|
||||
// Setup incentive state
|
||||
rewardsPerSecond := c("hard", 122354)
|
||||
bondDenom := "ukava"
|
||||
params := types.NewParams(
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
types.RewardPeriods{
|
||||
types.NewRewardPeriod(true, bondDenom, initialTime.Add(-1*oneYear), initialTime.Add(4*oneYear), rewardsPerSecond),
|
||||
},
|
||||
types.DefaultMultipliers,
|
||||
initialTime.Add(5*oneYear),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardDelegatorRewardAccrualTime(suite.ctx, bondDenom, initialTime)
|
||||
suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, bondDenom, sdk.ZeroDec())
|
||||
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleDelegatorRewardPeriod(bondDenom, rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime)
|
||||
blockDuration := 10 * time.Second
|
||||
|
||||
// Create 2 validators
|
||||
err := suite.deliverMsgCreateValidator(suite.ctx, suite.validatorAddrs[0], c(bondDenom, 10_000_000))
|
||||
@ -708,7 +678,7 @@ func (suite *KeeperTestSuite) TestRedelegationSyncsClaim() {
|
||||
|
||||
// Start a new block to accumulate some delegation rewards globally.
|
||||
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||
suite.ctx = suite.ctx.WithBlockTime(initialTime.Add(1 * blockDuration))
|
||||
suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(1 * blockDuration))
|
||||
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||
|
||||
// Redelegate the user's delegation between the two validators. This should trigger hooks that sync the user's claim.
|
||||
@ -729,3 +699,7 @@ func (suite *KeeperTestSuite) TestRedelegationSyncsClaim() {
|
||||
claim.Reward,
|
||||
)
|
||||
}
|
||||
|
||||
func TestDelegatorRewardsTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(DelegatorRewardsTestSuite))
|
||||
}
|
||||
|
@ -1,23 +1,75 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/stretchr/testify/suite"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/committee"
|
||||
committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
hardtypes "github.com/kava-labs/kava/x/hard/types"
|
||||
hardkeeper "github.com/kava-labs/kava/x/hard/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
// Test suite used for all keeper tests
|
||||
type SupplyRewardsTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
keeper keeper.Keeper
|
||||
hardKeeper hardkeeper.Keeper
|
||||
committeeKeeper committeekeeper.Keeper
|
||||
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
|
||||
genesisTime time.Time
|
||||
addrs []sdk.AccAddress
|
||||
}
|
||||
|
||||
// SetupTest is run automatically before each suite test
|
||||
func (suite *SupplyRewardsTestSuite) SetupTest() {
|
||||
config := sdk.GetConfig()
|
||||
app.SetBech32AddressPrefixes(config)
|
||||
|
||||
_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
|
||||
|
||||
suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func (suite *SupplyRewardsTestSuite) SetupApp() {
|
||||
suite.app = app.NewTestApp()
|
||||
|
||||
suite.keeper = suite.app.GetIncentiveKeeper()
|
||||
suite.hardKeeper = suite.app.GetHardKeeper()
|
||||
suite.committeeKeeper = suite.app.GetCommitteeKeeper()
|
||||
|
||||
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: suite.genesisTime})
|
||||
}
|
||||
|
||||
func (suite *SupplyRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGenesisBuilder, incentBuilder IncentiveGenesisBuilder, hardBuilder HardGenesisBuilder) {
|
||||
suite.SetupApp()
|
||||
|
||||
suite.app.InitializeFromGenesisStatesWithTime(
|
||||
suite.genesisTime,
|
||||
authBuilder.BuildMarshalled(),
|
||||
NewPricefeedGenStateMultiFromTime(suite.genesisTime),
|
||||
hardBuilder.BuildMarshalled(),
|
||||
NewCommitteeGenesisState(suite.addrs[:2]), // TODO add committee members to suite
|
||||
incentBuilder.BuildMarshalled(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SupplyRewardsTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
type args struct {
|
||||
deposit sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
timeElapsed int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
}
|
||||
@ -31,7 +83,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.000000856478000000"))},
|
||||
},
|
||||
@ -41,7 +92,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.010571385600000000"))},
|
||||
},
|
||||
@ -51,7 +101,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 0,
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.0"))},
|
||||
},
|
||||
@ -61,7 +110,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.000000856478000000")),
|
||||
@ -74,7 +122,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.010571385600000000")),
|
||||
@ -87,7 +134,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 0,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.0")),
|
||||
@ -100,7 +146,6 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 555555)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.010571385600000000")),
|
||||
@ -108,55 +153,26 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"single reward denom, no rewards",
|
||||
args{
|
||||
deposit: c("bnb", 1000000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
timeElapsed: 7,
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
},
|
||||
},
|
||||
// TODO test accumulate when there is a reward period with 0 rewardsPerSecond
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// Set up incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, tc.args.deposit.Denom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
if len(rewardIndexes) > 0 {
|
||||
suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, tc.args.deposit.Denom, rewardIndexes)
|
||||
// suite.SetupWithGenState(authBuilder)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime)
|
||||
if tc.args.rewardsPerSecond != nil {
|
||||
incentBuilder = incentBuilder.WithSimpleSupplyRewardPeriod(tc.args.deposit.Denom, tc.args.rewardsPerSecond)
|
||||
}
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.deposit.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.deposit.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits to increase total supplied amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Set up chain context at future time
|
||||
@ -189,12 +205,11 @@ func (suite *KeeperTestSuite) TestAccumulateHardSupplyRewards() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
func (suite *SupplyRewardsTestSuite) TestInitializeHardSupplyRewards() {
|
||||
|
||||
type args struct {
|
||||
moneyMarketRewardDenoms map[string][]string
|
||||
moneyMarketRewardDenoms map[string]sdk.Coins
|
||||
deposit sdk.Coins
|
||||
initialTime time.Time
|
||||
expectedClaimSupplyRewardIndexes types.MultiRewardIndexes
|
||||
}
|
||||
type test struct {
|
||||
@ -202,10 +217,9 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args args
|
||||
}
|
||||
|
||||
standardMoneyMarketRewardDenoms := map[string][]string{
|
||||
"bnb": {"hard"},
|
||||
"btcb": {"hard", "ukava"},
|
||||
"xrp": {},
|
||||
standardMoneyMarketRewardDenoms := map[string]sdk.Coins{
|
||||
"bnb": cs(c("hard", 1)),
|
||||
"btcb": cs(c("hard", 1), c("ukava", 1)),
|
||||
}
|
||||
|
||||
testCases := []test{
|
||||
@ -214,7 +228,6 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args{
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimSupplyRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -230,7 +243,6 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args{
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("btcb", 1000000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimSupplyRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"btcb",
|
||||
@ -247,7 +259,6 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args{
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("xrp", 1000000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimSupplyRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"xrp",
|
||||
@ -261,7 +272,6 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args{
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000), c("btcb", 1000000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimSupplyRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -284,7 +294,6 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
args{
|
||||
moneyMarketRewardDenoms: standardMoneyMarketRewardDenoms,
|
||||
deposit: cs(c("bnb", 1000000000000), c("xrp", 1000000000000)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedClaimSupplyRewardIndexes: types.MultiRewardIndexes{
|
||||
types.NewMultiRewardIndex(
|
||||
"bnb",
|
||||
@ -302,61 +311,20 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
userAddr := suite.addrs[3]
|
||||
|
||||
// Prepare money market + reward params
|
||||
i := 0
|
||||
var multiRewardPeriods types.MultiRewardPeriods
|
||||
var rewardPeriods types.RewardPeriods
|
||||
for moneyMarketDenom, rewardDenoms := range tc.args.moneyMarketRewardDenoms {
|
||||
// Set up multi reward periods for supply/borrow indexes with dynamic money market denoms/reward denoms
|
||||
var rewardsPerSecond sdk.Coins
|
||||
for _, rewardDenom := range rewardDenoms {
|
||||
rewardsPerSecond = append(rewardsPerSecond, sdk.NewCoin(rewardDenom, sdk.OneInt()))
|
||||
}
|
||||
multiRewardPeriod := types.NewMultiRewardPeriod(true, moneyMarketDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), rewardsPerSecond)
|
||||
multiRewardPeriods = append(multiRewardPeriods, multiRewardPeriod)
|
||||
|
||||
// Set up generic reward periods for usdx minting/delegator indexes
|
||||
if i == 0 && len(rewardDenoms) > 0 {
|
||||
rewardPeriod := types.NewRewardPeriod(true, moneyMarketDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), rewardsPerSecond[i])
|
||||
rewardPeriods = append(rewardPeriods, rewardPeriod)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize and set incentive params
|
||||
params := types.NewParams(
|
||||
rewardPeriods, multiRewardPeriods, multiRewardPeriods, rewardPeriods,
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
|
||||
// Set each money market's previous accrual time and supply reward indexes
|
||||
for moneyMarketDenom, rewardDenoms := range tc.args.moneyMarketRewardDenoms {
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardDenom := range rewardDenoms {
|
||||
rewardIndex := types.NewRewardIndex(rewardDenom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, moneyMarketDenom, tc.args.initialTime)
|
||||
if len(rewardIndexes) > 0 {
|
||||
suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, moneyMarketDenom, rewardIndexes)
|
||||
}
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime)
|
||||
for moneyMarketDenom, rewardsPerSecond := range tc.args.moneyMarketRewardDenoms {
|
||||
incentBuilder = incentBuilder.WithSimpleSupplyRewardPeriod(moneyMarketDenom, rewardsPerSecond)
|
||||
}
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, tc.args.deposit)
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, tc.args.deposit)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
claim, foundClaim := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
@ -366,12 +334,11 @@ func (suite *KeeperTestSuite) TestInitializeHardSupplyRewards() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
func (suite *SupplyRewardsTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
type args struct {
|
||||
incentiveSupplyRewardDenom string
|
||||
deposit sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
blockTimes []int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
expectedRewards sdk.Coins
|
||||
@ -394,7 +361,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.001223540000000000"))},
|
||||
expectedRewards: cs(c("hard", 12235400)),
|
||||
@ -407,7 +373,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("10.571385600000000000"))},
|
||||
expectedRewards: cs(c("hard", 105713856000)),
|
||||
@ -420,7 +385,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "ukava",
|
||||
deposit: c("ukava", 1),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.122353998776460010"))},
|
||||
expectedRewards: cs(),
|
||||
@ -433,7 +397,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.001223540000000000")),
|
||||
@ -449,7 +412,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("10.571385600000000000")),
|
||||
@ -465,7 +427,6 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 555555)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.001223540000000000")),
|
||||
@ -475,33 +436,12 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
updateRewardsViaCommmittee: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in incentive's hard supply reward params but it has no rewards; add reward",
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
updateRewardsViaCommmittee: true,
|
||||
updatedBaseDenom: "bnb",
|
||||
updatedRewardsPerSecond: cs(c("hard", 100000)),
|
||||
updatedExpectedRewards: cs(c("hard", 8640000000)),
|
||||
updatedExpectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.864")),
|
||||
},
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in incentive's hard supply reward params and has rewards; add new reward type",
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("1.057138560000000000")),
|
||||
@ -523,8 +463,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("zzz", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: nil,
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
@ -538,35 +477,12 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom incentive's hard supply reward params but it has no rewards; add multiple reward types",
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
updateRewardsViaCommmittee: true,
|
||||
updatedBaseDenom: "bnb",
|
||||
updatedRewardsPerSecond: cs(c("hard", 100000), c("ukava", 100500), c("swap", 500)),
|
||||
updatedExpectedRewards: cs(c("hard", 8640000000), c("ukava", 8683200000), c("swap", 43200000)),
|
||||
updatedExpectedRewardIndexes: types.RewardIndexes{
|
||||
types.NewRewardIndex("hard", d("0.864")),
|
||||
types.NewRewardIndex("ukava", d("0.86832")),
|
||||
types.NewRewardIndex("swap", d("0.00432")),
|
||||
},
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
{
|
||||
"denom is in hard's money market params but not in incentive's hard supply reward params; add multiple reward types",
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "bnb",
|
||||
deposit: c("zzz", 10000000000),
|
||||
rewardsPerSecond: sdk.Coins{},
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: nil,
|
||||
blockTimes: []int{100},
|
||||
expectedRewardIndexes: types.RewardIndexes{},
|
||||
expectedRewards: sdk.Coins{},
|
||||
@ -582,41 +498,21 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
updatedTimeDuration: 86400,
|
||||
},
|
||||
},
|
||||
// TODO test synchronize when there is a reward period with 0 rewardsPerSecond
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().
|
||||
WithSimpleAccount(suite.addrs[2], cs(c("ukava", 1e9))).
|
||||
WithSimpleAccount(userAddr, cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)))
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// Set up incentive state
|
||||
incentiveParams := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), c("hard", 1))},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, incentiveParams)
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime)
|
||||
if tc.args.rewardsPerSecond != nil {
|
||||
incentBuilder = incentBuilder.WithSimpleSupplyRewardPeriod(tc.args.incentiveSupplyRewardDenom, tc.args.rewardsPerSecond)
|
||||
}
|
||||
if len(rewardIndexes) > 0 {
|
||||
suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, tc.args.incentiveSupplyRewardDenom, rewardIndexes)
|
||||
}
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.incentiveSupplyRewardDenom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.incentiveSupplyRewardDenom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// Deposit a fixed amount from another user to dilute primary user's rewards per second.
|
||||
suite.Require().NoError(
|
||||
@ -624,9 +520,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
)
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Check that Hard hooks initialized a HardLiquidityProviderClaim with 0 reward indexes
|
||||
@ -662,7 +556,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// After we've accumulated, run synchronize
|
||||
deposit, found := hardKeeper.GetDeposit(suite.ctx, userAddr)
|
||||
deposit, found := suite.hardKeeper.GetDeposit(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.keeper.SynchronizeHardSupplyReward(suite.ctx, deposit)
|
||||
@ -714,7 +608,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
// Deposit denom's reward period does not exist
|
||||
_, found := currIncentiveHardSupplyRewardPeriods.GetMultiRewardPeriodIndex(tc.args.deposit.Denom)
|
||||
suite.Require().False(found)
|
||||
newMultiRewardPeriod := types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.updatedRewardsPerSecond)
|
||||
newMultiRewardPeriod := types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, suite.genesisTime, suite.genesisTime.Add(time.Hour*24*365*4), tc.args.updatedRewardsPerSecond)
|
||||
currIncentiveHardSupplyRewardPeriods = append(currIncentiveHardSupplyRewardPeriods, newMultiRewardPeriod)
|
||||
}
|
||||
|
||||
@ -742,7 +636,9 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
|
||||
// 5. Committee votes and passes proposal
|
||||
err = suite.committeeKeeper.AddVote(suite.ctx, proposalID, committeeMemberOne, committee.Yes)
|
||||
suite.Require().NoError(err)
|
||||
err = suite.committeeKeeper.AddVote(suite.ctx, proposalID, committeeMemberTwo, committee.Yes)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// 6. Check proposal passed
|
||||
com, found := suite.committeeKeeper.GetCommittee(suite.ctx, 1)
|
||||
@ -773,7 +669,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// After we've accumulated, run synchronize
|
||||
deposit, found = hardKeeper.GetDeposit(suite.ctx, userAddr)
|
||||
deposit, found = suite.hardKeeper.GetDeposit(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.keeper.SynchronizeHardSupplyReward(suite.ctx, deposit)
|
||||
@ -807,7 +703,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
func (suite *SupplyRewardsTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
type depositModification struct {
|
||||
coins sdk.Coins
|
||||
withdraw bool
|
||||
@ -817,7 +713,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit sdk.Coins
|
||||
modification depositModification
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
expectedSupplyIndexDenoms []string
|
||||
}
|
||||
type test struct {
|
||||
@ -832,7 +727,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("ukava", 10000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
||||
},
|
||||
},
|
||||
@ -842,7 +736,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
|
||||
},
|
||||
},
|
||||
@ -852,7 +745,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("bnb", 5000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb"},
|
||||
},
|
||||
},
|
||||
@ -862,7 +754,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("ukava", 10000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
||||
},
|
||||
},
|
||||
@ -872,7 +763,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
|
||||
},
|
||||
},
|
||||
@ -882,7 +772,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 10000000000)),
|
||||
modification: depositModification{coins: cs(c("bnb", 5000000000))},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"bnb"},
|
||||
},
|
||||
},
|
||||
@ -892,7 +781,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 1000000000)),
|
||||
modification: depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{},
|
||||
},
|
||||
},
|
||||
@ -902,7 +790,6 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 1000000000), c("ukava", 100000000)),
|
||||
modification: depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{"ukava"},
|
||||
},
|
||||
},
|
||||
@ -912,61 +799,32 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
firstDeposit: cs(c("bnb", 1000000000)),
|
||||
modification: depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
|
||||
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
expectedSupplyIndexDenoms: []string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// Set up generic reward periods
|
||||
var multiRewardPeriods types.MultiRewardPeriods
|
||||
var rewardPeriods types.RewardPeriods
|
||||
for i, denom := range tc.args.expectedSupplyIndexDenoms {
|
||||
// Create just one reward period for USDX Minting / Hard Delegator reward periods (otherwise params will panic on duplicate)
|
||||
if i == 0 {
|
||||
rewardPeriod := types.NewRewardPeriod(true, denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[i])
|
||||
rewardPeriods = append(rewardPeriods, rewardPeriod)
|
||||
}
|
||||
multiRewardPeriod := types.NewMultiRewardPeriod(true, denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)
|
||||
multiRewardPeriods = append(multiRewardPeriods, multiRewardPeriod)
|
||||
}
|
||||
|
||||
// Setup incentive state
|
||||
params := types.NewParams(
|
||||
rewardPeriods, multiRewardPeriods, multiRewardPeriods, rewardPeriods,
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleSupplyRewardPeriod("bnb", tc.args.rewardsPerSecond).
|
||||
WithSimpleSupplyRewardPeriod("ukava", tc.args.rewardsPerSecond).
|
||||
WithSimpleSupplyRewardPeriod("btcb", tc.args.rewardsPerSecond).
|
||||
WithSimpleSupplyRewardPeriod("xrp", tc.args.rewardsPerSecond)
|
||||
|
||||
// Set each denom's previous accrual time and supply reward factor
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
for _, denom := range tc.args.expectedSupplyIndexDenoms {
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, denom, tc.args.initialTime)
|
||||
suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, denom, rewardIndexes)
|
||||
}
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits (first time)
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, tc.args.firstDeposit)
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, tc.args.firstDeposit)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Confirm that a claim was created and populated with the correct supply indexes
|
||||
claimAfterFirstDeposit, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimAfterFirstDeposit, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
for _, coin := range tc.args.firstDeposit {
|
||||
_, hasIndex := claimAfterFirstDeposit.HasSupplyRewardIndex(coin.Denom)
|
||||
@ -976,14 +834,14 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
|
||||
// User modifies their Deposit by withdrawing or depositing more
|
||||
if tc.args.modification.withdraw {
|
||||
err = hardKeeper.Withdraw(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
err = suite.hardKeeper.Withdraw(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
} else {
|
||||
err = hardKeeper.Deposit(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
err = suite.hardKeeper.Deposit(suite.ctx, userAddr, tc.args.modification.coins)
|
||||
}
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Confirm that the claim contains all expected supply indexes
|
||||
claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(found)
|
||||
for _, denom := range tc.args.expectedSupplyIndexDenoms {
|
||||
_, hasIndex := claimAfterModification.HasSupplyRewardIndex(denom)
|
||||
@ -994,11 +852,10 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
func (suite *SupplyRewardsTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
type args struct {
|
||||
deposit sdk.Coin
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
blockTimes []int
|
||||
expectedRewardIndexes types.RewardIndexes
|
||||
expectedRewards sdk.Coins
|
||||
@ -1014,7 +871,6 @@ func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
args{
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.001223540000000000"))},
|
||||
expectedRewards: cs(c("hard", 12235400)),
|
||||
@ -1025,7 +881,6 @@ func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
args{
|
||||
deposit: c("bnb", 10000000000),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("10.571385600000000000"))},
|
||||
expectedRewards: cs(c("hard", 105713856000)),
|
||||
@ -1034,52 +889,21 @@ func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
|
||||
// Mint coins to hard module account
|
||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
||||
hardMaccCoins := sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(200000000)))
|
||||
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||
|
||||
// Set up incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.deposit.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
userAddr := suite.addrs[3]
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(
|
||||
userAddr,
|
||||
cs(c("bnb", 1e15), c("ukava", 1e15), c("btcb", 1e15), c("xrp", 1e15), c("zzz", 1e15)),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, tc.args.deposit.Denom, tc.args.initialTime)
|
||||
var rewardIndexes types.RewardIndexes
|
||||
for _, rewardCoin := range tc.args.rewardsPerSecond {
|
||||
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
|
||||
rewardIndexes = append(rewardIndexes, rewardIndex)
|
||||
}
|
||||
suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, tc.args.deposit.Denom, rewardIndexes)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().
|
||||
WithGenesisTime(suite.genesisTime).
|
||||
WithSimpleSupplyRewardPeriod(tc.args.deposit.Denom, tc.args.rewardsPerSecond)
|
||||
|
||||
// Set up hard state (interest factor for the relevant denom)
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.deposit.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.deposit.Denom, tc.args.initialTime)
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder, NewHardGenStateMulti(suite.genesisTime))
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
err := hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
err := suite.hardKeeper.Deposit(suite.ctx, userAddr, sdk.NewCoins(tc.args.deposit))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Check that Hard hooks initialized a HardLiquidityProviderClaim
|
||||
claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
suite.Require().True(found)
|
||||
multiRewardIndex, _ := claim.SupplyRewardIndexes.GetRewardIndex(tc.args.deposit.Denom)
|
||||
for _, expectedRewardIndex := range tc.args.expectedRewardIndexes {
|
||||
currRewardIndex, found := multiRewardIndex.RewardIndexes.GetRewardIndex(expectedRewardIndex.CollateralType)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(sdk.ZeroDec(), currRewardIndex.RewardFactor)
|
||||
}
|
||||
|
||||
// Run accumulator at several intervals
|
||||
var timeElapsed int
|
||||
previousBlockTime := suite.ctx.BlockTime()
|
||||
@ -1102,7 +926,7 @@ func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
|
||||
// Confirm that the user's claim hasn't been synced
|
||||
claimPre, foundPre := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
|
||||
claimPre, foundPre := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, userAddr)
|
||||
suite.Require().True(foundPre)
|
||||
multiRewardIndexPre, _ := claimPre.SupplyRewardIndexes.GetRewardIndex(tc.args.deposit.Denom)
|
||||
for _, expectedRewardIndex := range tc.args.expectedRewardIndexes {
|
||||
@ -1130,3 +954,7 @@ func (suite *KeeperTestSuite) TestSimulateHardSupplyRewardSynchronization() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSupplyRewardsTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(SupplyRewardsTestSuite))
|
||||
}
|
||||
|
@ -1,23 +1,68 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
cdpkeeper "github.com/kava-labs/kava/x/cdp/keeper"
|
||||
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
||||
"github.com/kava-labs/kava/x/incentive/types"
|
||||
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||
)
|
||||
|
||||
const (
|
||||
oneYear time.Duration = time.Hour * 24 * 365
|
||||
)
|
||||
// Test suite used for all keeper tests
|
||||
type USDXRewardsTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
keeper keeper.Keeper
|
||||
cdpKeeper cdpkeeper.Keeper
|
||||
|
||||
app app.TestApp
|
||||
ctx sdk.Context
|
||||
|
||||
genesisTime time.Time
|
||||
addrs []sdk.AccAddress
|
||||
}
|
||||
|
||||
// SetupTest is run automatically before each suite test
|
||||
func (suite *USDXRewardsTestSuite) SetupTest() {
|
||||
config := sdk.GetConfig()
|
||||
app.SetBech32AddressPrefixes(config)
|
||||
|
||||
_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
|
||||
|
||||
suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func (suite *USDXRewardsTestSuite) SetupApp() {
|
||||
suite.app = app.NewTestApp()
|
||||
|
||||
suite.keeper = suite.app.GetIncentiveKeeper()
|
||||
suite.cdpKeeper = suite.app.GetCDPKeeper()
|
||||
|
||||
suite.ctx = suite.app.NewContext(true, abci.Header{Height: 1, Time: suite.genesisTime})
|
||||
}
|
||||
|
||||
func (suite *USDXRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGenesisBuilder, incentBuilder IncentiveGenesisBuilder) {
|
||||
suite.SetupApp()
|
||||
|
||||
suite.app.InitializeFromGenesisStatesWithTime(
|
||||
suite.genesisTime,
|
||||
authBuilder.BuildMarshalled(),
|
||||
NewPricefeedGenStateMultiFromTime(suite.genesisTime),
|
||||
NewCDPGenStateMulti(),
|
||||
incentBuilder.BuildMarshalled(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *USDXRewardsTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
type args struct {
|
||||
ctype string
|
||||
rewardsPerSecond sdk.Coin
|
||||
initialTime time.Time
|
||||
initialTotalPrincipal sdk.Coin
|
||||
timeElapsed int
|
||||
expectedRewardFactor sdk.Dec
|
||||
@ -32,7 +77,6 @@ func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
initialTotalPrincipal: c("usdx", 1000000000000),
|
||||
timeElapsed: 7,
|
||||
expectedRewardFactor: d("0.000000856478000000"),
|
||||
@ -43,7 +87,6 @@ func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
initialTotalPrincipal: c("usdx", 1000000000000),
|
||||
timeElapsed: 86400,
|
||||
expectedRewardFactor: d("0.0105713856"),
|
||||
@ -54,7 +97,6 @@ func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
initialTotalPrincipal: c("usdx", 1000000000000),
|
||||
timeElapsed: 0,
|
||||
expectedRewardFactor: d("0.0"),
|
||||
@ -63,25 +105,12 @@ func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
|
||||
|
||||
suite.SetupWithGenState(app.NewAuthGenesisBuilder(), incentBuilder)
|
||||
|
||||
// setup cdp state
|
||||
cdpKeeper := suite.app.GetCDPKeeper()
|
||||
cdpKeeper.SetTotalPrincipal(suite.ctx, tc.args.ctype, cdptypes.DefaultStableDenom, tc.args.initialTotalPrincipal.Amount)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, tc.args.ctype, tc.args.initialTime)
|
||||
suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype, sdk.ZeroDec())
|
||||
suite.cdpKeeper.SetTotalPrincipal(suite.ctx, tc.args.ctype, cdptypes.DefaultStableDenom, tc.args.initialTotalPrincipal.Amount)
|
||||
|
||||
updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed))
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
@ -90,17 +119,16 @@ func (suite *KeeperTestSuite) TestAccumulateUSDXMintingRewards() {
|
||||
err := suite.keeper.AccumulateUSDXMintingRewards(suite.ctx, rewardPeriod)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
rewardFactor, found := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
|
||||
rewardFactor, _ := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
|
||||
suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
func (suite *USDXRewardsTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
type args struct {
|
||||
ctype string
|
||||
rewardsPerSecond sdk.Coin
|
||||
initialTime time.Time
|
||||
initialCollateral sdk.Coin
|
||||
initialPrincipal sdk.Coin
|
||||
blockTimes []int
|
||||
@ -118,7 +146,6 @@ func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
initialCollateral: c("bnb", 1000000000000),
|
||||
initialPrincipal: c("usdx", 10000000000),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
@ -131,7 +158,6 @@ func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
initialCollateral: c("bnb", 1000000000000),
|
||||
initialPrincipal: c("usdx", 10000000000),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
@ -142,30 +168,13 @@ func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(suite.addrs[0], cs(tc.args.initialCollateral))
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, tc.args.ctype, tc.args.initialTime)
|
||||
suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype, sdk.ZeroDec())
|
||||
|
||||
// setup account state
|
||||
sk := suite.app.GetSupplyKeeper()
|
||||
sk.MintCoins(suite.ctx, cdptypes.ModuleName, sdk.NewCoins(tc.args.initialCollateral))
|
||||
sk.SendCoinsFromModuleToAccount(suite.ctx, cdptypes.ModuleName, suite.addrs[0], sdk.NewCoins(tc.args.initialCollateral))
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
// setup cdp state
|
||||
cdpKeeper := suite.app.GetCDPKeeper()
|
||||
err := cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
|
||||
err := suite.cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||
@ -186,13 +195,13 @@ func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
}
|
||||
updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
|
||||
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
|
||||
cdp, found := cdpKeeper.GetCdpByOwnerAndCollateralType(suite.ctx, suite.addrs[0], tc.args.ctype)
|
||||
cdp, found := suite.cdpKeeper.GetCdpByOwnerAndCollateralType(suite.ctx, suite.addrs[0], tc.args.ctype)
|
||||
suite.Require().True(found)
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.keeper.SynchronizeUSDXMintingReward(suite.ctx, cdp)
|
||||
})
|
||||
|
||||
rewardFactor, found := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
|
||||
rewardFactor, _ := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
|
||||
suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
|
||||
|
||||
claim, found = suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||
@ -203,11 +212,10 @@ func (suite *KeeperTestSuite) TestSynchronizeUSDXMintingReward() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
func (suite *USDXRewardsTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
type args struct {
|
||||
ctype string
|
||||
rewardsPerSecond sdk.Coins
|
||||
initialTime time.Time
|
||||
rewardsPerSecond sdk.Coin
|
||||
initialCollateral sdk.Coin
|
||||
initialPrincipal sdk.Coin
|
||||
blockTimes []int
|
||||
@ -224,8 +232,7 @@ func (suite *KeeperTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
"10 blocks",
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: cs(c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialCollateral: c("bnb", 1000000000000),
|
||||
initialPrincipal: c("usdx", 10000000000),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
@ -237,8 +244,7 @@ func (suite *KeeperTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
"10 blocks - long block time",
|
||||
args{
|
||||
ctype: "bnb-a",
|
||||
rewardsPerSecond: cs(c("ukava", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
rewardsPerSecond: c("ukava", 122354),
|
||||
initialCollateral: c("bnb", 1000000000000),
|
||||
initialPrincipal: c("usdx", 10000000000),
|
||||
blockTimes: []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
|
||||
@ -249,31 +255,13 @@ func (suite *KeeperTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupWithGenState()
|
||||
suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime)
|
||||
authBuilder := app.NewAuthGenesisBuilder().WithSimpleAccount(suite.addrs[0], cs(tc.args.initialCollateral))
|
||||
incentBuilder := NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
|
||||
|
||||
// setup incentive state
|
||||
params := types.NewParams(
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)},
|
||||
types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0])},
|
||||
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
tc.args.initialTime.Add(time.Hour*24*365*5),
|
||||
)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetParams(suite.ctx, params)
|
||||
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, tc.args.ctype, tc.args.initialTime)
|
||||
suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype, sdk.ZeroDec())
|
||||
|
||||
// setup account state
|
||||
sk := suite.app.GetSupplyKeeper()
|
||||
sk.MintCoins(suite.ctx, cdptypes.ModuleName, sdk.NewCoins(tc.args.initialCollateral))
|
||||
sk.SendCoinsFromModuleToAccount(suite.ctx, cdptypes.ModuleName, suite.addrs[0], sdk.NewCoins(tc.args.initialCollateral))
|
||||
suite.SetupWithGenState(authBuilder, incentBuilder)
|
||||
|
||||
// setup cdp state
|
||||
cdpKeeper := suite.app.GetCDPKeeper()
|
||||
err := cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
|
||||
err := suite.cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||
@ -306,3 +294,7 @@ func (suite *KeeperTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUSDXRewardsTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(USDXRewardsTestSuite))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user