mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 08:15:19 +00:00
[R4R] fix: match reward payouts to current harvest v1 payouts (#786)
* fix: payout rewards on 1st or 15th of month * backport payout test * fix: add default case
This commit is contained in:
parent
37be34b4d6
commit
6118876074
@ -1,6 +1,8 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
@ -12,6 +14,15 @@ import (
|
|||||||
validatorvesting "github.com/kava-labs/kava/x/validator-vesting"
|
validatorvesting "github.com/kava-labs/kava/x/validator-vesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BeginningOfMonth harvest rewards that are claimed after the 15th at 14:00UTC of the month always vest on the first of the month
|
||||||
|
BeginningOfMonth = 1
|
||||||
|
// MidMonth harvest rewards that are claimed before the 15th at 14:00UTC of the month always vest on the 15 of the month
|
||||||
|
MidMonth = 15
|
||||||
|
// PaymentHour harvest rewards always vest at 14:00UTC
|
||||||
|
PaymentHour = 14
|
||||||
|
)
|
||||||
|
|
||||||
// ClaimUSDXMintingReward sends the reward amount to the input address and zero's out the claim in the store
|
// ClaimUSDXMintingReward sends the reward amount to the input address and zero's out the claim in the store
|
||||||
func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, addr sdk.AccAddress, multiplierName types.MultiplierName) error {
|
func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, addr sdk.AccAddress, multiplierName types.MultiplierName) error {
|
||||||
claim, found := k.GetUSDXMintingClaim(ctx, addr)
|
claim, found := k.GetUSDXMintingClaim(ctx, addr)
|
||||||
@ -40,7 +51,10 @@ func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, addr sdk.AccAddress, mul
|
|||||||
return types.ErrZeroClaim
|
return types.ErrZeroClaim
|
||||||
}
|
}
|
||||||
rewardCoin := sdk.NewCoin(claim.Reward.Denom, rewardAmount)
|
rewardCoin := sdk.NewCoin(claim.Reward.Denom, rewardAmount)
|
||||||
length := ctx.BlockTime().AddDate(0, int(multiplier.MonthsLockup), 0).Unix() - ctx.BlockTime().Unix()
|
length, err := k.GetPeriodLength(ctx, multiplier)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, sdk.NewCoins(rewardCoin), length)
|
err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, sdk.NewCoins(rewardCoin), length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -93,9 +107,12 @@ func (k Keeper) ClaimHardReward(ctx sdk.Context, addr sdk.AccAddress, multiplier
|
|||||||
}
|
}
|
||||||
rewardCoins = append(rewardCoins, sdk.NewCoin(coin.Denom, rewardAmount))
|
rewardCoins = append(rewardCoins, sdk.NewCoin(coin.Denom, rewardAmount))
|
||||||
}
|
}
|
||||||
length := ctx.BlockTime().AddDate(0, int(multiplier.MonthsLockup), 0).Unix() - ctx.BlockTime().Unix()
|
length, err := k.GetPeriodLength(ctx, multiplier)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err := k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, rewardCoins, length)
|
err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, rewardCoins, length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -170,6 +187,29 @@ func (k Keeper) SendTimeLockedCoinsToBaseAccount(ctx sdk.Context, senderModule s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPeriodLength returns the length of the period based on the input blocktime and multiplier
|
||||||
|
// note that pay dates are always the 1st or 15th of the month at 14:00UTC.
|
||||||
|
func (k Keeper) GetPeriodLength(ctx sdk.Context, multiplier types.Multiplier) (int64, error) {
|
||||||
|
|
||||||
|
if multiplier.MonthsLockup == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
switch multiplier.Name {
|
||||||
|
case types.Small, types.Medium, types.Large:
|
||||||
|
currentDay := ctx.BlockTime().Day()
|
||||||
|
payDay := BeginningOfMonth
|
||||||
|
monthOffset := int64(1)
|
||||||
|
if currentDay < MidMonth || (currentDay == MidMonth && ctx.BlockTime().Hour() < PaymentHour) {
|
||||||
|
payDay = MidMonth
|
||||||
|
monthOffset = int64(0)
|
||||||
|
}
|
||||||
|
periodEndDate := time.Date(ctx.BlockTime().Year(), ctx.BlockTime().Month(), payDay, PaymentHour, 0, 0, 0, time.UTC).AddDate(0, int(multiplier.MonthsLockup+monthOffset), 0)
|
||||||
|
return periodEndDate.Unix() - ctx.BlockTime().Unix(), nil
|
||||||
|
default:
|
||||||
|
return 0, types.ErrInvalidMultiplier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// addCoinsToVestingSchedule adds coins to the input account's vesting schedule where length is the amount of time (from the current block time), in seconds, that the coins will be vesting for
|
// addCoinsToVestingSchedule adds coins to the input account's vesting schedule where length is the amount of time (from the current block time), in seconds, that the coins will be vesting for
|
||||||
// the input address must be a periodic vesting account
|
// the input address must be a periodic vesting account
|
||||||
func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins, length int64) {
|
func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins, length int64) {
|
||||||
|
@ -2,7 +2,6 @@ package keeper_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaim() {
|
|||||||
multiplier: types.MultiplierName("large"),
|
multiplier: types.MultiplierName("large"),
|
||||||
timeElapsed: 86400,
|
timeElapsed: 86400,
|
||||||
expectedBalance: cs(c("usdx", 10000000000), c("ukava", 10576385600)),
|
expectedBalance: cs(c("usdx", 10000000000), c("ukava", 10576385600)),
|
||||||
expectedPeriods: vesting.Periods{vesting.Period{Length: 31536000, Amount: cs(c("ukava", 10571385600))}},
|
expectedPeriods: vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("ukava", 10571385600))}},
|
||||||
isPeriodicVestingAccount: true,
|
isPeriodicVestingAccount: true,
|
||||||
},
|
},
|
||||||
errArgs{
|
errArgs{
|
||||||
@ -144,7 +143,6 @@ func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaim() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
|
||||||
fmt.Println(claim)
|
|
||||||
suite.Require().True(found)
|
suite.Require().True(found)
|
||||||
suite.Require().Equal(c("ukava", 0), claim.Reward)
|
suite.Require().Equal(c("ukava", 0), claim.Reward)
|
||||||
} else {
|
} else {
|
||||||
@ -678,3 +676,142 @@ func (suite *KeeperTestSuite) SetupWithAccountState() {
|
|||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
suite.addrs = addrs
|
suite.addrs = addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGetPeriodLength() {
|
||||||
|
type args struct {
|
||||||
|
blockTime time.Time
|
||||||
|
multiplier types.Multiplier
|
||||||
|
expectedLength int64
|
||||||
|
}
|
||||||
|
type errArgs struct {
|
||||||
|
expectPass bool
|
||||||
|
contains string
|
||||||
|
}
|
||||||
|
type periodTest struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
errArgs errArgs
|
||||||
|
}
|
||||||
|
testCases := []periodTest{
|
||||||
|
{
|
||||||
|
name: "first half of month",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 11, 2, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2021, 5, 15, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 11, 2, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "first half of month long lockup",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 11, 2, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 24, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2022, 11, 15, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 11, 2, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "second half of month",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 12, 31, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2021, 7, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 12, 31, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "second half of month long lockup",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 12, 31, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Large, 24, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2023, 1, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 12, 31, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "end of feb",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2021, 2, 28, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2021, 9, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2021, 2, 28, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "leap year",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 2, 29, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2020, 9, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 2, 29, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "leap year long lockup",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 2, 29, 15, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Large, 24, sdk.MustNewDecFromStr("1")),
|
||||||
|
expectedLength: time.Date(2022, 3, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 2, 29, 15, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exactly half of month",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2021, 7, 1, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "just before half of month",
|
||||||
|
args: args{
|
||||||
|
blockTime: time.Date(2020, 12, 15, 13, 59, 59, 0, time.UTC),
|
||||||
|
multiplier: types.NewMultiplier(types.Medium, 6, sdk.MustNewDecFromStr("0.333333")),
|
||||||
|
expectedLength: time.Date(2021, 6, 15, 14, 0, 0, 0, time.UTC).Unix() - time.Date(2020, 12, 15, 13, 59, 59, 0, time.UTC).Unix(),
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
ctx := suite.ctx.WithBlockTime(tc.args.blockTime)
|
||||||
|
length, err := suite.keeper.GetPeriodLength(ctx, tc.args.multiplier)
|
||||||
|
if tc.errArgs.expectPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(tc.args.expectedLength, length)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user