mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +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
|
// Call incentive hook
|
||||||
if !borrow.Amount.Empty() {
|
k.AfterBorrowModified(ctx, borrow)
|
||||||
k.AfterBorrowModified(ctx, borrow)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
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)
|
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
|
supplyRewardIndexes := claim.SupplyRewardIndexes
|
||||||
for _, coin := range deposit.Amount {
|
// Create a new multi-reward index in the claim for every new deposit denom
|
||||||
_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(coin.Denom)
|
for _, denom := range uniqueDepositDenoms {
|
||||||
|
_, foundUserRewardIndexes := claim.SupplyRewardIndexes.GetRewardIndex(denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserRewardIndexes {
|
||||||
globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, coin.Denom)
|
globalSupplyRewardIndexes, foundGlobalSupplyRewardIndexes := k.GetHardSupplyRewardIndexes(ctx, denom)
|
||||||
var multiRewardIndex types.MultiRewardIndex
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
if foundGlobalSupplyRewardIndexes {
|
if foundGlobalSupplyRewardIndexes {
|
||||||
multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalSupplyRewardIndexes)
|
multiRewardIndex = types.NewMultiRewardIndex(denom, globalSupplyRewardIndexes)
|
||||||
} else {
|
} else {
|
||||||
multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
|
multiRewardIndex = types.NewMultiRewardIndex(denom, types.RewardIndexes{})
|
||||||
}
|
}
|
||||||
supplyRewardIndexes = append(supplyRewardIndexes, multiRewardIndex)
|
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
|
claim.SupplyRewardIndexes = supplyRewardIndexes
|
||||||
k.SetHardLiquidityProviderClaim(ctx, claim)
|
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) {
|
func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Borrow) {
|
||||||
claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower)
|
claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower)
|
||||||
if !found {
|
if !found {
|
||||||
claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil, nil)
|
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
|
borrowRewardIndexes := claim.BorrowRewardIndexes
|
||||||
for _, coin := range borrow.Amount {
|
// Create a new multi-reward index in the claim for every new borrow denom
|
||||||
_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(coin.Denom)
|
for _, denom := range uniqueBorrowDenoms {
|
||||||
|
_, foundUserRewardIndexes := claim.BorrowRewardIndexes.GetRewardIndex(denom)
|
||||||
if !foundUserRewardIndexes {
|
if !foundUserRewardIndexes {
|
||||||
globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, coin.Denom)
|
globalBorrowRewardIndexes, foundGlobalBorrowRewardIndexes := k.GetHardBorrowRewardIndexes(ctx, denom)
|
||||||
var multiRewardIndex types.MultiRewardIndex
|
var multiRewardIndex types.MultiRewardIndex
|
||||||
if foundGlobalBorrowRewardIndexes {
|
if foundGlobalBorrowRewardIndexes {
|
||||||
multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, globalBorrowRewardIndexes)
|
multiRewardIndex = types.NewMultiRewardIndex(denom, globalBorrowRewardIndexes)
|
||||||
} else {
|
} else {
|
||||||
multiRewardIndex = types.NewMultiRewardIndex(coin.Denom, types.RewardIndexes{})
|
multiRewardIndex = types.NewMultiRewardIndex(denom, types.RewardIndexes{})
|
||||||
}
|
}
|
||||||
borrowRewardIndexes = append(borrowRewardIndexes, multiRewardIndex)
|
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
|
claim.BorrowRewardIndexes = borrowRewardIndexes
|
||||||
k.SetHardLiquidityProviderClaim(ctx, claim)
|
k.SetHardLiquidityProviderClaim(ctx, claim)
|
||||||
}
|
}
|
||||||
@ -870,3 +890,27 @@ func (k Keeper) SimulateUSDXMintingSynchronization(ctx sdk.Context, claim types.
|
|||||||
|
|
||||||
return claim
|
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() {
|
func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
||||||
|
type depositModification struct {
|
||||||
|
coins sdk.Coins
|
||||||
|
withdraw bool
|
||||||
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
firstDeposit sdk.Coins
|
firstDeposit sdk.Coins
|
||||||
secondDeposit sdk.Coins
|
modification depositModification
|
||||||
rewardsPerSecond sdk.Coins
|
rewardsPerSecond sdk.Coins
|
||||||
initialTime time.Time
|
initialTime time.Time
|
||||||
expectedSupplyIndexDenoms []string
|
expectedSupplyIndexDenoms []string
|
||||||
@ -1719,7 +1724,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
|||||||
"single reward denom: update adds one supply reward index",
|
"single reward denom: update adds one supply reward index",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
firstDeposit: cs(c("bnb", 10000000000)),
|
||||||
secondDeposit: cs(c("ukava", 10000000000)),
|
modification: depositModification{coins: cs(c("ukava", 10000000000))},
|
||||||
rewardsPerSecond: cs(c("hard", 122354)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
||||||
@ -1729,7 +1734,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
|||||||
"single reward denom: update adds multiple supply reward indexes",
|
"single reward denom: update adds multiple supply reward indexes",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
|
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",
|
"single reward denom: update doesn't add duplicate supply reward index for same denom",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
firstDeposit: cs(c("bnb", 10000000000)),
|
||||||
secondDeposit: cs(c("bnb", 5000000000)),
|
modification: depositModification{coins: cs(c("bnb", 5000000000))},
|
||||||
rewardsPerSecond: cs(c("hard", 122354)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb"},
|
expectedSupplyIndexDenoms: []string{"bnb"},
|
||||||
@ -1749,7 +1754,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
|||||||
"multiple reward denoms: update adds one supply reward index",
|
"multiple reward denoms: update adds one supply reward index",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
expectedSupplyIndexDenoms: []string{"bnb", "ukava"},
|
||||||
@ -1759,7 +1764,7 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
|||||||
"multiple reward denoms: update adds multiple supply reward indexes",
|
"multiple reward denoms: update adds multiple supply reward indexes",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb", "ukava", "btcb", "xrp"},
|
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",
|
"multiple reward denoms: update doesn't add duplicate supply reward index for same denom",
|
||||||
args{
|
args{
|
||||||
firstDeposit: cs(c("bnb", 10000000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedSupplyIndexDenoms: []string{"bnb"},
|
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 {
|
for _, tc := range testCases {
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
@ -1833,18 +1868,22 @@ func (suite *KeeperTestSuite) TestUpdateHardSupplyIndexDenoms() {
|
|||||||
}
|
}
|
||||||
suite.Require().True(len(claimAfterFirstDeposit.SupplyRewardIndexes) == len(tc.args.firstDeposit))
|
suite.Require().True(len(claimAfterFirstDeposit.SupplyRewardIndexes) == len(tc.args.firstDeposit))
|
||||||
|
|
||||||
// User deposits (second time)
|
// User modifies their Deposit by withdrawing or depositing more
|
||||||
err = hardKeeper.Deposit(suite.ctx, userAddr, tc.args.secondDeposit)
|
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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Confirm that the claim contains all expected supply indexes
|
// 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)
|
suite.Require().True(found)
|
||||||
for _, denom := range tc.args.expectedSupplyIndexDenoms {
|
for _, denom := range tc.args.expectedSupplyIndexDenoms {
|
||||||
_, hasIndex := claimAfterSecondDeposit.HasSupplyRewardIndex(denom)
|
_, hasIndex := claimAfterModification.HasSupplyRewardIndex(denom)
|
||||||
suite.Require().True(hasIndex)
|
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() {
|
func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
||||||
|
type withdrawModification struct {
|
||||||
|
coins sdk.Coins
|
||||||
|
repay bool
|
||||||
|
}
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
initialDeposit sdk.Coins
|
initialDeposit sdk.Coins
|
||||||
firstBorrow sdk.Coins
|
firstBorrow sdk.Coins
|
||||||
secondBorrow sdk.Coins
|
modification withdrawModification
|
||||||
rewardsPerSecond sdk.Coins
|
rewardsPerSecond sdk.Coins
|
||||||
initialTime time.Time
|
initialTime time.Time
|
||||||
expectedBorrowIndexDenoms []string
|
expectedBorrowIndexDenoms []string
|
||||||
@ -2055,7 +2099,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("bnb", 10000000000)),
|
initialDeposit: cs(c("bnb", 10000000000)),
|
||||||
firstBorrow: cs(c("bnb", 50000000)),
|
firstBorrow: cs(c("bnb", 50000000)),
|
||||||
secondBorrow: cs(c("ukava", 500000000)),
|
modification: withdrawModification{coins: cs(c("ukava", 500000000))},
|
||||||
rewardsPerSecond: cs(c("hard", 122354)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
||||||
@ -2066,7 +2110,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("btcb", 10000000000)),
|
initialDeposit: cs(c("btcb", 10000000000)),
|
||||||
firstBorrow: cs(c("btcb", 50000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
||||||
@ -2077,7 +2121,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("bnb", 100000000000)),
|
initialDeposit: cs(c("bnb", 100000000000)),
|
||||||
firstBorrow: cs(c("bnb", 50000000)),
|
firstBorrow: cs(c("bnb", 50000000)),
|
||||||
secondBorrow: cs(c("bnb", 50000000000)),
|
modification: withdrawModification{coins: cs(c("bnb", 50000000000))},
|
||||||
rewardsPerSecond: cs(c("hard", 122354)),
|
rewardsPerSecond: cs(c("hard", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"bnb"},
|
expectedBorrowIndexDenoms: []string{"bnb"},
|
||||||
@ -2088,7 +2132,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("bnb", 10000000000)),
|
initialDeposit: cs(c("bnb", 10000000000)),
|
||||||
firstBorrow: cs(c("bnb", 50000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
expectedBorrowIndexDenoms: []string{"bnb", "ukava"},
|
||||||
@ -2099,7 +2143,7 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("btcb", 10000000000)),
|
initialDeposit: cs(c("btcb", 10000000000)),
|
||||||
firstBorrow: cs(c("btcb", 50000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
expectedBorrowIndexDenoms: []string{"btcb", "ukava", "bnb", "xrp"},
|
||||||
@ -2110,12 +2154,45 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
args{
|
args{
|
||||||
initialDeposit: cs(c("bnb", 100000000000)),
|
initialDeposit: cs(c("bnb", 100000000000)),
|
||||||
firstBorrow: cs(c("bnb", 50000000)),
|
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)),
|
rewardsPerSecond: cs(c("hard", 122354), c("ukava", 122354)),
|
||||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
expectedBorrowIndexDenoms: []string{"bnb"},
|
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 {
|
for _, tc := range testCases {
|
||||||
suite.Run(tc.name, func() {
|
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
|
// Mint coins to hard module account so it can service borrow requests
|
||||||
supplyKeeper := suite.app.GetSupplyKeeper()
|
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)
|
supplyKeeper.MintCoins(suite.ctx, hardtypes.ModuleAccountName, hardMaccCoins)
|
||||||
|
|
||||||
// Set up generic reward periods
|
// Set up generic reward periods
|
||||||
@ -2183,18 +2260,29 @@ func (suite *KeeperTestSuite) TestUpdateHardBorrowIndexDenoms() {
|
|||||||
}
|
}
|
||||||
suite.Require().True(len(claimAfterFirstBorrow.BorrowRewardIndexes) == len(tc.args.firstBorrow))
|
suite.Require().True(len(claimAfterFirstBorrow.BorrowRewardIndexes) == len(tc.args.firstBorrow))
|
||||||
|
|
||||||
// User borrows (second time)
|
// User modifies their Borrow by either repaying or borrowing more
|
||||||
err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.secondBorrow)
|
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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Confirm that claim's borrow reward indexes contain expected values
|
// 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)
|
suite.Require().True(found)
|
||||||
for _, coin := range tc.args.secondBorrow {
|
for _, coin := range tc.args.modification.coins {
|
||||||
_, hasIndex := claimAfterSecondBorrow.HasBorrowRewardIndex(coin.Denom)
|
_, hasIndex := claimAfterModification.HasBorrowRewardIndex(coin.Denom)
|
||||||
suite.Require().True(hasIndex)
|
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
|
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
|
// Validate validation for reward indexes
|
||||||
func (mris MultiRewardIndexes) Validate() error {
|
func (mris MultiRewardIndexes) Validate() error {
|
||||||
for _, mri := range mris {
|
for _, mri := range mris {
|
||||||
|
Loading…
Reference in New Issue
Block a user