mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +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"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
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/app"
|
||||||
"github.com/kava-labs/kava/x/cdp"
|
"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/hard"
|
||||||
"github.com/kava-labs/kava/x/pricefeed"
|
"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: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
|
||||||
{MarketID: "bnb:usd", BaseAsset: "bnb", 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: "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{
|
PostedPrices: []pricefeed.PostedPrice{
|
||||||
@ -142,6 +148,12 @@ func NewPricefeedGenStateMulti() app.GenesisState {
|
|||||||
Price: sdk.OneDec(),
|
Price: sdk.OneDec(),
|
||||||
Expiry: time.Now().Add(1 * time.Hour),
|
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)}
|
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("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("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("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),
|
sdk.NewDec(10),
|
||||||
), hard.DefaultAccumulationTimes, hard.DefaultDeposits, hard.DefaultBorrows,
|
), hard.DefaultAccumulationTimes, hard.DefaultDeposits, hard.DefaultBorrows,
|
||||||
@ -166,3 +179,72 @@ func NewHardGenStateMulti() app.GenesisState {
|
|||||||
|
|
||||||
return app.GenesisState{hard.ModuleName: hard.ModuleCdc.MustMarshalJSON(hardGS)}
|
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"
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
|
committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
|
||||||
hardkeeper "github.com/kava-labs/kava/x/hard/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/keeper"
|
||||||
"github.com/kava-labs/kava/x/incentive/types"
|
"github.com/kava-labs/kava/x/incentive/types"
|
||||||
@ -28,6 +29,7 @@ type KeeperTestSuite struct {
|
|||||||
keeper keeper.Keeper
|
keeper keeper.Keeper
|
||||||
hardKeeper hardkeeper.Keeper
|
hardKeeper hardkeeper.Keeper
|
||||||
stakingKeeper stakingkeeper.Keeper
|
stakingKeeper stakingkeeper.Keeper
|
||||||
|
committeeKeeper committeekeeper.Keeper
|
||||||
app app.TestApp
|
app app.TestApp
|
||||||
ctx sdk.Context
|
ctx sdk.Context
|
||||||
addrs []sdk.AccAddress
|
addrs []sdk.AccAddress
|
||||||
|
@ -262,10 +262,12 @@ func (k Keeper) InitializeHardSupplyReward(ctx sdk.Context, deposit hardtypes.De
|
|||||||
var supplyRewardIndexes types.MultiRewardIndexes
|
var supplyRewardIndexes types.MultiRewardIndexes
|
||||||
for _, coin := range deposit.Amount {
|
for _, coin := range deposit.Amount {
|
||||||
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
|
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
|
||||||
if !foundGlobalRewardIndexes {
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
continue
|
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)
|
supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,8 +298,8 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
userRewardIndexes, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
|
userMultiRewardIndex, foundUserMultiRewardIndex := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserMultiRewardIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,9 +310,14 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, globalRewardIndex := range globalRewardIndexes {
|
for _, globalRewardIndex := range globalRewardIndexes {
|
||||||
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
userRewardIndex, foundUserRewardIndex := userMultiRewardIndex.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundUserRewardIndex {
|
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
|
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||||
@ -324,7 +331,7 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundFactorIndex {
|
if !foundFactorIndex {
|
||||||
fmt.Printf("[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
|
fmt.Printf("[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
|
||||||
continue
|
continue
|
||||||
@ -348,10 +355,12 @@ func (k Keeper) InitializeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bor
|
|||||||
var borrowRewardIndexes types.MultiRewardIndexes
|
var borrowRewardIndexes types.MultiRewardIndexes
|
||||||
for _, coin := range borrow.Amount {
|
for _, coin := range borrow.Amount {
|
||||||
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
|
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
|
||||||
if !foundGlobalRewardIndexes {
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
continue
|
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)
|
borrowRewardIndexes = append(borrowRewardIndexes, multiRewardIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,8 +382,8 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
userRewardIndexes, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
|
userMultiRewardIndex, foundUserMultiRewardIndex := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserMultiRewardIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,9 +394,14 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, globalRewardIndex := range globalRewardIndexes {
|
for _, globalRewardIndex := range globalRewardIndexes {
|
||||||
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
userRewardIndex, foundUserRewardIndex := userMultiRewardIndex.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundUserRewardIndex {
|
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
|
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||||
@ -401,7 +415,7 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundFactorIndex {
|
if !foundFactorIndex {
|
||||||
fmt.Printf("\n[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
|
fmt.Printf("\n[LOG]: factor index for %s should always be found", coin.Denom) // TODO: remove before production
|
||||||
continue
|
continue
|
||||||
@ -425,11 +439,13 @@ func (k Keeper) UpdateHardSupplyIndexDenoms(ctx sdk.Context, deposit hardtypes.D
|
|||||||
for _, coin := range deposit.Amount {
|
for _, coin := range deposit.Amount {
|
||||||
_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
|
_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserRewardIndexes {
|
||||||
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
|
globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
|
||||||
if !foundGlobalRewardIndexes {
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
continue // No rewards for this coin type
|
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)
|
supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,11 +467,13 @@ func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Bo
|
|||||||
for _, coin := range borrow.Amount {
|
for _, coin := range borrow.Amount {
|
||||||
_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
|
_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserRewardIndexes {
|
||||||
globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
|
globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
|
||||||
if !foundGlobalRewardIndexes {
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
continue // No rewards for this coin type
|
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)
|
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)
|
userRewardIndexIndex, foundUserRewardIndexIndex := claim.SupplyRewardIndexes.GetRewardIndexIndex(ri.CollateralType)
|
||||||
if !foundUserRewardIndexIndex {
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, globalRewardIndex := range globalRewardIndexes {
|
for _, globalRewardIndex := range globalRewardIndexes {
|
||||||
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundUserRewardIndex {
|
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
|
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||||
@ -705,7 +725,7 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
|
|||||||
|
|
||||||
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundFactorIndex {
|
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
|
continue
|
||||||
}
|
}
|
||||||
claim.SupplyRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
|
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)
|
userRewardIndexIndex, foundUserRewardIndexIndex := claim.BorrowRewardIndexes.GetRewardIndexIndex(ri.CollateralType)
|
||||||
if !foundUserRewardIndexIndex {
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, globalRewardIndex := range globalRewardIndexes {
|
for _, globalRewardIndex := range globalRewardIndexes {
|
||||||
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundUserRewardIndex {
|
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
|
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||||
@ -755,7 +777,7 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
|
|||||||
|
|
||||||
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||||
if !foundFactorIndex {
|
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
|
continue
|
||||||
}
|
}
|
||||||
claim.BorrowRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
|
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
|
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
|
// RewardIndex stores reward accumulation information
|
||||||
type RewardIndex struct {
|
type RewardIndex struct {
|
||||||
@ -330,80 +422,6 @@ func (ris RewardIndexes) Validate() error {
|
|||||||
return nil
|
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
|
// MultiRewardIndex stores reward accumulation information on multiple reward types
|
||||||
type MultiRewardIndex struct {
|
type MultiRewardIndex struct {
|
||||||
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
|
Loading…
Reference in New Issue
Block a user