mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
Add weighted bkava support for earn incentives (#1299)
* Add bkava handler for earn incentives * Add bkava accum tests * Add bkava denoms in index state * Set storeTimeEquals to default value * Add supply expected keepers * Add tests for proportional adjustment * Add liquid keeper to incentive keeper * Use weighted reward periods for bkava * Add liquid keeper to tests * Add Accumulate override rewards period with deccoins * Adjust test to handle sub unit coins * Add liquid keeper to test * Fix div by zero for proportional rewards * Update test for actual expected values * Update expected indexes to be same for different vaults * Allow no stored time for vaults that have no indexes or state * Add test for partial bkava deposit * Add math check to test * Deterministically iterate over bkava denoms * Remove unused expected liquid method GetAllDerivativeDenoms
This commit is contained in:
parent
26a4b93588
commit
651de460ca
@ -619,6 +619,8 @@ func NewApp(
|
|||||||
app.stakingKeeper,
|
app.stakingKeeper,
|
||||||
&swapKeeper,
|
&swapKeeper,
|
||||||
&savingsKeeper,
|
&savingsKeeper,
|
||||||
|
// TODO: Liquid keeper
|
||||||
|
nil,
|
||||||
&earnKeeper,
|
&earnKeeper,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func (suite *ClaimTests) TestCannotClaimWhenMultiplierNotRecognised() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -70,7 +70,7 @@ func (suite *ClaimTests) TestCannotClaimAfterEndTime() {
|
|||||||
ClaimEnd: endTime,
|
ClaimEnd: endTime,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.ctx = suite.ctx.WithBlockTime(endTime.Add(time.Nanosecond))
|
suite.ctx = suite.ctx.WithBlockTime(endTime.Add(time.Nanosecond))
|
||||||
|
|
||||||
|
@ -18,7 +18,12 @@ import (
|
|||||||
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
func i(in int64) sdk.Int { return sdk.NewInt(in) }
|
||||||
func d(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) }
|
func d(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) }
|
||||||
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
||||||
|
func dc(denom string, amount string) sdk.DecCoin {
|
||||||
|
return sdk.NewDecCoinFromDec(denom, sdk.MustNewDecFromStr(amount))
|
||||||
|
}
|
||||||
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
||||||
|
func toDcs(coins ...sdk.Coin) sdk.DecCoins { return sdk.NewDecCoinsFromCoins(coins...) }
|
||||||
|
func dcs(coins ...sdk.DecCoin) sdk.DecCoins { return sdk.NewDecCoins(coins...) }
|
||||||
|
|
||||||
func NewCDPGenStateMulti(cdc codec.JSONCodec) app.GenesisState {
|
func NewCDPGenStateMulti(cdc codec.JSONCodec) app.GenesisState {
|
||||||
cdpGenesis := cdptypes.GenesisState{
|
cdpGenesis := cdptypes.GenesisState{
|
||||||
|
@ -22,6 +22,7 @@ type Keeper struct {
|
|||||||
stakingKeeper types.StakingKeeper
|
stakingKeeper types.StakingKeeper
|
||||||
swapKeeper types.SwapKeeper
|
swapKeeper types.SwapKeeper
|
||||||
savingsKeeper types.SavingsKeeper
|
savingsKeeper types.SavingsKeeper
|
||||||
|
liquidKeeper types.LiquidKeeper
|
||||||
earnKeeper types.EarnKeeper
|
earnKeeper types.EarnKeeper
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ type Keeper struct {
|
|||||||
func NewKeeper(
|
func NewKeeper(
|
||||||
cdc codec.Codec, key sdk.StoreKey, paramstore types.ParamSubspace, bk types.BankKeeper,
|
cdc codec.Codec, key sdk.StoreKey, paramstore types.ParamSubspace, bk types.BankKeeper,
|
||||||
cdpk types.CdpKeeper, hk types.HardKeeper, ak types.AccountKeeper, stk types.StakingKeeper,
|
cdpk types.CdpKeeper, hk types.HardKeeper, ak types.AccountKeeper, stk types.StakingKeeper,
|
||||||
swpk types.SwapKeeper, svk types.SavingsKeeper, ek types.EarnKeeper,
|
swpk types.SwapKeeper, svk types.SavingsKeeper, lqk types.LiquidKeeper, ek types.EarnKeeper,
|
||||||
) Keeper {
|
) Keeper {
|
||||||
if !paramstore.HasKeyTable() {
|
if !paramstore.HasKeyTable() {
|
||||||
paramstore = paramstore.WithKeyTable(types.ParamKeyTable())
|
paramstore = paramstore.WithKeyTable(types.ParamKeyTable())
|
||||||
@ -46,6 +47,7 @@ func NewKeeper(
|
|||||||
stakingKeeper: stk,
|
stakingKeeper: stk,
|
||||||
swapKeeper: swpk,
|
swapKeeper: swpk,
|
||||||
savingsKeeper: svk,
|
savingsKeeper: svk,
|
||||||
|
liquidKeeper: lqk,
|
||||||
earnKeeper: ek,
|
earnKeeper: ek,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func (suite *AccumulateBorrowRewardsTests) TestStateUpdatedWhenBlockTimeHasIncre
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.storeGlobalBorrowIndexes(types.MultiRewardIndexes{
|
suite.storeGlobalBorrowIndexes(types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -91,7 +91,7 @@ func (suite *AccumulateBorrowRewardsTests) TestStateUnchangedWhenBlockTimeHasNot
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -136,7 +136,7 @@ func (suite *AccumulateBorrowRewardsTests) TestNoAccumulationWhenSourceSharesAre
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper() // zero total borrows
|
hardKeeper := newFakeHardKeeper() // zero total borrows
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -182,7 +182,7 @@ func (suite *AccumulateBorrowRewardsTests) TestStateAddedWhenStateDoesNotExist()
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -225,7 +225,7 @@ func (suite *AccumulateBorrowRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper()
|
hardKeeper := newFakeHardKeeper()
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -253,7 +253,7 @@ func (suite *AccumulateBorrowRewardsTests) TestNoAccumulationWhenBeforeStartTime
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -299,7 +299,7 @@ func (suite *AccumulateBorrowRewardsTests) TestPanicWhenCurrentTimeLessThanPrevi
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalBorrow(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, denom, previousAccrualTime)
|
suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, denom, previousAccrualTime)
|
||||||
|
@ -36,7 +36,7 @@ func TestAccumulateDelegatorRewards(t *testing.T) {
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased() {
|
func (suite *AccumulateDelegatorRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased() {
|
||||||
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.storeGlobalDelegatorIndexes(types.MultiRewardIndexes{
|
suite.storeGlobalDelegatorIndexes(types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -86,7 +86,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestStateUpdatedWhenBlockTimeHasIn
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() {
|
func (suite *AccumulateDelegatorRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() {
|
||||||
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -129,7 +129,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestStateUnchangedWhenBlockTimeHas
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenSourceSharesAreZero() {
|
func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenSourceSharesAreZero() {
|
||||||
stakingKeeper := newFakeStakingKeeper() // zero total bonded
|
stakingKeeper := newFakeStakingKeeper() // zero total bonded
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -173,7 +173,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenSourceShares
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
func (suite *AccumulateDelegatorRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
||||||
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -214,7 +214,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestStateAddedWhenStateDoesNotExis
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
func (suite *AccumulateDelegatorRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
||||||
stakingKeeper := newFakeStakingKeeper()
|
stakingKeeper := newFakeStakingKeeper()
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -240,7 +240,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestNoPanicWhenStateDoesNotExist()
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenBeforeStartTime() {
|
func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenBeforeStartTime() {
|
||||||
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -284,7 +284,7 @@ func (suite *AccumulateDelegatorRewardsTests) TestNoAccumulationWhenBeforeStartT
|
|||||||
|
|
||||||
func (suite *AccumulateDelegatorRewardsTests) TestPanicWhenCurrentTimeLessThanPrevious() {
|
func (suite *AccumulateDelegatorRewardsTests) TestPanicWhenCurrentTimeLessThanPrevious() {
|
||||||
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
stakingKeeper := newFakeStakingKeeper().addBondedTokens(1e6)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetPreviousDelegatorRewardAccrualTime(suite.ctx, types.BondDenom, previousAccrualTime)
|
suite.keeper.SetPreviousDelegatorRewardAccrualTime(suite.ctx, types.BondDenom, previousAccrualTime)
|
||||||
|
@ -58,7 +58,7 @@ func (suite *InitializeDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreSetWh
|
|||||||
DelegatorShares: d("1000"),
|
DelegatorShares: d("1000"),
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, sk, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, sk, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
|
@ -37,7 +37,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUnchangedWhenGl
|
|||||||
delegator := arbitraryAddress()
|
delegator := arbitraryAddress()
|
||||||
|
|
||||||
stakingKeeper := &fakeStakingKeeper{} // use an empty staking keeper that returns no delegations
|
stakingKeeper := &fakeStakingKeeper{} // use an empty staking keeper that returns no delegations
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -58,7 +58,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUnchangedWhenGl
|
|||||||
func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() {
|
func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() {
|
||||||
delegator := arbitraryAddress()
|
delegator := arbitraryAddress()
|
||||||
|
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, &fakeStakingKeeper{}, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, &fakeStakingKeeper{}, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -97,7 +97,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFac
|
|||||||
unslashedBondedValidator(validatorAddress),
|
unslashedBondedValidator(validatorAddress),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -142,7 +142,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenNewReward
|
|||||||
unslashedBondedValidator(validatorAddress),
|
unslashedBondedValidator(validatorAddress),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -192,7 +192,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenGlobalFac
|
|||||||
unslashedBondedValidator(validatorAddress),
|
unslashedBondedValidator(validatorAddress),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.DelegatorClaim{
|
claim := types.DelegatorClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -299,7 +299,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenValAddrIsNil()
|
|||||||
unslashedNotBondedValidator(validatorAddresses[3]),
|
unslashedNotBondedValidator(validatorAddresses[3]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.Equal(
|
suite.Equal(
|
||||||
d("11"), // delegation to bonded validators
|
d("11"), // delegation to bonded validators
|
||||||
@ -343,7 +343,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenExcludingAVali
|
|||||||
unslashedNotBondedValidator(validatorAddresses[3]),
|
unslashedNotBondedValidator(validatorAddresses[3]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.Equal(
|
suite.Equal(
|
||||||
d("10"),
|
d("10"),
|
||||||
@ -387,7 +387,7 @@ func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenIncludingAVali
|
|||||||
unslashedNotBondedValidator(validatorAddresses[3]),
|
unslashedNotBondedValidator(validatorAddresses[3]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.Equal(
|
suite.Equal(
|
||||||
d("111"),
|
d("111"),
|
||||||
|
@ -2,6 +2,9 @@ package keeper
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
@ -12,26 +15,137 @@ import (
|
|||||||
// AccumulateEarnRewards calculates new rewards to distribute this block and updates the global indexes to reflect this.
|
// AccumulateEarnRewards calculates new rewards to distribute this block and updates the global indexes to reflect this.
|
||||||
// The provided rewardPeriod must be valid to avoid panics in calculating time durations.
|
// The provided rewardPeriod must be valid to avoid panics in calculating time durations.
|
||||||
func (k Keeper) AccumulateEarnRewards(ctx sdk.Context, rewardPeriod types.MultiRewardPeriod) {
|
func (k Keeper) AccumulateEarnRewards(ctx sdk.Context, rewardPeriod types.MultiRewardPeriod) {
|
||||||
previousAccrualTime, found := k.GetEarnRewardAccrualTime(ctx, rewardPeriod.CollateralType)
|
if rewardPeriod.CollateralType == "bkava" {
|
||||||
|
k.accumulateEarnBkavaRewards(ctx, rewardPeriod)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
k.accumulateEarnRewards(
|
||||||
|
ctx,
|
||||||
|
rewardPeriod.CollateralType,
|
||||||
|
rewardPeriod.Start,
|
||||||
|
rewardPeriod.End,
|
||||||
|
sdk.NewDecCoinsFromCoins(rewardPeriod.RewardsPerSecond...),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProportionalRewardsPerSecond(
|
||||||
|
rewardPeriod types.MultiRewardPeriod,
|
||||||
|
totalBkavaSupply sdk.Int,
|
||||||
|
singleBkavaSupply sdk.Int,
|
||||||
|
) sdk.DecCoins {
|
||||||
|
// Rate per bkava-xxx = rewardsPerSecond * % of bkava-xxx
|
||||||
|
// = rewardsPerSecond * (bkava-xxx / total bkava)
|
||||||
|
// = (rewardsPerSecond * bkava-xxx) / total bkava
|
||||||
|
|
||||||
|
newRate := sdk.NewDecCoins()
|
||||||
|
|
||||||
|
// Prevent division by zero, if there are no total shares then there are no
|
||||||
|
// rewards.
|
||||||
|
if totalBkavaSupply.IsZero() {
|
||||||
|
return newRate
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rewardCoin := range rewardPeriod.RewardsPerSecond {
|
||||||
|
scaledAmount := rewardCoin.Amount.ToDec().
|
||||||
|
Mul(singleBkavaSupply.ToDec()).
|
||||||
|
Quo(totalBkavaSupply.ToDec())
|
||||||
|
|
||||||
|
newRate = newRate.Add(sdk.NewDecCoinFromDec(rewardCoin.Denom, scaledAmount))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRate
|
||||||
|
}
|
||||||
|
|
||||||
|
// accumulateEarnBkavaRewards does the same as AccumulateEarnRewards but for
|
||||||
|
// *all* bkava vaults.
|
||||||
|
func (k Keeper) accumulateEarnBkavaRewards(ctx sdk.Context, rewardPeriod types.MultiRewardPeriod) {
|
||||||
|
// TODO: Get staking rewards and distribute
|
||||||
|
|
||||||
|
// All bkava vault denoms
|
||||||
|
bkavaVaultsDenoms := make(map[string]bool)
|
||||||
|
|
||||||
|
// bkava vault denoms from earn records (non-empty vaults)
|
||||||
|
k.earnKeeper.IterateVaultRecords(ctx, func(record earntypes.VaultRecord) (stop bool) {
|
||||||
|
// TODO: Replace with single bkava denom check method from liquid
|
||||||
|
if strings.HasPrefix(record.TotalShares.Denom, "bkava-") {
|
||||||
|
bkavaVaultsDenoms[record.TotalShares.Denom] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
// bkava vault denoms from past incentive indexes, may include vaults
|
||||||
|
// that were fully withdrawn.
|
||||||
|
k.IterateEarnRewardIndexes(ctx, func(vaultDenom string, indexes types.RewardIndexes) (stop bool) {
|
||||||
|
if strings.HasPrefix(vaultDenom, "bkava-") {
|
||||||
|
bkavaVaultsDenoms[vaultDenom] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
totalBkavaSupply := k.liquidKeeper.GetTotalDerivativeSupply(ctx)
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
sortedBkavaVaultsDenoms := make([]string, len(bkavaVaultsDenoms))
|
||||||
|
for vaultDenom := range bkavaVaultsDenoms {
|
||||||
|
sortedBkavaVaultsDenoms[i] = vaultDenom
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the vault denoms to ensure deterministic iteration order.
|
||||||
|
sort.Strings(sortedBkavaVaultsDenoms)
|
||||||
|
|
||||||
|
// Accumulate rewards for each bkava vault.
|
||||||
|
for _, bkavaDenom := range sortedBkavaVaultsDenoms {
|
||||||
|
k.accumulateEarnRewards(
|
||||||
|
ctx,
|
||||||
|
bkavaDenom,
|
||||||
|
rewardPeriod.Start,
|
||||||
|
rewardPeriod.End,
|
||||||
|
GetProportionalRewardsPerSecond(
|
||||||
|
rewardPeriod,
|
||||||
|
totalBkavaSupply,
|
||||||
|
k.liquidKeeper.GetDerivativeSupply(ctx, bkavaDenom),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) accumulateEarnRewards(
|
||||||
|
ctx sdk.Context,
|
||||||
|
collateralType string,
|
||||||
|
periodStart time.Time,
|
||||||
|
periodEnd time.Time,
|
||||||
|
periodRewardsPerSecond sdk.DecCoins,
|
||||||
|
) {
|
||||||
|
previousAccrualTime, found := k.GetEarnRewardAccrualTime(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
previousAccrualTime = ctx.BlockTime()
|
previousAccrualTime = ctx.BlockTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
indexes, found := k.GetEarnRewardIndexes(ctx, rewardPeriod.CollateralType)
|
indexes, found := k.GetEarnRewardIndexes(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
indexes = types.RewardIndexes{}
|
indexes = types.RewardIndexes{}
|
||||||
}
|
}
|
||||||
|
|
||||||
acc := types.NewAccumulator(previousAccrualTime, indexes)
|
acc := types.NewAccumulator(previousAccrualTime, indexes)
|
||||||
|
|
||||||
totalSource := k.getEarnTotalSourceShares(ctx, rewardPeriod.CollateralType)
|
totalSourceShares := k.getEarnTotalSourceShares(ctx, collateralType)
|
||||||
|
|
||||||
acc.Accumulate(rewardPeriod, totalSource, ctx.BlockTime())
|
acc.AccumulateDecCoins(
|
||||||
|
periodStart,
|
||||||
|
periodEnd,
|
||||||
|
periodRewardsPerSecond,
|
||||||
|
totalSourceShares,
|
||||||
|
ctx.BlockTime(),
|
||||||
|
)
|
||||||
|
|
||||||
k.SetEarnRewardAccrualTime(ctx, rewardPeriod.CollateralType, acc.PreviousAccumulationTime)
|
k.SetEarnRewardAccrualTime(ctx, collateralType, acc.PreviousAccumulationTime)
|
||||||
if len(acc.Indexes) > 0 {
|
if len(acc.Indexes) > 0 {
|
||||||
// the store panics when setting empty or nil indexes
|
// the store panics when setting empty or nil indexes
|
||||||
k.SetEarnRewardIndexes(ctx, rewardPeriod.CollateralType, acc.Indexes)
|
k.SetEarnRewardIndexes(ctx, collateralType, acc.Indexes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,12 @@ type AccumulateEarnRewardsTests struct {
|
|||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) storedTimeEquals(vaultDenom string, expected time.Time) {
|
func (suite *AccumulateEarnRewardsTests) storedTimeEquals(vaultDenom string, expected time.Time) {
|
||||||
storedTime, found := suite.keeper.GetEarnRewardAccrualTime(suite.ctx, vaultDenom)
|
storedTime, found := suite.keeper.GetEarnRewardAccrualTime(suite.ctx, vaultDenom)
|
||||||
suite.True(found)
|
suite.Equal(found, expected != time.Time{}, "expected time is %v but time found = %v", expected, found)
|
||||||
|
if found {
|
||||||
suite.Equal(expected, storedTime)
|
suite.Equal(expected, storedTime)
|
||||||
|
} else {
|
||||||
|
suite.Empty(storedTime)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) storedIndexesEqual(vaultDenom string, expected types.RewardIndexes) {
|
func (suite *AccumulateEarnRewardsTests) storedIndexesEqual(vaultDenom string, expected types.RewardIndexes) {
|
||||||
@ -38,7 +42,7 @@ func (suite *AccumulateEarnRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreas
|
|||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
suite.storeGlobalEarnIndexes(types.MultiRewardIndexes{
|
suite.storeGlobalEarnIndexes(types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -86,11 +90,222 @@ func (suite *AccumulateEarnRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreas
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased_bkava() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
earnKeeper := newFakeEarnKeeper().
|
||||||
|
addVault(vaultDenom1, earntypes.NewVaultShare(vaultDenom1, d("800000"))).
|
||||||
|
addVault(vaultDenom2, earntypes.NewVaultShare(vaultDenom2, d("200000")))
|
||||||
|
|
||||||
|
liquidKeeper := newFakeLiquidKeeper().
|
||||||
|
addDerivative(vaultDenom1, i(800000)).
|
||||||
|
addDerivative(vaultDenom2, i(200000))
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
globalIndexes := types.MultiRewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom1,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom2,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.storeGlobalEarnIndexes(globalIndexes)
|
||||||
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom1, previousAccrualTime)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom2, previousAccrualTime)
|
||||||
|
|
||||||
|
newAccrualTime := previousAccrualTime.Add(1 * time.Hour)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(newAccrualTime)
|
||||||
|
|
||||||
|
rewardPeriod := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava", // reward period is set for "bkava" to apply to all vaults
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(c("earn", 2000), c("ukava", 1000)), // same denoms as in global indexes
|
||||||
|
)
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, rewardPeriod)
|
||||||
|
|
||||||
|
// check time and factors
|
||||||
|
|
||||||
|
suite.storedTimeEquals(vaultDenom1, newAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, newAccrualTime)
|
||||||
|
|
||||||
|
// Each vault gets the same ukava per second, assuming shares prices are the same.
|
||||||
|
// The share amount determines how much is actually distributed to the vault.
|
||||||
|
expectedIndexes := types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("7.22"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("3.64"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, expectedIndexes)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, expectedIndexes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreased_bkava_partialDeposit() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
vaultDenom1Supply := i(800000)
|
||||||
|
vaultDenom2Supply := i(200000)
|
||||||
|
|
||||||
|
liquidKeeper := newFakeLiquidKeeper().
|
||||||
|
addDerivative(vaultDenom1, vaultDenom1Supply).
|
||||||
|
addDerivative(vaultDenom2, vaultDenom2Supply)
|
||||||
|
|
||||||
|
vault2Shares := d("100000")
|
||||||
|
|
||||||
|
// More bkava minted than deposited into earn
|
||||||
|
// Rewards are higher per-share as a result
|
||||||
|
earnKeeper := newFakeEarnKeeper().
|
||||||
|
addVault(vaultDenom1, earntypes.NewVaultShare(vaultDenom1, d("700000"))).
|
||||||
|
addVault(vaultDenom2, earntypes.NewVaultShare(vaultDenom2, vault2Shares))
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
globalIndexes := types.MultiRewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom1,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom2,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.storeGlobalEarnIndexes(globalIndexes)
|
||||||
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom1, previousAccrualTime)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom2, previousAccrualTime)
|
||||||
|
|
||||||
|
newAccrualTime := previousAccrualTime.Add(1 * time.Hour)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(newAccrualTime)
|
||||||
|
|
||||||
|
rewardPeriod := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava", // reward period is set for "bkava" to apply to all vaults
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(c("earn", 2000), c("ukava", 1000)), // same denoms as in global indexes
|
||||||
|
)
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, rewardPeriod)
|
||||||
|
|
||||||
|
// check time and factors
|
||||||
|
|
||||||
|
suite.storedTimeEquals(vaultDenom1, newAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, newAccrualTime)
|
||||||
|
|
||||||
|
// Slightly increased rewards due to less bkava deposited
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("8.248571428571428571"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("4.154285714285714286"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Much higher rewards per share because only a small amount of bkava is
|
||||||
|
// deposited. The **total** amount of incentives distributed to this vault
|
||||||
|
// is still the same proportional amount.
|
||||||
|
|
||||||
|
// Fixed amount total rewards distributed to the vault
|
||||||
|
// Fewer shares deposited -> higher rewards per share
|
||||||
|
|
||||||
|
// 7.2ukava shares per second for 1 hour (started with 0.04)
|
||||||
|
// total rewards claimable = 7.2 * 100000 shares = 720000 ukava
|
||||||
|
|
||||||
|
// 720000ukava distributed which is 20% of total bkava ukava rewards
|
||||||
|
// total rewards for *all* bkava vaults for 1 hour
|
||||||
|
// = 1000ukava per second * 3600 == 3600000ukava
|
||||||
|
// vaultDenom2 has 20% of the total bkava amount so it should get 20% of 3600000ukava == 720000ukava
|
||||||
|
|
||||||
|
vault2expectedIndexes := types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("14.42"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("7.24"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, vault2expectedIndexes)
|
||||||
|
|
||||||
|
// Verify math described above
|
||||||
|
totalVault2DistributedUkava := i(int64(time.Hour.Seconds())).
|
||||||
|
ToDec().
|
||||||
|
Mul(rewardPeriod.RewardsPerSecond.AmountOf("ukava").ToDec()).
|
||||||
|
// 20% of total rewards
|
||||||
|
// vault 2 supply / (vault 1 supply + vault 2 supply)
|
||||||
|
Mul(
|
||||||
|
vaultDenom2Supply.ToDec().
|
||||||
|
Quo(vaultDenom1Supply.Add(vaultDenom2Supply).ToDec()),
|
||||||
|
)
|
||||||
|
|
||||||
|
totalVault2ClaimableRewards := vault2expectedIndexes[1].
|
||||||
|
RewardFactor.Sub(d("0.04")). // Rewards per share for 1 hr, excluding the starting value
|
||||||
|
Mul(vault2Shares) // * Shares in vault to get total rewards for entire vault
|
||||||
|
|
||||||
|
suite.Equal(totalVault2DistributedUkava, totalVault2ClaimableRewards)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() {
|
func (suite *AccumulateEarnRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased() {
|
||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -131,11 +346,86 @@ func (suite *AccumulateEarnRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIn
|
|||||||
suite.storedIndexesEqual(vaultDenom, expected)
|
suite.storedIndexesEqual(vaultDenom, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIncreased_bkava() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
earnKeeper := newFakeEarnKeeper().
|
||||||
|
addVault(vaultDenom1, earntypes.NewVaultShare(vaultDenom1, d("1000000"))).
|
||||||
|
addVault(vaultDenom2, earntypes.NewVaultShare(vaultDenom2, d("1000000")))
|
||||||
|
|
||||||
|
liquidKeeper := newFakeLiquidKeeper().
|
||||||
|
addDerivative(vaultDenom1, i(1000000)).
|
||||||
|
addDerivative(vaultDenom2, i(1000000))
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom1,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom2,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
suite.storeGlobalEarnIndexes(previousIndexes)
|
||||||
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom1, previousAccrualTime)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom2, previousAccrualTime)
|
||||||
|
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(previousAccrualTime)
|
||||||
|
|
||||||
|
period := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava",
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(c("earn", 2000), c("ukava", 1000)), // same denoms as in global indexes
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, period)
|
||||||
|
|
||||||
|
// check time and factors
|
||||||
|
|
||||||
|
suite.storedTimeEquals(vaultDenom1, previousAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, previousAccrualTime)
|
||||||
|
|
||||||
|
expected, f := previousIndexes.Get(vaultDenom1)
|
||||||
|
suite.True(f)
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, expected)
|
||||||
|
|
||||||
|
expected, f = previousIndexes.Get(vaultDenom2)
|
||||||
|
suite.True(f)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, expected)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenSourceSharesAreZero() {
|
func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenSourceSharesAreZero() {
|
||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper() // no vault, so no source shares
|
earnKeeper := newFakeEarnKeeper() // no vault, so no source shares
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
liquidKeeper := newFakeLiquidKeeper()
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -177,11 +467,82 @@ func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenSourceSharesAreZe
|
|||||||
suite.storedIndexesEqual(vaultDenom, expected)
|
suite.storedIndexesEqual(vaultDenom, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenSourceSharesAreZero_bkava() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
earnKeeper := newFakeEarnKeeper() // no vault, so no source shares
|
||||||
|
liquidKeeper := newFakeLiquidKeeper()
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom1,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: vaultDenom2,
|
||||||
|
RewardIndexes: types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.02"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.04"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
suite.storeGlobalEarnIndexes(previousIndexes)
|
||||||
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom1, previousAccrualTime)
|
||||||
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom2, previousAccrualTime)
|
||||||
|
|
||||||
|
firstAccrualTime := previousAccrualTime.Add(7 * time.Second)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(firstAccrualTime)
|
||||||
|
|
||||||
|
period := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava",
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(c("earn", 2000), c("ukava", 1000)), // same denoms as in global indexes
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: There are no bkava vaults to iterate over, so the accrual times are
|
||||||
|
// not updated
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, period)
|
||||||
|
|
||||||
|
// check time and factors
|
||||||
|
|
||||||
|
suite.storedTimeEquals(vaultDenom1, firstAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, firstAccrualTime)
|
||||||
|
|
||||||
|
expected, f := previousIndexes.Get(vaultDenom1)
|
||||||
|
suite.True(f)
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, expected)
|
||||||
|
|
||||||
|
expected, f = previousIndexes.Get(vaultDenom2)
|
||||||
|
suite.True(f)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, expected)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
func (suite *AccumulateEarnRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -220,11 +581,70 @@ func (suite *AccumulateEarnRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestStateAddedWhenStateDoesNotExist_bkava() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
earnKeeper := newFakeEarnKeeper().
|
||||||
|
addVault(vaultDenom1, earntypes.NewVaultShare(vaultDenom1, d("1000000"))).
|
||||||
|
addVault(vaultDenom2, earntypes.NewVaultShare(vaultDenom2, d("1000000")))
|
||||||
|
|
||||||
|
liquidKeeper := newFakeLiquidKeeper().
|
||||||
|
addDerivative(vaultDenom1, i(1000000)).
|
||||||
|
addDerivative(vaultDenom2, i(1000000))
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
period := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava",
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(c("earn", 2000), c("ukava", 1000)),
|
||||||
|
)
|
||||||
|
|
||||||
|
firstAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(firstAccrualTime)
|
||||||
|
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, period)
|
||||||
|
|
||||||
|
// After the first accumulation only the current block time should be stored.
|
||||||
|
// The indexes will be empty as no time has passed since the previous block because it didn't exist.
|
||||||
|
suite.storedTimeEquals(vaultDenom1, firstAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, firstAccrualTime)
|
||||||
|
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, nil)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, nil)
|
||||||
|
|
||||||
|
secondAccrualTime := firstAccrualTime.Add(10 * time.Second)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(secondAccrualTime)
|
||||||
|
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, period)
|
||||||
|
|
||||||
|
// After the second accumulation both current block time and indexes should be stored.
|
||||||
|
suite.storedTimeEquals(vaultDenom1, secondAccrualTime)
|
||||||
|
suite.storedTimeEquals(vaultDenom2, secondAccrualTime)
|
||||||
|
|
||||||
|
expectedIndexes := types.RewardIndexes{
|
||||||
|
{
|
||||||
|
CollateralType: "earn",
|
||||||
|
RewardFactor: d("0.01"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CollateralType: "ukava",
|
||||||
|
RewardFactor: d("0.005"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, expectedIndexes)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, expectedIndexes)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
func (suite *AccumulateEarnRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper()
|
earnKeeper := newFakeEarnKeeper()
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -248,11 +668,47 @@ func (suite *AccumulateEarnRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
|||||||
suite.storedIndexesEqual(vaultDenom, nil)
|
suite.storedIndexesEqual(vaultDenom, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccumulateEarnRewardsTests) TestNoPanicWhenStateDoesNotExist_bkava() {
|
||||||
|
vaultDenom1 := "bkava-meow"
|
||||||
|
vaultDenom2 := "bkava-woof"
|
||||||
|
|
||||||
|
earnKeeper := newFakeEarnKeeper()
|
||||||
|
liquidKeeper := newFakeLiquidKeeper()
|
||||||
|
|
||||||
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, liquidKeeper, earnKeeper)
|
||||||
|
|
||||||
|
period := types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"bkava",
|
||||||
|
time.Unix(0, 0), // ensure the test is within start and end times
|
||||||
|
distantFuture,
|
||||||
|
cs(),
|
||||||
|
)
|
||||||
|
|
||||||
|
accrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(accrualTime)
|
||||||
|
|
||||||
|
// Accumulate with no earn shares and no rewards per second will result in no increment to the indexes.
|
||||||
|
// No increment and no previous indexes stored, results in an updated of nil. Setting this in the state panics.
|
||||||
|
// Check there is no panic.
|
||||||
|
suite.NotPanics(func() {
|
||||||
|
// This does not update any state, as there are no bkava vaults
|
||||||
|
// to iterate over, denoms are unknown
|
||||||
|
suite.keeper.AccumulateEarnRewards(suite.ctx, period)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Times are not stored for vaults with no state
|
||||||
|
suite.storedTimeEquals(vaultDenom1, time.Time{})
|
||||||
|
suite.storedTimeEquals(vaultDenom2, time.Time{})
|
||||||
|
suite.storedIndexesEqual(vaultDenom1, nil)
|
||||||
|
suite.storedIndexesEqual(vaultDenom2, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenBeforeStartTime() {
|
func (suite *AccumulateEarnRewardsTests) TestNoAccumulationWhenBeforeStartTime() {
|
||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -298,7 +754,7 @@ func (suite *AccumulateEarnRewardsTests) TestPanicWhenCurrentTimeLessThanPreviou
|
|||||||
vaultDenom := "usdx"
|
vaultDenom := "usdx"
|
||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
earnKeeper := newFakeEarnKeeper().addVault(vaultDenom, earntypes.NewVaultShare(vaultDenom, d("1000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom, previousAccrualTime)
|
suite.keeper.SetEarnRewardAccrualTime(suite.ctx, vaultDenom, previousAccrualTime)
|
||||||
|
86
x/incentive/keeper/rewards_earn_proportional_test.go
Normal file
86
x/incentive/keeper/rewards_earn_proportional_test.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/kava-labs/kava/x/incentive/keeper"
|
||||||
|
"github.com/kava-labs/kava/x/incentive/types"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetProportionalRewardPeriod(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
giveRewardPeriod types.MultiRewardPeriod
|
||||||
|
giveTotalBkavaSupply sdk.Int
|
||||||
|
giveSingleBkavaSupply sdk.Int
|
||||||
|
wantRewardsPerSecond sdk.DecCoins
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"full amount",
|
||||||
|
types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
time.Time{},
|
||||||
|
time.Time{},
|
||||||
|
cs(c("ukava", 100), c("hard", 200)),
|
||||||
|
),
|
||||||
|
i(100),
|
||||||
|
i(100),
|
||||||
|
toDcs(c("ukava", 100), c("hard", 200)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"3/4 amount",
|
||||||
|
types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
time.Time{},
|
||||||
|
time.Time{},
|
||||||
|
cs(c("ukava", 100), c("hard", 200)),
|
||||||
|
),
|
||||||
|
i(10_000000),
|
||||||
|
i(7_500000),
|
||||||
|
toDcs(c("ukava", 75), c("hard", 150)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"half amount",
|
||||||
|
types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
time.Time{},
|
||||||
|
time.Time{},
|
||||||
|
cs(c("ukava", 100), c("hard", 200)),
|
||||||
|
),
|
||||||
|
i(100),
|
||||||
|
i(50),
|
||||||
|
toDcs(c("ukava", 50), c("hard", 100)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"under 1 unit",
|
||||||
|
types.NewMultiRewardPeriod(
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
time.Time{},
|
||||||
|
time.Time{},
|
||||||
|
cs(c("ukava", 100), c("hard", 200)),
|
||||||
|
),
|
||||||
|
i(1000), // total bkava
|
||||||
|
i(1), // bkava supply of this specific vault
|
||||||
|
dcs(dc("ukava", "0.1"), dc("hard", "0.2")), // rewards per second rounded to 0 if under 1ukava/1hard
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
rewardsPerSecond := keeper.GetProportionalRewardsPerSecond(
|
||||||
|
tt.giveRewardPeriod,
|
||||||
|
tt.giveTotalBkavaSupply,
|
||||||
|
tt.giveSingleBkavaSupply,
|
||||||
|
)
|
||||||
|
|
||||||
|
require.Equal(t, tt.wantRewardsPerSecond, rewardsPerSecond)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -324,7 +324,7 @@ func (suite *SynchronizeEarnRewardTests) TestGetSyncedClaim_ClaimUnchangedWhenNo
|
|||||||
|
|
||||||
earnKeeper := newFakeEarnKeeper().
|
earnKeeper := newFakeEarnKeeper().
|
||||||
addDeposit(owner, earntypes.NewVaultShare("usdx", d("1000000000")))
|
addDeposit(owner, earntypes.NewVaultShare("usdx", d("1000000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
claim := types.EarnClaim{
|
claim := types.EarnClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -357,7 +357,7 @@ func (suite *SynchronizeEarnRewardTests) TestGetSyncedClaim_ClaimUpdatedWhenMiss
|
|||||||
owner := arbitraryAddress()
|
owner := arbitraryAddress()
|
||||||
|
|
||||||
// owner has no shares in any vault
|
// owner has no shares in any vault
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, newFakeEarnKeeper())
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, newFakeEarnKeeper())
|
||||||
|
|
||||||
claim := types.EarnClaim{
|
claim := types.EarnClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -419,7 +419,7 @@ func (suite *SynchronizeEarnRewardTests) TestGetSyncedClaim_ClaimUpdatedWhenMiss
|
|||||||
addVault(VaultDenom_2, earntypes.NewVaultShare(VaultDenom_2, d("1000000000"))).
|
addVault(VaultDenom_2, earntypes.NewVaultShare(VaultDenom_2, d("1000000000"))).
|
||||||
addDeposit(owner, earntypes.NewVaultShare(VaultDenom_1, d("1000000000"))).
|
addDeposit(owner, earntypes.NewVaultShare(VaultDenom_1, d("1000000000"))).
|
||||||
addDeposit(owner, earntypes.NewVaultShare(VaultDenom_2, d("1000000000")))
|
addDeposit(owner, earntypes.NewVaultShare(VaultDenom_2, d("1000000000")))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, earnKeeper)
|
||||||
|
|
||||||
claim := types.EarnClaim{
|
claim := types.EarnClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
|
@ -38,7 +38,7 @@ func (suite *AccumulateSupplyRewardsTests) TestStateUpdatedWhenBlockTimeHasIncre
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.storeGlobalSupplyIndexes(types.MultiRewardIndexes{
|
suite.storeGlobalSupplyIndexes(types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -90,7 +90,7 @@ func (suite *AccumulateSupplyRewardsTests) TestStateUnchangedWhenBlockTimeHasNot
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -135,7 +135,7 @@ func (suite *AccumulateSupplyRewardsTests) TestNoAccumulationWhenSourceSharesAre
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper() // zero total supplys
|
hardKeeper := newFakeHardKeeper() // zero total supplys
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -181,7 +181,7 @@ func (suite *AccumulateSupplyRewardsTests) TestStateAddedWhenStateDoesNotExist()
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -224,7 +224,7 @@ func (suite *AccumulateSupplyRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper()
|
hardKeeper := newFakeHardKeeper()
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -252,7 +252,7 @@ func (suite *AccumulateSupplyRewardsTests) TestNoAccumulationWhenBeforeStartTime
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -298,7 +298,7 @@ func (suite *AccumulateSupplyRewardsTests) TestPanicWhenCurrentTimeLessThanPrevi
|
|||||||
denom := "bnb"
|
denom := "bnb"
|
||||||
|
|
||||||
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
hardKeeper := newFakeHardKeeper().addTotalSupply(c(denom, 1e6), d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, hardKeeper, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, denom, previousAccrualTime)
|
suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, denom, previousAccrualTime)
|
||||||
|
@ -37,7 +37,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreas
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
suite.storeGlobalSwapIndexes(types.MultiRewardIndexes{
|
suite.storeGlobalSwapIndexes(types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -89,7 +89,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIn
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -134,7 +134,7 @@ func (suite *AccumulateSwapRewardsTests) TestNoAccumulationWhenSourceSharesAreZe
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper() // no pools, so no source shares
|
swapKeeper := newFakeSwapKeeper() // no pools, so no source shares
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -180,7 +180,7 @@ func (suite *AccumulateSwapRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -223,7 +223,7 @@ func (suite *AccumulateSwapRewardsTests) TestNoPanicWhenStateDoesNotExist() {
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper()
|
swapKeeper := newFakeSwapKeeper()
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewMultiRewardPeriod(
|
period := types.NewMultiRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -251,7 +251,7 @@ func (suite *AccumulateSwapRewardsTests) TestNoAccumulationWhenBeforeStartTime()
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.MultiRewardIndexes{
|
previousIndexes := types.MultiRewardIndexes{
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ func (suite *AccumulateSwapRewardsTests) TestPanicWhenCurrentTimeLessThanPreviou
|
|||||||
pool := "btc:usdx"
|
pool := "btc:usdx"
|
||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
swapKeeper := newFakeSwapKeeper().addPool(pool, i(1e6))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetSwapRewardAccrualTime(suite.ctx, pool, previousAccrualTime)
|
suite.keeper.SetSwapRewardAccrualTime(suite.ctx, pool, previousAccrualTime)
|
||||||
|
@ -323,7 +323,7 @@ func (suite *SynchronizeSwapRewardTests) TestGetSyncedClaim_ClaimUnchangedWhenNo
|
|||||||
|
|
||||||
swapKeeper := newFakeSwapKeeper().
|
swapKeeper := newFakeSwapKeeper().
|
||||||
addDeposit(poolID_1, owner, i(1e9))
|
addDeposit(poolID_1, owner, i(1e9))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.SwapClaim{
|
claim := types.SwapClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -356,7 +356,7 @@ func (suite *SynchronizeSwapRewardTests) TestGetSyncedClaim_ClaimUpdatedWhenMiss
|
|||||||
owner := arbitraryAddress()
|
owner := arbitraryAddress()
|
||||||
|
|
||||||
// owner has no shares in any pool
|
// owner has no shares in any pool
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, newFakeSwapKeeper(), nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, newFakeSwapKeeper(), nil, nil, nil)
|
||||||
|
|
||||||
claim := types.SwapClaim{
|
claim := types.SwapClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
@ -416,7 +416,7 @@ func (suite *SynchronizeSwapRewardTests) TestGetSyncedClaim_ClaimUpdatedWhenMiss
|
|||||||
swapKeeper := newFakeSwapKeeper().
|
swapKeeper := newFakeSwapKeeper().
|
||||||
addDeposit(poolID_1, owner, i(1e9)).
|
addDeposit(poolID_1, owner, i(1e9)).
|
||||||
addDeposit(poolID_2, owner, i(1e9))
|
addDeposit(poolID_2, owner, i(1e9))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, swapKeeper, nil, nil, nil)
|
||||||
|
|
||||||
claim := types.SwapClaim{
|
claim := types.SwapClaim{
|
||||||
BaseMultiClaim: types.BaseMultiClaim{
|
BaseMultiClaim: types.BaseMultiClaim{
|
||||||
|
@ -34,7 +34,7 @@ func (suite *AccumulateUSDXRewardsTests) TestStateUpdatedWhenBlockTimeHasIncreas
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
suite.storeGlobalUSDXIndexes(types.RewardIndexes{
|
suite.storeGlobalUSDXIndexes(types.RewardIndexes{
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ func (suite *AccumulateUSDXRewardsTests) TestStateUnchangedWhenBlockTimeHasNotIn
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.RewardIndexes{
|
previousIndexes := types.RewardIndexes{
|
||||||
{
|
{
|
||||||
@ -104,7 +104,7 @@ func (suite *AccumulateUSDXRewardsTests) TestNoAccumulationWhenSourceSharesAreZe
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper() // zero total borrows
|
cdpKeeper := newFakeCDPKeeper() // zero total borrows
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.RewardIndexes{
|
previousIndexes := types.RewardIndexes{
|
||||||
{
|
{
|
||||||
@ -141,7 +141,7 @@ func (suite *AccumulateUSDXRewardsTests) TestStateAddedWhenStateDoesNotExist() {
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
period := types.NewRewardPeriod(
|
period := types.NewRewardPeriod(
|
||||||
true,
|
true,
|
||||||
@ -174,7 +174,7 @@ func (suite *AccumulateUSDXRewardsTests) TestNoAccumulationWhenBeforeStartTime()
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousIndexes := types.RewardIndexes{
|
previousIndexes := types.RewardIndexes{
|
||||||
{
|
{
|
||||||
@ -211,7 +211,7 @@ func (suite *AccumulateUSDXRewardsTests) TestPanicWhenCurrentTimeLessThanPreviou
|
|||||||
cType := "bnb-a"
|
cType := "bnb-a"
|
||||||
|
|
||||||
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
cdpKeeper := newFakeCDPKeeper().addTotalPrincipal(i(1e6)).addInterestFactor(d("1"))
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, cdpKeeper, nil, nil, nil, nil, nil, nil, nil)
|
||||||
|
|
||||||
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
previousAccrualTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, cType, previousAccrualTime)
|
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, cType, previousAccrualTime)
|
||||||
|
@ -2,6 +2,7 @@ package keeper_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
@ -59,7 +60,7 @@ func (suite *unitTester) SetupSuite() {
|
|||||||
|
|
||||||
func (suite *unitTester) SetupTest() {
|
func (suite *unitTester) SetupTest() {
|
||||||
suite.ctx = NewTestContext(suite.incentiveStoreKey)
|
suite.ctx = NewTestContext(suite.incentiveStoreKey)
|
||||||
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil)
|
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *unitTester) TearDownTest() {
|
func (suite *unitTester) TearDownTest() {
|
||||||
@ -67,8 +68,13 @@ func (suite *unitTester) TearDownTest() {
|
|||||||
suite.ctx = sdk.Context{}
|
suite.ctx = sdk.Context{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *unitTester) NewKeeper(paramSubspace types.ParamSubspace, bk types.BankKeeper, cdpk types.CdpKeeper, hk types.HardKeeper, ak types.AccountKeeper, stk types.StakingKeeper, swk types.SwapKeeper, svk types.SavingsKeeper, ek types.EarnKeeper) keeper.Keeper {
|
func (suite *unitTester) NewKeeper(
|
||||||
return keeper.NewKeeper(suite.cdc, suite.incentiveStoreKey, paramSubspace, bk, cdpk, hk, ak, stk, swk, svk, ek)
|
paramSubspace types.ParamSubspace,
|
||||||
|
bk types.BankKeeper, cdpk types.CdpKeeper, hk types.HardKeeper,
|
||||||
|
ak types.AccountKeeper, stk types.StakingKeeper, swk types.SwapKeeper,
|
||||||
|
svk types.SavingsKeeper, lqk types.LiquidKeeper, ek types.EarnKeeper,
|
||||||
|
) keeper.Keeper {
|
||||||
|
return keeper.NewKeeper(suite.cdc, suite.incentiveStoreKey, paramSubspace, bk, cdpk, hk, ak, stk, swk, svk, lqk, ek)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *unitTester) storeGlobalBorrowIndexes(indexes types.MultiRewardIndexes) {
|
func (suite *unitTester) storeGlobalBorrowIndexes(indexes types.MultiRewardIndexes) {
|
||||||
@ -412,6 +418,66 @@ func (k *fakeEarnKeeper) GetVaultAccountShares(
|
|||||||
return accShares, found
|
return accShares, found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *fakeEarnKeeper) IterateVaultRecords(
|
||||||
|
ctx sdk.Context,
|
||||||
|
cb func(record earntypes.VaultRecord) (stop bool),
|
||||||
|
) {
|
||||||
|
for _, vaultShares := range k.vaultShares {
|
||||||
|
cb(earntypes.VaultRecord{
|
||||||
|
TotalShares: vaultShares,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fakeLiquidKeeper is a stub liquid keeper.
|
||||||
|
// It can be used to return values to the incentive keeper without having to initialize a full liquid keeper.
|
||||||
|
type fakeLiquidKeeper struct {
|
||||||
|
derivatives map[string]sdk.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.LiquidKeeper = newFakeLiquidKeeper()
|
||||||
|
|
||||||
|
func newFakeLiquidKeeper() *fakeLiquidKeeper {
|
||||||
|
return &fakeLiquidKeeper{
|
||||||
|
derivatives: map[string]sdk.Int{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *fakeLiquidKeeper) addDerivative(denom string, supply sdk.Int) *fakeLiquidKeeper {
|
||||||
|
k.derivatives[denom] = supply
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *fakeLiquidKeeper) IsDerivativeDenom(ctx sdk.Context, denom string) bool {
|
||||||
|
return strings.HasPrefix(denom, "bkava-")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *fakeLiquidKeeper) GetAllDerivativeDenoms(ctx sdk.Context) (denoms []string) {
|
||||||
|
for denom := range k.derivatives {
|
||||||
|
denoms = append(denoms, denom)
|
||||||
|
}
|
||||||
|
|
||||||
|
return denoms
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *fakeLiquidKeeper) GetTotalDerivativeSupply(ctx sdk.Context) sdk.Int {
|
||||||
|
totalSupply := sdk.ZeroInt()
|
||||||
|
for _, supply := range k.derivatives {
|
||||||
|
totalSupply = totalSupply.Add(supply)
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalSupply
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *fakeLiquidKeeper) GetDerivativeSupply(ctx sdk.Context, denom string) sdk.Int {
|
||||||
|
supply, found := k.derivatives[denom]
|
||||||
|
if !found {
|
||||||
|
return sdk.ZeroInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
return supply
|
||||||
|
}
|
||||||
|
|
||||||
// Assorted Testing Data
|
// Assorted Testing Data
|
||||||
|
|
||||||
// note: amino panics when encoding times ≥ the start of year 10000.
|
// note: amino panics when encoding times ≥ the start of year 10000.
|
||||||
|
@ -31,12 +31,29 @@ func NewAccumulator(previousAccrual time.Time, indexes RewardIndexes) *Accumulat
|
|||||||
//
|
//
|
||||||
// totalSourceShares is the sum of all users' source shares. For example:total btcb supplied to hard, total usdx borrowed from all bnb CDPs, or total shares in a swap pool.
|
// totalSourceShares is the sum of all users' source shares. For example:total btcb supplied to hard, total usdx borrowed from all bnb CDPs, or total shares in a swap pool.
|
||||||
func (acc *Accumulator) Accumulate(period MultiRewardPeriod, totalSourceShares sdk.Dec, currentTime time.Time) {
|
func (acc *Accumulator) Accumulate(period MultiRewardPeriod, totalSourceShares sdk.Dec, currentTime time.Time) {
|
||||||
accumulationDuration := acc.getTimeElapsedWithinLimits(acc.PreviousAccumulationTime, currentTime, period.Start, period.End)
|
acc.AccumulateDecCoins(
|
||||||
|
period.Start,
|
||||||
|
period.End,
|
||||||
|
sdk.NewDecCoinsFromCoins(period.RewardsPerSecond...),
|
||||||
|
totalSourceShares,
|
||||||
|
currentTime,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
indexesIncrement := acc.calculateNewRewards(period.RewardsPerSecond, totalSourceShares, accumulationDuration)
|
// AccumulateDecCoins
|
||||||
|
func (acc *Accumulator) AccumulateDecCoins(
|
||||||
|
periodStart time.Time,
|
||||||
|
periodEnd time.Time,
|
||||||
|
periodRewardsPerSecond sdk.DecCoins,
|
||||||
|
totalSourceShares sdk.Dec,
|
||||||
|
currentTime time.Time,
|
||||||
|
) {
|
||||||
|
accumulationDuration := acc.getTimeElapsedWithinLimits(acc.PreviousAccumulationTime, currentTime, periodStart, periodEnd)
|
||||||
|
|
||||||
|
indexesIncrement := acc.calculateNewRewards(periodRewardsPerSecond, totalSourceShares, accumulationDuration)
|
||||||
|
|
||||||
acc.Indexes = acc.Indexes.Add(indexesIncrement)
|
acc.Indexes = acc.Indexes.Add(indexesIncrement)
|
||||||
acc.PreviousAccumulationTime = minTime(period.End, currentTime)
|
acc.PreviousAccumulationTime = minTime(periodEnd, currentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTimeElapsedWithinLimits returns the duration between start and end times, capped by min and max times.
|
// getTimeElapsedWithinLimits returns the duration between start and end times, capped by min and max times.
|
||||||
@ -59,7 +76,7 @@ func (*Accumulator) getTimeElapsedWithinLimits(start, end, limitMin, limitMax ti
|
|||||||
// The total rewards to distribute in this block are given by reward rate * duration. This value divided by the sum of all source shares to give
|
// The total rewards to distribute in this block are given by reward rate * duration. This value divided by the sum of all source shares to give
|
||||||
// total rewards per source share, which is what the indexes store.
|
// total rewards per source share, which is what the indexes store.
|
||||||
// Note, duration is rounded to the nearest second to keep rewards calculation consistent with kava-7.
|
// Note, duration is rounded to the nearest second to keep rewards calculation consistent with kava-7.
|
||||||
func (*Accumulator) calculateNewRewards(rewardsPerSecond sdk.Coins, totalSourceShares sdk.Dec, duration time.Duration) RewardIndexes {
|
func (*Accumulator) calculateNewRewards(rewardsPerSecond sdk.DecCoins, totalSourceShares sdk.Dec, duration time.Duration) RewardIndexes {
|
||||||
if totalSourceShares.LTE(sdk.ZeroDec()) {
|
if totalSourceShares.LTE(sdk.ZeroDec()) {
|
||||||
// When there is zero source shares, there is no users with deposits/borrows/delegations to pay out the current block's rewards to.
|
// When there is zero source shares, there is no users with deposits/borrows/delegations to pay out the current block's rewards to.
|
||||||
// So drop the rewards and pay out nothing.
|
// So drop the rewards and pay out nothing.
|
||||||
@ -93,10 +110,10 @@ func maxTime(t1, t2 time.Time) time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newRewardIndexesFromCoins is a helper function to initialize a RewardIndexes slice with the values from a Coins slice.
|
// newRewardIndexesFromCoins is a helper function to initialize a RewardIndexes slice with the values from a Coins slice.
|
||||||
func newRewardIndexesFromCoins(coins sdk.Coins) RewardIndexes {
|
func newRewardIndexesFromCoins(coins sdk.DecCoins) RewardIndexes {
|
||||||
var indexes RewardIndexes
|
var indexes RewardIndexes
|
||||||
for _, coin := range coins {
|
for _, coin := range coins {
|
||||||
indexes = append(indexes, NewRewardIndex(coin.Denom, coin.Amount.ToDec()))
|
indexes = append(indexes, NewRewardIndex(coin.Denom, coin.Amount))
|
||||||
}
|
}
|
||||||
return indexes
|
return indexes
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,11 @@ func TestAccumulator(t *testing.T) {
|
|||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
acc := &Accumulator{}
|
acc := &Accumulator{}
|
||||||
indexes := acc.calculateNewRewards(tc.args.rewardsPerSecond, tc.args.totalSourceShares, tc.args.duration)
|
indexes := acc.calculateNewRewards(
|
||||||
|
sdk.NewDecCoinsFromCoins(tc.args.rewardsPerSecond...),
|
||||||
|
tc.args.totalSourceShares,
|
||||||
|
tc.args.duration,
|
||||||
|
)
|
||||||
|
|
||||||
require.Equal(t, tc.expected, indexes)
|
require.Equal(t, tc.expected, indexes)
|
||||||
})
|
})
|
||||||
|
@ -68,6 +68,14 @@ type SavingsKeeper interface {
|
|||||||
type EarnKeeper interface {
|
type EarnKeeper interface {
|
||||||
GetVaultTotalShares(ctx sdk.Context, denom string) (shares earntypes.VaultShare, found bool)
|
GetVaultTotalShares(ctx sdk.Context, denom string) (shares earntypes.VaultShare, found bool)
|
||||||
GetVaultAccountShares(ctx sdk.Context, acc sdk.AccAddress) (shares earntypes.VaultShares, found bool)
|
GetVaultAccountShares(ctx sdk.Context, acc sdk.AccAddress) (shares earntypes.VaultShares, found bool)
|
||||||
|
IterateVaultRecords(ctx sdk.Context, cb func(record earntypes.VaultRecord) (stop bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LiquidKeeper defines the required methods needed by this modules keeper
|
||||||
|
type LiquidKeeper interface {
|
||||||
|
IsDerivativeDenom(ctx sdk.Context, denom string) bool
|
||||||
|
GetTotalDerivativeSupply(ctx sdk.Context) sdk.Int
|
||||||
|
GetDerivativeSupply(ctx sdk.Context, denom string) sdk.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountKeeper expected interface for the account keeper (noalias)
|
// AccountKeeper expected interface for the account keeper (noalias)
|
||||||
|
Loading…
Reference in New Issue
Block a user