mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-25 07:45:18 +00:00
Fix index sync when deposits/borrows are small (#886)
* sync indexes when deposit is small * add test for borrow index sync when zero rewards * update test for borrow index updates * fix synchronize hard supply reward Co-authored-by: denalimarsh <denalimarsh@gmail.com>
This commit is contained in:
parent
656c5a80b8
commit
d601481b95
@ -222,7 +222,7 @@ func (suite *KeeperTestSuite) SetupWithGenState() {
|
||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||
|
||||
tApp.InitializeFromGenesisStates(
|
||||
NewAuthGenState(allAddrs, cs(c("ukava", 5_000_000))),
|
||||
NewAuthGenState(allAddrs, cs(c("ukava", 1_000_000_000))),
|
||||
NewStakingGenesisState(),
|
||||
NewPricefeedGenStateMulti(),
|
||||
NewCDPGenStateMulti(),
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
@ -54,7 +55,7 @@ func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaim() {
|
||||
multipliers: types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||
multiplier: types.MultiplierName("large"),
|
||||
timeElapsed: 86400,
|
||||
expectedBalance: cs(c("usdx", 10000000000), c("ukava", 10576385600)),
|
||||
expectedBalance: cs(c("usdx", 10000000000), c("ukava", 11571385600)),
|
||||
expectedPeriods: vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("ukava", 10571385600))}},
|
||||
isPeriodicVestingAccount: true,
|
||||
},
|
||||
@ -135,7 +136,7 @@ func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaim() {
|
||||
suite.Require().NoError(err)
|
||||
ak := suite.app.GetAccountKeeper()
|
||||
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
||||
suite.Require().Equal(tc.args.expectedBalance, acc.GetCoins())
|
||||
suite.Require().Equal(tc.args.expectedBalance, acc.GetCoins()) // TODO check balance change to decouple from initialized account balance.
|
||||
|
||||
if tc.args.isPeriodicVestingAccount {
|
||||
vacc, ok := acc.(*vesting.PeriodicVestingAccount)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
@ -252,7 +253,6 @@ func (k Keeper) SynchronizeUSDXMintingReward(ctx sdk.Context, cdp cdptypes.CDP)
|
||||
newRewardsCoin := sdk.NewCoin(types.USDXMintingRewardDenom, newRewardsAmount)
|
||||
claim.Reward = claim.Reward.Add(newRewardsCoin)
|
||||
k.SetUSDXMintingClaim(ctx, claim)
|
||||
return
|
||||
}
|
||||
|
||||
// InitializeHardSupplyReward initializes the supply-side of a hard liquidity provider claim
|
||||
@ -321,19 +321,18 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D
|
||||
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||
userRewardFactor := userRewardIndex.RewardFactor
|
||||
rewardsAccumulatedFactor := globalRewardFactor.Sub(userRewardFactor)
|
||||
if rewardsAccumulatedFactor.IsZero() {
|
||||
continue
|
||||
}
|
||||
newRewardsAmount := rewardsAccumulatedFactor.Mul(deposit.Amount.AmountOf(coin.Denom).ToDec()).RoundInt()
|
||||
if newRewardsAmount.IsZero() || newRewardsAmount.IsNegative() {
|
||||
continue
|
||||
if rewardsAccumulatedFactor.IsNegative() {
|
||||
panic(fmt.Sprintf("reward accumulation factor cannot be negative: %s", rewardsAccumulatedFactor))
|
||||
}
|
||||
|
||||
newRewardsAmount := rewardsAccumulatedFactor.Mul(deposit.Amount.AmountOf(coin.Denom).ToDec()).RoundInt()
|
||||
|
||||
factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||
if !foundFactorIndex {
|
||||
if !foundFactorIndex { // should never trigger, as we basically do this check at the start of this loop
|
||||
continue
|
||||
}
|
||||
claim.SupplyRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
|
||||
|
||||
newRewardsCoin := sdk.NewCoin(userRewardIndex.CollateralType, newRewardsAmount)
|
||||
claim.Reward = claim.Reward.Add(newRewardsCoin)
|
||||
}
|
||||
@ -403,16 +402,14 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo
|
||||
globalRewardFactor := globalRewardIndex.RewardFactor
|
||||
userRewardFactor := userRewardIndex.RewardFactor
|
||||
rewardsAccumulatedFactor := globalRewardFactor.Sub(userRewardFactor)
|
||||
if rewardsAccumulatedFactor.IsZero() {
|
||||
continue
|
||||
}
|
||||
newRewardsAmount := rewardsAccumulatedFactor.Mul(borrow.Amount.AmountOf(coin.Denom).ToDec()).RoundInt()
|
||||
if newRewardsAmount.IsZero() || newRewardsAmount.IsNegative() {
|
||||
continue
|
||||
if rewardsAccumulatedFactor.IsNegative() {
|
||||
panic(fmt.Sprintf("reward accumulation factor cannot be negative: %s", rewardsAccumulatedFactor))
|
||||
}
|
||||
|
||||
newRewardsAmount := rewardsAccumulatedFactor.Mul(borrow.Amount.AmountOf(coin.Denom).ToDec()).RoundInt()
|
||||
|
||||
factorIndex, foundFactorIndex := userMultiRewardIndex.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType)
|
||||
if !foundFactorIndex {
|
||||
if !foundFactorIndex { // should never trigger
|
||||
continue
|
||||
}
|
||||
claim.BorrowRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor
|
||||
|
@ -391,7 +391,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
|
||||
testCases := []test{
|
||||
{
|
||||
"10 blocks",
|
||||
"single reward denom: 10 blocks",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
@ -404,7 +404,7 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
},
|
||||
},
|
||||
{
|
||||
"10 blocks - long block time",
|
||||
"single reward denom: 10 blocks - long block time",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "bnb",
|
||||
borrow: c("bnb", 10000000000),
|
||||
@ -415,6 +415,19 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
expectedRewards: cs(c("hard", 105713856031)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"single reward denom: user reward index updated when reward is zero",
|
||||
args{
|
||||
incentiveBorrowRewardDenom: "ukava",
|
||||
borrow: c("ukava", 1), // borrow a tiny amount so that rewards round to zero
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.122354003908172328"))},
|
||||
expectedRewards: cs(),
|
||||
updateRewardsViaCommmittee: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"multiple reward denoms: 10 blocks",
|
||||
args{
|
||||
@ -602,6 +615,18 @@ func (suite *KeeperTestSuite) TestSynchronizeHardBorrowReward() {
|
||||
suite.hardKeeper.SetSupplyInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.borrow.Denom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.borrow.Denom, tc.args.initialTime)
|
||||
// Set the minimum borrow to 0 to allow testing small borrows
|
||||
hardParams := suite.hardKeeper.GetParams(suite.ctx)
|
||||
hardParams.MinimumBorrowUSDValue = sdk.ZeroDec()
|
||||
suite.hardKeeper.SetParams(suite.ctx, hardParams)
|
||||
|
||||
// Borrow a fixed amount from another user to dilute primary user's rewards per second.
|
||||
suite.Require().NoError(
|
||||
suite.hardKeeper.Deposit(suite.ctx, suite.addrs[2], cs(c("ukava", 200_000_000))),
|
||||
)
|
||||
suite.Require().NoError(
|
||||
suite.hardKeeper.Borrow(suite.ctx, suite.addrs[2], cs(c("ukava", 100_000_000))),
|
||||
)
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
@ -1284,6 +1309,19 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
updateRewardsViaCommmittee: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"single reward denom: user reward index updated when reward is zero",
|
||||
args{
|
||||
incentiveSupplyRewardDenom: "ukava",
|
||||
deposit: c("ukava", 1),
|
||||
rewardsPerSecond: cs(c("hard", 122354)),
|
||||
initialTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||
blockTimes: []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
|
||||
expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("0.122353998776460010"))},
|
||||
expectedRewards: cs(),
|
||||
updateRewardsViaCommmittee: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"multiple reward denoms: 10 blocks",
|
||||
args{
|
||||
@ -1475,6 +1513,11 @@ func (suite *KeeperTestSuite) TestSynchronizeHardSupplyReward() {
|
||||
suite.hardKeeper.SetBorrowInterestFactor(suite.ctx, tc.args.incentiveSupplyRewardDenom, sdk.MustNewDecFromStr("1.0"))
|
||||
suite.hardKeeper.SetPreviousAccrualTime(suite.ctx, tc.args.incentiveSupplyRewardDenom, tc.args.initialTime)
|
||||
|
||||
// Deposit a fixed amount from another user to dilute primary user's rewards per second.
|
||||
suite.Require().NoError(
|
||||
suite.hardKeeper.Deposit(suite.ctx, suite.addrs[2], cs(c("ukava", 100_000_000))),
|
||||
)
|
||||
|
||||
// User deposits and borrows to increase total borrowed amount
|
||||
hardKeeper := suite.app.GetHardKeeper()
|
||||
userAddr := suite.addrs[3]
|
||||
|
Loading…
Reference in New Issue
Block a user