mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 00:37:28 +00:00 
			
		
		
		
	Allocate Hard supply/borrow rewards to legacy suppliers/borrowers (#833)
* initialize hard supply reward for empty rewards * add god committee to integration test * organize claim types, add helper methods * reorder integration test's god committee * legacy suppliers earn rewards + tests * update InitializeHardBorrowReward + test * remove formatting comments from tests * allocate rewards to legacy borrowers + test * apply change to update index denom methods * Update querier to show synced rewards for legacy deposits/borrows (#834) * update simulated sync method to show rewards for legacy deposits/borrows * more explicity debuging logs * revisions Co-authored-by: Kevin Davis <karzak@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									c5fc1c6b4f
								
							
						
					
					
						commit
						6045a94b39
					
				@ -4,9 +4,14 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	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"
 | 
			
		||||
	"github.com/kava-labs/kava/x/pricefeed"
 | 
			
		||||
)
 | 
			
		||||
@ -109,6 +114,7 @@ func NewPricefeedGenStateMulti() app.GenesisState {
 | 
			
		||||
				{MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
			
		||||
				{MarketID: "bnb:usd", BaseAsset: "bnb", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
			
		||||
				{MarketID: "busd:usd", BaseAsset: "busd", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
			
		||||
				{MarketID: "zzz:usd", BaseAsset: "zzz", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PostedPrices: []pricefeed.PostedPrice{
 | 
			
		||||
@ -142,6 +148,12 @@ func NewPricefeedGenStateMulti() app.GenesisState {
 | 
			
		||||
				Price:         sdk.OneDec(),
 | 
			
		||||
				Expiry:        time.Now().Add(1 * time.Hour),
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				MarketID:      "zzz:usd",
 | 
			
		||||
				OracleAddress: sdk.AccAddress{},
 | 
			
		||||
				Price:         sdk.MustNewDecFromStr("2.00"),
 | 
			
		||||
				Expiry:        time.Now().Add(1 * time.Hour),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)}
 | 
			
		||||
@ -158,6 +170,7 @@ func NewHardGenStateMulti() app.GenesisState {
 | 
			
		||||
			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,
 | 
			
		||||
@ -166,3 +179,72 @@ func NewHardGenStateMulti() app.GenesisState {
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStakingGenesisState() app.GenesisState {
 | 
			
		||||
	genState := staking.DefaultGenesisState()
 | 
			
		||||
	genState.Params.BondDenom = "ukava"
 | 
			
		||||
	return app.GenesisState{
 | 
			
		||||
		staking.ModuleName: staking.ModuleCdc.MustMarshalJSON(genState),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *KeeperTestSuite) SetupWithGenState() {
 | 
			
		||||
	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))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tApp := app.NewTestApp()
 | 
			
		||||
	ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
 | 
			
		||||
 | 
			
		||||
	tApp.InitializeFromGenesisStates(
 | 
			
		||||
		NewAuthGenState(allAddrs, cs(c("ukava", 5_000_000))),
 | 
			
		||||
		NewStakingGenesisState(),
 | 
			
		||||
		NewPricefeedGenStateMulti(),
 | 
			
		||||
		NewCDPGenStateMulti(),
 | 
			
		||||
		NewHardGenStateMulti(),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Set up a god committee
 | 
			
		||||
	committeeModKeeper := tApp.GetCommitteeKeeper()
 | 
			
		||||
	godCommittee := committeetypes.Committee{
 | 
			
		||||
		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,
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ import (
 | 
			
		||||
	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"
 | 
			
		||||
@ -25,13 +26,14 @@ import (
 | 
			
		||||
type KeeperTestSuite struct {
 | 
			
		||||
	suite.Suite
 | 
			
		||||
 | 
			
		||||
	keeper         keeper.Keeper
 | 
			
		||||
	hardKeeper     hardkeeper.Keeper
 | 
			
		||||
	stakingKeeper  stakingkeeper.Keeper
 | 
			
		||||
	app            app.TestApp
 | 
			
		||||
	ctx            sdk.Context
 | 
			
		||||
	addrs          []sdk.AccAddress
 | 
			
		||||
	validatorAddrs []sdk.ValAddress
 | 
			
		||||
	keeper          keeper.Keeper
 | 
			
		||||
	hardKeeper      hardkeeper.Keeper
 | 
			
		||||
	stakingKeeper   stakingkeeper.Keeper
 | 
			
		||||
	committeeKeeper committeekeeper.Keeper
 | 
			
		||||
	app             app.TestApp
 | 
			
		||||
	ctx             sdk.Context
 | 
			
		||||
	addrs           []sdk.AccAddress
 | 
			
		||||
	validatorAddrs  []sdk.ValAddress
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The default state used by each test
 | 
			
		||||
 | 
			
		||||
@ -262,10 +262,12 @@ func (k Keeper) InitializeHardSupplyReward(ctx sdk.Context, deposit hardtypes.De
 | 
			
		||||
	var supplyRewardIndexes types.MultiRewardIndexes
 | 
			
		||||
	for _, coin := range deposit.Amount {
 | 
			
		||||
		globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
		if !foundGlobalRewardIndexes {
 | 
			
		||||
			continue
 | 
			
		||||
		var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
		if foundGlobalRewardIndexes {
 | 
			
		||||
			multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
		} else {
 | 
			
		||||
			multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
		}
 | 
			
		||||
		multiRewardIndex := types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
		supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -296,8 +298,8 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		userRewardIndexes, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
		userMultiRewardIndex, foundUserMultiRewardIndex := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserMultiRewardIndex {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -308,9 +310,14 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, globalRewardIndex := range globalRewardIndexes {
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userMultiRewardIndex.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundUserRewardIndex {
 | 
			
		||||
				continue
 | 
			
		||||
				// User deposited this coin type before it had rewards. When new rewards are added, legacy depositors
 | 
			
		||||
				// should immediately begin earning rewards. Enable users to do so by updating their claim with the global
 | 
			
		||||
				// reward index denom and start their reward factor at 0.0
 | 
			
		||||
				userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec())
 | 
			
		||||
				userMultiRewardIndex.RewardIndexes = append(userMultiRewardIndex.RewardIndexes, userRewardIndex)
 | 
			
		||||
				claim.SupplyRewardIndexes[userRewardIndexIndex] = userMultiRewardIndex
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			globalRewardFactor := globalRewardIndex.RewardFactor
 | 
			
		||||
@ -324,7 +331,7 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundFactorIndex {
 | 
			
		||||
				fmt.Printf("[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
 | 
			
		||||
				continue
 | 
			
		||||
@ -348,10 +355,12 @@ func (k Keeper) InitializeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bor
 | 
			
		||||
	var borrowRewardIndexes types.MultiRewardIndexes
 | 
			
		||||
	for _, coin := range borrow.Amount {
 | 
			
		||||
		globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
		if !foundGlobalRewardIndexes {
 | 
			
		||||
			continue
 | 
			
		||||
		var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
		if foundGlobalRewardIndexes {
 | 
			
		||||
			multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
		} else {
 | 
			
		||||
			multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
		}
 | 
			
		||||
		multiRewardIndex := types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
		borrowRewardIndexes = append(borrowRewardIndexes, multiRewardIndex)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -373,8 +382,8 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		userRewardIndexes, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
		userMultiRewardIndex, foundUserMultiRewardIndex := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserMultiRewardIndex {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -385,9 +394,14 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, globalRewardIndex := range globalRewardIndexes {
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userMultiRewardIndex.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundUserRewardIndex {
 | 
			
		||||
				continue
 | 
			
		||||
				// User borrowed this coin type before it had rewards. When new rewards are added, legacy borrowers
 | 
			
		||||
				// should immediately begin earning rewards. Enable users to do so by updating their claim with the global
 | 
			
		||||
				// reward index denom and start their reward factor at 0.0
 | 
			
		||||
				userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec())
 | 
			
		||||
				userMultiRewardIndex.RewardIndexes = append(userMultiRewardIndex.RewardIndexes, userRewardIndex)
 | 
			
		||||
				claim.BorrowRewardIndexes[userRewardIndexIndex] = userMultiRewardIndex
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			globalRewardFactor := globalRewardIndex.RewardFactor
 | 
			
		||||
@ -401,7 +415,7 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundFactorIndex {
 | 
			
		||||
				fmt.Printf("\n[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
 | 
			
		||||
				continue
 | 
			
		||||
@ -425,11 +439,13 @@ func (k Keeper) UpdateHardSupplyIndexDenoms(ctx sdk.Context, deposit hardtypes.D
 | 
			
		||||
	for _, coin := range deposit.Amount {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
			globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			if !foundGlobalRewardIndexes {
 | 
			
		||||
				continue // No rewards for this coin type
 | 
			
		||||
			globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
			if foundGlobalSupplyRewardIndexes {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalSupplyRewardIndexes)
 | 
			
		||||
			} else {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
			}
 | 
			
		||||
			multiRewardIndex := types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
			supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -451,11 +467,13 @@ func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Bo
 | 
			
		||||
	for _, coin := range borrow.Amount {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
			globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			if !foundGlobalRewardIndexes {
 | 
			
		||||
				continue // No rewards for this coin type
 | 
			
		||||
			globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
			if foundGlobalBorrowRewardIndexes {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalBorrowRewardIndexes)
 | 
			
		||||
			} else {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
			}
 | 
			
		||||
			multiRewardIndex := types.NewMultiRewardIndex(coin.Denom, globalRewardIndexes)
 | 
			
		||||
			borrowRewardIndexes = append(borrowRewardIndexes, multiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -678,14 +696,16 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
 | 
			
		||||
 | 
			
		||||
		userRewardIndexIndex, foundUserRewardIndexIndex := claim.SupplyRewardIndexes.GetRewardIndexIndex(ri.CollateralType)
 | 
			
		||||
		if !foundUserRewardIndexIndex {
 | 
			
		||||
			fmt.Printf("\n[LOG]: factor index for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
			fmt.Printf("\n[LOG]: claim.SupplyRewardIndexes.GetRewardIndexIndex for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, globalRewardIndex := range globalRewardIndexes {
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundUserRewardIndex {
 | 
			
		||||
				continue
 | 
			
		||||
				userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec())
 | 
			
		||||
				userRewardIndexes.RewardIndexes = append(userRewardIndexes.RewardIndexes, userRewardIndex)
 | 
			
		||||
				claim.SupplyRewardIndexes[userRewardIndexIndex].RewardIndexes = append(claim.SupplyRewardIndexes[userRewardIndexIndex].RewardIndexes, userRewardIndex)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			globalRewardFactor := globalRewardIndex.RewardFactor
 | 
			
		||||
@ -705,7 +725,7 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
 | 
			
		||||
 | 
			
		||||
			factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundFactorIndex {
 | 
			
		||||
				fmt.Printf("[LOG]: factor index for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
				fmt.Printf("[LOG]: userRewardIndexes.RewardIndexes.GetFactorIndex for %s should always be found", globalRewardIndex.CollateralType) // TODO: remove before production
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			claim.SupplyRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
 | 
			
		||||
@ -728,14 +748,16 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
 | 
			
		||||
 | 
			
		||||
		userRewardIndexIndex, foundUserRewardIndexIndex := claim.BorrowRewardIndexes.GetRewardIndexIndex(ri.CollateralType)
 | 
			
		||||
		if !foundUserRewardIndexIndex {
 | 
			
		||||
			fmt.Printf("\n[LOG]: factor index for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
			fmt.Printf("\n[LOG]: claim.BorrowRewardIndexes.GetRewardIndexIndex for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, globalRewardIndex := range globalRewardIndexes {
 | 
			
		||||
			userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundUserRewardIndex {
 | 
			
		||||
				continue
 | 
			
		||||
				userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec())
 | 
			
		||||
				userRewardIndexes.RewardIndexes = append(userRewardIndexes.RewardIndexes, userRewardIndex)
 | 
			
		||||
				claim.BorrowRewardIndexes[userRewardIndexIndex].RewardIndexes = append(claim.BorrowRewardIndexes[userRewardIndexIndex].RewardIndexes, userRewardIndex)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			globalRewardFactor := globalRewardIndex.RewardFactor
 | 
			
		||||
@ -755,7 +777,7 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
 | 
			
		||||
 | 
			
		||||
			factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
 | 
			
		||||
			if !foundFactorIndex {
 | 
			
		||||
				fmt.Printf("[LOG]: factor index for %s should always be found", ri.CollateralType) // TODO: remove before production
 | 
			
		||||
				fmt.Printf("[LOG]: userRewardIndexes.RewardIndexes.GetFactorIndex for %s should always be found", globalRewardIndex.CollateralType) // TODO: remove before production
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			claim.BorrowRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -264,9 +264,101 @@ func (cs HardLiquidityProviderClaims) Validate() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------- Subcomponents of Custom Claim Types --------------
 | 
			
		||||
// ---------------------- Reward periods are used by the params ----------------------
 | 
			
		||||
 | 
			
		||||
// TODO: refactor RewardPeriod name from 'collateralType' to 'denom'
 | 
			
		||||
// MultiRewardPeriod supports multiple reward types
 | 
			
		||||
type MultiRewardPeriod struct {
 | 
			
		||||
	Active           bool      `json:"active" yaml:"active"`
 | 
			
		||||
	CollateralType   string    `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	Start            time.Time `json:"start" yaml:"start"`
 | 
			
		||||
	End              time.Time `json:"end" yaml:"end"`
 | 
			
		||||
	RewardsPerSecond sdk.Coins `json:"rewards_per_second" yaml:"rewards_per_second"` // per second reward payouts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (mrp MultiRewardPeriod) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Reward Period:
 | 
			
		||||
	Collateral Type: %s,
 | 
			
		||||
	Start: %s,
 | 
			
		||||
	End: %s,
 | 
			
		||||
	Rewards Per Second: %s,
 | 
			
		||||
	Active %t,
 | 
			
		||||
	`, mrp.CollateralType, mrp.Start, mrp.End, mrp.RewardsPerSecond, mrp.Active)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiRewardPeriod returns a new MultiRewardPeriod
 | 
			
		||||
func NewMultiRewardPeriod(active bool, collateralType string, start time.Time, end time.Time, reward sdk.Coins) MultiRewardPeriod {
 | 
			
		||||
	return MultiRewardPeriod{
 | 
			
		||||
		Active:           active,
 | 
			
		||||
		CollateralType:   collateralType,
 | 
			
		||||
		Start:            start,
 | 
			
		||||
		End:              end,
 | 
			
		||||
		RewardsPerSecond: reward,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a MultiRewardPeriod.
 | 
			
		||||
func (mrp MultiRewardPeriod) Validate() error {
 | 
			
		||||
	if mrp.Start.IsZero() {
 | 
			
		||||
		return errors.New("reward period start time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.End.IsZero() {
 | 
			
		||||
		return errors.New("reward period end time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.Start.After(mrp.End) {
 | 
			
		||||
		return fmt.Errorf("end period time %s cannot be before start time %s", mrp.End, mrp.Start)
 | 
			
		||||
	}
 | 
			
		||||
	if !mrp.RewardsPerSecond.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", mrp.RewardsPerSecond)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(mrp.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("reward period collateral type cannot be blank: %s", mrp)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardPeriods array of MultiRewardPeriod
 | 
			
		||||
type MultiRewardPeriods []MultiRewardPeriod
 | 
			
		||||
 | 
			
		||||
// GetMultiRewardPeriod fetches a MultiRewardPeriod from an array of MultiRewardPeriods by its denom
 | 
			
		||||
func (mrps MultiRewardPeriods) GetMultiRewardPeriod(denom string) (MultiRewardPeriod, bool) {
 | 
			
		||||
	for _, rp := range mrps {
 | 
			
		||||
		if rp.CollateralType == denom {
 | 
			
		||||
			return rp, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return MultiRewardPeriod{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMultiRewardPeriodIndex returns the index of a MultiRewardPeriod inside array MultiRewardPeriods
 | 
			
		||||
func (mrps MultiRewardPeriods) GetMultiRewardPeriodIndex(denom string) (int, bool) {
 | 
			
		||||
	for i, rp := range mrps {
 | 
			
		||||
		if rp.CollateralType == denom {
 | 
			
		||||
			return i, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the RewardPeriods are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (mrps MultiRewardPeriods) Validate() error {
 | 
			
		||||
	seenPeriods := make(map[string]bool)
 | 
			
		||||
	for _, rp := range mrps {
 | 
			
		||||
		if seenPeriods[rp.CollateralType] {
 | 
			
		||||
			return fmt.Errorf("duplicated reward period with collateral type %s", rp.CollateralType)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := rp.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		seenPeriods[rp.CollateralType] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------- Reward indexes are used internally in the store ----------------------
 | 
			
		||||
 | 
			
		||||
// RewardIndex stores reward accumulation information
 | 
			
		||||
type RewardIndex struct {
 | 
			
		||||
@ -330,80 +422,6 @@ func (ris RewardIndexes) Validate() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// MultiRewardPeriod supports multiple reward types
 | 
			
		||||
type MultiRewardPeriod struct {
 | 
			
		||||
	Active           bool      `json:"active" yaml:"active"`
 | 
			
		||||
	CollateralType   string    `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	Start            time.Time `json:"start" yaml:"start"`
 | 
			
		||||
	End              time.Time `json:"end" yaml:"end"`
 | 
			
		||||
	RewardsPerSecond sdk.Coins `json:"rewards_per_second" yaml:"rewards_per_second"` // per second reward payouts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (mrp MultiRewardPeriod) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Reward Period:
 | 
			
		||||
	Collateral Type: %s,
 | 
			
		||||
	Start: %s,
 | 
			
		||||
	End: %s,
 | 
			
		||||
	Rewards Per Second: %s,
 | 
			
		||||
	Active %t,
 | 
			
		||||
	`, mrp.CollateralType, mrp.Start, mrp.End, mrp.RewardsPerSecond, mrp.Active)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiRewardPeriod returns a new MultiRewardPeriod
 | 
			
		||||
func NewMultiRewardPeriod(active bool, collateralType string, start time.Time, end time.Time, reward sdk.Coins) MultiRewardPeriod {
 | 
			
		||||
	return MultiRewardPeriod{
 | 
			
		||||
		Active:           active,
 | 
			
		||||
		CollateralType:   collateralType,
 | 
			
		||||
		Start:            start,
 | 
			
		||||
		End:              end,
 | 
			
		||||
		RewardsPerSecond: reward,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a MultiRewardPeriod.
 | 
			
		||||
func (mrp MultiRewardPeriod) Validate() error {
 | 
			
		||||
	if mrp.Start.IsZero() {
 | 
			
		||||
		return errors.New("reward period start time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.End.IsZero() {
 | 
			
		||||
		return errors.New("reward period end time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.Start.After(mrp.End) {
 | 
			
		||||
		return fmt.Errorf("end period time %s cannot be before start time %s", mrp.End, mrp.Start)
 | 
			
		||||
	}
 | 
			
		||||
	if !mrp.RewardsPerSecond.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", mrp.RewardsPerSecond)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(mrp.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("reward period collateral type cannot be blank: %s", mrp)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardPeriods array of MultiRewardPeriod
 | 
			
		||||
type MultiRewardPeriods []MultiRewardPeriod
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the RewardPeriods are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (mrps MultiRewardPeriods) Validate() error {
 | 
			
		||||
	seenPeriods := make(map[string]bool)
 | 
			
		||||
	for _, rp := range mrps {
 | 
			
		||||
		if seenPeriods[rp.CollateralType] {
 | 
			
		||||
			return fmt.Errorf("duplicated reward period with collateral type %s", rp.CollateralType)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := rp.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		seenPeriods[rp.CollateralType] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardIndex stores reward accumulation information on multiple reward types
 | 
			
		||||
type MultiRewardIndex struct {
 | 
			
		||||
	CollateralType string        `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user