mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +00:00
Call incentive hooks before CDPs are modified in begin blocker (#897)
* call hook before cdp changed * test that risky cdps accrue rewards accurately * fix typos * clarify test comments
This commit is contained in:
parent
e6bad99564
commit
ffbf31742f
@ -159,6 +159,7 @@ func (k Keeper) CalculateNewInterest(ctx sdk.Context, cdp types.CDP) sdk.Coin {
|
|||||||
func (k Keeper) SynchronizeInterestForRiskyCDPs(ctx sdk.Context, slice sdk.Int, targetRatio sdk.Dec, collateralType string) error {
|
func (k Keeper) SynchronizeInterestForRiskyCDPs(ctx sdk.Context, slice sdk.Int, targetRatio sdk.Dec, collateralType string) error {
|
||||||
cdps := k.GetSliceOfCDPsByRatioAndType(ctx, slice, targetRatio, collateralType)
|
cdps := k.GetSliceOfCDPsByRatioAndType(ctx, slice, targetRatio, collateralType)
|
||||||
for _, cdp := range cdps {
|
for _, cdp := range cdps {
|
||||||
|
k.hooks.BeforeCDPModified(ctx, cdp)
|
||||||
k.SynchronizeInterest(ctx, cdp)
|
k.SynchronizeInterest(ctx, cdp)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
70
x/incentive/keeper/cdp_test.go
Normal file
70
x/incentive/keeper/cdp_test.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
cdptypes "github.com/kava-labs/kava/x/cdp/types"
|
||||||
|
"github.com/kava-labs/kava/x/incentive/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestRiskyCDPsAccumulateRewards() {
|
||||||
|
suite.SetupWithGenState()
|
||||||
|
initialTime := suite.ctx.BlockTime()
|
||||||
|
|
||||||
|
// Setup incentive state
|
||||||
|
collateralType := "bnb-a"
|
||||||
|
rewardsPerSecond := c(types.USDXMintingRewardDenom, 1_000_000)
|
||||||
|
params := types.NewParams(
|
||||||
|
types.RewardPeriods{types.NewRewardPeriod(true, collateralType, initialTime, initialTime.Add(4*oneYear), rewardsPerSecond)},
|
||||||
|
nil, // hard rewards not needed
|
||||||
|
nil,
|
||||||
|
nil, // delegator rewards not needed
|
||||||
|
types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))},
|
||||||
|
initialTime.Add(5*oneYear),
|
||||||
|
)
|
||||||
|
suite.keeper.SetParams(suite.ctx, params)
|
||||||
|
suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, collateralType, initialTime)
|
||||||
|
suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, collateralType, sdk.ZeroDec())
|
||||||
|
|
||||||
|
// Setup cdp state containing one CDP
|
||||||
|
cdpKeeper := suite.app.GetCDPKeeper()
|
||||||
|
initialCollateral := c("bnb", 1_000_000_000)
|
||||||
|
initialPrincipal := c("usdx", 100_000_000)
|
||||||
|
cdpKeeper.SetPreviousAccrualTime(suite.ctx, collateralType, suite.ctx.BlockTime())
|
||||||
|
cdpKeeper.SetInterestFactor(suite.ctx, collateralType, sdk.OneDec())
|
||||||
|
// add coins to user's address // TODO move this to auth genesis setup
|
||||||
|
sk := suite.app.GetSupplyKeeper()
|
||||||
|
sk.MintCoins(suite.ctx, cdptypes.ModuleName, cs(initialCollateral))
|
||||||
|
sk.SendCoinsFromModuleToAccount(suite.ctx, cdptypes.ModuleName, suite.addrs[0], cs(initialCollateral))
|
||||||
|
|
||||||
|
err := cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], initialCollateral, initialPrincipal, collateralType)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// Skip ahead two blocks to accumulate both interest and usdx reward for the cdp
|
||||||
|
// Two blocks are required because the cdp begin blocker runs before incentive begin blocker.
|
||||||
|
// In the first begin block the cdp is synced, which triggers its claim to sync. But no global rewards have accumulated yet so the sync does nothing.
|
||||||
|
// Global rewards accumulate immediately after during the incentive begin blocker.
|
||||||
|
// Rewards are added to the cdp's claim in the next block when the cdp is synced.
|
||||||
|
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(10 * time.Minute))
|
||||||
|
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) // height and time in header are ignored by module begin blockers
|
||||||
|
|
||||||
|
_ = suite.app.EndBlocker(suite.ctx, abci.RequestEndBlock{})
|
||||||
|
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(10 * time.Minute))
|
||||||
|
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{})
|
||||||
|
|
||||||
|
// check cdp rewards
|
||||||
|
cdp, found := cdpKeeper.GetCdpByOwnerAndCollateralType(suite.ctx, suite.addrs[0], collateralType)
|
||||||
|
suite.Require().True(found)
|
||||||
|
// This additional sync adds the rewards accumulated at the end of the last begin block.
|
||||||
|
// They weren't added during the begin blocker as the incentive BB runs after the CDP BB.
|
||||||
|
suite.keeper.SynchronizeUSDXMintingReward(suite.ctx, cdp)
|
||||||
|
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||||
|
suite.Require().True(found)
|
||||||
|
|
||||||
|
// rewards are roughly rewardsPerSecond * secondsElapsed (10mins) * num blocks (2)
|
||||||
|
suite.Require().Equal(c(types.USDXMintingRewardDenom, 1_200_001_671), claim.Reward)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user