mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 04:47:27 +00:00 
			
		
		
		
	Fix: delete incentive reward factors on full withdraw/repay (#885)
* delete incentive reward index on repay/withdraw * call hook on borrow in all cases * additional types functionality * extend tests to cover fix * update naming convention in tests * update test comment * feat: add set difference unit tests * clarify test names Co-authored-by: karzak <kjydavis3@gmail.com>
This commit is contained in:
		
							parent
							
								
									d601481b95
								
							
						
					
					
						commit
						eb856b5a1f
					
				@ -67,9 +67,7 @@ func (k Keeper) Repay(ctx sdk.Context, sender, owner sdk.AccAddress, coins sdk.C
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Call incentive hook
 | 
			
		||||
	if !borrow.Amount.Empty() {
 | 
			
		||||
	k.AfterBorrowModified(ctx, borrow)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.EventManager().EmitEvent(
 | 
			
		||||
		sdk.NewEvent(
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								x/incentive/keeper/diff_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								x/incentive/keeper/diff_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
package keeper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestSetDiff(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name     string
 | 
			
		||||
		setA     []string
 | 
			
		||||
		setB     []string
 | 
			
		||||
		expected []string
 | 
			
		||||
	}{
 | 
			
		||||
		{"empty", []string{}, []string{}, []string(nil)},
 | 
			
		||||
		{"diff equal sets", []string{"busd", "usdx"}, []string{"busd", "usdx"}, []string(nil)},
 | 
			
		||||
		{"diff set empty", []string{"bnb", "ukava", "usdx"}, []string{}, []string{"bnb", "ukava", "usdx"}},
 | 
			
		||||
		{"input set empty", []string{}, []string{"bnb", "ukava", "usdx"}, []string(nil)},
 | 
			
		||||
		{"diff set with common elements", []string{"bnb", "btcb", "usdx", "xrpb"}, []string{"bnb", "usdx"}, []string{"btcb", "xrpb"}},
 | 
			
		||||
		{"diff set with all common elements", []string{"bnb", "usdx"}, []string{"bnb", "btcb", "usdx", "xrpb"}, []string(nil)},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			require.Equal(t, tt.expected, setDifference(tt.setA, tt.setB))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -427,51 +427,71 @@ func (k Keeper) UpdateHardSupplyIndexDenoms(ctx sdk.Context, deposit hardtypes.D
 | 
			
		||||
		claim = types.NewHardLiquidityProviderClaim(deposit.Depositor, sdk.Coins{}, nil, nil, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	depositDenoms := getDenoms(deposit.Amount)
 | 
			
		||||
	supplyRewardIndexDenoms := claim.SupplyRewardIndexes.GetCollateralTypes()
 | 
			
		||||
 | 
			
		||||
	uniqueDepositDenoms := setDifference(depositDenoms, supplyRewardIndexDenoms)
 | 
			
		||||
	uniqueSupplyRewardDenoms := setDifference(supplyRewardIndexDenoms, depositDenoms)
 | 
			
		||||
 | 
			
		||||
	supplyRewardIndexes := claim.SupplyRewardIndexes
 | 
			
		||||
	for _, coin := range deposit.Amount {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
	// Create a new multi-reward index in the claim for every new deposit denom
 | 
			
		||||
	for _, denom := range uniqueDepositDenoms {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
			globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, denom)
 | 
			
		||||
			var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
			if foundGlobalSupplyRewardIndexes {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalSupplyRewardIndexes)
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(denom, globalSupplyRewardIndexes)
 | 
			
		||||
			} else {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(denom, types.RewardIndexes{})
 | 
			
		||||
			}
 | 
			
		||||
			supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(supplyRewardIndexes) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	// Delete multi-reward index from claim if the collateral type is no longer deposited
 | 
			
		||||
	for _, denom := range uniqueSupplyRewardDenoms {
 | 
			
		||||
		supplyRewardIndexes = supplyRewardIndexes.RemoveRewardIndex(denom)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	claim.SupplyRewardIndexes = supplyRewardIndexes
 | 
			
		||||
	k.SetHardLiquidityProviderClaim(ctx, claim)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateHardBorrowIndexDenoms adds any new borrow denoms to the claim's supply reward index
 | 
			
		||||
// UpdateHardBorrowIndexDenoms adds any new borrow denoms to the claim's borrow reward index
 | 
			
		||||
func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Borrow) {
 | 
			
		||||
	claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower)
 | 
			
		||||
	if !found {
 | 
			
		||||
		claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	borrowDenoms := getDenoms(borrow.Amount)
 | 
			
		||||
	borrowRewardIndexDenoms := claim.BorrowRewardIndexes.GetCollateralTypes()
 | 
			
		||||
 | 
			
		||||
	uniqueBorrowDenoms := setDifference(borrowDenoms, borrowRewardIndexDenoms)
 | 
			
		||||
	uniqueBorrowRewardDenoms := setDifference(borrowRewardIndexDenoms, borrowDenoms)
 | 
			
		||||
 | 
			
		||||
	borrowRewardIndexes := claim.BorrowRewardIndexes
 | 
			
		||||
	for _, coin := range borrow.Amount {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
 | 
			
		||||
	// Create a new multi-reward index in the claim for every new borrow denom
 | 
			
		||||
	for _, denom := range uniqueBorrowDenoms {
 | 
			
		||||
		_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(denom)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
			globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
 | 
			
		||||
			globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, denom)
 | 
			
		||||
			var multiRewardIndex types.MultiRewardIndex
 | 
			
		||||
			if foundGlobalBorrowRewardIndexes {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalBorrowRewardIndexes)
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(denom, globalBorrowRewardIndexes)
 | 
			
		||||
			} else {
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
 | 
			
		||||
				multiRewardIndex = types.NewMultiRewardIndex(denom, types.RewardIndexes{})
 | 
			
		||||
			}
 | 
			
		||||
			borrowRewardIndexes = append(borrowRewardIndexes, multiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(borrowRewardIndexes) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	// Delete multi-reward index from claim if the collateral type is no longer borrowed
 | 
			
		||||
	for _, denom := range uniqueBorrowRewardDenoms {
 | 
			
		||||
		borrowRewardIndexes = borrowRewardIndexes.RemoveRewardIndex(denom)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	claim.BorrowRewardIndexes = borrowRewardIndexes
 | 
			
		||||
	k.SetHardLiquidityProviderClaim(ctx, claim)
 | 
			
		||||
}
 | 
			
		||||
@ -870,3 +890,27 @@ func (k Keeper) SimulateUSDXMintingSynchronization(ctx sdk.Context, claim types.
 | 
			
		||||
 | 
			
		||||
	return claim
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set setDifference: A - B
 | 
			
		||||
func setDifference(a, b []string) (diff []string) {
 | 
			
		||||
	m := make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
	for _, item := range b {
 | 
			
		||||
		m[item] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, item := range a {
 | 
			
		||||
		if _, ok := m[item]; !ok {
 | 
			
		||||
			diff = append(diff, item)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getDenoms(coins sdk.Coins) []string {
 | 
			
		||||
	denoms := []string{}
 | 
			
		||||
	for _, coin := range coins {
 | 
			
		||||
		denoms = append(denoms, coin.Denom)
 | 
			
		||||
	}
 | 
			
		||||
	return denoms
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1702,9 +1702,14 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
	type depositModification struct {
 | 
			
		||||
		coins    sdk.Coins
 | 
			
		||||
		withdraw bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type args struct {
 | 
			
		||||
		firstDeposit              sdk.Coins
 | 
			
		||||
		secondDeposit             sdk.Coins
 | 
			
		||||
		modification              depositModification
 | 
			
		||||
		rewardsPerSecond          sdk.Coins
 | 
			
		||||
		initialTime               time.Time
 | 
			
		||||
		expectedSupplyIndexDenoms []string
 | 
			
		||||
@ -1719,7 +1724,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"single reward denom: update adds one supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("ukava", 10000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("ukava", 10000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
 | 
			
		||||
@ -1729,7 +1734,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"single reward denom: update adds multiple supply reward indexes",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
 | 
			
		||||
@ -1739,7 +1744,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"single reward denom: update doesn't add duplicate supply reward index for same denom",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("bnb", 5000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("bnb", 5000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb"},
 | 
			
		||||
@ -1749,7 +1754,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"multiple reward denoms: update adds one supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("ukava", 10000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("ukava", 10000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
 | 
			
		||||
@ -1759,7 +1764,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"multiple reward denoms: update adds multiple supply reward indexes",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("ukava", 10000000000), c("btcb", 10000000000), c("xrp", 10000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
 | 
			
		||||
@ -1769,12 +1774,42 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			"multiple reward denoms: update doesn't add duplicate supply reward index for same denom",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 10000000000)),
 | 
			
		||||
				secondDeposit:             cs(c("bnb", 5000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("bnb", 5000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"bnb"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"single reward denom: fully withdrawing a denom deletes the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 1000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"single reward denom: fully withdrawing a denom deletes only the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 1000000000), c("ukava", 100000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{"ukava"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"multiple reward denoms: fully repaying a denom deletes the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				firstDeposit:              cs(c("bnb", 1000000000)),
 | 
			
		||||
				modification:              depositModification{coins: cs(c("bnb", 1100000000)), withdraw: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedSupplyIndexDenoms: []string{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		suite.Run(tc.name, func() {
 | 
			
		||||
@ -1833,18 +1868,22 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().True(len(claimAfterFirstDeposit.SupplyRewardIndexes) == len(tc.args.firstDeposit))
 | 
			
		||||
 | 
			
		||||
			// User deposits (second time)
 | 
			
		||||
			err = hardKeeper.Deposit(suite.ctx, userAddr, tc.args.secondDeposit)
 | 
			
		||||
			// User modifies their Deposit by withdrawing or depositing more
 | 
			
		||||
			if tc.args.modification.withdraw {
 | 
			
		||||
				err = hardKeeper.Withdraw(suite.ctx, userAddr, tc.args.modification.coins)
 | 
			
		||||
			} else {
 | 
			
		||||
				err = hardKeeper.Deposit(suite.ctx, userAddr, tc.args.modification.coins)
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
			// Confirm that the claim contains all expected supply indexes
 | 
			
		||||
			claimAfterSecondDeposit, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
 | 
			
		||||
			claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			for _, denom := range tc.args.expectedSupplyIndexDenoms {
 | 
			
		||||
				_, hasIndex := claimAfterSecondDeposit.HasSupplyRewardIndex(denom)
 | 
			
		||||
				_, hasIndex := claimAfterModification.HasSupplyRewardIndex(denom)
 | 
			
		||||
				suite.Require().True(hasIndex)
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().True(len(claimAfterSecondDeposit.SupplyRewardIndexes) == len(tc.args.expectedSupplyIndexDenoms))
 | 
			
		||||
			suite.Require().True(len(claimAfterModification.SupplyRewardIndexes) == len(tc.args.expectedSupplyIndexDenoms))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -2036,10 +2075,15 @@ func (suite *KeeperTestSuite) TestInitializeHardBorrowRewards() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
	type withdrawModification struct {
 | 
			
		||||
		coins sdk.Coins
 | 
			
		||||
		repay bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type args struct {
 | 
			
		||||
		initialDeposit            sdk.Coins
 | 
			
		||||
		firstBorrow               sdk.Coins
 | 
			
		||||
		secondBorrow              sdk.Coins
 | 
			
		||||
		modification              withdrawModification
 | 
			
		||||
		rewardsPerSecond          sdk.Coins
 | 
			
		||||
		initialTime               time.Time
 | 
			
		||||
		expectedBorrowIndexDenoms []string
 | 
			
		||||
@ -2055,7 +2099,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 10000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("ukava", 500000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("ukava", 500000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
 | 
			
		||||
@ -2066,7 +2110,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("btcb", 10000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("btcb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
 | 
			
		||||
@ -2077,7 +2121,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 100000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("bnb", 50000000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("bnb", 50000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"bnb"},
 | 
			
		||||
@ -2088,7 +2132,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 10000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("ukava", 500000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("ukava", 500000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
 | 
			
		||||
@ -2099,7 +2143,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("btcb", 10000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("btcb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("ukava", 500000000), c("bnb", 50000000000), c("xrp", 50000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
 | 
			
		||||
@ -2110,12 +2154,45 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 100000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 50000000)),
 | 
			
		||||
				secondBorrow:              cs(c("bnb", 50000000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("bnb", 50000000000))},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"bnb"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"single reward denom: fully repaying a denom deletes the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 1000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 100000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"single reward denom: fully repaying a denom deletes only the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 1000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 100000000), c("ukava", 10000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"ukava"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"multiple reward denoms: fully repaying a denom deletes the denom's supply reward index",
 | 
			
		||||
			args{
 | 
			
		||||
				initialDeposit:            cs(c("bnb", 1000000000)),
 | 
			
		||||
				firstBorrow:               cs(c("bnb", 100000000), c("ukava", 10000000)),
 | 
			
		||||
				modification:              withdrawModification{coins: cs(c("bnb", 1100000000)), repay: true},
 | 
			
		||||
				rewardsPerSecond:          cs(c("hard", 122354), c("ukava", 122354)),
 | 
			
		||||
				initialTime:               time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
				expectedBorrowIndexDenoms: []string{"ukava"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		suite.Run(tc.name, func() {
 | 
			
		||||
@ -2124,7 +2201,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
 | 
			
		||||
			// Mint coins to hard module account so it can service borrow requests
 | 
			
		||||
			supplyKeeper := suite.app.GetSupplyKeeper()
 | 
			
		||||
			hardMaccCoins := tc.args.firstBorrow.Add(tc.args.secondBorrow...)
 | 
			
		||||
			hardMaccCoins := tc.args.firstBorrow.Add(tc.args.modification.coins...)
 | 
			
		||||
			supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
 | 
			
		||||
 | 
			
		||||
			// Set up generic reward periods
 | 
			
		||||
@ -2183,18 +2260,29 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().True(len(claimAfterFirstBorrow.BorrowRewardIndexes) == len(tc.args.firstBorrow))
 | 
			
		||||
 | 
			
		||||
			// User borrows (second time)
 | 
			
		||||
			err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.secondBorrow)
 | 
			
		||||
			// User modifies their Borrow by either repaying or borrowing more
 | 
			
		||||
			if tc.args.modification.repay {
 | 
			
		||||
				err = hardKeeper.Repay(suite.ctx, userAddr, userAddr, tc.args.modification.coins)
 | 
			
		||||
			} else {
 | 
			
		||||
				err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.modification.coins)
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
			// Confirm that claim's borrow reward indexes contain expected values
 | 
			
		||||
			claimAfterSecondBorrow, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
 | 
			
		||||
			claimAfterModification, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3])
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			for _, coin := range tc.args.secondBorrow {
 | 
			
		||||
				_, hasIndex := claimAfterSecondBorrow.HasBorrowRewardIndex(coin.Denom)
 | 
			
		||||
			for _, coin := range tc.args.modification.coins {
 | 
			
		||||
				_, hasIndex := claimAfterModification.HasBorrowRewardIndex(coin.Denom)
 | 
			
		||||
				if tc.args.modification.repay {
 | 
			
		||||
					// Only false if denom is repaid in full
 | 
			
		||||
					if tc.args.modification.coins.AmountOf(coin.Denom).GTE(tc.args.firstBorrow.AmountOf(coin.Denom)) {
 | 
			
		||||
						suite.Require().False(hasIndex)
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					suite.Require().True(hasIndex)
 | 
			
		||||
				}
 | 
			
		||||
			suite.Require().True(len(claimAfterSecondBorrow.BorrowRewardIndexes) == len(tc.args.expectedBorrowIndexDenoms))
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().True(len(claimAfterModification.BorrowRewardIndexes) == len(tc.args.expectedBorrowIndexDenoms))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -486,6 +486,25 @@ func (mris MultiRewardIndexes) GetRewardIndexIndex(denom string) (int, bool) {
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetCollateralTypes returns a slice of containing all collateral types
 | 
			
		||||
func (mris MultiRewardIndexes) GetCollateralTypes() []string {
 | 
			
		||||
	var collateralTypes []string
 | 
			
		||||
	for _, ri := range mris {
 | 
			
		||||
		collateralTypes = append(collateralTypes, ri.CollateralType)
 | 
			
		||||
	}
 | 
			
		||||
	return collateralTypes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveRewardIndex removes a denom's reward interest factor value
 | 
			
		||||
func (mris MultiRewardIndexes) RemoveRewardIndex(denom string) MultiRewardIndexes {
 | 
			
		||||
	for i, ri := range mris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return append(mris[:i], mris[i+1:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return mris
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate validation for reward indexes
 | 
			
		||||
func (mris MultiRewardIndexes) Validate() error {
 | 
			
		||||
	for _, mri := range mris {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user