mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 06:37:26 +00:00 
			
		
		
		
	Update reward vesting length calculation (#624)
* use remaining length when sending coins to vesting account * query claims that have corresponding claim periods * cleanup comments * remove debugging statements * fix bug with inserting period in middle of vesting schedule * apply review suggestion
This commit is contained in:
		
							parent
							
								
									fca16da84a
								
							
						
					
					
						commit
						c0006ca8eb
					
				@ -1,6 +1,8 @@
 | 
				
			|||||||
package keeper
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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"
 | 
				
			||||||
@ -34,6 +36,7 @@ func (k Keeper) PayoutClaim(ctx sdk.Context, addr sdk.AccAddress, collateralType
 | 
				
			|||||||
			types.EventTypeClaim,
 | 
								types.EventTypeClaim,
 | 
				
			||||||
			sdk.NewAttribute(types.AttributeKeyClaimedBy, addr.String()),
 | 
								sdk.NewAttribute(types.AttributeKeyClaimedBy, addr.String()),
 | 
				
			||||||
			sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.Reward.String()),
 | 
								sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.Reward.String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyClaimPeriod, fmt.Sprintf("%d", claim.ClaimPeriodID)),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@ -141,16 +144,22 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
 | 
				
			|||||||
	// Add the new vesting coins to OriginalVesting
 | 
						// Add the new vesting coins to OriginalVesting
 | 
				
			||||||
	vacc.OriginalVesting = vacc.OriginalVesting.Add(amt...)
 | 
						vacc.OriginalVesting = vacc.OriginalVesting.Add(amt...)
 | 
				
			||||||
	// update vesting periods
 | 
						// update vesting periods
 | 
				
			||||||
 | 
						// EndTime = 100
 | 
				
			||||||
 | 
						// BlockTime  = 110
 | 
				
			||||||
 | 
						// length == 6
 | 
				
			||||||
	if vacc.EndTime < ctx.BlockTime().Unix() {
 | 
						if vacc.EndTime < ctx.BlockTime().Unix() {
 | 
				
			||||||
		// edge case one - the vesting account's end time is in the past (ie, all previous vesting periods have completed)
 | 
							// edge case one - the vesting account's end time is in the past (ie, all previous vesting periods have completed)
 | 
				
			||||||
		// append a new period to the vesting account, update the end time, update the account in the store and return
 | 
							// append a new period to the vesting account, update the end time, update the account in the store and return
 | 
				
			||||||
		newPeriodLength := (ctx.BlockTime().Unix() - vacc.EndTime) + length
 | 
							newPeriodLength := (ctx.BlockTime().Unix() - vacc.EndTime) + length // 110 - 100 + 6 = 16
 | 
				
			||||||
		newPeriod := types.NewPeriod(amt, newPeriodLength)
 | 
							newPeriod := types.NewPeriod(amt, newPeriodLength)
 | 
				
			||||||
		vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
 | 
							vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
 | 
				
			||||||
		vacc.EndTime = ctx.BlockTime().Unix() + length
 | 
							vacc.EndTime = ctx.BlockTime().Unix() + length
 | 
				
			||||||
		k.accountKeeper.SetAccount(ctx, vacc)
 | 
							k.accountKeeper.SetAccount(ctx, vacc)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// StartTime = 110
 | 
				
			||||||
 | 
						// BlockTime = 100
 | 
				
			||||||
 | 
						// length = 6
 | 
				
			||||||
	if vacc.StartTime > ctx.BlockTime().Unix() {
 | 
						if vacc.StartTime > ctx.BlockTime().Unix() {
 | 
				
			||||||
		// edge case two - the vesting account's start time is in the future (all periods have not started)
 | 
							// edge case two - the vesting account's start time is in the future (all periods have not started)
 | 
				
			||||||
		// update the start time to now and adjust the period lengths in place - a new period will be inserted in the next code block
 | 
							// update the start time to now and adjust the period lengths in place - a new period will be inserted in the next code block
 | 
				
			||||||
@ -158,7 +167,7 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
 | 
				
			|||||||
		for i, period := range vacc.VestingPeriods {
 | 
							for i, period := range vacc.VestingPeriods {
 | 
				
			||||||
			updatedPeriod := period
 | 
								updatedPeriod := period
 | 
				
			||||||
			if i == 0 {
 | 
								if i == 0 {
 | 
				
			||||||
				updatedPeriod = types.NewPeriod(period.Amount, (vacc.StartTime-ctx.BlockTime().Unix())+period.Length)
 | 
									updatedPeriod = types.NewPeriod(period.Amount, (vacc.StartTime-ctx.BlockTime().Unix())+period.Length) // 110 - 100 + 6 = 16
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			updatedPeriods = append(updatedPeriods, updatedPeriod)
 | 
								updatedPeriods = append(updatedPeriods, updatedPeriod)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -167,11 +176,12 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// logic for inserting a new vesting period into the existing vesting schedule
 | 
						// logic for inserting a new vesting period into the existing vesting schedule
 | 
				
			||||||
	totalPeriodLength := types.GetTotalVestingPeriodLength(vacc.VestingPeriods)
 | 
						remainingLength := vacc.EndTime - ctx.BlockTime().Unix()
 | 
				
			||||||
 | 
						elapsedTime := ctx.BlockTime().Unix() - vacc.StartTime
 | 
				
			||||||
	proposedEndTime := ctx.BlockTime().Unix() + length
 | 
						proposedEndTime := ctx.BlockTime().Unix() + length
 | 
				
			||||||
	if totalPeriodLength < length {
 | 
						if remainingLength < length {
 | 
				
			||||||
		// in the case that the proposed length is longer than the sum of all previous period lengths, create a new period with length equal to the difference between the proposed length and the previous total length
 | 
							// in the case that the proposed length is longer than the remaining length of all vesting periods, create a new period with length equal to the difference between the proposed length and the previous total length
 | 
				
			||||||
		newPeriodLength := length - totalPeriodLength
 | 
							newPeriodLength := length - remainingLength
 | 
				
			||||||
		newPeriod := types.NewPeriod(amt, newPeriodLength)
 | 
							newPeriod := types.NewPeriod(amt, newPeriodLength)
 | 
				
			||||||
		vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
 | 
							vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
 | 
				
			||||||
		// update the end time so that the sum of all period lengths equals endTime - startTime
 | 
							// update the end time so that the sum of all period lengths equals endTime - startTime
 | 
				
			||||||
@ -184,6 +194,19 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
 | 
				
			|||||||
		// Expected result:
 | 
							// Expected result:
 | 
				
			||||||
		// {[l: 1, a: 1], [l:2, a: 1], [l:2, a:x], [l:6, a:3], [l:5, a:3]}
 | 
							// {[l: 1, a: 1], [l:2, a: 1], [l:2, a:x], [l:6, a:3], [l:5, a:3]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// StartTime = 100
 | 
				
			||||||
 | 
							// Periods = [5,5,5,5]
 | 
				
			||||||
 | 
							// EndTime = 120
 | 
				
			||||||
 | 
							// BlockTime = 101
 | 
				
			||||||
 | 
							// length = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// for period in Periods:
 | 
				
			||||||
 | 
							// iteration  1:
 | 
				
			||||||
 | 
							// lengthCounter = 5
 | 
				
			||||||
 | 
							// if 5 < 101 - 100 + 2 - no
 | 
				
			||||||
 | 
							// if 5 = 3 - no
 | 
				
			||||||
 | 
							// else
 | 
				
			||||||
 | 
							// newperiod = 2 - 0
 | 
				
			||||||
		newPeriods := vesting.Periods{}
 | 
							newPeriods := vesting.Periods{}
 | 
				
			||||||
		lengthCounter := int64(0)
 | 
							lengthCounter := int64(0)
 | 
				
			||||||
		appendRemaining := false
 | 
							appendRemaining := false
 | 
				
			||||||
@ -193,14 +216,14 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
 | 
				
			|||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			lengthCounter += period.Length
 | 
								lengthCounter += period.Length
 | 
				
			||||||
			if lengthCounter < length {
 | 
								if lengthCounter < elapsedTime+length { // 1
 | 
				
			||||||
				newPeriods = append(newPeriods, period)
 | 
									newPeriods = append(newPeriods, period)
 | 
				
			||||||
			} else if lengthCounter == length {
 | 
								} else if lengthCounter == elapsedTime+length {
 | 
				
			||||||
				newPeriod := types.NewPeriod(period.Amount.Add(amt...), period.Length)
 | 
									newPeriod := types.NewPeriod(period.Amount.Add(amt...), period.Length)
 | 
				
			||||||
				newPeriods = append(newPeriods, newPeriod)
 | 
									newPeriods = append(newPeriods, newPeriod)
 | 
				
			||||||
				appendRemaining = true
 | 
									appendRemaining = true
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				newPeriod := types.NewPeriod(amt, length-types.GetTotalVestingPeriodLength(newPeriods))
 | 
									newPeriod := types.NewPeriod(amt, elapsedTime+length-types.GetTotalVestingPeriodLength(newPeriods))
 | 
				
			||||||
				previousPeriod := types.NewPeriod(period.Amount, period.Length-newPeriod.Length)
 | 
									previousPeriod := types.NewPeriod(period.Amount, period.Length-newPeriod.Length)
 | 
				
			||||||
				newPeriods = append(newPeriods, newPeriod, previousPeriod)
 | 
									newPeriods = append(newPeriods, newPeriod, previousPeriod)
 | 
				
			||||||
				appendRemaining = true
 | 
									appendRemaining = true
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ package keeper_test
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
@ -35,7 +36,7 @@ func (suite *KeeperTestSuite) setupChain() {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	supplyKeeper := tApp.GetSupplyKeeper()
 | 
						supplyKeeper := tApp.GetSupplyKeeper()
 | 
				
			||||||
	macc := supplyKeeper.GetModuleAccount(ctx, kavadist.ModuleName)
 | 
						macc := supplyKeeper.GetModuleAccount(ctx, kavadist.ModuleName)
 | 
				
			||||||
	err := supplyKeeper.MintCoins(ctx, macc.GetName(), cs(c("ukava", 500)))
 | 
						err := supplyKeeper.MintCoins(ctx, macc.GetName(), cs(c("ukava", 600)))
 | 
				
			||||||
	suite.Require().NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// sets addrs[0] to be a periodic vesting account
 | 
						// sets addrs[0] to be a periodic vesting account
 | 
				
			||||||
@ -99,157 +100,290 @@ func (suite *KeeperTestSuite) setupExpiredClaims() {
 | 
				
			|||||||
	suite.addrs = addrs
 | 
						suite.addrs = addrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *KeeperTestSuite) TestSendCoinsToPeriodicVestingAccount() {
 | 
					func createPeriodicVestingAccount(origVesting sdk.Coins, periods vesting.Periods, startTime, endTime int64) (*vesting.PeriodicVestingAccount, error) {
 | 
				
			||||||
	suite.setupChain()
 | 
						_, addr := app.GeneratePrivKeyAddressPairs(1)
 | 
				
			||||||
 | 
						bacc := auth.NewBaseAccountWithAddress(addr[0])
 | 
				
			||||||
	type args struct {
 | 
						bacc.Coins = origVesting
 | 
				
			||||||
		coins  sdk.Coins
 | 
						bva, err := vesting.NewBaseVestingAccount(&bacc, origVesting, endTime)
 | 
				
			||||||
		length int64
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &vesting.PeriodicVestingAccount{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						pva := vesting.NewPeriodicVestingAccountRaw(bva, startTime, periods)
 | 
				
			||||||
 | 
						err = pva.Validate()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &vesting.PeriodicVestingAccount{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pva, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *KeeperTestSuite) TestSendCoinsToPeriodicVestingAccount() {
 | 
				
			||||||
 | 
						type accountArgs struct {
 | 
				
			||||||
 | 
							periods          vesting.Periods
 | 
				
			||||||
 | 
							origVestingCoins sdk.Coins
 | 
				
			||||||
 | 
							startTime        int64
 | 
				
			||||||
 | 
							endTime          int64
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						type args struct {
 | 
				
			||||||
 | 
							accArgs             accountArgs
 | 
				
			||||||
 | 
							period              vesting.Period
 | 
				
			||||||
 | 
							ctxTime             time.Time
 | 
				
			||||||
 | 
							mintModAccountCoins bool
 | 
				
			||||||
 | 
							expectedPeriods     vesting.Periods
 | 
				
			||||||
 | 
							expectedStartTime   int64
 | 
				
			||||||
 | 
							expectedEndTime     int64
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	type errArgs struct {
 | 
						type errArgs struct {
 | 
				
			||||||
		expectErr bool
 | 
							expectErr bool
 | 
				
			||||||
		errType   error
 | 
							contains  string
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						type testCase struct {
 | 
				
			||||||
	type vestingAccountTest struct {
 | 
							name    string
 | 
				
			||||||
		name                    string
 | 
							args    args
 | 
				
			||||||
		blockTime               time.Time
 | 
							errArgs errArgs
 | 
				
			||||||
		args                    args
 | 
					 | 
				
			||||||
		errArgs                 errArgs
 | 
					 | 
				
			||||||
		expectedPeriods         vesting.Periods
 | 
					 | 
				
			||||||
		expectedOriginalVesting sdk.Coins
 | 
					 | 
				
			||||||
		expectedCoins           sdk.Coins
 | 
					 | 
				
			||||||
		expectedStartTime       int64
 | 
					 | 
				
			||||||
		expectedEndTime         int64
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						type testCases []testCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type vestingAccountTests []vestingAccountTest
 | 
						tests := testCases{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
	testCases := vestingAccountTests{
 | 
								name: "insert period at beginning schedule",
 | 
				
			||||||
		vestingAccountTest{
 | 
								args: args{
 | 
				
			||||||
			name:      "insert period into an existing vesting schedule",
 | 
									accArgs: accountArgs{
 | 
				
			||||||
			blockTime: time.Unix(100, 0),
 | 
										periods: vesting.Periods{
 | 
				
			||||||
			args:      args{coins: cs(c("ukava", 100)), length: 5},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
			errArgs:   errArgs{expectErr: false, errType: nil},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
			expectedPeriods: vesting.Periods{
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
										startTime:        100,
 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
										endTime:          120,
 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 2, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(101, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 3, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 2, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   120,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedOriginalVesting: cs(c("ukava", 500)),
 | 
								errArgs: errArgs{
 | 
				
			||||||
			expectedCoins:           cs(c("ukava", 500)),
 | 
									expectErr: false,
 | 
				
			||||||
			expectedStartTime:       int64(100),
 | 
									contains:  "",
 | 
				
			||||||
			expectedEndTime:         int64(116),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		vestingAccountTest{
 | 
					 | 
				
			||||||
			name:      "append period to the end of an existing vesting schedule",
 | 
					 | 
				
			||||||
			blockTime: time.Unix(100, 0),
 | 
					 | 
				
			||||||
			args:      args{coins: cs(c("ukava", 100)), length: 17},
 | 
					 | 
				
			||||||
			errArgs:   errArgs{expectErr: false, errType: nil},
 | 
					 | 
				
			||||||
			expectedPeriods: vesting.Periods{
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedOriginalVesting: cs(c("ukava", 600)),
 | 
					 | 
				
			||||||
			expectedCoins:           cs(c("ukava", 600)),
 | 
					 | 
				
			||||||
			expectedStartTime:       int64(100),
 | 
					 | 
				
			||||||
			expectedEndTime:         int64(117),
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		vestingAccountTest{
 | 
							{
 | 
				
			||||||
			name:      "append period to the end of a completed vesting schedule",
 | 
								name: "insert period at beginning with new start time",
 | 
				
			||||||
			blockTime: time.Unix(120, 0),
 | 
								args: args{
 | 
				
			||||||
			args:      args{coins: cs(c("ukava", 100)), length: 5},
 | 
									accArgs: accountArgs{
 | 
				
			||||||
			errArgs:   errArgs{expectErr: false, errType: nil},
 | 
										periods: vesting.Periods{
 | 
				
			||||||
			expectedPeriods: vesting.Periods{
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
										startTime:        100,
 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
										endTime:          120,
 | 
				
			||||||
				vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))},
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(80, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 18, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
									expectedStartTime: 80,
 | 
				
			||||||
 | 
									expectedEndTime:   120,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedOriginalVesting: cs(c("ukava", 700)),
 | 
								errArgs: errArgs{
 | 
				
			||||||
			expectedCoins:           cs(c("ukava", 700)),
 | 
									expectErr: false,
 | 
				
			||||||
			expectedStartTime:       int64(100),
 | 
									contains:  "",
 | 
				
			||||||
			expectedEndTime:         int64(125),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		vestingAccountTest{
 | 
					 | 
				
			||||||
			name:      "prepend period to to an upcoming vesting schedule",
 | 
					 | 
				
			||||||
			blockTime: time.Unix(90, 0),
 | 
					 | 
				
			||||||
			args:      args{coins: cs(c("ukava", 100)), length: 5},
 | 
					 | 
				
			||||||
			errArgs:   errArgs{expectErr: false, errType: nil},
 | 
					 | 
				
			||||||
			expectedPeriods: vesting.Periods{
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
				vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedOriginalVesting: cs(c("ukava", 800)),
 | 
					 | 
				
			||||||
			expectedCoins:           cs(c("ukava", 800)),
 | 
					 | 
				
			||||||
			expectedStartTime:       int64(90),
 | 
					 | 
				
			||||||
			expectedEndTime:         int64(125),
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		vestingAccountTest{
 | 
							{
 | 
				
			||||||
			name:      "add period that coincides with an existing end time",
 | 
								name: "insert period in middle of schedule",
 | 
				
			||||||
			blockTime: time.Unix(90, 0),
 | 
								args: args{
 | 
				
			||||||
			args:      args{coins: cs(c("ukava", 100)), length: 11},
 | 
									accArgs: accountArgs{
 | 
				
			||||||
			errArgs:   errArgs{expectErr: false, errType: nil},
 | 
										periods: vesting.Periods{
 | 
				
			||||||
			expectedPeriods: vesting.Periods{
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 200))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
				vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
 | 
										startTime:        100,
 | 
				
			||||||
				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
 | 
										endTime:          120,
 | 
				
			||||||
				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
 | 
									},
 | 
				
			||||||
				vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))},
 | 
									period:              vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(101, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 3, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 2, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   120,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs: errArgs{
 | 
				
			||||||
 | 
									expectErr: false,
 | 
				
			||||||
 | 
									contains:  "",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedOriginalVesting: cs(c("ukava", 900)),
 | 
					 | 
				
			||||||
			expectedCoins:           cs(c("ukava", 900)),
 | 
					 | 
				
			||||||
			expectedStartTime:       int64(90),
 | 
					 | 
				
			||||||
			expectedEndTime:         int64(125),
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		vestingAccountTest{
 | 
							{
 | 
				
			||||||
			name:                    "insufficient module account balance",
 | 
								name: "append to end of schedule",
 | 
				
			||||||
			blockTime:               time.Unix(90, 0),
 | 
								args: args{
 | 
				
			||||||
			args:                    args{coins: cs(c("ukava", 1000)), length: 11},
 | 
									accArgs: accountArgs{
 | 
				
			||||||
			errArgs:                 errArgs{expectErr: true, errType: types.ErrInsufficientModAccountBalance},
 | 
										periods: vesting.Periods{
 | 
				
			||||||
			expectedPeriods:         vesting.Periods{},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
			expectedOriginalVesting: sdk.Coins{},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
			expectedCoins:           sdk.Coins{},
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
			expectedStartTime:       int64(0),
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
			expectedEndTime:         int64(0),
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
 | 
										startTime:        100,
 | 
				
			||||||
 | 
										endTime:          120,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(125, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 12, Amount: cs(c("ukava", 6))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   132,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs: errArgs{
 | 
				
			||||||
 | 
									expectErr: false,
 | 
				
			||||||
 | 
									contains:  "",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "add coins to existing period",
 | 
				
			||||||
 | 
								args: args{
 | 
				
			||||||
 | 
									accArgs: accountArgs{
 | 
				
			||||||
 | 
										periods: vesting.Periods{
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
 | 
										startTime:        100,
 | 
				
			||||||
 | 
										endTime:          120,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 5, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(110, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 11))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   120,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs: errArgs{
 | 
				
			||||||
 | 
									expectErr: false,
 | 
				
			||||||
 | 
									contains:  "",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "insufficient mod account balance",
 | 
				
			||||||
 | 
								args: args{
 | 
				
			||||||
 | 
									accArgs: accountArgs{
 | 
				
			||||||
 | 
										periods: vesting.Periods{
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
 | 
										startTime:        100,
 | 
				
			||||||
 | 
										endTime:          120,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(125, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: false,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 12, Amount: cs(c("ukava", 6))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   132,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs: errArgs{
 | 
				
			||||||
 | 
									expectErr: true,
 | 
				
			||||||
 | 
									contains:  "insufficient funds",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "add large period mid schedule",
 | 
				
			||||||
 | 
								args: args{
 | 
				
			||||||
 | 
									accArgs: accountArgs{
 | 
				
			||||||
 | 
										periods: vesting.Periods{
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
											vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
 | 
				
			||||||
 | 
										origVestingCoins: cs(c("ukava", 20)),
 | 
				
			||||||
 | 
										startTime:        100,
 | 
				
			||||||
 | 
										endTime:          120,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									period:              vesting.Period{Length: 50, Amount: cs(c("ukava", 6))},
 | 
				
			||||||
 | 
									ctxTime:             time.Unix(110, 0),
 | 
				
			||||||
 | 
									mintModAccountCoins: true,
 | 
				
			||||||
 | 
									expectedPeriods: vesting.Periods{
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
 | 
				
			||||||
 | 
										vesting.Period{Length: 40, Amount: cs(c("ukava", 6))}},
 | 
				
			||||||
 | 
									expectedStartTime: 100,
 | 
				
			||||||
 | 
									expectedEndTime:   160,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs: errArgs{
 | 
				
			||||||
 | 
									expectErr: false,
 | 
				
			||||||
 | 
									contains:  "",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
	for _, tc := range testCases {
 | 
					 | 
				
			||||||
		suite.Run(tc.name, func() {
 | 
							suite.Run(tc.name, func() {
 | 
				
			||||||
			suite.ctx = suite.ctx.WithBlockTime(tc.blockTime)
 | 
								// create the periodic vesting account
 | 
				
			||||||
			err := suite.keeper.SendTimeLockedCoinsToAccount(suite.ctx, kavadist.ModuleName, suite.addrs[0], tc.args.coins, tc.args.length)
 | 
								pva, err := createPeriodicVestingAccount(tc.args.accArgs.origVestingCoins, tc.args.accArgs.periods, tc.args.accArgs.startTime, tc.args.accArgs.endTime)
 | 
				
			||||||
 | 
								suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// setup store state with account and kavadist module account
 | 
				
			||||||
 | 
								suite.ctx = suite.ctx.WithBlockTime(tc.args.ctxTime)
 | 
				
			||||||
 | 
								ak := suite.app.GetAccountKeeper()
 | 
				
			||||||
 | 
								ak.SetAccount(suite.ctx, pva)
 | 
				
			||||||
 | 
								// mint module account coins if required
 | 
				
			||||||
 | 
								if tc.args.mintModAccountCoins {
 | 
				
			||||||
 | 
									sk := suite.app.GetSupplyKeeper()
 | 
				
			||||||
 | 
									err = sk.MintCoins(suite.ctx, kavadist.ModuleName, tc.args.period.Amount)
 | 
				
			||||||
 | 
									suite.Require().NoError(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = suite.keeper.SendTimeLockedCoinsToPeriodicVestingAccount(suite.ctx, kavadist.ModuleName, pva.Address, tc.args.period.Amount, tc.args.period.Length)
 | 
				
			||||||
			if tc.errArgs.expectErr {
 | 
								if tc.errArgs.expectErr {
 | 
				
			||||||
				suite.Require().True(errors.Is(err, tc.errArgs.errType))
 | 
									suite.Require().Error(err)
 | 
				
			||||||
 | 
									suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains))
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				suite.Require().NoError(err)
 | 
									suite.Require().NoError(err)
 | 
				
			||||||
				acc := suite.getAccount(suite.addrs[0])
 | 
					
 | 
				
			||||||
 | 
									acc := suite.getAccount(pva.Address)
 | 
				
			||||||
				vacc, ok := acc.(*vesting.PeriodicVestingAccount)
 | 
									vacc, ok := acc.(*vesting.PeriodicVestingAccount)
 | 
				
			||||||
				suite.True(ok)
 | 
									suite.Require().True(ok)
 | 
				
			||||||
				suite.Equal(tc.expectedPeriods, vacc.VestingPeriods)
 | 
									suite.Require().Equal(tc.args.expectedPeriods, vacc.VestingPeriods)
 | 
				
			||||||
				suite.Equal(tc.expectedOriginalVesting, vacc.OriginalVesting)
 | 
									suite.Require().Equal(tc.args.expectedStartTime, vacc.StartTime)
 | 
				
			||||||
				suite.Equal(tc.expectedCoins, vacc.Coins)
 | 
									suite.Require().Equal(tc.args.expectedEndTime, vacc.EndTime)
 | 
				
			||||||
				suite.Equal(tc.expectedStartTime, vacc.StartTime)
 | 
					 | 
				
			||||||
				suite.Equal(tc.expectedEndTime, vacc.EndTime)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -300,7 +434,7 @@ func (suite *KeeperTestSuite) TestPayoutClaim() {
 | 
				
			|||||||
	suite.keeper.SetClaim(suite.ctx, c3)
 | 
						suite.keeper.SetClaim(suite.ctx, c3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// existing claim with corresponding claim period successfully claimed by existing periodic vesting account
 | 
						// existing claim with corresponding claim period successfully claimed by existing periodic vesting account
 | 
				
			||||||
	err := suite.keeper.PayoutClaim(suite.ctx, suite.addrs[0], "bnb", 1)
 | 
						err := suite.keeper.PayoutClaim(suite.ctx.WithBlockTime(time.Unix(3700, 0)), suite.addrs[0], "bnb", 1)
 | 
				
			||||||
	suite.Require().NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
	acc := suite.getAccount(suite.addrs[0])
 | 
						acc := suite.getAccount(suite.addrs[0])
 | 
				
			||||||
	// account is a periodic vesting account
 | 
						// account is a periodic vesting account
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user